1#include <linux/delay.h>
2#include "XGIfb.h"
3
4#include "vb_def.h"
5#include "vb_init.h"
6#include "vb_util.h"
7#include "vb_table.h"
8#include "vb_setmode.h"
9
10#define  IndexMask 0xff
11#define TVCLKBASE_315_25 (TVCLKBASE_315 + 25)
12
13static const unsigned short XGINew_VGA_DAC[] = {
14	0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15,
15	0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F,
16	0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18,
17	0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F,
18	0x00, 0x10, 0x1F, 0x2F, 0x3F, 0x1F, 0x27, 0x2F,
19	0x37, 0x3F, 0x2D, 0x31, 0x36, 0x3A, 0x3F, 0x00,
20	0x07, 0x0E, 0x15, 0x1C, 0x0E, 0x11, 0x15, 0x18,
21	0x1C, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x04,
22	0x08, 0x0C, 0x10, 0x08, 0x0A, 0x0C, 0x0E, 0x10,
23	0x0B, 0x0C, 0x0D, 0x0F, 0x10};
24
25void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
26{
27	pVBInfo->MCLKData = XGI340New_MCLKData;
28
29	pVBInfo->LCDResInfo = 0;
30	pVBInfo->LCDTypeInfo = 0;
31	pVBInfo->LCDInfo = 0;
32	pVBInfo->VBInfo = 0;
33	pVBInfo->TVInfo = 0;
34
35	pVBInfo->SR18 = XGI340_SR18;
36	pVBInfo->CR40 = XGI340_cr41;
37
38	if (ChipType < XG20)
39		XGI_GetVBType(pVBInfo);
40
41	/* 310 customization related */
42	if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV))
43		pVBInfo->LCDCapList = XGI_LCDDLCapList;
44	else
45		pVBInfo->LCDCapList = XGI_LCDCapList;
46
47	if (ChipType >= XG20)
48		pVBInfo->XGINew_CR97 = 0x10;
49
50	if (ChipType == XG27) {
51		unsigned char temp;
52
53		pVBInfo->MCLKData = XGI27New_MCLKData;
54		pVBInfo->CR40 = XGI27_cr41;
55		pVBInfo->XGINew_CR97 = 0xc1;
56		pVBInfo->SR18 = XG27_SR18;
57
58		/*Z11m DDR*/
59		temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
60		/* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
61		if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08))
62			pVBInfo->XGINew_CR97 = 0x80;
63	}
64
65}
66
67static void XGI_SetSeqRegs(struct vb_device_info *pVBInfo)
68{
69	unsigned char SRdata, i;
70
71	xgifb_reg_set(pVBInfo->P3c4, 0x00, 0x03); /* Set SR0 */
72
73	for (i = 0; i < 4; i++) {
74		/* Get SR1,2,3,4 from file */
75		/* SR1 is with screen off 0x20 */
76		SRdata = XGI330_StandTable.SR[i];
77		xgifb_reg_set(pVBInfo->P3c4, i+1, SRdata); /* Set SR 1 2 3 4 */
78	}
79}
80
81static void XGI_SetCRTCRegs(struct vb_device_info *pVBInfo)
82{
83	unsigned char CRTCdata;
84	unsigned short i;
85
86	CRTCdata = xgifb_reg_get(pVBInfo->P3d4, 0x11);
87	CRTCdata &= 0x7f;
88	xgifb_reg_set(pVBInfo->P3d4, 0x11, CRTCdata); /* Unlock CRTC */
89
90	for (i = 0; i <= 0x18; i++) {
91		/* Get CRTC from file */
92		CRTCdata = XGI330_StandTable.CRTC[i];
93		xgifb_reg_set(pVBInfo->P3d4, i, CRTCdata); /* Set CRTC(3d4) */
94	}
95}
96
97static void XGI_SetATTRegs(unsigned short ModeIdIndex,
98			   struct vb_device_info *pVBInfo)
99{
100	unsigned char ARdata;
101	unsigned short i, modeflag;
102
103	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
104
105	for (i = 0; i <= 0x13; i++) {
106		ARdata = XGI330_StandTable.ATTR[i];
107
108		if ((modeflag & Charx8Dot) && i == 0x13) { /* ifndef Dot9 */
109			if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
110				ARdata = 0;
111			} else if ((pVBInfo->VBInfo &
112				     (SetCRT2ToTV | SetCRT2ToLCD)) &&
113				    (pVBInfo->VBInfo & SetInSlaveMode)) {
114					ARdata = 0;
115			}
116		}
117
118		inb(pVBInfo->P3da); /* reset 3da */
119		outb(i, pVBInfo->P3c0); /* set index */
120		outb(ARdata, pVBInfo->P3c0); /* set data */
121	}
122
123	inb(pVBInfo->P3da); /* reset 3da */
124	outb(0x14, pVBInfo->P3c0); /* set index */
125	outb(0x00, pVBInfo->P3c0); /* set data */
126	inb(pVBInfo->P3da); /* Enable Attribute */
127	outb(0x20, pVBInfo->P3c0);
128}
129
130static void XGI_SetGRCRegs(struct vb_device_info *pVBInfo)
131{
132	unsigned char GRdata;
133	unsigned short i;
134
135	for (i = 0; i <= 0x08; i++) {
136		/* Get GR from file */
137		GRdata = XGI330_StandTable.GRC[i];
138		xgifb_reg_set(pVBInfo->P3ce, i, GRdata); /* Set GR(3ce) */
139	}
140
141	if (pVBInfo->ModeType > ModeVGA) {
142		GRdata = xgifb_reg_get(pVBInfo->P3ce, 0x05);
143		GRdata &= 0xBF; /* 256 color disable */
144		xgifb_reg_set(pVBInfo->P3ce, 0x05, GRdata);
145	}
146}
147
148static void XGI_ClearExt1Regs(struct vb_device_info *pVBInfo)
149{
150	unsigned short i;
151
152	for (i = 0x0A; i <= 0x0E; i++)
153		xgifb_reg_set(pVBInfo->P3c4, i, 0x00); /* Clear SR0A-SR0E */
154}
155
156static unsigned char XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo)
157{
158
159	xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, 0x20);
160	xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[0].SR2B);
161	xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[0].SR2C);
162
163	xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, 0x10);
164	xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[1].SR2B);
165	xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[1].SR2C);
166
167	xgifb_reg_and(pVBInfo->P3c4, 0x31, ~0x30);
168	return 0;
169}
170
171static unsigned char XGI_AjustCRT2Rate(unsigned short ModeIdIndex,
172		unsigned short RefreshRateTableIndex, unsigned short *i,
173		struct vb_device_info *pVBInfo)
174{
175	unsigned short tempax, tempbx, resinfo, modeflag, infoflag;
176
177	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
178	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
179	tempbx = XGI330_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
180	tempax = 0;
181
182	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
183		tempax |= SupportRAMDAC2;
184
185		if (pVBInfo->VBType & VB_XGI301C)
186			tempax |= SupportCRT2in301C;
187	}
188
189	/* 301b */
190	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
191		tempax |= SupportLCD;
192
193		if (pVBInfo->LCDResInfo != Panel_1280x1024 &&
194		    pVBInfo->LCDResInfo != Panel_1280x960 &&
195		    (pVBInfo->LCDInfo & LCDNonExpanding) &&
196		    resinfo >= 9)
197			return 0;
198	}
199
200	if (pVBInfo->VBInfo & SetCRT2ToHiVision) { /* for HiTV */
201		tempax |= SupportHiVision;
202		if ((pVBInfo->VBInfo & SetInSlaveMode) &&
203		    ((resinfo == 4) ||
204		     (resinfo == 3 && (pVBInfo->SetFlag & TVSimuMode)) ||
205		     (resinfo > 7)))
206			return 0;
207	} else if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO | SetCRT2ToSVIDEO |
208				      SetCRT2ToSCART | SetCRT2ToYPbPr525750 |
209				      SetCRT2ToHiVision)) {
210		tempax |= SupportTV;
211
212		if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV |
213				       VB_SIS302LV | VB_XGI301C))
214			tempax |= SupportTV1024;
215
216		if (!(pVBInfo->VBInfo & TVSetPAL) &&
217		    (modeflag & NoSupportSimuTV) &&
218		    (pVBInfo->VBInfo & SetInSlaveMode) &&
219		    (!(pVBInfo->VBInfo & SetNotSimuMode)))
220			return 0;
221	}
222
223	for (; XGI330_RefIndex[RefreshRateTableIndex + (*i)].ModeID ==
224	       tempbx; (*i)--) {
225		infoflag = XGI330_RefIndex[RefreshRateTableIndex + (*i)].
226				Ext_InfoFlag;
227		if (infoflag & tempax)
228			return 1;
229
230		if ((*i) == 0)
231			break;
232	}
233
234	for ((*i) = 0;; (*i)++) {
235		infoflag = XGI330_RefIndex[RefreshRateTableIndex + (*i)].
236				Ext_InfoFlag;
237		if (XGI330_RefIndex[RefreshRateTableIndex + (*i)].ModeID
238				!= tempbx) {
239			return 0;
240		}
241
242		if (infoflag & tempax)
243			return 1;
244	}
245	return 1;
246}
247
248static void XGI_SetSync(unsigned short RefreshRateTableIndex,
249		struct vb_device_info *pVBInfo)
250{
251	unsigned short sync, temp;
252
253	/* di+0x00 */
254	sync = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8;
255	sync &= 0xC0;
256	temp = 0x2F;
257	temp |= sync;
258	outb(temp, pVBInfo->P3c2); /* Set Misc(3c2) */
259}
260
261static void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo,
262		struct xgi_hw_device_info *HwDeviceExtension)
263{
264	unsigned char data, data1, pushax;
265	unsigned short i, j;
266
267	/* unlock cr0-7 */
268	data = xgifb_reg_get(pVBInfo->P3d4, 0x11);
269	data &= 0x7F;
270	xgifb_reg_set(pVBInfo->P3d4, 0x11, data);
271
272	data = pVBInfo->TimingH.data[0];
273	xgifb_reg_set(pVBInfo->P3d4, 0, data);
274
275	for (i = 0x01; i <= 0x04; i++) {
276		data = pVBInfo->TimingH.data[i];
277		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 1), data);
278	}
279
280	for (i = 0x05; i <= 0x06; i++) {
281		data = pVBInfo->TimingH.data[i];
282		xgifb_reg_set(pVBInfo->P3c4, (unsigned short) (i + 6), data);
283	}
284
285	j = xgifb_reg_get(pVBInfo->P3c4, 0x0e);
286	j &= 0x1F;
287	data = pVBInfo->TimingH.data[7];
288	data &= 0xE0;
289	data |= j;
290	xgifb_reg_set(pVBInfo->P3c4, 0x0e, data);
291
292	if (HwDeviceExtension->jChipType >= XG20) {
293		data = xgifb_reg_get(pVBInfo->P3d4, 0x04);
294		data = data - 1;
295		xgifb_reg_set(pVBInfo->P3d4, 0x04, data);
296		data = xgifb_reg_get(pVBInfo->P3d4, 0x05);
297		data1 = data;
298		data1 &= 0xE0;
299		data &= 0x1F;
300		if (data == 0) {
301			pushax = data;
302			data = xgifb_reg_get(pVBInfo->P3c4, 0x0c);
303			data &= 0xFB;
304			xgifb_reg_set(pVBInfo->P3c4, 0x0c, data);
305			data = pushax;
306		}
307		data = data - 1;
308		data |= data1;
309		xgifb_reg_set(pVBInfo->P3d4, 0x05, data);
310		data = xgifb_reg_get(pVBInfo->P3c4, 0x0e);
311		data >>= 5;
312		data = data + 3;
313		if (data > 7)
314			data = data - 7;
315		data <<= 5;
316		xgifb_reg_and_or(pVBInfo->P3c4, 0x0e, ~0xE0, data);
317	}
318}
319
320static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex,
321				struct vb_device_info *pVBInfo)
322{
323	unsigned char data;
324	unsigned short i, j;
325
326	for (i = 0x00; i <= 0x01; i++) {
327		data = pVBInfo->TimingV.data[i];
328		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 6), data);
329	}
330
331	for (i = 0x02; i <= 0x03; i++) {
332		data = pVBInfo->TimingV.data[i];
333		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 0x0e), data);
334	}
335
336	for (i = 0x04; i <= 0x05; i++) {
337		data = pVBInfo->TimingV.data[i];
338		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 0x11), data);
339	}
340
341	j = xgifb_reg_get(pVBInfo->P3c4, 0x0a);
342	j &= 0xC0;
343	data = pVBInfo->TimingV.data[6];
344	data &= 0x3F;
345	data |= j;
346	xgifb_reg_set(pVBInfo->P3c4, 0x0a, data);
347
348	data = pVBInfo->TimingV.data[6];
349	data &= 0x80;
350	data >>= 2;
351
352	i = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
353	i &= DoubleScanMode;
354	if (i)
355		data |= 0x80;
356
357	j = xgifb_reg_get(pVBInfo->P3d4, 0x09);
358	j &= 0x5F;
359	data |= j;
360	xgifb_reg_set(pVBInfo->P3d4, 0x09, data);
361}
362
363static void XGI_SetCRT1CRTC(unsigned short ModeIdIndex,
364		unsigned short RefreshRateTableIndex,
365		struct vb_device_info *pVBInfo,
366		struct xgi_hw_device_info *HwDeviceExtension)
367{
368	unsigned char index, data;
369	unsigned short i;
370
371	/* Get index */
372	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
373	index = index & IndexMask;
374
375	data = xgifb_reg_get(pVBInfo->P3d4, 0x11);
376	data &= 0x7F;
377	xgifb_reg_set(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */
378
379	for (i = 0; i < 8; i++)
380		pVBInfo->TimingH.data[i]
381				= XGI_CRT1Table[index].CR[i];
382
383	for (i = 0; i < 7; i++)
384		pVBInfo->TimingV.data[i]
385				= XGI_CRT1Table[index].CR[i + 8];
386
387	XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
388
389	XGI_SetCRT1Timing_V(ModeIdIndex, pVBInfo);
390
391	if (pVBInfo->ModeType > 0x03)
392		xgifb_reg_set(pVBInfo->P3d4, 0x14, 0x4F);
393}
394
395/* --------------------------------------------------------------------- */
396/* Function : XGI_SetXG21CRTC */
397/* Input : Stand or enhance CRTC table */
398/* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */
399/* Description : Set LCD timing */
400/* --------------------------------------------------------------------- */
401static void XGI_SetXG21CRTC(unsigned short RefreshRateTableIndex,
402		struct vb_device_info *pVBInfo)
403{
404	unsigned char index, Tempax, Tempbx, Tempcx, Tempdx;
405	unsigned short Temp1, Temp2, Temp3;
406
407	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
408	/* Tempax: CR4 HRS */
409	Tempax = XGI_CRT1Table[index].CR[3];
410	Tempcx = Tempax; /* Tempcx: HRS */
411	/* SR2E[7:0]->HRS */
412	xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
413
414	Tempdx = XGI_CRT1Table[index].CR[5]; /* SRB */
415	Tempdx &= 0xC0; /* Tempdx[7:6]: SRB[7:6] */
416	Temp1 = Tempdx; /* Temp1[7:6]: HRS[9:8] */
417	Temp1 <<= 2; /* Temp1[9:8]: HRS[9:8] */
418	Temp1 |= Tempax; /* Temp1[9:0]: HRS[9:0] */
419
420	Tempax = XGI_CRT1Table[index].CR[4]; /* CR5 HRE */
421	Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
422
423	Tempbx = XGI_CRT1Table[index].CR[6]; /* SRC */
424	Tempbx &= 0x04; /* Tempbx[2]: HRE[5] */
425	Tempbx <<= 3; /* Tempbx[5]: HRE[5] */
426	Tempax |= Tempbx; /* Tempax[5:0]: HRE[5:0] */
427
428	Temp2 = Temp1 & 0x3C0; /* Temp2[9:6]: HRS[9:6] */
429	Temp2 |= Tempax; /* Temp2[9:0]: HRE[9:0] */
430
431	Tempcx &= 0x3F; /* Tempcx[5:0]: HRS[5:0] */
432	if (Tempax < Tempcx) /* HRE < HRS */
433		Temp2 |= 0x40; /* Temp2 + 0x40 */
434
435	Temp2 &= 0xFF;
436	Tempax = (unsigned char) Temp2; /* Tempax: HRE[7:0] */
437	Tempax <<= 2; /* Tempax[7:2]: HRE[5:0] */
438	Tempdx >>= 6; /* Tempdx[7:6]->[1:0] HRS[9:8] */
439	Tempax |= Tempdx; /* HRE[5:0]HRS[9:8] */
440	/* SR2F D[7:2]->HRE, D[1:0]->HRS */
441	xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax);
442	xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
443
444	/* CR10 VRS */
445	Tempax = XGI_CRT1Table[index].CR[10];
446	Tempbx = Tempax; /* Tempbx: VRS */
447	Tempax &= 0x01; /* Tempax[0]: VRS[0] */
448	xgifb_reg_or(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS[0] */
449	/* CR7[2][7] VRE */
450	Tempax = XGI_CRT1Table[index].CR[9];
451	Tempcx = Tempbx >> 1; /* Tempcx[6:0]: VRS[7:1] */
452	Tempdx = Tempax & 0x04; /* Tempdx[2]: CR7[2] */
453	Tempdx <<= 5; /* Tempdx[7]: VRS[8] */
454	Tempcx |= Tempdx; /* Tempcx[7:0]: VRS[8:1] */
455	xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempcx); /* SR34[8:1]->VRS */
456
457	Temp1 = Tempdx; /* Temp1[7]: Tempdx[7] */
458	Temp1 <<= 1; /* Temp1[8]: VRS[8] */
459	Temp1 |= Tempbx; /* Temp1[8:0]: VRS[8:0] */
460	Tempax &= 0x80;
461	Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
462	Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
463	/* Tempax: SRA */
464	Tempax = XGI_CRT1Table[index].CR[14];
465	Tempax &= 0x08; /* Tempax[3]: VRS[3] */
466	Temp2 = Tempax;
467	Temp2 <<= 7; /* Temp2[10]: VRS[10] */
468	Temp1 |= Temp2; /* Temp1[10:0]: VRS[10:0] */
469
470	/* Tempax: CR11 VRE */
471	Tempax = XGI_CRT1Table[index].CR[11];
472	Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
473	/* Tempbx: SRA */
474	Tempbx = XGI_CRT1Table[index].CR[14];
475	Tempbx &= 0x20; /* Tempbx[5]: VRE[5] */
476	Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
477	Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
478	Temp2 = Temp1 & 0x7E0; /* Temp2[10:5]: VRS[10:5] */
479	Temp2 |= Tempax; /* Temp2[10:5]: VRE[10:5] */
480
481	Temp3 = Temp1 & 0x1F; /* Temp3[4:0]: VRS[4:0] */
482	if (Tempax < Temp3) /* VRE < VRS */
483		Temp2 |= 0x20; /* VRE + 0x20 */
484
485	Temp2 &= 0xFF;
486	Tempax = (unsigned char) Temp2; /* Tempax: VRE[7:0] */
487	Tempax <<= 2; /* Tempax[7:0]; VRE[5:0]00 */
488	Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */
489	Temp1 >>= 9; /* Temp1[1:0]: VRS[10:9] */
490	Tempbx = (unsigned char) Temp1;
491	Tempax |= Tempbx; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */
492	Tempax &= 0x7F;
493	/* SR3F D[7:2]->VRE D[1:0]->VRS */
494	xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax);
495}
496
497static void XGI_SetXG27CRTC(unsigned short RefreshRateTableIndex,
498			    struct vb_device_info *pVBInfo)
499{
500	unsigned short index, Tempax, Tempbx, Tempcx;
501
502	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
503	/* Tempax: CR4 HRS */
504	Tempax = XGI_CRT1Table[index].CR[3];
505	Tempbx = Tempax; /* Tempbx: HRS[7:0] */
506	/* SR2E[7:0]->HRS */
507	xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax);
508
509	/* SR0B */
510	Tempax = XGI_CRT1Table[index].CR[5];
511	Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
512	Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */
513
514	Tempax = XGI_CRT1Table[index].CR[4]; /* CR5 HRE */
515	Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
516	Tempcx = Tempax; /* Tempcx: HRE[4:0] */
517
518	Tempax = XGI_CRT1Table[index].CR[6]; /* SRC */
519	Tempax &= 0x04; /* Tempax[2]: HRE[5] */
520	Tempax <<= 3; /* Tempax[5]: HRE[5] */
521	Tempcx |= Tempax; /* Tempcx[5:0]: HRE[5:0] */
522
523	Tempbx = Tempbx & 0x3C0; /* Tempbx[9:6]: HRS[9:6] */
524	Tempbx |= Tempcx; /* Tempbx: HRS[9:6]HRE[5:0] */
525
526	/* Tempax: CR4 HRS */
527	Tempax = XGI_CRT1Table[index].CR[3];
528	Tempax &= 0x3F; /* Tempax: HRS[5:0] */
529	if (Tempcx <= Tempax) /* HRE[5:0] < HRS[5:0] */
530		Tempbx += 0x40; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
531
532	Tempax = XGI_CRT1Table[index].CR[5]; /* SR0B */
533	Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
534	Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/
535	Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */
536	/* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */
537	xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax);
538	xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
539
540	/* CR10 VRS */
541	Tempax = XGI_CRT1Table[index].CR[10];
542	/* SR34[7:0]->VRS[7:0] */
543	xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempax);
544
545	Tempcx = Tempax; /* Tempcx <= VRS[7:0] */
546	/* CR7[7][2] VRS[9][8] */
547	Tempax = XGI_CRT1Table[index].CR[9];
548	Tempbx = Tempax; /* Tempbx <= CR07[7:0] */
549	Tempax = Tempax & 0x04; /* Tempax[2]: CR7[2]: VRS[8] */
550	Tempax >>= 2; /* Tempax[0]: VRS[8] */
551	/* SR35[0]: VRS[8] */
552	xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x01, Tempax);
553	Tempcx |= (Tempax << 8); /* Tempcx <= VRS[8:0] */
554	Tempcx |= ((Tempbx & 0x80) << 2); /* Tempcx <= VRS[9:0] */
555	/* Tempax: SR0A */
556	Tempax = XGI_CRT1Table[index].CR[14];
557	Tempax &= 0x08; /* SR0A[3] VRS[10] */
558	Tempcx |= (Tempax << 7); /* Tempcx <= VRS[10:0] */
559
560	/* Tempax: CR11 VRE */
561	Tempax = XGI_CRT1Table[index].CR[11];
562	Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
563	/* Tempbx: SR0A */
564	Tempbx = XGI_CRT1Table[index].CR[14];
565	Tempbx &= 0x20; /* Tempbx[5]: SR0A[5]: VRE[4] */
566	Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
567	Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
568	Tempbx = Tempcx; /* Tempbx: VRS[10:0] */
569	Tempbx &= 0x7E0; /* Tempbx[10:5]: VRS[10:5] */
570	Tempbx |= Tempax; /* Tempbx: VRS[10:5]VRE[4:0] */
571
572	if (Tempbx <= Tempcx) /* VRE <= VRS */
573		Tempbx |= 0x20; /* VRE + 0x20 */
574
575	/* Tempax: Tempax[7:0]; VRE[5:0]00 */
576	Tempax = (Tempbx << 2) & 0xFF;
577	/* SR3F[7:2]:VRE[5:0] */
578	xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, Tempax);
579	Tempax = Tempcx >> 8;
580	/* SR35[2:0]:VRS[10:8] */
581	xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07, Tempax);
582}
583
584static void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo)
585{
586	unsigned char temp;
587
588	/* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
589	temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
590	temp = (temp & 3) << 6;
591	/* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */
592	xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0xc0, temp & 0x80);
593	/* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */
594	xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80);
595
596}
597
598static void xgifb_set_lcd(int chip_id,
599			  struct vb_device_info *pVBInfo,
600			  unsigned short RefreshRateTableIndex)
601{
602	unsigned short temp;
603
604	xgifb_reg_set(pVBInfo->P3d4, 0x2E, 0x00);
605	xgifb_reg_set(pVBInfo->P3d4, 0x2F, 0x00);
606	xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x00);
607	xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x00);
608
609	if (chip_id == XG27) {
610		temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
611		if ((temp & 0x03) == 0) { /* dual 12 */
612			xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x13);
613			xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x13);
614		}
615	}
616
617	if (chip_id == XG27) {
618		XGI_SetXG27FPBits(pVBInfo);
619	} else {
620		temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
621		if (temp & 0x01) {
622			/* 18 bits FP */
623			xgifb_reg_or(pVBInfo->P3c4, 0x06, 0x40);
624			xgifb_reg_or(pVBInfo->P3c4, 0x09, 0x40);
625		}
626	}
627
628	xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x01); /* Negative blank polarity */
629
630	xgifb_reg_and(pVBInfo->P3c4, 0x30, ~0x20); /* Hsync polarity */
631	xgifb_reg_and(pVBInfo->P3c4, 0x35, ~0x80); /* Vsync polarity */
632
633	temp = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
634	if (temp & 0x4000)
635		/* Hsync polarity */
636		xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20);
637	if (temp & 0x8000)
638		/* Vsync polarity */
639		xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80);
640}
641
642/* --------------------------------------------------------------------- */
643/* Function : XGI_UpdateXG21CRTC */
644/* Input : */
645/* Output : CRT1 CRTC */
646/* Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing */
647/* --------------------------------------------------------------------- */
648static void XGI_UpdateXG21CRTC(unsigned short ModeNo,
649			       struct vb_device_info *pVBInfo,
650			       unsigned short RefreshRateTableIndex)
651{
652	int index = -1;
653
654	xgifb_reg_and(pVBInfo->P3d4, 0x11, 0x7F); /* Unlock CR0~7 */
655	if (ModeNo == 0x2E &&
656	    (XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC ==
657						      RES640x480x60))
658		index = 12;
659	else if (ModeNo == 0x2E && (XGI330_RefIndex[RefreshRateTableIndex].
660				Ext_CRT1CRTC == RES640x480x72))
661		index = 13;
662	else if (ModeNo == 0x2F)
663		index = 14;
664	else if (ModeNo == 0x50)
665		index = 15;
666	else if (ModeNo == 0x59)
667		index = 16;
668
669	if (index != -1) {
670		xgifb_reg_set(pVBInfo->P3d4, 0x02,
671				XGI_UpdateCRT1Table[index].CR02);
672		xgifb_reg_set(pVBInfo->P3d4, 0x03,
673				XGI_UpdateCRT1Table[index].CR03);
674		xgifb_reg_set(pVBInfo->P3d4, 0x15,
675				XGI_UpdateCRT1Table[index].CR15);
676		xgifb_reg_set(pVBInfo->P3d4, 0x16,
677				XGI_UpdateCRT1Table[index].CR16);
678	}
679}
680
681static void XGI_SetCRT1DE(unsigned short ModeIdIndex,
682		unsigned short RefreshRateTableIndex,
683		struct vb_device_info *pVBInfo)
684{
685	unsigned short resindex, tempax, tempbx, tempcx, temp, modeflag;
686
687	unsigned char data;
688
689	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
690
691	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
692	tempax = XGI330_ModeResInfo[resindex].HTotal;
693	tempbx = XGI330_ModeResInfo[resindex].VTotal;
694
695	if (modeflag & HalfDCLK)
696		tempax >>= 1;
697
698	if (modeflag & HalfDCLK)
699		tempax <<= 1;
700
701	temp = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
702
703	if (temp & InterlaceMode)
704		tempbx >>= 1;
705
706	if (modeflag & DoubleScanMode)
707		tempbx <<= 1;
708
709	tempcx = 8;
710
711	tempax /= tempcx;
712	tempax -= 1;
713	tempbx -= 1;
714	tempcx = tempax;
715	temp = xgifb_reg_get(pVBInfo->P3d4, 0x11);
716	data = xgifb_reg_get(pVBInfo->P3d4, 0x11);
717	data &= 0x7F;
718	xgifb_reg_set(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */
719	xgifb_reg_set(pVBInfo->P3d4, 0x01, (unsigned short) (tempcx & 0xff));
720	xgifb_reg_and_or(pVBInfo->P3d4, 0x0b, ~0x0c,
721			(unsigned short) ((tempcx & 0x0ff00) >> 10));
722	xgifb_reg_set(pVBInfo->P3d4, 0x12, (unsigned short) (tempbx & 0xff));
723	tempax = 0;
724	tempbx >>= 8;
725
726	if (tempbx & 0x01)
727		tempax |= 0x02;
728
729	if (tempbx & 0x02)
730		tempax |= 0x40;
731
732	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x42, tempax);
733	data = xgifb_reg_get(pVBInfo->P3d4, 0x07);
734	tempax = 0;
735
736	if (tempbx & 0x04)
737		tempax |= 0x02;
738
739	xgifb_reg_and_or(pVBInfo->P3d4, 0x0a, ~0x02, tempax);
740	xgifb_reg_set(pVBInfo->P3d4, 0x11, temp);
741}
742
743static void XGI_SetCRT1Offset(unsigned short ModeNo,
744			      unsigned short ModeIdIndex,
745			      unsigned short RefreshRateTableIndex,
746			      struct xgi_hw_device_info *HwDeviceExtension,
747			      struct vb_device_info *pVBInfo)
748{
749	unsigned short temp, ah, al, temp2, i, DisplayUnit;
750
751	/* GetOffset */
752	temp = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
753	temp >>= 8;
754	temp = XGI330_ScreenOffset[temp];
755
756	temp2 = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
757	temp2 &= InterlaceMode;
758
759	if (temp2)
760		temp <<= 1;
761
762	temp2 = pVBInfo->ModeType - ModeEGA;
763
764	switch (temp2) {
765	case 0:
766		temp2 = 1;
767		break;
768	case 1:
769		temp2 = 2;
770		break;
771	case 2:
772		temp2 = 4;
773		break;
774	case 3:
775		temp2 = 4;
776		break;
777	case 4:
778		temp2 = 6;
779		break;
780	case 5:
781		temp2 = 8;
782		break;
783	default:
784		break;
785	}
786
787	if ((ModeNo >= 0x26) && (ModeNo <= 0x28))
788		temp = temp * temp2 + temp2 / 2;
789	else
790		temp *= temp2;
791
792	/* SetOffset */
793	DisplayUnit = temp;
794	temp2 = temp;
795	temp >>= 8; /* ah */
796	temp &= 0x0F;
797	i = xgifb_reg_get(pVBInfo->P3c4, 0x0E);
798	i &= 0xF0;
799	i |= temp;
800	xgifb_reg_set(pVBInfo->P3c4, 0x0E, i);
801
802	temp = (unsigned char) temp2;
803	temp &= 0xFF; /* al */
804	xgifb_reg_set(pVBInfo->P3d4, 0x13, temp);
805
806	/* SetDisplayUnit */
807	temp2 = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
808	temp2 &= InterlaceMode;
809	if (temp2)
810		DisplayUnit >>= 1;
811
812	DisplayUnit <<= 5;
813	ah = (DisplayUnit & 0xff00) >> 8;
814	al = DisplayUnit & 0x00ff;
815	if (al == 0)
816		ah += 1;
817	else
818		ah += 2;
819
820	if (HwDeviceExtension->jChipType >= XG20)
821		if ((ModeNo == 0x4A) | (ModeNo == 0x49))
822			ah -= 1;
823
824	xgifb_reg_set(pVBInfo->P3c4, 0x10, ah);
825}
826
827static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeIdIndex,
828		unsigned short RefreshRateTableIndex,
829		struct vb_device_info *pVBInfo)
830{
831	unsigned short VCLKIndex, modeflag;
832
833	/* si+Ext_ResInfo */
834	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
835
836	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { /*301b*/
837		if (pVBInfo->LCDResInfo != Panel_1024x768)
838			/* LCDXlat2VCLK */
839			VCLKIndex = VCLK108_2_315 + 5;
840		else
841			VCLKIndex = VCLK65_315 + 2; /* LCDXlat1VCLK */
842	} else if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
843		if (pVBInfo->SetFlag & RPLLDIV2XO)
844			VCLKIndex = TVCLKBASE_315_25 + HiTVVCLKDIV2;
845		else
846			VCLKIndex = TVCLKBASE_315_25 + HiTVVCLK;
847
848		if (pVBInfo->SetFlag & TVSimuMode) {
849			if (modeflag & Charx8Dot)
850				VCLKIndex = TVCLKBASE_315_25 + HiTVSimuVCLK;
851			else
852				VCLKIndex = TVCLKBASE_315_25 + HiTVTextVCLK;
853		}
854
855		/* 301lv */
856		if (pVBInfo->VBType & VB_SIS301LV) {
857			if (pVBInfo->SetFlag & RPLLDIV2XO)
858				VCLKIndex = YPbPr525iVCLK_2;
859			else
860				VCLKIndex = YPbPr525iVCLK;
861		}
862	} else if (pVBInfo->VBInfo & SetCRT2ToTV) {
863		if (pVBInfo->SetFlag & RPLLDIV2XO)
864			VCLKIndex = TVCLKBASE_315_25 + TVVCLKDIV2;
865		else
866			VCLKIndex = TVCLKBASE_315_25 + TVVCLK;
867	} else { /* for CRT2 */
868		/* di+Ext_CRTVCLK */
869		VCLKIndex = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
870		VCLKIndex &= IndexMask;
871	}
872
873	return VCLKIndex;
874}
875
876static void XGI_SetCRT1VCLK(unsigned short ModeIdIndex,
877			    struct xgi_hw_device_info *HwDeviceExtension,
878			    unsigned short RefreshRateTableIndex,
879			    struct vb_device_info *pVBInfo)
880{
881	unsigned char index, data;
882	unsigned short vclkindex;
883
884	if ((pVBInfo->IF_DEF_LVDS == 0) &&
885	    (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV |
886				VB_SIS302LV | VB_XGI301C)) &&
887	    (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) {
888		vclkindex = XGI_GetVCLK2Ptr(ModeIdIndex, RefreshRateTableIndex,
889					    pVBInfo);
890		data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
891		xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
892		data = XGI_VBVCLKData[vclkindex].Part4_A;
893		xgifb_reg_set(pVBInfo->P3c4, 0x2B, data);
894		data = XGI_VBVCLKData[vclkindex].Part4_B;
895		xgifb_reg_set(pVBInfo->P3c4, 0x2C, data);
896		xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
897	} else {
898		index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
899		data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
900		xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
901		xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[index].SR2B);
902		xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[index].SR2C);
903		xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
904	}
905
906	if (HwDeviceExtension->jChipType >= XG20) {
907		if (XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag &
908		    HalfDCLK) {
909			data = xgifb_reg_get(pVBInfo->P3c4, 0x2B);
910			xgifb_reg_set(pVBInfo->P3c4, 0x2B, data);
911			data = xgifb_reg_get(pVBInfo->P3c4, 0x2C);
912			index = data;
913			index &= 0xE0;
914			data &= 0x1F;
915			data <<= 1;
916			data += 1;
917			data |= index;
918			xgifb_reg_set(pVBInfo->P3c4, 0x2C, data);
919		}
920	}
921}
922
923static void XGI_SetXG21FPBits(struct vb_device_info *pVBInfo)
924{
925	unsigned char temp;
926
927	temp = xgifb_reg_get(pVBInfo->P3d4, 0x37); /* D[0] 1: 18bit */
928	temp = (temp & 1) << 6;
929	/* SR06[6] 18bit Dither */
930	xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x40, temp);
931	/* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */
932	xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80);
933
934}
935
936static void XGI_SetCRT1FIFO(struct xgi_hw_device_info *HwDeviceExtension,
937			    struct vb_device_info *pVBInfo)
938{
939	unsigned short data;
940
941	data = xgifb_reg_get(pVBInfo->P3c4, 0x3D);
942	data &= 0xfe;
943	xgifb_reg_set(pVBInfo->P3c4, 0x3D, data); /* diable auto-threshold */
944
945	xgifb_reg_set(pVBInfo->P3c4, 0x08, 0x34);
946	data = xgifb_reg_get(pVBInfo->P3c4, 0x09);
947	data &= 0xC0;
948	xgifb_reg_set(pVBInfo->P3c4, 0x09, data | 0x30);
949	data = xgifb_reg_get(pVBInfo->P3c4, 0x3D);
950	data |= 0x01;
951	xgifb_reg_set(pVBInfo->P3c4, 0x3D, data);
952
953	if (HwDeviceExtension->jChipType == XG21)
954		XGI_SetXG21FPBits(pVBInfo); /* Fix SR9[7:6] can't read back */
955}
956
957static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
958		unsigned short RefreshRateTableIndex,
959		struct vb_device_info *pVBInfo)
960{
961	unsigned short data, data2 = 0;
962	short VCLK;
963
964	unsigned char index;
965
966	index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
967	index &= IndexMask;
968	VCLK = XGI_VCLKData[index].CLOCK;
969
970	data = xgifb_reg_get(pVBInfo->P3c4, 0x32);
971	data &= 0xf3;
972	if (VCLK >= 200)
973		data |= 0x0c; /* VCLK > 200 */
974
975	if (HwDeviceExtension->jChipType >= XG20)
976		data &= ~0x04; /* 2 pixel mode */
977
978	xgifb_reg_set(pVBInfo->P3c4, 0x32, data);
979
980	if (HwDeviceExtension->jChipType < XG20) {
981		data = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
982		data &= 0xE7;
983		if (VCLK < 200)
984			data |= 0x10;
985		xgifb_reg_set(pVBInfo->P3c4, 0x1F, data);
986	}
987
988	data2 = 0x00;
989
990	xgifb_reg_and_or(pVBInfo->P3c4, 0x07, 0xFC, data2);
991	if (HwDeviceExtension->jChipType >= XG27)
992		xgifb_reg_and_or(pVBInfo->P3c4, 0x40, 0xFC, data2 & 0x03);
993
994}
995
996static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
997		unsigned short ModeIdIndex,
998		unsigned short RefreshRateTableIndex,
999		struct vb_device_info *pVBInfo)
1000{
1001	unsigned short data, data2, data3, infoflag = 0, modeflag, resindex,
1002			xres;
1003
1004	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1005	infoflag = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
1006
1007	if (xgifb_reg_get(pVBInfo->P3d4, 0x31) & 0x01)
1008		xgifb_reg_and_or(pVBInfo->P3c4, 0x1F, 0x3F, 0x00);
1009
1010	data = infoflag;
1011	data2 = 0;
1012	data2 |= 0x02;
1013	data3 = pVBInfo->ModeType - ModeVGA;
1014	data3 <<= 2;
1015	data2 |= data3;
1016	data &= InterlaceMode;
1017
1018	if (data)
1019		data2 |= 0x20;
1020
1021	xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x3F, data2);
1022	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1023	xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
1024
1025	data = 0x0000;
1026	if (infoflag & InterlaceMode) {
1027		if (xres == 1024)
1028			data = 0x0035;
1029		else if (xres == 1280)
1030			data = 0x0048;
1031	}
1032
1033	xgifb_reg_and_or(pVBInfo->P3d4, 0x19, 0xFF, data);
1034	xgifb_reg_and_or(pVBInfo->P3d4, 0x19, 0xFC, 0);
1035
1036	if (modeflag & HalfDCLK)
1037		xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xF7, 0x08);
1038
1039	data2 = 0;
1040
1041	if (modeflag & LineCompareOff)
1042		data2 |= 0x08;
1043
1044	xgifb_reg_and_or(pVBInfo->P3c4, 0x0F, ~0x48, data2);
1045	data = 0x60;
1046	data = data ^ 0x60;
1047	data = data ^ 0xA0;
1048	xgifb_reg_and_or(pVBInfo->P3c4, 0x21, 0x1F, data);
1049
1050	XGI_SetVCLKState(HwDeviceExtension, RefreshRateTableIndex, pVBInfo);
1051
1052	data = xgifb_reg_get(pVBInfo->P3d4, 0x31);
1053
1054	if (HwDeviceExtension->jChipType == XG27) {
1055		if (data & 0x40)
1056			data = 0x2c;
1057		else
1058			data = 0x6c;
1059		xgifb_reg_set(pVBInfo->P3d4, 0x52, data);
1060		xgifb_reg_or(pVBInfo->P3d4, 0x51, 0x10);
1061	} else if (HwDeviceExtension->jChipType >= XG20) {
1062		if (data & 0x40)
1063			data = 0x33;
1064		else
1065			data = 0x73;
1066		xgifb_reg_set(pVBInfo->P3d4, 0x52, data);
1067		xgifb_reg_set(pVBInfo->P3d4, 0x51, 0x02);
1068	} else {
1069		if (data & 0x40)
1070			data = 0x2c;
1071		else
1072			data = 0x6c;
1073		xgifb_reg_set(pVBInfo->P3d4, 0x52, data);
1074	}
1075
1076}
1077
1078static void XGI_WriteDAC(unsigned short dl,
1079			 unsigned short ah,
1080			 unsigned short al,
1081			 unsigned short dh,
1082			 struct vb_device_info *pVBInfo)
1083{
1084	unsigned short temp, bh, bl;
1085
1086	bh = ah;
1087	bl = al;
1088
1089	if (dl != 0) {
1090		temp = bh;
1091		bh = dh;
1092		dh = temp;
1093		if (dl == 1) {
1094			temp = bl;
1095			bl = dh;
1096			dh = temp;
1097		} else {
1098			temp = bl;
1099			bl = bh;
1100			bh = temp;
1101		}
1102	}
1103	outb((unsigned short) dh, pVBInfo->P3c9);
1104	outb((unsigned short) bh, pVBInfo->P3c9);
1105	outb((unsigned short) bl, pVBInfo->P3c9);
1106}
1107
1108static void XGI_LoadDAC(struct vb_device_info *pVBInfo)
1109{
1110	unsigned short data, data2, i, k, m, n, o, si, di, bx, dl, al, ah, dh;
1111	const unsigned short *table = XGINew_VGA_DAC;
1112
1113	outb(0xFF, pVBInfo->P3c6);
1114	outb(0x00, pVBInfo->P3c8);
1115
1116	for (i = 0; i < 16; i++) {
1117		data = table[i];
1118
1119		for (k = 0; k < 3; k++) {
1120			data2 = 0;
1121
1122			if (data & 0x01)
1123				data2 = 0x2A;
1124
1125			if (data & 0x02)
1126				data2 += 0x15;
1127
1128			outb(data2, pVBInfo->P3c9);
1129			data >>= 2;
1130		}
1131	}
1132
1133	for (i = 16; i < 32; i++) {
1134		data = table[i];
1135
1136		for (k = 0; k < 3; k++)
1137			outb(data, pVBInfo->P3c9);
1138	}
1139
1140	si = 32;
1141
1142	for (m = 0; m < 9; m++) {
1143		di = si;
1144		bx = si + 0x04;
1145		dl = 0;
1146
1147		for (n = 0; n < 3; n++) {
1148			for (o = 0; o < 5; o++) {
1149				dh = table[si];
1150				ah = table[di];
1151				al = table[bx];
1152				si++;
1153				XGI_WriteDAC(dl, ah, al, dh, pVBInfo);
1154			}
1155
1156			si -= 2;
1157
1158			for (o = 0; o < 3; o++) {
1159				dh = table[bx];
1160				ah = table[di];
1161				al = table[si];
1162				si--;
1163				XGI_WriteDAC(dl, ah, al, dh, pVBInfo);
1164			}
1165
1166			dl++;
1167		}
1168
1169		si += 5;
1170	}
1171}
1172
1173static void XGI_GetLVDSResInfo(unsigned short ModeIdIndex,
1174			       struct vb_device_info *pVBInfo)
1175{
1176	unsigned short resindex, xres, yres, modeflag;
1177
1178	/* si+Ext_ResInfo */
1179	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1180
1181	/* si+Ext_ResInfo */
1182	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1183
1184	xres = XGI330_ModeResInfo[resindex].HTotal;
1185	yres = XGI330_ModeResInfo[resindex].VTotal;
1186
1187	if (modeflag & HalfDCLK)
1188		xres <<= 1;
1189
1190	if (modeflag & DoubleScanMode)
1191		yres <<= 1;
1192
1193	if (xres == 720)
1194		xres = 640;
1195
1196	pVBInfo->VGAHDE = xres;
1197	pVBInfo->HDE = xres;
1198	pVBInfo->VGAVDE = yres;
1199	pVBInfo->VDE = yres;
1200}
1201
1202static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table,
1203		unsigned short ModeIdIndex,
1204		struct vb_device_info *pVBInfo)
1205{
1206	unsigned short i, tempdx, tempbx, modeflag;
1207
1208	tempbx = 0;
1209
1210	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1211
1212	i = 0;
1213
1214	while (table[i].PANELID != 0xff) {
1215		tempdx = pVBInfo->LCDResInfo;
1216		if (tempbx & 0x0080) { /* OEMUtil */
1217			tempbx &= (~0x0080);
1218			tempdx = pVBInfo->LCDTypeInfo;
1219		}
1220
1221		if (pVBInfo->LCDInfo & EnableScalingLCD)
1222			tempdx &= (~PanelResInfo);
1223
1224		if (table[i].PANELID == tempdx) {
1225			tempbx = table[i].MASK;
1226			tempdx = pVBInfo->LCDInfo;
1227
1228			if (modeflag & HalfDCLK)
1229				tempdx |= SetLCDLowResolution;
1230
1231			tempbx &= tempdx;
1232			if (tempbx == table[i].CAP)
1233				break;
1234		}
1235		i++;
1236	}
1237
1238	return table[i].DATAPTR;
1239}
1240
1241static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeIdIndex,
1242		unsigned short RefreshRateTableIndex,
1243		struct vb_device_info *pVBInfo)
1244{
1245	unsigned short i, tempdx, tempal, modeflag;
1246
1247	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1248	tempal = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
1249	tempal = tempal & 0x3f;
1250	tempdx = pVBInfo->TVInfo;
1251
1252	if (pVBInfo->VBInfo & SetInSlaveMode)
1253		tempdx = tempdx | SetTVLockMode;
1254
1255	if (modeflag & HalfDCLK)
1256		tempdx = tempdx | SetTVLowResolution;
1257
1258	i = 0;
1259
1260	while (XGI_TVDataTable[i].MASK != 0xffff) {
1261		if ((tempdx & XGI_TVDataTable[i].MASK) ==
1262			XGI_TVDataTable[i].CAP)
1263			break;
1264		i++;
1265	}
1266
1267	return &XGI_TVDataTable[i].DATAPTR[tempal];
1268}
1269
1270static void XGI_GetLVDSData(unsigned short ModeIdIndex,
1271			    struct vb_device_info *pVBInfo)
1272{
1273	struct SiS_LVDSData const *LCDPtr;
1274
1275	if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
1276		return;
1277
1278	LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDataPtr, ModeIdIndex, pVBInfo);
1279	pVBInfo->VGAHT	= LCDPtr->VGAHT;
1280	pVBInfo->VGAVT	= LCDPtr->VGAVT;
1281	pVBInfo->HT	= LCDPtr->LCDHT;
1282	pVBInfo->VT	= LCDPtr->LCDVT;
1283
1284	if (pVBInfo->LCDInfo & (SetLCDtoNonExpanding | EnableScalingLCD))
1285		return;
1286
1287	if ((pVBInfo->LCDResInfo == Panel_1024x768) ||
1288	    (pVBInfo->LCDResInfo == Panel_1024x768x75)) {
1289		pVBInfo->HDE = 1024;
1290		pVBInfo->VDE = 768;
1291	} else if ((pVBInfo->LCDResInfo == Panel_1280x1024) ||
1292		   (pVBInfo->LCDResInfo == Panel_1280x1024x75)) {
1293		pVBInfo->HDE = 1280;
1294		pVBInfo->VDE = 1024;
1295	} else if (pVBInfo->LCDResInfo == Panel_1400x1050) {
1296		pVBInfo->HDE = 1400;
1297		pVBInfo->VDE = 1050;
1298	} else {
1299		pVBInfo->HDE = 1600;
1300		pVBInfo->VDE = 1200;
1301	}
1302}
1303
1304static void XGI_ModCRT1Regs(unsigned short ModeIdIndex,
1305			    struct xgi_hw_device_info *HwDeviceExtension,
1306			    struct vb_device_info *pVBInfo)
1307{
1308	unsigned short i;
1309	struct XGI_LVDSCRT1HDataStruct const *LCDPtr = NULL;
1310	struct XGI_LVDSCRT1VDataStruct const *LCDPtr1 = NULL;
1311
1312	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
1313		LCDPtr = XGI_GetLcdPtr(xgifb_epllcd_crt1_h, ModeIdIndex,
1314				       pVBInfo);
1315
1316		for (i = 0; i < 8; i++)
1317			pVBInfo->TimingH.data[i] = LCDPtr[0].Reg[i];
1318	}
1319
1320	XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
1321
1322	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
1323		LCDPtr1 = XGI_GetLcdPtr(xgifb_epllcd_crt1_v, ModeIdIndex,
1324					pVBInfo);
1325		for (i = 0; i < 7; i++)
1326			pVBInfo->TimingV.data[i] = LCDPtr1[0].Reg[i];
1327	}
1328
1329	XGI_SetCRT1Timing_V(ModeIdIndex, pVBInfo);
1330}
1331
1332static unsigned short XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo)
1333{
1334	unsigned char tempal, tempah, tempbl, i;
1335
1336	tempah = xgifb_reg_get(pVBInfo->P3d4, 0x36);
1337	tempal = tempah & 0x0F;
1338	tempah = tempah & 0xF0;
1339	i = 0;
1340	tempbl = pVBInfo->LCDCapList[i].LCD_ID;
1341
1342	while (tempbl != 0xFF) {
1343		if (tempbl & 0x80) { /* OEMUtil */
1344			tempal = tempah;
1345			tempbl = tempbl & ~(0x80);
1346		}
1347
1348		if (tempal == tempbl)
1349			break;
1350
1351		i++;
1352
1353		tempbl = pVBInfo->LCDCapList[i].LCD_ID;
1354	}
1355
1356	return i;
1357}
1358
1359static unsigned short XGI_GetLCDCapPtr1(struct vb_device_info *pVBInfo)
1360{
1361	unsigned short tempah, tempal, tempbl, i;
1362
1363	tempal = pVBInfo->LCDResInfo;
1364	tempah = pVBInfo->LCDTypeInfo;
1365
1366	i = 0;
1367	tempbl = pVBInfo->LCDCapList[i].LCD_ID;
1368
1369	while (tempbl != 0xFF) {
1370		if ((tempbl & 0x80) && (tempbl != 0x80)) {
1371			tempal = tempah;
1372			tempbl &= ~0x80;
1373		}
1374
1375		if (tempal == tempbl)
1376			break;
1377
1378		i++;
1379		tempbl = pVBInfo->LCDCapList[i].LCD_ID;
1380	}
1381
1382	if (tempbl == 0xFF) {
1383		pVBInfo->LCDResInfo = Panel_1024x768;
1384		pVBInfo->LCDTypeInfo = 0;
1385		i = 0;
1386	}
1387
1388	return i;
1389}
1390
1391static void XGI_GetLCDSync(unsigned short *HSyncWidth,
1392			   unsigned short *VSyncWidth,
1393			   struct vb_device_info *pVBInfo)
1394{
1395	unsigned short Index;
1396
1397	Index = XGI_GetLCDCapPtr(pVBInfo);
1398	*HSyncWidth = pVBInfo->LCDCapList[Index].LCD_HSyncWidth;
1399	*VSyncWidth = pVBInfo->LCDCapList[Index].LCD_VSyncWidth;
1400}
1401
1402static void XGI_SetLVDSRegs(unsigned short ModeIdIndex,
1403			    struct vb_device_info *pVBInfo)
1404{
1405	unsigned short tempbx, tempax, tempcx, tempdx, push1, push2, modeflag;
1406	unsigned long temp, temp1, temp2, temp3, push3;
1407	struct XGI330_LCDDataDesStruct2 const *LCDPtr1 = NULL;
1408
1409	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1410	LCDPtr1 = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeIdIndex, pVBInfo);
1411
1412	XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
1413	push1 = tempbx;
1414	push2 = tempax;
1415
1416	/* GetLCDResInfo */
1417	if ((pVBInfo->LCDResInfo == Panel_1024x768) ||
1418	    (pVBInfo->LCDResInfo == Panel_1024x768x75)) {
1419		tempax = 1024;
1420		tempbx = 768;
1421	} else if ((pVBInfo->LCDResInfo == Panel_1280x1024) ||
1422		   (pVBInfo->LCDResInfo == Panel_1280x1024x75)) {
1423		tempax = 1280;
1424		tempbx = 1024;
1425	} else if (pVBInfo->LCDResInfo == Panel_1400x1050) {
1426		tempax = 1400;
1427		tempbx = 1050;
1428	} else {
1429		tempax = 1600;
1430		tempbx = 1200;
1431	}
1432
1433	if (pVBInfo->LCDInfo & SetLCDtoNonExpanding) {
1434		pVBInfo->HDE = tempax;
1435		pVBInfo->VDE = tempbx;
1436		pVBInfo->VGAHDE = tempax;
1437		pVBInfo->VGAVDE = tempbx;
1438	}
1439
1440	tempax = pVBInfo->HT;
1441
1442	tempbx = LCDPtr1->LCDHDES;
1443
1444	tempcx = pVBInfo->HDE;
1445	tempbx = tempbx & 0x0fff;
1446	tempcx += tempbx;
1447
1448	if (tempcx >= tempax)
1449		tempcx -= tempax;
1450
1451	xgifb_reg_set(pVBInfo->Part1Port, 0x1A, tempbx & 0x07);
1452
1453	tempcx >>= 3;
1454	tempbx >>= 3;
1455
1456	xgifb_reg_set(pVBInfo->Part1Port, 0x16,
1457			(unsigned short) (tempbx & 0xff));
1458	xgifb_reg_set(pVBInfo->Part1Port, 0x17,
1459			(unsigned short) (tempcx & 0xff));
1460
1461	tempax = pVBInfo->HT;
1462
1463	tempbx = LCDPtr1->LCDHRS;
1464
1465	tempcx = push2;
1466
1467	if (pVBInfo->LCDInfo & EnableScalingLCD)
1468		tempcx = LCDPtr1->LCDHSync;
1469
1470	tempcx += tempbx;
1471
1472	if (tempcx >= tempax)
1473		tempcx -= tempax;
1474
1475	tempax = tempbx & 0x07;
1476	tempax >>= 5;
1477	tempcx >>= 3;
1478	tempbx >>= 3;
1479
1480	tempcx &= 0x1f;
1481	tempax |= tempcx;
1482
1483	xgifb_reg_set(pVBInfo->Part1Port, 0x15, tempax);
1484	xgifb_reg_set(pVBInfo->Part1Port, 0x14,
1485			(unsigned short) (tempbx & 0xff));
1486
1487	tempax = pVBInfo->VT;
1488	tempbx = LCDPtr1->LCDVDES;
1489	tempcx = pVBInfo->VDE;
1490
1491	tempbx = tempbx & 0x0fff;
1492	tempcx += tempbx;
1493	if (tempcx >= tempax)
1494		tempcx -= tempax;
1495
1496	xgifb_reg_set(pVBInfo->Part1Port, 0x1b,
1497			(unsigned short) (tempbx & 0xff));
1498	xgifb_reg_set(pVBInfo->Part1Port, 0x1c,
1499			(unsigned short) (tempcx & 0xff));
1500
1501	tempbx = (tempbx >> 8) & 0x07;
1502	tempcx = (tempcx >> 8) & 0x07;
1503
1504	xgifb_reg_set(pVBInfo->Part1Port, 0x1d,
1505			(unsigned short) ((tempcx << 3)
1506					| tempbx));
1507
1508	tempax = pVBInfo->VT;
1509	tempbx = LCDPtr1->LCDVRS;
1510
1511	tempcx = push1;
1512
1513	if (pVBInfo->LCDInfo & EnableScalingLCD)
1514		tempcx = LCDPtr1->LCDVSync;
1515
1516	tempcx += tempbx;
1517	if (tempcx >= tempax)
1518		tempcx -= tempax;
1519
1520	xgifb_reg_set(pVBInfo->Part1Port, 0x18,
1521			(unsigned short) (tempbx & 0xff));
1522	xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, ~0x0f,
1523			(unsigned short) (tempcx & 0x0f));
1524
1525	tempax = ((tempbx >> 8) & 0x07) << 3;
1526
1527	tempbx = pVBInfo->VGAVDE;
1528	if (tempbx != pVBInfo->VDE)
1529		tempax |= 0x40;
1530
1531	if (pVBInfo->LCDInfo & XGI_EnableLVDSDDA)
1532		tempax |= 0x40;
1533
1534	xgifb_reg_and_or(pVBInfo->Part1Port, 0x1a, 0x07,
1535				tempax);
1536
1537	tempbx = pVBInfo->VDE;
1538	tempax = pVBInfo->VGAVDE;
1539
1540	temp = tempax; /* 0430 ylshieh */
1541	temp1 = (temp << 18) / tempbx;
1542
1543	tempdx = (unsigned short) ((temp << 18) % tempbx);
1544
1545	if (tempdx != 0)
1546		temp1 += 1;
1547
1548	temp2 = temp1;
1549	push3 = temp2;
1550
1551	xgifb_reg_set(pVBInfo->Part1Port, 0x37,
1552			(unsigned short) (temp2 & 0xff));
1553	xgifb_reg_set(pVBInfo->Part1Port, 0x36,
1554			(unsigned short) ((temp2 >> 8) & 0xff));
1555
1556	tempbx = (unsigned short) (temp2 >> 16);
1557	tempax = tempbx & 0x03;
1558
1559	tempbx = pVBInfo->VGAVDE;
1560	if (tempbx == pVBInfo->VDE)
1561		tempax |= 0x04;
1562
1563	xgifb_reg_set(pVBInfo->Part1Port, 0x35, tempax);
1564
1565	if (pVBInfo->VBType & VB_XGI301C) {
1566		temp2 = push3;
1567		xgifb_reg_set(pVBInfo->Part4Port,
1568			      0x3c,
1569			      (unsigned short) (temp2 & 0xff));
1570		xgifb_reg_set(pVBInfo->Part4Port,
1571			      0x3b,
1572			      (unsigned short) ((temp2 >> 8) &
1573			      0xff));
1574		tempbx = (unsigned short) (temp2 >> 16);
1575		xgifb_reg_and_or(pVBInfo->Part4Port, 0x3a,
1576				~0xc0,
1577				(unsigned short) ((tempbx &
1578						   0xff) << 6));
1579
1580		tempcx = pVBInfo->VGAVDE;
1581		if (tempcx == pVBInfo->VDE)
1582			xgifb_reg_and_or(pVBInfo->Part4Port,
1583					0x30, ~0x0c, 0x00);
1584		else
1585			xgifb_reg_and_or(pVBInfo->Part4Port,
1586					0x30, ~0x0c, 0x08);
1587	}
1588
1589	tempcx = pVBInfo->VGAHDE;
1590	tempbx = pVBInfo->HDE;
1591
1592	temp1 = tempcx << 16;
1593
1594	tempax = (unsigned short) (temp1 / tempbx);
1595
1596	if ((tempbx & 0xffff) == (tempcx & 0xffff))
1597		tempax = 65535;
1598
1599	temp3 = tempax;
1600	temp1 = pVBInfo->VGAHDE << 16;
1601
1602	temp1 /= temp3;
1603	temp3 <<= 16;
1604	temp1 -= 1;
1605
1606	temp3 = (temp3 & 0xffff0000) + (temp1 & 0xffff);
1607
1608	tempax = (unsigned short) (temp3 & 0xff);
1609	xgifb_reg_set(pVBInfo->Part1Port, 0x1f, tempax);
1610
1611	temp1 = pVBInfo->VGAVDE << 18;
1612	temp1 = temp1 / push3;
1613	tempbx = (unsigned short) (temp1 & 0xffff);
1614
1615	if (pVBInfo->LCDResInfo == Panel_1024x768)
1616		tempbx -= 1;
1617
1618	tempax = ((tempbx >> 8) & 0xff) << 3;
1619	tempax |= (unsigned short) ((temp3 >> 8) & 0x07);
1620	xgifb_reg_set(pVBInfo->Part1Port, 0x20,
1621			(unsigned short) (tempax & 0xff));
1622	xgifb_reg_set(pVBInfo->Part1Port, 0x21,
1623			(unsigned short) (tempbx & 0xff));
1624
1625	temp3 >>= 16;
1626
1627	if (modeflag & HalfDCLK)
1628		temp3 >>= 1;
1629
1630	xgifb_reg_set(pVBInfo->Part1Port, 0x22,
1631			(unsigned short) ((temp3 >> 8) & 0xff));
1632	xgifb_reg_set(pVBInfo->Part1Port, 0x23,
1633			(unsigned short) (temp3 & 0xff));
1634}
1635
1636/* --------------------------------------------------------------------- */
1637/* Function : XGI_GETLCDVCLKPtr */
1638/* Input : */
1639/* Output : al -> VCLK Index */
1640/* Description : */
1641/* --------------------------------------------------------------------- */
1642static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
1643		struct vb_device_info *pVBInfo)
1644{
1645	unsigned short index;
1646
1647	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
1648		index = XGI_GetLCDCapPtr1(pVBInfo);
1649
1650		if (pVBInfo->VBInfo & SetCRT2ToLCD) { /* LCDB */
1651			*di_0 = pVBInfo->LCDCapList[index].LCUCHAR_VCLKData1;
1652			*di_1 = pVBInfo->LCDCapList[index].LCUCHAR_VCLKData2;
1653		} else { /* LCDA */
1654			*di_0 = pVBInfo->LCDCapList[index].LCDA_VCLKData1;
1655			*di_1 = pVBInfo->LCDCapList[index].LCDA_VCLKData2;
1656		}
1657	}
1658}
1659
1660static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
1661		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
1662{
1663
1664	unsigned short index, modeflag;
1665	unsigned char tempal;
1666
1667	/* si+Ext_ResInfo */
1668	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1669
1670	if ((pVBInfo->SetFlag & ProgrammingCRT2) &&
1671	    (!(pVBInfo->LCDInfo & EnableScalingLCD))) { /* {LCDA/LCDB} */
1672		index = XGI_GetLCDCapPtr(pVBInfo);
1673		tempal = pVBInfo->LCDCapList[index].LCD_VCLK;
1674
1675		if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))
1676			return tempal;
1677
1678		/* {TV} */
1679		if (pVBInfo->VBType &
1680		    (VB_SIS301B |
1681		     VB_SIS302B |
1682		     VB_SIS301LV |
1683		     VB_SIS302LV |
1684		     VB_XGI301C)) {
1685			if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
1686				tempal = TVCLKBASE_315 + HiTVVCLKDIV2;
1687				if (!(pVBInfo->TVInfo & RPLLDIV2XO))
1688					tempal = TVCLKBASE_315 + HiTVVCLK;
1689				if (pVBInfo->TVInfo & TVSimuMode) {
1690					tempal = TVCLKBASE_315 + HiTVSimuVCLK;
1691					if (!(modeflag & Charx8Dot))
1692						tempal = TVCLKBASE_315 +
1693								HiTVTextVCLK;
1694
1695				}
1696				return tempal;
1697			}
1698
1699			if (pVBInfo->TVInfo & TVSetYPbPr750p) {
1700				tempal = XGI_YPbPr750pVCLK;
1701				return tempal;
1702			}
1703
1704			if (pVBInfo->TVInfo & TVSetYPbPr525p) {
1705				tempal = YPbPr525pVCLK;
1706				return tempal;
1707			}
1708
1709			tempal = NTSC1024VCLK;
1710
1711			if (!(pVBInfo->TVInfo & NTSC1024x768)) {
1712				tempal = TVCLKBASE_315 + TVVCLKDIV2;
1713				if (!(pVBInfo->TVInfo & RPLLDIV2XO))
1714					tempal = TVCLKBASE_315 + TVVCLK;
1715			}
1716
1717			if (pVBInfo->VBInfo & SetCRT2ToTV)
1718				return tempal;
1719		}
1720	} /* {End of VB} */
1721
1722	inb((pVBInfo->P3ca + 0x02));
1723	tempal = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
1724	return tempal;
1725}
1726
1727static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
1728		unsigned char *di_1, struct vb_device_info *pVBInfo)
1729{
1730	if (pVBInfo->VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B
1731			| VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
1732		if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) &&
1733		    (pVBInfo->SetFlag & ProgrammingCRT2)) {
1734			*di_0 = XGI_VBVCLKData[tempal].Part4_A;
1735			*di_1 = XGI_VBVCLKData[tempal].Part4_B;
1736		}
1737	} else {
1738		*di_0 = XGI_VCLKData[tempal].SR2B;
1739		*di_1 = XGI_VCLKData[tempal].SR2C;
1740	}
1741}
1742
1743static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex,
1744		unsigned short RefreshRateTableIndex,
1745		struct vb_device_info *pVBInfo)
1746{
1747	unsigned char di_0, di_1, tempal;
1748	int i;
1749
1750	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo);
1751	XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
1752	XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
1753
1754	for (i = 0; i < 4; i++) {
1755		xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30,
1756				(unsigned short) (0x10 * i));
1757		if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA))
1758				&& (!(pVBInfo->VBInfo & SetInSlaveMode))) {
1759			xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0);
1760			xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1);
1761		} else {
1762			xgifb_reg_set(pVBInfo->P3c4, 0x2b, di_0);
1763			xgifb_reg_set(pVBInfo->P3c4, 0x2c, di_1);
1764		}
1765	}
1766}
1767
1768static void XGI_UpdateModeInfo(struct vb_device_info *pVBInfo)
1769{
1770	unsigned short tempcl, tempch, temp, tempbl, tempax;
1771
1772	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
1773			| VB_SIS302LV | VB_XGI301C)) {
1774		tempcl = 0;
1775		tempch = 0;
1776		temp = xgifb_reg_get(pVBInfo->P3c4, 0x01);
1777
1778		if (!(temp & 0x20)) {
1779			temp = xgifb_reg_get(pVBInfo->P3d4, 0x17);
1780			if (temp & 0x80) {
1781				temp = xgifb_reg_get(pVBInfo->P3d4, 0x53);
1782				if (!(temp & 0x40))
1783					tempcl |= ActiveCRT1;
1784			}
1785		}
1786
1787		temp = xgifb_reg_get(pVBInfo->Part1Port, 0x2e);
1788		temp &= 0x0f;
1789
1790		if (!(temp == 0x08)) {
1791			/* Check ChannelA */
1792			tempax = xgifb_reg_get(pVBInfo->Part1Port, 0x13);
1793			if (tempax & 0x04)
1794				tempcl = tempcl | ActiveLCD;
1795
1796			temp &= 0x05;
1797
1798			if (!(tempcl & ActiveLCD))
1799				if (temp == 0x01)
1800					tempcl |= ActiveCRT2;
1801
1802			if (temp == 0x04)
1803				tempcl |= ActiveLCD;
1804
1805			if (temp == 0x05) {
1806				temp = xgifb_reg_get(pVBInfo->Part2Port, 0x00);
1807
1808				if (!(temp & 0x08))
1809					tempch |= ActiveAVideo;
1810
1811				if (!(temp & 0x04))
1812					tempch |= ActiveSVideo;
1813
1814				if (temp & 0x02)
1815					tempch |= ActiveSCART;
1816
1817				if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
1818					if (temp & 0x01)
1819						tempch |= ActiveHiTV;
1820				}
1821
1822				if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
1823					temp = xgifb_reg_get(
1824							pVBInfo->Part2Port,
1825							0x4d);
1826
1827					if (temp & 0x10)
1828						tempch |= ActiveYPbPr;
1829				}
1830
1831				if (tempch != 0)
1832					tempcl |= ActiveTV;
1833			}
1834		}
1835
1836		temp = xgifb_reg_get(pVBInfo->P3d4, 0x3d);
1837		if (tempcl & ActiveLCD) {
1838			if ((pVBInfo->SetFlag & ReserveTVOption)) {
1839				if (temp & ActiveTV)
1840					tempcl |= ActiveTV;
1841			}
1842		}
1843		temp = tempcl;
1844		tempbl = ~XGI_ModeSwitchStatus;
1845		xgifb_reg_and_or(pVBInfo->P3d4, 0x3d, tempbl, temp);
1846
1847		if (!(pVBInfo->SetFlag & ReserveTVOption))
1848			xgifb_reg_set(pVBInfo->P3d4, 0x3e, tempch);
1849	}
1850}
1851
1852void XGI_GetVBType(struct vb_device_info *pVBInfo)
1853{
1854	unsigned short flag, tempbx, tempah;
1855
1856	tempbx = VB_SIS302B;
1857	flag = xgifb_reg_get(pVBInfo->Part4Port, 0x00);
1858	if (flag == 0x02)
1859		goto finish;
1860
1861	tempbx = VB_SIS301;
1862	flag = xgifb_reg_get(pVBInfo->Part4Port, 0x01);
1863	if (flag < 0xB0)
1864		goto finish;
1865
1866	tempbx = VB_SIS301B;
1867	if (flag < 0xC0)
1868		goto bigger_than_0xB0;
1869
1870	tempbx = VB_XGI301C;
1871	if (flag < 0xD0)
1872		goto bigger_than_0xB0;
1873
1874	tempbx = VB_SIS301LV;
1875	if (flag < 0xE0)
1876		goto bigger_than_0xB0;
1877
1878	tempbx = VB_SIS302LV;
1879	tempah = xgifb_reg_get(pVBInfo->Part4Port, 0x39);
1880	if (tempah != 0xFF)
1881		tempbx = VB_XGI301C;
1882
1883bigger_than_0xB0:
1884	if (tempbx & (VB_SIS301B | VB_SIS302B)) {
1885		flag = xgifb_reg_get(pVBInfo->Part4Port, 0x23);
1886		if (!(flag & 0x02))
1887			tempbx = tempbx | VB_NoLCD;
1888	}
1889
1890finish:
1891	pVBInfo->VBType = tempbx;
1892}
1893
1894static void XGI_GetVBInfo(unsigned short ModeIdIndex,
1895		struct vb_device_info *pVBInfo)
1896{
1897	unsigned short tempax, push, tempbx, temp, modeflag;
1898
1899	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1900	pVBInfo->SetFlag = 0;
1901	pVBInfo->ModeType = modeflag & ModeTypeMask;
1902	tempbx = 0;
1903
1904	if (!(pVBInfo->VBType & 0xFFFF))
1905		return;
1906
1907	/* Check Display Device */
1908	temp = xgifb_reg_get(pVBInfo->P3d4, 0x30);
1909	tempbx = tempbx | temp;
1910	temp = xgifb_reg_get(pVBInfo->P3d4, 0x31);
1911	push = temp;
1912	push <<= 8;
1913	tempax = temp << 8;
1914	tempbx = tempbx | tempax;
1915	temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | XGI_SetCRT2ToLCDA
1916		| SetInSlaveMode | DisableCRT2Display);
1917	temp = 0xFFFF ^ temp;
1918	tempbx &= temp;
1919
1920	temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
1921
1922	if (pVBInfo->VBType & (VB_SIS302B | VB_SIS301LV | VB_SIS302LV |
1923			       VB_XGI301C)) {
1924		if (temp & EnableDualEdge) {
1925			tempbx |= SetCRT2ToDualEdge;
1926			if (temp & SetToLCDA)
1927				tempbx |= XGI_SetCRT2ToLCDA;
1928		}
1929	}
1930
1931	if (pVBInfo->VBType & (VB_SIS301LV|VB_SIS302LV|VB_XGI301C)) {
1932		if (temp & SetYPbPr) {
1933			/* shampoo add for new scratch */
1934			temp = xgifb_reg_get(pVBInfo->P3d4, 0x35);
1935			temp &= YPbPrMode;
1936			tempbx |= SetCRT2ToHiVision;
1937
1938			if (temp != YPbPrMode1080i) {
1939				tempbx &= (~SetCRT2ToHiVision);
1940				tempbx |= SetCRT2ToYPbPr525750;
1941			}
1942		}
1943	}
1944
1945	tempax = push; /* restore CR31 */
1946
1947	temp = 0x09FC;
1948
1949	if (!(tempbx & temp)) {
1950		tempax |= DisableCRT2Display;
1951		tempbx = 0;
1952	}
1953
1954	if (!(pVBInfo->VBType & VB_NoLCD)) {
1955		if (tempbx & XGI_SetCRT2ToLCDA) {
1956			if (tempbx & SetSimuScanMode)
1957				tempbx &= (~(SetCRT2ToLCD | SetCRT2ToRAMDAC |
1958					     SwitchCRT2));
1959			else
1960				tempbx &= (~(SetCRT2ToLCD | SetCRT2ToRAMDAC |
1961					     SetCRT2ToTV | SwitchCRT2));
1962		}
1963	}
1964
1965	/* shampoo add */
1966	/* for driver abnormal */
1967	if (!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1968		if (tempbx & SetCRT2ToRAMDAC) {
1969			tempbx &= (0xFF00 | SetCRT2ToRAMDAC |
1970				   SwitchCRT2 | SetSimuScanMode);
1971			tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750));
1972		}
1973	}
1974
1975	if (!(pVBInfo->VBType & VB_NoLCD)) {
1976		if (tempbx & SetCRT2ToLCD) {
1977			tempbx &= (0xFF00 | SetCRT2ToLCD | SwitchCRT2 |
1978				   SetSimuScanMode);
1979			tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750));
1980		}
1981	}
1982
1983	if (tempbx & SetCRT2ToSCART) {
1984		tempbx &= (0xFF00 | SetCRT2ToSCART | SwitchCRT2 |
1985			   SetSimuScanMode);
1986		tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750));
1987	}
1988
1989	if (tempbx & SetCRT2ToYPbPr525750)
1990		tempbx &= (0xFF00 | SwitchCRT2 | SetSimuScanMode);
1991
1992	if (tempbx & SetCRT2ToHiVision)
1993		tempbx &= (0xFF00 | SetCRT2ToHiVision | SwitchCRT2 |
1994			   SetSimuScanMode);
1995
1996	if (tempax & DisableCRT2Display) { /* Set Display Device Info */
1997		if (!(tempbx & (SwitchCRT2 | SetSimuScanMode)))
1998			tempbx = DisableCRT2Display;
1999	}
2000
2001	if (!(tempbx & DisableCRT2Display)) {
2002		if ((!(tempbx & DriverMode)) || (!(modeflag & CRT2Mode))) {
2003			if (!(tempbx & XGI_SetCRT2ToLCDA))
2004				tempbx |= (SetInSlaveMode | SetSimuScanMode);
2005		}
2006
2007		/* LCD+TV can't support in slave mode
2008		 * (Force LCDA+TV->LCDB) */
2009		if ((tempbx & SetInSlaveMode) && (tempbx & XGI_SetCRT2ToLCDA)) {
2010			tempbx ^= (SetCRT2ToLCD | XGI_SetCRT2ToLCDA |
2011				   SetCRT2ToDualEdge);
2012			pVBInfo->SetFlag |= ReserveTVOption;
2013		}
2014	}
2015
2016	pVBInfo->VBInfo = tempbx;
2017}
2018
2019static void XGI_GetTVInfo(unsigned short ModeIdIndex,
2020		struct vb_device_info *pVBInfo)
2021{
2022	unsigned short tempbx = 0, resinfo = 0, modeflag, index1;
2023
2024	if (pVBInfo->VBInfo & SetCRT2ToTV) {
2025		modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2026		resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2027
2028		tempbx = xgifb_reg_get(pVBInfo->P3d4, 0x35);
2029		if (tempbx & TVSetPAL) {
2030			tempbx &= (SetCHTVOverScan |
2031				   TVSetPALM |
2032				   TVSetPALN |
2033				   TVSetPAL);
2034			if (tempbx & TVSetPALM)
2035				/* set to NTSC if PAL-M */
2036				tempbx &= ~TVSetPAL;
2037		} else
2038			tempbx &= (SetCHTVOverScan |
2039				   TVSetNTSCJ |
2040				   TVSetPAL);
2041
2042		if (pVBInfo->VBInfo & SetCRT2ToSCART)
2043			tempbx |= TVSetPAL;
2044
2045		if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
2046			index1 = xgifb_reg_get(pVBInfo->P3d4, 0x35);
2047			index1 &= YPbPrMode;
2048
2049			if (index1 == YPbPrMode525i)
2050				tempbx |= TVSetYPbPr525i;
2051
2052			if (index1 == YPbPrMode525p)
2053				tempbx = tempbx | TVSetYPbPr525p;
2054			if (index1 == YPbPrMode750p)
2055				tempbx = tempbx | TVSetYPbPr750p;
2056		}
2057
2058		if (pVBInfo->VBInfo & SetCRT2ToHiVision)
2059			tempbx = tempbx | TVSetHiVision | TVSetPAL;
2060
2061		if ((pVBInfo->VBInfo & SetInSlaveMode) &&
2062		    (!(pVBInfo->VBInfo & SetNotSimuMode)))
2063			tempbx |= TVSimuMode;
2064
2065		if (!(tempbx & TVSetPAL) && (modeflag > 13) && (resinfo == 8))
2066			/* NTSC 1024x768, */
2067			tempbx |= NTSC1024x768;
2068
2069		tempbx |= RPLLDIV2XO;
2070
2071		if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
2072			if (pVBInfo->VBInfo & SetInSlaveMode)
2073				tempbx &= (~RPLLDIV2XO);
2074		} else if (tempbx & (TVSetYPbPr525p | TVSetYPbPr750p)) {
2075			tempbx &= (~RPLLDIV2XO);
2076		} else if (!(pVBInfo->VBType & (VB_SIS301B | VB_SIS302B |
2077						VB_SIS301LV | VB_SIS302LV |
2078						VB_XGI301C))) {
2079			if (tempbx & TVSimuMode)
2080				tempbx &= (~RPLLDIV2XO);
2081		}
2082	}
2083	pVBInfo->TVInfo = tempbx;
2084}
2085
2086static unsigned char XGI_GetLCDInfo(unsigned short ModeIdIndex,
2087				    struct vb_device_info *pVBInfo)
2088{
2089	unsigned short temp, tempax, tempbx, resinfo = 0, LCDIdIndex;
2090
2091	pVBInfo->LCDResInfo = 0;
2092	pVBInfo->LCDTypeInfo = 0;
2093	pVBInfo->LCDInfo = 0;
2094
2095	/* si+Ext_ResInfo // */
2096	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2097	temp = xgifb_reg_get(pVBInfo->P3d4, 0x36); /* Get LCD Res.Info */
2098	tempbx = temp & 0x0F;
2099
2100	if (tempbx == 0)
2101		tempbx = Panel_1024x768; /* default */
2102
2103	/* LCD75 */
2104	if ((tempbx == Panel_1024x768) || (tempbx == Panel_1280x1024)) {
2105		if (pVBInfo->VBInfo & DriverMode) {
2106			tempax = xgifb_reg_get(pVBInfo->P3d4, 0x33);
2107			if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
2108				tempax &= 0x0F;
2109			else
2110				tempax >>= 4;
2111
2112			if ((resinfo == 6) || (resinfo == 9)) {
2113				if (tempax >= 3)
2114					tempbx |= PanelRef75Hz;
2115			} else if ((resinfo == 7) || (resinfo == 8)) {
2116				if (tempax >= 4)
2117					tempbx |= PanelRef75Hz;
2118			}
2119		}
2120	}
2121
2122	pVBInfo->LCDResInfo = tempbx;
2123
2124	/* End of LCD75 */
2125
2126	if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
2127		return 0;
2128
2129	tempbx = 0;
2130
2131	temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
2132
2133	temp &= (ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable);
2134
2135	tempbx |= temp;
2136
2137	LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo);
2138
2139	tempax = pVBInfo->LCDCapList[LCDIdIndex].LCD_Capability;
2140
2141	if (((pVBInfo->VBType & VB_SIS302LV) ||
2142	     (pVBInfo->VBType & VB_XGI301C)) && (tempax & XGI_LCDDualLink))
2143		tempbx |= SetLCDDualLink;
2144
2145	if ((pVBInfo->LCDResInfo == Panel_1400x1050) &&
2146	    (pVBInfo->VBInfo & SetCRT2ToLCD) && (resinfo == 9) &&
2147	    (!(tempbx & EnableScalingLCD)))
2148		/*
2149		 * set to center in 1280x1024 LCDB
2150		 * for Panel_1400x1050
2151		 */
2152		tempbx |= SetLCDtoNonExpanding;
2153
2154	if (pVBInfo->VBInfo & SetInSlaveMode) {
2155		if (pVBInfo->VBInfo & SetNotSimuMode)
2156			tempbx |= XGI_LCDVESATiming;
2157	} else {
2158		tempbx |= XGI_LCDVESATiming;
2159	}
2160
2161	pVBInfo->LCDInfo = tempbx;
2162
2163	return 1;
2164}
2165
2166unsigned char XGI_SearchModeID(unsigned short ModeNo,
2167			       unsigned short *ModeIdIndex)
2168{
2169	for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
2170		if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
2171			break;
2172		if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
2173			return 0;
2174	}
2175
2176	return 1;
2177}
2178
2179static unsigned char XG21GPIODataTransfer(unsigned char ujDate)
2180{
2181	unsigned char ujRet = 0;
2182	unsigned char i = 0;
2183
2184	for (i = 0; i < 8; i++) {
2185		ujRet <<= 1;
2186		ujRet |= (ujDate >> i) & 1;
2187	}
2188
2189	return ujRet;
2190}
2191
2192/*----------------------------------------------------------------------------*/
2193/* output                                                                     */
2194/*      bl[5] : LVDS signal                                                   */
2195/*      bl[1] : LVDS backlight                                                */
2196/*      bl[0] : LVDS VDD                                                      */
2197/*----------------------------------------------------------------------------*/
2198static unsigned char XGI_XG21GetPSCValue(struct vb_device_info *pVBInfo)
2199{
2200	unsigned char CR4A, temp;
2201
2202	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
2203	xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x23); /* enable GPIO write */
2204
2205	temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
2206
2207	temp = XG21GPIODataTransfer(temp);
2208	temp &= 0x23;
2209	xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
2210	return temp;
2211}
2212
2213/*----------------------------------------------------------------------------*/
2214/* output                                                                     */
2215/*      bl[5] : LVDS signal                                                   */
2216/*      bl[1] : LVDS backlight                                                */
2217/*      bl[0] : LVDS VDD                                                      */
2218/*----------------------------------------------------------------------------*/
2219static unsigned char XGI_XG27GetPSCValue(struct vb_device_info *pVBInfo)
2220{
2221	unsigned char CR4A, CRB4, temp;
2222
2223	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
2224	xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x0C); /* enable GPIO write */
2225
2226	temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
2227
2228	temp &= 0x0C;
2229	temp >>= 2;
2230	xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
2231	CRB4 = xgifb_reg_get(pVBInfo->P3d4, 0xB4);
2232	temp |= ((CRB4 & 0x04) << 3);
2233	return temp;
2234}
2235
2236/*----------------------------------------------------------------------------*/
2237/* input                                                                      */
2238/*      bl[5] : 1;LVDS signal on                                              */
2239/*      bl[1] : 1;LVDS backlight on                                           */
2240/*      bl[0] : 1:LVDS VDD on                                                 */
2241/*      bh: 100000b : clear bit 5, to set bit5                                */
2242/*          000010b : clear bit 1, to set bit1                                */
2243/*          000001b : clear bit 0, to set bit0                                */
2244/*----------------------------------------------------------------------------*/
2245static void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
2246		struct vb_device_info *pVBInfo)
2247{
2248	unsigned char CR4A, temp;
2249
2250	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
2251	tempbh &= 0x23;
2252	tempbl &= 0x23;
2253	xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
2254
2255	if (tempbh & 0x20) {
2256		temp = (tempbl >> 4) & 0x02;
2257
2258		/* CR B4[1] */
2259		xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
2260
2261	}
2262
2263	temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
2264
2265	temp = XG21GPIODataTransfer(temp);
2266	temp &= ~tempbh;
2267	temp |= tempbl;
2268	xgifb_reg_set(pVBInfo->P3d4, 0x48, temp);
2269}
2270
2271static void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
2272		struct vb_device_info *pVBInfo)
2273{
2274	unsigned char CR4A, temp;
2275	unsigned short tempbh0, tempbl0;
2276
2277	tempbh0 = tempbh;
2278	tempbl0 = tempbl;
2279	tempbh0 &= 0x20;
2280	tempbl0 &= 0x20;
2281	tempbh0 >>= 3;
2282	tempbl0 >>= 3;
2283
2284	if (tempbh & 0x20) {
2285		temp = (tempbl >> 4) & 0x02;
2286
2287		/* CR B4[1] */
2288		xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
2289
2290	}
2291	xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~tempbh0, tempbl0);
2292
2293	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
2294	tempbh &= 0x03;
2295	tempbl &= 0x03;
2296	tempbh <<= 2;
2297	tempbl <<= 2; /* GPIOC,GPIOD */
2298	xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
2299	xgifb_reg_and_or(pVBInfo->P3d4, 0x48, ~tempbh, tempbl);
2300}
2301
2302static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info,
2303		struct xgi_hw_device_info *pXGIHWDE,
2304		struct vb_device_info *pVBInfo)
2305{
2306
2307	xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x00);
2308	if (pXGIHWDE->jChipType == XG21) {
2309		if (pVBInfo->IF_DEF_LVDS == 1) {
2310			if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x1)) {
2311				/* LVDS VDD on */
2312				XGI_XG21BLSignalVDD(0x01, 0x01, pVBInfo);
2313				mdelay(xgifb_info->lvds_data.PSC_S2);
2314			}
2315			if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x20))
2316				/* LVDS signal on */
2317				XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo);
2318			mdelay(xgifb_info->lvds_data.PSC_S3);
2319			/* LVDS backlight on */
2320			XGI_XG21BLSignalVDD(0x02, 0x02, pVBInfo);
2321		} else {
2322			/* DVO/DVI signal on */
2323			XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo);
2324		}
2325
2326	}
2327
2328	if (pXGIHWDE->jChipType == XG27) {
2329		if (pVBInfo->IF_DEF_LVDS == 1) {
2330			if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x1)) {
2331				/* LVDS VDD on */
2332				XGI_XG27BLSignalVDD(0x01, 0x01, pVBInfo);
2333				mdelay(xgifb_info->lvds_data.PSC_S2);
2334			}
2335			if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x20))
2336				/* LVDS signal on */
2337				XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo);
2338			mdelay(xgifb_info->lvds_data.PSC_S3);
2339			/* LVDS backlight on */
2340			XGI_XG27BLSignalVDD(0x02, 0x02, pVBInfo);
2341		} else {
2342			/* DVO/DVI signal on */
2343			XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo);
2344		}
2345
2346	}
2347}
2348
2349void XGI_DisplayOff(struct xgifb_video_info *xgifb_info,
2350		struct xgi_hw_device_info *pXGIHWDE,
2351		struct vb_device_info *pVBInfo)
2352{
2353
2354	if (pXGIHWDE->jChipType == XG21) {
2355		if (pVBInfo->IF_DEF_LVDS == 1) {
2356			/* LVDS backlight off */
2357			XGI_XG21BLSignalVDD(0x02, 0x00, pVBInfo);
2358			mdelay(xgifb_info->lvds_data.PSC_S3);
2359		} else {
2360			/* DVO/DVI signal off */
2361			XGI_XG21BLSignalVDD(0x20, 0x00, pVBInfo);
2362		}
2363	}
2364
2365	if (pXGIHWDE->jChipType == XG27) {
2366		if ((XGI_XG27GetPSCValue(pVBInfo) & 0x2)) {
2367			/* LVDS backlight off */
2368			XGI_XG27BLSignalVDD(0x02, 0x00, pVBInfo);
2369			mdelay(xgifb_info->lvds_data.PSC_S3);
2370		}
2371
2372		if (pVBInfo->IF_DEF_LVDS == 0)
2373			/* DVO/DVI signal off */
2374			XGI_XG27BLSignalVDD(0x20, 0x00, pVBInfo);
2375	}
2376
2377	xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x20);
2378}
2379
2380static void XGI_WaitDisply(struct vb_device_info *pVBInfo)
2381{
2382	while ((inb(pVBInfo->P3da) & 0x01))
2383		break;
2384
2385	while (!(inb(pVBInfo->P3da) & 0x01))
2386		break;
2387}
2388
2389static void XGI_AutoThreshold(struct vb_device_info *pVBInfo)
2390{
2391	xgifb_reg_or(pVBInfo->Part1Port, 0x01, 0x40);
2392}
2393
2394static void XGI_SaveCRT2Info(unsigned short ModeNo,
2395			     struct vb_device_info *pVBInfo)
2396{
2397	unsigned short temp1, temp2;
2398
2399	/* reserve CR34 for CRT1 Mode No */
2400	xgifb_reg_set(pVBInfo->P3d4, 0x34, ModeNo);
2401	temp1 = (pVBInfo->VBInfo & SetInSlaveMode) >> 8;
2402	temp2 = ~(SetInSlaveMode >> 8);
2403	xgifb_reg_and_or(pVBInfo->P3d4, 0x31, temp2, temp1);
2404}
2405
2406static void XGI_GetCRT2ResInfo(unsigned short ModeIdIndex,
2407			       struct vb_device_info *pVBInfo)
2408{
2409	unsigned short xres, yres, modeflag, resindex;
2410
2411	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2412	xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
2413	yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
2414	/* si+St_ModeFlag */
2415	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2416
2417	if (modeflag & HalfDCLK)
2418		xres *= 2;
2419
2420	if (modeflag & DoubleScanMode)
2421		yres *= 2;
2422
2423	if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
2424		goto exit;
2425
2426	if (pVBInfo->LCDResInfo == Panel_1600x1200) {
2427		if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
2428			if (yres == 1024)
2429				yres = 1056;
2430		}
2431	}
2432
2433	if (pVBInfo->LCDResInfo == Panel_1280x1024) {
2434		if (yres == 400)
2435			yres = 405;
2436		else if (yres == 350)
2437			yres = 360;
2438
2439		if (pVBInfo->LCDInfo & XGI_LCDVESATiming) {
2440			if (yres == 360)
2441				yres = 375;
2442		}
2443	}
2444
2445	if (pVBInfo->LCDResInfo == Panel_1024x768) {
2446		if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
2447			if (!(pVBInfo->LCDInfo & LCDNonExpanding)) {
2448				if (yres == 350)
2449					yres = 357;
2450				else if (yres == 400)
2451					yres = 420;
2452				else if (yres == 480)
2453					yres = 525;
2454			}
2455		}
2456	}
2457
2458	if (xres == 720)
2459		xres = 640;
2460
2461exit:
2462	pVBInfo->VGAHDE = xres;
2463	pVBInfo->HDE = xres;
2464	pVBInfo->VGAVDE = yres;
2465	pVBInfo->VDE = yres;
2466}
2467
2468static unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo)
2469{
2470
2471	if ((pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) &&
2472			(pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */
2473		return 1;
2474
2475	return 0;
2476}
2477
2478static void XGI_GetRAMDAC2DATA(unsigned short ModeIdIndex,
2479			       unsigned short RefreshRateTableIndex,
2480			       struct vb_device_info *pVBInfo)
2481{
2482	unsigned short tempax, tempbx, temp1, temp2, modeflag = 0, tempcx,
2483			CRT1Index;
2484
2485	pVBInfo->RVBHCMAX = 1;
2486	pVBInfo->RVBHCFACT = 1;
2487	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2488	CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
2489	CRT1Index &= IndexMask;
2490	temp1 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[0];
2491	temp2 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[5];
2492	tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
2493	tempbx = (unsigned short) XGI_CRT1Table[CRT1Index].CR[8];
2494	tempcx = (unsigned short)
2495			XGI_CRT1Table[CRT1Index].CR[14] << 8;
2496	tempcx &= 0x0100;
2497	tempcx <<= 2;
2498	tempbx |= tempcx;
2499	temp1 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[9];
2500
2501	if (temp1 & 0x01)
2502		tempbx |= 0x0100;
2503
2504	if (temp1 & 0x20)
2505		tempbx |= 0x0200;
2506	tempax += 5;
2507
2508	if (modeflag & Charx8Dot)
2509		tempax *= 8;
2510	else
2511		tempax *= 9;
2512
2513	pVBInfo->VGAHT = tempax;
2514	pVBInfo->HT = tempax;
2515	tempbx++;
2516	pVBInfo->VGAVT = tempbx;
2517	pVBInfo->VT = tempbx;
2518}
2519
2520static void XGI_GetCRT2Data(unsigned short ModeIdIndex,
2521		unsigned short RefreshRateTableIndex,
2522		struct vb_device_info *pVBInfo)
2523{
2524	unsigned short tempax = 0, tempbx = 0, modeflag, resinfo;
2525
2526	struct SiS_LCDData const *LCDPtr = NULL;
2527
2528	/* si+Ext_ResInfo */
2529	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2530	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2531	pVBInfo->NewFlickerMode = 0;
2532	pVBInfo->RVBHRS = 50;
2533
2534	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
2535		XGI_GetRAMDAC2DATA(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
2536		return;
2537	}
2538
2539	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
2540		LCDPtr = XGI_GetLcdPtr(XGI_LCDDataTable, ModeIdIndex,
2541				       pVBInfo);
2542
2543		pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX;
2544		pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT;
2545		pVBInfo->VGAHT = LCDPtr->VGAHT;
2546		pVBInfo->VGAVT = LCDPtr->VGAVT;
2547		pVBInfo->HT = LCDPtr->LCDHT;
2548		pVBInfo->VT = LCDPtr->LCDVT;
2549
2550		if (pVBInfo->LCDResInfo == Panel_1024x768) {
2551			tempax = 1024;
2552			tempbx = 768;
2553
2554			if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
2555				if (pVBInfo->VGAVDE == 357)
2556					tempbx = 527;
2557				else if (pVBInfo->VGAVDE == 420)
2558					tempbx = 620;
2559				else if (pVBInfo->VGAVDE == 525)
2560					tempbx = 775;
2561				else if (pVBInfo->VGAVDE == 600)
2562					tempbx = 775;
2563			}
2564		} else if (pVBInfo->LCDResInfo == Panel_1024x768x75) {
2565			tempax = 1024;
2566			tempbx = 768;
2567		} else if (pVBInfo->LCDResInfo == Panel_1280x1024) {
2568			tempax = 1280;
2569			if (pVBInfo->VGAVDE == 360)
2570				tempbx = 768;
2571			else if (pVBInfo->VGAVDE == 375)
2572				tempbx = 800;
2573			else if (pVBInfo->VGAVDE == 405)
2574				tempbx = 864;
2575			else
2576				tempbx = 1024;
2577		} else if (pVBInfo->LCDResInfo == Panel_1280x1024x75) {
2578			tempax = 1280;
2579			tempbx = 1024;
2580		} else if (pVBInfo->LCDResInfo == Panel_1280x960) {
2581			tempax = 1280;
2582			if (pVBInfo->VGAVDE == 350)
2583				tempbx = 700;
2584			else if (pVBInfo->VGAVDE == 400)
2585				tempbx = 800;
2586			else if (pVBInfo->VGAVDE == 1024)
2587				tempbx = 960;
2588			else
2589				tempbx = 960;
2590		} else if (pVBInfo->LCDResInfo == Panel_1400x1050) {
2591			tempax = 1400;
2592			tempbx = 1050;
2593
2594			if (pVBInfo->VGAVDE == 1024) {
2595				tempax = 1280;
2596				tempbx = 1024;
2597			}
2598		} else if (pVBInfo->LCDResInfo == Panel_1600x1200) {
2599			tempax = 1600;
2600			tempbx = 1200; /* alan 10/14/2003 */
2601			if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
2602				if (pVBInfo->VGAVDE == 350)
2603					tempbx = 875;
2604				else if (pVBInfo->VGAVDE == 400)
2605					tempbx = 1000;
2606			}
2607		}
2608
2609		if (pVBInfo->LCDInfo & LCDNonExpanding) {
2610			tempax = pVBInfo->VGAHDE;
2611			tempbx = pVBInfo->VGAVDE;
2612		}
2613
2614		pVBInfo->HDE = tempax;
2615		pVBInfo->VDE = tempbx;
2616		return;
2617	}
2618
2619	if (pVBInfo->VBInfo & (SetCRT2ToTV)) {
2620		struct SiS_TVData const *TVPtr;
2621
2622		TVPtr = XGI_GetTVPtr(ModeIdIndex, RefreshRateTableIndex,
2623				     pVBInfo);
2624
2625		pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX;
2626		pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT;
2627		pVBInfo->VGAHT = TVPtr->VGAHT;
2628		pVBInfo->VGAVT = TVPtr->VGAVT;
2629		pVBInfo->HDE = TVPtr->TVHDE;
2630		pVBInfo->VDE = TVPtr->TVVDE;
2631		pVBInfo->RVBHRS = TVPtr->RVBHRS;
2632		pVBInfo->NewFlickerMode = TVPtr->FlickerMode;
2633
2634		if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
2635			if (resinfo == 0x08)
2636				pVBInfo->NewFlickerMode = 0x40;
2637			else if (resinfo == 0x09)
2638				pVBInfo->NewFlickerMode = 0x40;
2639			else if (resinfo == 0x12)
2640				pVBInfo->NewFlickerMode = 0x40;
2641
2642			if (pVBInfo->VGAVDE == 350)
2643				pVBInfo->TVInfo |= TVSimuMode;
2644
2645			tempax = ExtHiTVHT;
2646			tempbx = ExtHiTVVT;
2647
2648			if (pVBInfo->VBInfo & SetInSlaveMode) {
2649				if (pVBInfo->TVInfo & TVSimuMode) {
2650					tempax = StHiTVHT;
2651					tempbx = StHiTVVT;
2652
2653					if (!(modeflag & Charx8Dot)) {
2654						tempax = StHiTextTVHT;
2655						tempbx = StHiTextTVVT;
2656					}
2657				}
2658			}
2659		} else if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
2660			if (pVBInfo->TVInfo & TVSetYPbPr750p) {
2661				tempax = YPbPrTV750pHT; /* Ext750pTVHT */
2662				tempbx = YPbPrTV750pVT; /* Ext750pTVVT */
2663			}
2664
2665			if (pVBInfo->TVInfo & TVSetYPbPr525p) {
2666				tempax = YPbPrTV525pHT; /* Ext525pTVHT */
2667				tempbx = YPbPrTV525pVT; /* Ext525pTVVT */
2668			} else if (pVBInfo->TVInfo & TVSetYPbPr525i) {
2669				tempax = YPbPrTV525iHT; /* Ext525iTVHT */
2670				tempbx = YPbPrTV525iVT; /* Ext525iTVVT */
2671				if (pVBInfo->TVInfo & NTSC1024x768)
2672					tempax = NTSC1024x768HT;
2673			}
2674		} else {
2675			tempax = PALHT;
2676			tempbx = PALVT;
2677			if (!(pVBInfo->TVInfo & TVSetPAL)) {
2678				tempax = NTSCHT;
2679				tempbx = NTSCVT;
2680				if (pVBInfo->TVInfo & NTSC1024x768)
2681					tempax = NTSC1024x768HT;
2682			}
2683		}
2684
2685		pVBInfo->HT = tempax;
2686		pVBInfo->VT = tempbx;
2687	}
2688}
2689
2690static void XGI_SetCRT2VCLK(unsigned short ModeIdIndex,
2691		unsigned short RefreshRateTableIndex,
2692		struct vb_device_info *pVBInfo)
2693{
2694	unsigned char di_0, di_1, tempal;
2695
2696	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo);
2697	XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
2698	XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
2699
2700	if (pVBInfo->VBType & VB_SIS301) { /* shampoo 0129 */
2701		/* 301 */
2702		xgifb_reg_set(pVBInfo->Part4Port, 0x0A, 0x10);
2703		xgifb_reg_set(pVBInfo->Part4Port, 0x0B, di_1);
2704		xgifb_reg_set(pVBInfo->Part4Port, 0x0A, di_0);
2705	} else { /* 301b/302b/301lv/302lv */
2706		xgifb_reg_set(pVBInfo->Part4Port, 0x0A, di_0);
2707		xgifb_reg_set(pVBInfo->Part4Port, 0x0B, di_1);
2708	}
2709
2710	xgifb_reg_set(pVBInfo->Part4Port, 0x00, 0x12);
2711
2712	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC)
2713		xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x28);
2714	else
2715		xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x08);
2716}
2717
2718static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex)
2719{
2720	unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
2721	short index;
2722	unsigned short modeflag;
2723
2724	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2725	index = (modeflag & ModeTypeMask) - ModeEGA;
2726
2727	if (index < 0)
2728		index = 0;
2729
2730	return ColorDepth[index];
2731}
2732
2733static unsigned short XGI_GetOffset(unsigned short ModeNo,
2734				    unsigned short ModeIdIndex,
2735		unsigned short RefreshRateTableIndex)
2736{
2737	unsigned short temp, colordepth, modeinfo, index, infoflag,
2738			ColorDepth[] = { 0x01, 0x02, 0x04 };
2739
2740	modeinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
2741	infoflag = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
2742
2743	index = (modeinfo >> 8) & 0xFF;
2744
2745	temp = XGI330_ScreenOffset[index];
2746
2747	if (infoflag & InterlaceMode)
2748		temp <<= 1;
2749
2750	colordepth = XGI_GetColorDepth(ModeIdIndex);
2751
2752	if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) {
2753		temp = ModeNo - 0x7C;
2754		colordepth = ColorDepth[temp];
2755		temp = 0x6B;
2756		if (infoflag & InterlaceMode)
2757			temp <<= 1;
2758	}
2759	return temp * colordepth;
2760}
2761
2762static void XGI_SetCRT2Offset(unsigned short ModeNo,
2763		unsigned short ModeIdIndex,
2764		unsigned short RefreshRateTableIndex,
2765		struct vb_device_info *pVBInfo)
2766{
2767	unsigned short offset;
2768	unsigned char temp;
2769
2770	if (pVBInfo->VBInfo & SetInSlaveMode)
2771		return;
2772
2773	offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex);
2774	temp = (unsigned char) (offset & 0xFF);
2775	xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp);
2776	temp = (unsigned char) ((offset & 0xFF00) >> 8);
2777	xgifb_reg_set(pVBInfo->Part1Port, 0x09, temp);
2778	temp = (unsigned char) (((offset >> 3) & 0xFF) + 1);
2779	xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp);
2780}
2781
2782static void XGI_SetCRT2FIFO(struct vb_device_info *pVBInfo)
2783{
2784	/* threshold high ,disable auto threshold */
2785	xgifb_reg_set(pVBInfo->Part1Port, 0x01, 0x3B);
2786	/* threshold low default 04h */
2787	xgifb_reg_and_or(pVBInfo->Part1Port, 0x02, ~(0x3F), 0x04);
2788}
2789
2790static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
2791		unsigned short RefreshRateTableIndex,
2792		struct vb_device_info *pVBInfo)
2793{
2794	u8 tempcx;
2795
2796	XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
2797	XGI_SetCRT2FIFO(pVBInfo);
2798
2799	for (tempcx = 4; tempcx < 7; tempcx++)
2800		xgifb_reg_set(pVBInfo->Part1Port, tempcx, 0x0);
2801
2802	xgifb_reg_set(pVBInfo->Part1Port, 0x50, 0x00);
2803	xgifb_reg_set(pVBInfo->Part1Port, 0x02, 0x44); /* temp 0206 */
2804}
2805
2806static void XGI_SetGroup1(unsigned short ModeIdIndex,
2807		unsigned short RefreshRateTableIndex,
2808		struct vb_device_info *pVBInfo)
2809{
2810	unsigned short temp = 0, tempax = 0, tempbx = 0, tempcx = 0,
2811			pushbx = 0, CRT1Index, modeflag;
2812
2813	CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
2814	CRT1Index &= IndexMask;
2815	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2816
2817	/* bainy change table name */
2818	if (modeflag & HalfDCLK) {
2819		/* BTVGA2HT 0x08,0x09 */
2820		temp = (pVBInfo->VGAHT / 2 - 1) & 0x0FF;
2821		xgifb_reg_set(pVBInfo->Part1Port, 0x08, temp);
2822		temp = (((pVBInfo->VGAHT / 2 - 1) & 0xFF00) >> 8) << 4;
2823		xgifb_reg_and_or(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
2824		/* BTVGA2HDEE 0x0A,0x0C */
2825		temp = (pVBInfo->VGAHDE / 2 + 16) & 0x0FF;
2826		xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
2827		tempcx = ((pVBInfo->VGAHT - pVBInfo->VGAHDE) / 2) >> 2;
2828		pushbx = pVBInfo->VGAHDE / 2 + 16;
2829		tempcx >>= 1;
2830		tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
2831		tempcx += tempbx;
2832
2833		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
2834			tempbx = XGI_CRT1Table[CRT1Index].CR[4];
2835			tempbx |= ((XGI_CRT1Table[CRT1Index].CR[14] &
2836						0xC0) << 2);
2837			tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
2838			tempcx = XGI_CRT1Table[CRT1Index].CR[5];
2839			tempcx &= 0x1F;
2840			temp = XGI_CRT1Table[CRT1Index].CR[15];
2841			temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
2842			tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
2843		}
2844
2845		tempbx += 4;
2846		tempcx += 4;
2847
2848		if (tempcx > (pVBInfo->VGAHT / 2))
2849			tempcx = pVBInfo->VGAHT / 2;
2850
2851		temp = tempbx & 0x00FF;
2852
2853		xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
2854	} else {
2855		temp = (pVBInfo->VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
2856		xgifb_reg_set(pVBInfo->Part1Port, 0x08, temp);
2857		temp = (((pVBInfo->VGAHT - 1) & 0xFF00) >> 8) << 4;
2858		xgifb_reg_and_or(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
2859		/* BTVGA2HDEE 0x0A,0x0C */
2860		temp = (pVBInfo->VGAHDE + 16) & 0x0FF;
2861		xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
2862		tempcx = (pVBInfo->VGAHT - pVBInfo->VGAHDE) >> 2; /* cx */
2863		pushbx = pVBInfo->VGAHDE + 16;
2864		tempcx >>= 1;
2865		tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
2866		tempcx += tempbx;
2867
2868		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
2869			tempbx = XGI_CRT1Table[CRT1Index].CR[3];
2870			tempbx |= ((XGI_CRT1Table[CRT1Index].CR[5] &
2871						0xC0) << 2);
2872			tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
2873			tempcx = XGI_CRT1Table[CRT1Index].CR[4];
2874			tempcx &= 0x1F;
2875			temp = XGI_CRT1Table[CRT1Index].CR[6];
2876			temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
2877			tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
2878			tempbx += 16;
2879			tempcx += 16;
2880		}
2881
2882		if (tempcx > pVBInfo->VGAHT)
2883			tempcx = pVBInfo->VGAHT;
2884
2885		temp = tempbx & 0x00FF;
2886		xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
2887	}
2888
2889	tempax = (tempax & 0x00FF) | (tempbx & 0xFF00);
2890	tempbx = pushbx;
2891	tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
2892	tempax |= (tempbx & 0xFF00);
2893	temp = (tempax & 0xFF00) >> 8;
2894	xgifb_reg_set(pVBInfo->Part1Port, 0x0C, temp);
2895	temp = tempcx & 0x00FF;
2896	xgifb_reg_set(pVBInfo->Part1Port, 0x0D, temp);
2897	tempcx = (pVBInfo->VGAVT - 1);
2898	temp = tempcx & 0x00FF;
2899
2900	xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp);
2901	tempbx = pVBInfo->VGAVDE - 1;
2902	temp = tempbx & 0x00FF;
2903	xgifb_reg_set(pVBInfo->Part1Port, 0x0F, temp);
2904	temp = ((tempbx & 0xFF00) << 3) >> 8;
2905	temp |= ((tempcx & 0xFF00) >> 8);
2906	xgifb_reg_set(pVBInfo->Part1Port, 0x12, temp);
2907
2908	/* BTVGA2VRS 0x10,0x11 */
2909	tempbx = (pVBInfo->VGAVT + pVBInfo->VGAVDE) >> 1;
2910	/* BTVGA2VRE 0x11 */
2911	tempcx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) >> 4) + tempbx + 1;
2912
2913	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
2914		tempbx = XGI_CRT1Table[CRT1Index].CR[10];
2915		temp = XGI_CRT1Table[CRT1Index].CR[9];
2916
2917		if (temp & 0x04)
2918			tempbx |= 0x0100;
2919
2920		if (temp & 0x080)
2921			tempbx |= 0x0200;
2922
2923		temp = XGI_CRT1Table[CRT1Index].CR[14];
2924
2925		if (temp & 0x08)
2926			tempbx |= 0x0400;
2927
2928		temp = XGI_CRT1Table[CRT1Index].CR[11];
2929		tempcx = (tempcx & 0xFF00) | (temp & 0x00FF);
2930	}
2931
2932	temp = tempbx & 0x00FF;
2933	xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
2934	temp = ((tempbx & 0xFF00) >> 8) << 4;
2935	temp = ((tempcx & 0x000F) | (temp));
2936	xgifb_reg_set(pVBInfo->Part1Port, 0x11, temp);
2937	tempax = 0;
2938
2939	if (modeflag & DoubleScanMode)
2940		tempax |= 0x80;
2941
2942	if (modeflag & HalfDCLK)
2943		tempax |= 0x40;
2944
2945	xgifb_reg_and_or(pVBInfo->Part1Port, 0x2C, ~0x0C0, tempax);
2946}
2947
2948static unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo)
2949{
2950	unsigned long tempax, tempbx;
2951
2952	tempbx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) * pVBInfo->RVBHCMAX)
2953			& 0xFFFF;
2954	tempax = (pVBInfo->VT - pVBInfo->VDE) * pVBInfo->RVBHCFACT;
2955	tempax = (tempax * pVBInfo->HT) / tempbx;
2956
2957	return (unsigned short) tempax;
2958}
2959
2960static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
2961		struct vb_device_info *pVBInfo)
2962{
2963	unsigned short push1, push2, tempax, tempbx = 0, tempcx, temp, resinfo,
2964			modeflag;
2965
2966	/* si+Ext_ResInfo */
2967	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2968	resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2969
2970	if (!(pVBInfo->VBInfo & SetInSlaveMode))
2971		return;
2972
2973	temp = 0xFF; /* set MAX HT */
2974	xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp);
2975	tempcx = 0x08;
2976
2977	if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C))
2978		modeflag |= Charx8Dot;
2979
2980	tempax = pVBInfo->VGAHDE; /* 0x04 Horizontal Display End */
2981
2982	if (modeflag & HalfDCLK)
2983		tempax >>= 1;
2984
2985	tempax = (tempax / tempcx) - 1;
2986	tempbx |= ((tempax & 0x00FF) << 8);
2987	temp = tempax & 0x00FF;
2988	xgifb_reg_set(pVBInfo->Part1Port, 0x04, temp);
2989
2990	temp = (tempbx & 0xFF00) >> 8;
2991
2992	if (pVBInfo->VBInfo & SetCRT2ToTV) {
2993		if (!(pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
2994				| VB_SIS302LV | VB_XGI301C)))
2995			temp += 2;
2996
2997		if ((pVBInfo->VBInfo & SetCRT2ToHiVision) &&
2998		    !(pVBInfo->VBType & VB_SIS301LV) && (resinfo == 7))
2999				temp -= 2;
3000	}
3001
3002	/* 0x05 Horizontal Display Start */
3003	xgifb_reg_set(pVBInfo->Part1Port, 0x05, temp);
3004	/* 0x06 Horizontal Blank end */
3005	xgifb_reg_set(pVBInfo->Part1Port, 0x06, 0x03);
3006
3007	if (!(pVBInfo->VBInfo & DisableCRT2Display)) { /* 030226 bainy */
3008		if (pVBInfo->VBInfo & SetCRT2ToTV)
3009			tempax = pVBInfo->VGAHT;
3010		else
3011			tempax = XGI_GetVGAHT2(pVBInfo);
3012	}
3013
3014	if (tempax >= pVBInfo->VGAHT)
3015		tempax = pVBInfo->VGAHT;
3016
3017	if (modeflag & HalfDCLK)
3018		tempax >>= 1;
3019
3020	tempax = (tempax / tempcx) - 5;
3021	tempcx = tempax; /* 20030401 0x07 horizontal Retrace Start */
3022	if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3023		temp = (tempbx & 0x00FF) - 1;
3024		if (!(modeflag & HalfDCLK)) {
3025			temp -= 6;
3026			if (pVBInfo->TVInfo & TVSimuMode) {
3027				temp -= 4;
3028				temp -= 10;
3029			}
3030		}
3031	} else {
3032		tempbx = (tempbx & 0xFF00) >> 8;
3033		tempcx = (tempcx + tempbx) >> 1;
3034		temp = (tempcx & 0x00FF) + 2;
3035
3036		if (pVBInfo->VBInfo & SetCRT2ToTV) {
3037			temp -= 1;
3038			if (!(modeflag & HalfDCLK)) {
3039				if ((modeflag & Charx8Dot)) {
3040					temp += 4;
3041					if (pVBInfo->VGAHDE >= 800)
3042						temp -= 6;
3043				}
3044			}
3045		} else if (!(modeflag & HalfDCLK)) {
3046			temp -= 4;
3047			if (pVBInfo->LCDResInfo != Panel_1280x960 &&
3048			    pVBInfo->VGAHDE >= 800) {
3049				temp -= 7;
3050				if (pVBInfo->VGAHDE >= 1280 &&
3051				    pVBInfo->LCDResInfo != Panel_1280x960 &&
3052				    (pVBInfo->LCDInfo & LCDNonExpanding))
3053					temp += 28;
3054			}
3055		}
3056	}
3057
3058	/* 0x07 Horizontal Retrace Start */
3059	xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp);
3060	/* 0x08 Horizontal Retrace End */
3061	xgifb_reg_set(pVBInfo->Part1Port, 0x08, 0);
3062
3063	if (pVBInfo->VBInfo & SetCRT2ToTV) {
3064		if (pVBInfo->TVInfo & TVSimuMode) {
3065			if (ModeNo == 0x50) {
3066				if (pVBInfo->TVInfo == SetNTSCTV) {
3067					xgifb_reg_set(pVBInfo->Part1Port,
3068							0x07, 0x30);
3069					xgifb_reg_set(pVBInfo->Part1Port,
3070							0x08, 0x03);
3071				} else {
3072					xgifb_reg_set(pVBInfo->Part1Port,
3073							0x07, 0x2f);
3074					xgifb_reg_set(pVBInfo->Part1Port,
3075							0x08, 0x02);
3076				}
3077			}
3078		}
3079	}
3080
3081	xgifb_reg_set(pVBInfo->Part1Port, 0x18, 0x03); /* 0x18 SR0B */
3082	xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0xF0, 0x00);
3083	xgifb_reg_set(pVBInfo->Part1Port, 0x09, 0xFF); /* 0x09 Set Max VT */
3084
3085	tempbx = pVBInfo->VGAVT;
3086	push1 = tempbx;
3087	tempcx = 0x121;
3088	tempbx = pVBInfo->VGAVDE; /* 0x0E Virtical Display End */
3089
3090	if (tempbx == 357)
3091		tempbx = 350;
3092	if (tempbx == 360)
3093		tempbx = 350;
3094	if (tempbx == 375)
3095		tempbx = 350;
3096	if (tempbx == 405)
3097		tempbx = 400;
3098	if (tempbx == 525)
3099		tempbx = 480;
3100
3101	push2 = tempbx;
3102
3103	if (pVBInfo->VBInfo & SetCRT2ToLCD) {
3104		if (pVBInfo->LCDResInfo == Panel_1024x768) {
3105			if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
3106				if (tempbx == 350)
3107					tempbx += 5;
3108				if (tempbx == 480)
3109					tempbx += 5;
3110			}
3111		}
3112	}
3113	tempbx--;
3114	tempbx--;
3115	temp = tempbx & 0x00FF;
3116	/* 0x10 vertical Blank Start */
3117	xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
3118	tempbx = push2;
3119	tempbx--;
3120	temp = tempbx & 0x00FF;
3121	xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp);
3122
3123	if (tempbx & 0x0100)
3124		tempcx |= 0x0002;
3125
3126	tempax = 0x000B;
3127
3128	if (modeflag & DoubleScanMode)
3129		tempax |= 0x08000;
3130
3131	if (tempbx & 0x0200)
3132		tempcx |= 0x0040;
3133
3134	temp = (tempax & 0xFF00) >> 8;
3135	xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
3136
3137	if (tempbx & 0x0400)
3138		tempcx |= 0x0600;
3139
3140	/* 0x11 Vertival Blank End */
3141	xgifb_reg_set(pVBInfo->Part1Port, 0x11, 0x00);
3142
3143	tempax = push1;
3144	tempax -= tempbx; /* 0x0C Vertical Retrace Start */
3145	tempax >>= 2;
3146	push1 = tempax; /* push ax */
3147
3148	if (resinfo != 0x09) {
3149		tempax <<= 1;
3150		tempbx += tempax;
3151	}
3152
3153	if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3154		if ((pVBInfo->VBType & VB_SIS301LV) &&
3155		    !(pVBInfo->TVInfo & TVSetHiVision)) {
3156			if ((pVBInfo->TVInfo & TVSimuMode) &&
3157			    (pVBInfo->TVInfo & TVSetPAL)) {
3158				if (!(pVBInfo->VBType & VB_SIS301LV) ||
3159				    !(pVBInfo->TVInfo &
3160				      (TVSetYPbPr525p |
3161				       TVSetYPbPr750p |
3162				       TVSetHiVision)))
3163					tempbx += 40;
3164			}
3165		} else {
3166			tempbx -= 10;
3167		}
3168	} else if (pVBInfo->TVInfo & TVSimuMode) {
3169		if (pVBInfo->TVInfo & TVSetPAL) {
3170			if (pVBInfo->VBType & VB_SIS301LV) {
3171				if (!(pVBInfo->TVInfo &
3172				    (TVSetYPbPr525p |
3173				     TVSetYPbPr750p |
3174				     TVSetHiVision)))
3175					tempbx += 40;
3176			} else {
3177				tempbx += 40;
3178			}
3179		}
3180	}
3181	tempax = push1;
3182	tempax >>= 2;
3183	tempax++;
3184	tempax += tempbx;
3185	push1 = tempax; /* push ax */
3186
3187	if ((pVBInfo->TVInfo & TVSetPAL)) {
3188		if (tempbx <= 513) {
3189			if (tempax >= 513)
3190				tempbx = 513;
3191		}
3192	}
3193
3194	temp = tempbx & 0x00FF;
3195	xgifb_reg_set(pVBInfo->Part1Port, 0x0C, temp);
3196	tempbx--;
3197	temp = tempbx & 0x00FF;
3198	xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
3199
3200	if (tempbx & 0x0100)
3201		tempcx |= 0x0008;
3202
3203	if (tempbx & 0x0200)
3204		xgifb_reg_and_or(pVBInfo->Part1Port, 0x0B, 0x0FF, 0x20);
3205
3206	tempbx++;
3207
3208	if (tempbx & 0x0100)
3209		tempcx |= 0x0004;
3210
3211	if (tempbx & 0x0200)
3212		tempcx |= 0x0080;
3213
3214	if (tempbx & 0x0400)
3215		tempcx |= 0x0C00;
3216
3217	tempbx = push1; /* pop ax */
3218	temp = tempbx & 0x00FF;
3219	temp &= 0x0F;
3220	/* 0x0D vertical Retrace End */
3221	xgifb_reg_set(pVBInfo->Part1Port, 0x0D, temp);
3222
3223	if (tempbx & 0x0010)
3224		tempcx |= 0x2000;
3225
3226	temp = tempcx & 0x00FF;
3227	xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp); /* 0x0A CR07 */
3228	temp = (tempcx & 0x0FF00) >> 8;
3229	xgifb_reg_set(pVBInfo->Part1Port, 0x17, temp); /* 0x17 SR0A */
3230	tempax = modeflag;
3231	temp = (tempax & 0xFF00) >> 8;
3232
3233	temp = (temp >> 1) & 0x09;
3234
3235	if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C))
3236		temp |= 0x01;
3237
3238	xgifb_reg_set(pVBInfo->Part1Port, 0x16, temp); /* 0x16 SR01 */
3239	xgifb_reg_set(pVBInfo->Part1Port, 0x0F, 0); /* 0x0F CR14 */
3240	xgifb_reg_set(pVBInfo->Part1Port, 0x12, 0); /* 0x12 CR17 */
3241
3242	if (pVBInfo->LCDInfo & LCDRGB18Bit)
3243		temp = 0x80;
3244	else
3245		temp = 0x00;
3246
3247	xgifb_reg_set(pVBInfo->Part1Port, 0x1A, temp); /* 0x1A SR0E */
3248}
3249
3250static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
3251		struct vb_device_info *pVBInfo)
3252{
3253	unsigned short i, j, tempax, tempbx, tempcx, temp, push1, push2,
3254			modeflag;
3255	unsigned char const *TimingPoint;
3256
3257	unsigned long longtemp, tempeax, tempebx, temp2, tempecx;
3258
3259	/* si+Ext_ResInfo */
3260	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3261
3262	tempax = 0;
3263
3264	if (!(pVBInfo->VBInfo & SetCRT2ToAVIDEO))
3265		tempax |= 0x0800;
3266
3267	if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
3268		tempax |= 0x0400;
3269
3270	if (pVBInfo->VBInfo & SetCRT2ToSCART)
3271		tempax |= 0x0200;
3272
3273	if (!(pVBInfo->TVInfo & TVSetPAL))
3274		tempax |= 0x1000;
3275
3276	if (pVBInfo->VBInfo & SetCRT2ToHiVision)
3277		tempax |= 0x0100;
3278
3279	if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))
3280		tempax &= 0xfe00;
3281
3282	tempax = (tempax & 0xff00) >> 8;
3283
3284	xgifb_reg_set(pVBInfo->Part2Port, 0x0, tempax);
3285	TimingPoint = XGI330_NTSCTiming;
3286
3287	if (pVBInfo->TVInfo & TVSetPAL)
3288		TimingPoint = XGI330_PALTiming;
3289
3290	if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3291		TimingPoint = XGI330_HiTVExtTiming;
3292
3293		if (pVBInfo->VBInfo & SetInSlaveMode)
3294			TimingPoint = XGI330_HiTVSt2Timing;
3295
3296		if (pVBInfo->SetFlag & TVSimuMode)
3297			TimingPoint = XGI330_HiTVSt1Timing;
3298
3299		if (!(modeflag & Charx8Dot))
3300			TimingPoint = XGI330_HiTVTextTiming;
3301	}
3302
3303	if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
3304		if (pVBInfo->TVInfo & TVSetYPbPr525i)
3305			TimingPoint = XGI330_YPbPr525iTiming;
3306
3307		if (pVBInfo->TVInfo & TVSetYPbPr525p)
3308			TimingPoint = XGI330_YPbPr525pTiming;
3309
3310		if (pVBInfo->TVInfo & TVSetYPbPr750p)
3311			TimingPoint = XGI330_YPbPr750pTiming;
3312	}
3313
3314	for (i = 0x01, j = 0; i <= 0x2D; i++, j++)
3315		xgifb_reg_set(pVBInfo->Part2Port, i, TimingPoint[j]);
3316
3317	for (i = 0x39; i <= 0x45; i++, j++)
3318		/* di->temp2[j] */
3319		xgifb_reg_set(pVBInfo->Part2Port, i, TimingPoint[j]);
3320
3321	if (pVBInfo->VBInfo & SetCRT2ToTV)
3322		xgifb_reg_and_or(pVBInfo->Part2Port, 0x3A, 0x1F, 0x00);
3323
3324	temp = pVBInfo->NewFlickerMode;
3325	temp &= 0x80;
3326	xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xFF, temp);
3327
3328	if (pVBInfo->TVInfo & TVSetPAL)
3329		tempax = 520;
3330	else
3331		tempax = 440;
3332
3333	if (pVBInfo->VDE <= tempax) {
3334		tempax -= pVBInfo->VDE;
3335		tempax >>= 2;
3336		tempax = (tempax & 0x00FF) | ((tempax & 0x00FF) << 8);
3337		push1 = tempax;
3338		temp = (tempax & 0xFF00) >> 8;
3339		temp += (unsigned short) TimingPoint[0];
3340
3341		if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3342				| VB_SIS302LV | VB_XGI301C)) {
3343			if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO
3344					| SetCRT2ToSVIDEO | SetCRT2ToSCART
3345					| SetCRT2ToYPbPr525750)) {
3346				tempcx = pVBInfo->VGAHDE;
3347				if (tempcx >= 1024) {
3348					temp = 0x17; /* NTSC */
3349					if (pVBInfo->TVInfo & TVSetPAL)
3350						temp = 0x19; /* PAL */
3351				}
3352			}
3353		}
3354
3355		xgifb_reg_set(pVBInfo->Part2Port, 0x01, temp);
3356		tempax = push1;
3357		temp = (tempax & 0xFF00) >> 8;
3358		temp += TimingPoint[1];
3359
3360		if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3361				| VB_SIS302LV | VB_XGI301C)) {
3362			if ((pVBInfo->VBInfo & (SetCRT2ToAVIDEO
3363					| SetCRT2ToSVIDEO | SetCRT2ToSCART
3364					| SetCRT2ToYPbPr525750))) {
3365				tempcx = pVBInfo->VGAHDE;
3366				if (tempcx >= 1024) {
3367					temp = 0x1D; /* NTSC */
3368					if (pVBInfo->TVInfo & TVSetPAL)
3369						temp = 0x52; /* PAL */
3370				}
3371			}
3372		}
3373		xgifb_reg_set(pVBInfo->Part2Port, 0x02, temp);
3374	}
3375
3376	/* 301b */
3377	tempcx = pVBInfo->HT;
3378
3379	if (XGI_IsLCDDualLink(pVBInfo))
3380		tempcx >>= 1;
3381
3382	tempcx -= 2;
3383	temp = tempcx & 0x00FF;
3384	xgifb_reg_set(pVBInfo->Part2Port, 0x1B, temp);
3385
3386	temp = (tempcx & 0xFF00) >> 8;
3387	xgifb_reg_and_or(pVBInfo->Part2Port, 0x1D, ~0x0F, temp);
3388
3389	tempcx = pVBInfo->HT >> 1;
3390	push1 = tempcx; /* push cx */
3391	tempcx += 7;
3392
3393	if (pVBInfo->VBInfo & SetCRT2ToHiVision)
3394		tempcx -= 4;
3395
3396	temp = tempcx & 0x00FF;
3397	temp <<= 4;
3398	xgifb_reg_and_or(pVBInfo->Part2Port, 0x22, 0x0F, temp);
3399
3400	tempbx = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
3401	tempbx += tempcx;
3402	push2 = tempbx;
3403	temp = tempbx & 0x00FF;
3404	xgifb_reg_set(pVBInfo->Part2Port, 0x24, temp);
3405	temp = (tempbx & 0xFF00) >> 8;
3406	temp <<= 4;
3407	xgifb_reg_and_or(pVBInfo->Part2Port, 0x25, 0x0F, temp);
3408
3409	tempbx = push2;
3410	tempbx = tempbx + 8;
3411	if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3412		tempbx = tempbx - 4;
3413		tempcx = tempbx;
3414	}
3415
3416	temp = (tempbx & 0x00FF) << 4;
3417	xgifb_reg_and_or(pVBInfo->Part2Port, 0x29, 0x0F, temp);
3418
3419	j += 2;
3420	tempcx += (TimingPoint[j] | ((TimingPoint[j + 1]) << 8));
3421	temp = tempcx & 0x00FF;
3422	xgifb_reg_set(pVBInfo->Part2Port, 0x27, temp);
3423	temp = ((tempcx & 0xFF00) >> 8) << 4;
3424	xgifb_reg_and_or(pVBInfo->Part2Port, 0x28, 0x0F, temp);
3425
3426	tempcx += 8;
3427	if (pVBInfo->VBInfo & SetCRT2ToHiVision)
3428		tempcx -= 4;
3429
3430	temp = tempcx & 0xFF;
3431	temp <<= 4;
3432	xgifb_reg_and_or(pVBInfo->Part2Port, 0x2A, 0x0F, temp);
3433
3434	tempcx = push1; /* pop cx */
3435	j += 2;
3436	temp = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
3437	tempcx -= temp;
3438	temp = tempcx & 0x00FF;
3439	temp <<= 4;
3440	xgifb_reg_and_or(pVBInfo->Part2Port, 0x2D, 0x0F, temp);
3441
3442	tempcx -= 11;
3443
3444	if (!(pVBInfo->VBInfo & SetCRT2ToTV)) {
3445		tempax = XGI_GetVGAHT2(pVBInfo);
3446		tempcx = tempax - 1;
3447	}
3448	temp = tempcx & 0x00FF;
3449	xgifb_reg_set(pVBInfo->Part2Port, 0x2E, temp);
3450
3451	tempbx = pVBInfo->VDE;
3452
3453	if (pVBInfo->VGAVDE == 360)
3454		tempbx = 746;
3455	if (pVBInfo->VGAVDE == 375)
3456		tempbx = 746;
3457	if (pVBInfo->VGAVDE == 405)
3458		tempbx = 853;
3459
3460	if (pVBInfo->VBInfo & SetCRT2ToTV) {
3461		if (pVBInfo->VBType &
3462		    (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
3463			if (!(pVBInfo->TVInfo &
3464			    (TVSetYPbPr525p | TVSetYPbPr750p)))
3465				tempbx >>= 1;
3466		} else
3467			tempbx >>= 1;
3468	}
3469
3470	tempbx -= 2;
3471	temp = tempbx & 0x00FF;
3472
3473	if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3474		if (pVBInfo->VBType & VB_SIS301LV) {
3475			if (pVBInfo->TVInfo & TVSetHiVision) {
3476				if (pVBInfo->VBInfo & SetInSlaveMode) {
3477					if (ModeNo == 0x2f)
3478						temp += 1;
3479				}
3480			}
3481		} else if (pVBInfo->VBInfo & SetInSlaveMode) {
3482			if (ModeNo == 0x2f)
3483				temp += 1;
3484		}
3485	}
3486
3487	xgifb_reg_set(pVBInfo->Part2Port, 0x2F, temp);
3488
3489	temp = (tempcx & 0xFF00) >> 8;
3490	temp |= ((tempbx & 0xFF00) >> 8) << 6;
3491
3492	if (!(pVBInfo->VBInfo & SetCRT2ToHiVision)) {
3493		if (pVBInfo->VBType & VB_SIS301LV) {
3494			if (pVBInfo->TVInfo & TVSetHiVision) {
3495				temp |= 0x10;
3496
3497				if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
3498					temp |= 0x20;
3499			}
3500		} else {
3501			temp |= 0x10;
3502			if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
3503				temp |= 0x20;
3504		}
3505	}
3506
3507	xgifb_reg_set(pVBInfo->Part2Port, 0x30, temp);
3508
3509	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3510			| VB_SIS302LV | VB_XGI301C)) { /* TV gatingno */
3511		tempbx = pVBInfo->VDE;
3512		tempcx = tempbx - 2;
3513
3514		if (pVBInfo->VBInfo & SetCRT2ToTV) {
3515			if (!(pVBInfo->TVInfo & (TVSetYPbPr525p
3516					| TVSetYPbPr750p)))
3517				tempbx >>= 1;
3518		}
3519
3520		if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
3521			temp = 0;
3522			if (tempcx & 0x0400)
3523				temp |= 0x20;
3524
3525			if (tempbx & 0x0400)
3526				temp |= 0x40;
3527
3528			xgifb_reg_set(pVBInfo->Part4Port, 0x10, temp);
3529		}
3530
3531		temp = (((tempbx - 3) & 0x0300) >> 8) << 5;
3532		xgifb_reg_set(pVBInfo->Part2Port, 0x46, temp);
3533		temp = (tempbx - 3) & 0x00FF;
3534		xgifb_reg_set(pVBInfo->Part2Port, 0x47, temp);
3535	}
3536
3537	tempbx = tempbx & 0x00FF;
3538
3539	if (!(modeflag & HalfDCLK)) {
3540		tempcx = pVBInfo->VGAHDE;
3541		if (tempcx >= pVBInfo->HDE) {
3542			tempbx |= 0x2000;
3543			tempax &= 0x00FF;
3544		}
3545	}
3546
3547	tempcx = 0x0101;
3548
3549	if (pVBInfo->VBInfo & SetCRT2ToTV) { /*301b*/
3550		if (pVBInfo->VGAHDE >= 1024) {
3551			tempcx = 0x1920;
3552			if (pVBInfo->VGAHDE >= 1280) {
3553				tempcx = 0x1420;
3554				tempbx = tempbx & 0xDFFF;
3555			}
3556		}
3557	}
3558
3559	if (!(tempbx & 0x2000)) {
3560		if (modeflag & HalfDCLK)
3561			tempcx = (tempcx & 0xFF00) | ((tempcx & 0x00FF) << 1);
3562
3563		push1 = tempbx;
3564		tempeax = pVBInfo->VGAHDE;
3565		tempebx = (tempcx & 0xFF00) >> 8;
3566		longtemp = tempeax * tempebx;
3567		tempecx = tempcx & 0x00FF;
3568		longtemp = longtemp / tempecx;
3569
3570		/* 301b */
3571		tempecx = 8 * 1024;
3572
3573		if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3574				| VB_SIS302LV | VB_XGI301C)) {
3575			tempecx = tempecx * 8;
3576		}
3577
3578		longtemp = longtemp * tempecx;
3579		tempecx = pVBInfo->HDE;
3580		temp2 = longtemp % tempecx;
3581		tempeax = longtemp / tempecx;
3582		if (temp2 != 0)
3583			tempeax += 1;
3584
3585		tempax = (unsigned short) tempeax;
3586
3587		/* 301b */
3588		if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3589				| VB_SIS302LV | VB_XGI301C)) {
3590			tempcx = ((tempax & 0xFF00) >> 5) >> 8;
3591		}
3592		/* end 301b */
3593
3594		tempbx = push1;
3595		tempbx = (unsigned short) (((tempeax & 0x0000FF00) & 0x1F00)
3596				| (tempbx & 0x00FF));
3597		tempax = (unsigned short) (((tempeax & 0x000000FF) << 8)
3598				| (tempax & 0x00FF));
3599		temp = (tempax & 0xFF00) >> 8;
3600	} else {
3601		temp = (tempax & 0x00FF) >> 8;
3602	}
3603
3604	xgifb_reg_set(pVBInfo->Part2Port, 0x44, temp);
3605	temp = (tempbx & 0xFF00) >> 8;
3606	xgifb_reg_and_or(pVBInfo->Part2Port, 0x45, ~0x03F, temp);
3607	temp = tempcx & 0x00FF;
3608
3609	if (tempbx & 0x2000)
3610		temp = 0;
3611
3612	if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
3613		temp |= 0x18;
3614
3615	xgifb_reg_and_or(pVBInfo->Part2Port, 0x46, ~0x1F, temp);
3616	if (pVBInfo->TVInfo & TVSetPAL) {
3617		tempbx = 0x0382;
3618		tempcx = 0x007e;
3619	} else {
3620		tempbx = 0x0369;
3621		tempcx = 0x0061;
3622	}
3623
3624	temp = tempbx & 0x00FF;
3625	xgifb_reg_set(pVBInfo->Part2Port, 0x4b, temp);
3626	temp = tempcx & 0x00FF;
3627	xgifb_reg_set(pVBInfo->Part2Port, 0x4c, temp);
3628
3629	temp = ((tempcx & 0xFF00) >> 8) & 0x03;
3630	temp <<= 2;
3631	temp |= ((tempbx & 0xFF00) >> 8) & 0x03;
3632
3633	if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
3634		temp |= 0x10;
3635
3636		if (pVBInfo->TVInfo & TVSetYPbPr525p)
3637			temp |= 0x20;
3638
3639		if (pVBInfo->TVInfo & TVSetYPbPr750p)
3640			temp |= 0x60;
3641	}
3642
3643	xgifb_reg_set(pVBInfo->Part2Port, 0x4d, temp);
3644	temp = xgifb_reg_get(pVBInfo->Part2Port, 0x43); /* 301b change */
3645	xgifb_reg_set(pVBInfo->Part2Port, 0x43, (unsigned short) (temp - 3));
3646
3647	if (!(pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))) {
3648		if (pVBInfo->TVInfo & NTSC1024x768) {
3649			TimingPoint = XGI_NTSC1024AdjTime;
3650			for (i = 0x1c, j = 0; i <= 0x30; i++, j++) {
3651				xgifb_reg_set(pVBInfo->Part2Port, i,
3652						TimingPoint[j]);
3653			}
3654			xgifb_reg_set(pVBInfo->Part2Port, 0x43, 0x72);
3655		}
3656	}
3657
3658	/* Modify for 301C PALM Support */
3659	if (pVBInfo->VBType & VB_XGI301C) {
3660		if (pVBInfo->TVInfo & TVSetPALM)
3661			xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x08,
3662					0x08); /* PALM Mode */
3663	}
3664
3665	if (pVBInfo->TVInfo & TVSetPALM) {
3666		tempax = xgifb_reg_get(pVBInfo->Part2Port, 0x01);
3667		tempax--;
3668		xgifb_reg_and(pVBInfo->Part2Port, 0x01, tempax);
3669
3670		xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xEF);
3671	}
3672
3673	if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3674		if (!(pVBInfo->VBInfo & SetInSlaveMode))
3675			xgifb_reg_set(pVBInfo->Part2Port, 0x0B, 0x00);
3676	}
3677}
3678
3679static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
3680		struct vb_device_info *pVBInfo)
3681{
3682	unsigned short pushbx, tempax, tempbx, tempcx, temp, tempah,
3683			tempbh, tempch;
3684
3685	struct XGI_LCDDesStruct const *LCDBDesPtr = NULL;
3686
3687	/* si+Ext_ResInfo */
3688	if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
3689		return;
3690
3691	tempbx = pVBInfo->HDE; /* RHACTE=HDE-1 */
3692
3693	if (XGI_IsLCDDualLink(pVBInfo))
3694		tempbx >>= 1;
3695
3696	tempbx -= 1;
3697	temp = tempbx & 0x00FF;
3698	xgifb_reg_set(pVBInfo->Part2Port, 0x2C, temp);
3699	temp = (tempbx & 0xFF00) >> 8;
3700	temp <<= 4;
3701	xgifb_reg_and_or(pVBInfo->Part2Port, 0x2B, 0x0F, temp);
3702	temp = 0x01;
3703
3704	xgifb_reg_set(pVBInfo->Part2Port, 0x0B, temp);
3705	tempbx = pVBInfo->VDE; /* RTVACTEO=(VDE-1)&0xFF */
3706	tempbx--;
3707	temp = tempbx & 0x00FF;
3708	xgifb_reg_set(pVBInfo->Part2Port, 0x03, temp);
3709	temp = ((tempbx & 0xFF00) >> 8) & 0x07;
3710	xgifb_reg_and_or(pVBInfo->Part2Port, 0x0C, ~0x07, temp);
3711
3712	tempcx = pVBInfo->VT - 1;
3713	temp = tempcx & 0x00FF; /* RVTVT=VT-1 */
3714	xgifb_reg_set(pVBInfo->Part2Port, 0x19, temp);
3715	temp = (tempcx & 0xFF00) >> 8;
3716	temp <<= 5;
3717	xgifb_reg_set(pVBInfo->Part2Port, 0x1A, temp);
3718	xgifb_reg_and_or(pVBInfo->Part2Port, 0x09, 0xF0, 0x00);
3719	xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xF0, 0x00);
3720	xgifb_reg_and_or(pVBInfo->Part2Port, 0x17, 0xFB, 0x00);
3721	xgifb_reg_and_or(pVBInfo->Part2Port, 0x18, 0xDF, 0x00);
3722
3723	/* Customized LCDB Does not add */
3724	if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV))
3725		LCDBDesPtr = XGI_GetLcdPtr(xgifb_lcddldes, ModeIdIndex,
3726					   pVBInfo);
3727	else
3728		LCDBDesPtr = XGI_GetLcdPtr(XGI_LCDDesDataTable, ModeIdIndex,
3729					   pVBInfo);
3730
3731	tempah = pVBInfo->LCDResInfo;
3732	tempah &= PanelResInfo;
3733
3734	if ((tempah == Panel_1024x768) || (tempah == Panel_1024x768x75)) {
3735		tempbx = 1024;
3736		tempcx = 768;
3737	} else if ((tempah == Panel_1280x1024) ||
3738		   (tempah == Panel_1280x1024x75)) {
3739		tempbx = 1280;
3740		tempcx = 1024;
3741	} else if (tempah == Panel_1400x1050) {
3742		tempbx = 1400;
3743		tempcx = 1050;
3744	} else {
3745		tempbx = 1600;
3746		tempcx = 1200;
3747	}
3748
3749	if (pVBInfo->LCDInfo & EnableScalingLCD) {
3750		tempbx = pVBInfo->HDE;
3751		tempcx = pVBInfo->VDE;
3752	}
3753
3754	pushbx = tempbx;
3755	tempax = pVBInfo->VT;
3756	pVBInfo->LCDHDES = LCDBDesPtr->LCDHDES;
3757	pVBInfo->LCDHRS = LCDBDesPtr->LCDHRS;
3758	pVBInfo->LCDVDES = LCDBDesPtr->LCDVDES;
3759	pVBInfo->LCDVRS = LCDBDesPtr->LCDVRS;
3760	tempbx = pVBInfo->LCDVDES;
3761	tempcx += tempbx;
3762
3763	if (tempcx >= tempax)
3764		tempcx -= tempax; /* lcdvdes */
3765
3766	temp = tempbx & 0x00FF; /* RVEQ1EQ=lcdvdes */
3767	xgifb_reg_set(pVBInfo->Part2Port, 0x05, temp);
3768	temp = tempcx & 0x00FF;
3769	xgifb_reg_set(pVBInfo->Part2Port, 0x06, temp);
3770	tempch = ((tempcx & 0xFF00) >> 8) & 0x07;
3771	tempbh = ((tempbx & 0xFF00) >> 8) & 0x07;
3772	tempah = tempch;
3773	tempah <<= 3;
3774	tempah |= tempbh;
3775	xgifb_reg_set(pVBInfo->Part2Port, 0x02, tempah);
3776
3777	/* getlcdsync() */
3778	XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
3779	tempcx = tempbx;
3780	tempax = pVBInfo->VT;
3781	tempbx = pVBInfo->LCDVRS;
3782
3783	tempcx += tempbx;
3784	if (tempcx >= tempax)
3785		tempcx -= tempax;
3786
3787	temp = tempbx & 0x00FF; /* RTVACTEE=lcdvrs */
3788	xgifb_reg_set(pVBInfo->Part2Port, 0x04, temp);
3789	temp = (tempbx & 0xFF00) >> 8;
3790	temp <<= 4;
3791	temp |= (tempcx & 0x000F);
3792	xgifb_reg_set(pVBInfo->Part2Port, 0x01, temp);
3793	tempcx = pushbx;
3794	tempax = pVBInfo->HT;
3795	tempbx = pVBInfo->LCDHDES;
3796	tempbx &= 0x0FFF;
3797
3798	if (XGI_IsLCDDualLink(pVBInfo)) {
3799		tempax >>= 1;
3800		tempbx >>= 1;
3801		tempcx >>= 1;
3802	}
3803
3804	if (pVBInfo->VBType & VB_SIS302LV)
3805		tempbx += 1;
3806
3807	if (pVBInfo->VBType & VB_XGI301C) /* tap4 */
3808		tempbx += 1;
3809
3810	tempcx += tempbx;
3811
3812	if (tempcx >= tempax)
3813		tempcx -= tempax;
3814
3815	temp = tempbx & 0x00FF;
3816	xgifb_reg_set(pVBInfo->Part2Port, 0x1F, temp); /* RHBLKE=lcdhdes */
3817	temp = ((tempbx & 0xFF00) >> 8) << 4;
3818	xgifb_reg_set(pVBInfo->Part2Port, 0x20, temp);
3819	temp = tempcx & 0x00FF;
3820	xgifb_reg_set(pVBInfo->Part2Port, 0x23, temp); /* RHEQPLE=lcdhdee */
3821	temp = (tempcx & 0xFF00) >> 8;
3822	xgifb_reg_set(pVBInfo->Part2Port, 0x25, temp);
3823
3824	XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
3825	tempcx = tempax;
3826	tempax = pVBInfo->HT;
3827	tempbx = pVBInfo->LCDHRS;
3828	if (XGI_IsLCDDualLink(pVBInfo)) {
3829		tempax >>= 1;
3830		tempbx >>= 1;
3831		tempcx >>= 1;
3832	}
3833
3834	if (pVBInfo->VBType & VB_SIS302LV)
3835		tempbx += 1;
3836
3837	tempcx += tempbx;
3838
3839	if (tempcx >= tempax)
3840		tempcx -= tempax;
3841
3842	temp = tempbx & 0x00FF; /* RHBURSTS=lcdhrs */
3843	xgifb_reg_set(pVBInfo->Part2Port, 0x1C, temp);
3844
3845	temp = (tempbx & 0xFF00) >> 8;
3846	temp <<= 4;
3847	xgifb_reg_and_or(pVBInfo->Part2Port, 0x1D, ~0x0F0, temp);
3848	temp = tempcx & 0x00FF; /* RHSYEXP2S=lcdhre */
3849	xgifb_reg_set(pVBInfo->Part2Port, 0x21, temp);
3850
3851	if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
3852		if (pVBInfo->VGAVDE == 525) {
3853			if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B
3854					| VB_SIS301LV | VB_SIS302LV
3855					| VB_XGI301C)) {
3856				temp = 0xC6;
3857			} else
3858				temp = 0xC4;
3859
3860			xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp);
3861			xgifb_reg_set(pVBInfo->Part2Port, 0x30, 0xB3);
3862		}
3863
3864		if (pVBInfo->VGAVDE == 420) {
3865			if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B
3866					| VB_SIS301LV | VB_SIS302LV
3867					| VB_XGI301C)) {
3868				temp = 0x4F;
3869			} else
3870				temp = 0x4E;
3871			xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp);
3872		}
3873	}
3874}
3875
3876/* --------------------------------------------------------------------- */
3877/* Function : XGI_GetTap4Ptr */
3878/* Input : */
3879/* Output : di -> Tap4 Reg. Setting Pointer */
3880/* Description : */
3881/* --------------------------------------------------------------------- */
3882static struct XGI301C_Tap4TimingStruct const
3883*XGI_GetTap4Ptr(unsigned short tempcx, struct vb_device_info *pVBInfo)
3884{
3885	unsigned short tempax, tempbx, i;
3886	struct XGI301C_Tap4TimingStruct const *Tap4TimingPtr;
3887
3888	if (tempcx == 0) {
3889		tempax = pVBInfo->VGAHDE;
3890		tempbx = pVBInfo->HDE;
3891	} else {
3892		tempax = pVBInfo->VGAVDE;
3893		tempbx = pVBInfo->VDE;
3894	}
3895
3896	if (tempax <= tempbx)
3897		return &xgifb_tap4_timing[0];
3898	Tap4TimingPtr = xgifb_ntsc_525_tap4_timing; /* NTSC */
3899
3900	if (pVBInfo->TVInfo & TVSetPAL)
3901		Tap4TimingPtr = PALTap4Timing;
3902
3903	if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
3904		if ((pVBInfo->TVInfo & TVSetYPbPr525i) ||
3905			(pVBInfo->TVInfo & TVSetYPbPr525p))
3906			Tap4TimingPtr = xgifb_ntsc_525_tap4_timing;
3907		if (pVBInfo->TVInfo & TVSetYPbPr750p)
3908			Tap4TimingPtr = YPbPr750pTap4Timing;
3909	}
3910
3911	if (pVBInfo->VBInfo & SetCRT2ToHiVision)
3912		Tap4TimingPtr = xgifb_tap4_timing;
3913
3914	i = 0;
3915	while (Tap4TimingPtr[i].DE != 0xFFFF) {
3916		if (Tap4TimingPtr[i].DE == tempax)
3917			break;
3918		i++;
3919	}
3920	return &Tap4TimingPtr[i];
3921}
3922
3923static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
3924{
3925	unsigned short i, j;
3926	struct XGI301C_Tap4TimingStruct const *Tap4TimingPtr;
3927
3928	if (!(pVBInfo->VBType & VB_XGI301C))
3929		return;
3930
3931	Tap4TimingPtr = XGI_GetTap4Ptr(0, pVBInfo); /* Set Horizontal Scaling */
3932	for (i = 0x80, j = 0; i <= 0xBF; i++, j++)
3933		xgifb_reg_set(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]);
3934
3935	if ((pVBInfo->VBInfo & SetCRT2ToTV) &&
3936	    (!(pVBInfo->VBInfo & SetCRT2ToHiVision))) {
3937		/* Set Vertical Scaling */
3938		Tap4TimingPtr = XGI_GetTap4Ptr(1, pVBInfo);
3939		for (i = 0xC0, j = 0; i < 0xFF; i++, j++)
3940			xgifb_reg_set(pVBInfo->Part2Port,
3941				      i,
3942				      Tap4TimingPtr->Reg[j]);
3943	}
3944
3945	if ((pVBInfo->VBInfo & SetCRT2ToTV) &&
3946	    (!(pVBInfo->VBInfo & SetCRT2ToHiVision)))
3947		/* Enable V.Scaling */
3948		xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x04);
3949	else
3950		/* Enable H.Scaling */
3951		xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x10);
3952}
3953
3954static void XGI_SetGroup3(unsigned short ModeIdIndex,
3955			  struct vb_device_info *pVBInfo)
3956{
3957	unsigned short i;
3958	unsigned char const *tempdi;
3959	unsigned short modeflag;
3960
3961	/* si+Ext_ResInfo */
3962	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3963
3964	xgifb_reg_set(pVBInfo->Part3Port, 0x00, 0x00);
3965	if (pVBInfo->TVInfo & TVSetPAL) {
3966		xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA);
3967		xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8);
3968	} else {
3969		xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xF5);
3970		xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xB7);
3971	}
3972
3973	if (!(pVBInfo->VBInfo & SetCRT2ToTV))
3974		return;
3975
3976	if (pVBInfo->TVInfo & TVSetPALM) {
3977		xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA);
3978		xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8);
3979		xgifb_reg_set(pVBInfo->Part3Port, 0x3D, 0xA8);
3980	}
3981
3982	if ((pVBInfo->VBInfo & SetCRT2ToHiVision) || (pVBInfo->VBInfo
3983			& SetCRT2ToYPbPr525750)) {
3984		if (pVBInfo->TVInfo & TVSetYPbPr525i)
3985			return;
3986
3987		tempdi = XGI330_HiTVGroup3Data;
3988		if (pVBInfo->SetFlag & TVSimuMode) {
3989			tempdi = XGI330_HiTVGroup3Simu;
3990			if (!(modeflag & Charx8Dot))
3991				tempdi = XGI330_HiTVGroup3Text;
3992		}
3993
3994		if (pVBInfo->TVInfo & TVSetYPbPr525p)
3995			tempdi = XGI330_Ren525pGroup3;
3996
3997		if (pVBInfo->TVInfo & TVSetYPbPr750p)
3998			tempdi = XGI330_Ren750pGroup3;
3999
4000		for (i = 0; i <= 0x3E; i++)
4001			xgifb_reg_set(pVBInfo->Part3Port, i, tempdi[i]);
4002
4003		if (pVBInfo->VBType & VB_XGI301C) { /* Marcovision */
4004			if (pVBInfo->TVInfo & TVSetYPbPr525p)
4005				xgifb_reg_set(pVBInfo->Part3Port, 0x28, 0x3f);
4006		}
4007	}
4008}
4009
4010static void XGI_SetGroup4(unsigned short ModeIdIndex,
4011		unsigned short RefreshRateTableIndex,
4012		struct vb_device_info *pVBInfo)
4013{
4014	unsigned short tempax, tempcx, tempbx, modeflag, temp, temp2;
4015
4016	unsigned long tempebx, tempeax, templong;
4017
4018	/* si+Ext_ResInfo */
4019	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
4020	temp = pVBInfo->RVBHCFACT;
4021	xgifb_reg_set(pVBInfo->Part4Port, 0x13, temp);
4022
4023	tempbx = pVBInfo->RVBHCMAX;
4024	temp = tempbx & 0x00FF;
4025	xgifb_reg_set(pVBInfo->Part4Port, 0x14, temp);
4026	temp2 = ((tempbx & 0xFF00) >> 8) << 7;
4027	tempcx = pVBInfo->VGAHT - 1;
4028	temp = tempcx & 0x00FF;
4029	xgifb_reg_set(pVBInfo->Part4Port, 0x16, temp);
4030
4031	temp = ((tempcx & 0xFF00) >> 8) << 3;
4032	temp2 |= temp;
4033
4034	tempcx = pVBInfo->VGAVT - 1;
4035	if (!(pVBInfo->VBInfo & SetCRT2ToTV))
4036		tempcx -= 5;
4037
4038	temp = tempcx & 0x00FF;
4039	xgifb_reg_set(pVBInfo->Part4Port, 0x17, temp);
4040	temp = temp2 | ((tempcx & 0xFF00) >> 8);
4041	xgifb_reg_set(pVBInfo->Part4Port, 0x15, temp);
4042	xgifb_reg_or(pVBInfo->Part4Port, 0x0D, 0x08);
4043	tempcx = pVBInfo->VBInfo;
4044	tempbx = pVBInfo->VGAHDE;
4045
4046	if (modeflag & HalfDCLK)
4047		tempbx >>= 1;
4048
4049	if (XGI_IsLCDDualLink(pVBInfo))
4050		tempbx >>= 1;
4051
4052	if (tempcx & SetCRT2ToHiVision) {
4053		temp = 0;
4054		if (tempbx <= 1024)
4055			temp = 0xA0;
4056		if (tempbx == 1280)
4057			temp = 0xC0;
4058	} else if (tempcx & SetCRT2ToTV) {
4059		temp = 0xA0;
4060		if (tempbx <= 800)
4061			temp = 0x80;
4062	} else {
4063		temp = 0x80;
4064		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
4065			temp = 0;
4066			if (tempbx > 800)
4067				temp = 0x60;
4068		}
4069	}
4070
4071	if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p)) {
4072		temp = 0x00;
4073		if (pVBInfo->VGAHDE == 1280)
4074			temp = 0x40;
4075		if (pVBInfo->VGAHDE == 1024)
4076			temp = 0x20;
4077	}
4078	xgifb_reg_and_or(pVBInfo->Part4Port, 0x0E, ~0xEF, temp);
4079
4080	tempebx = pVBInfo->VDE;
4081
4082	tempcx = pVBInfo->RVBHRS;
4083	temp = tempcx & 0x00FF;
4084	xgifb_reg_set(pVBInfo->Part4Port, 0x18, temp);
4085
4086	tempeax = pVBInfo->VGAVDE;
4087	tempcx |= 0x04000;
4088
4089	if (tempeax <= tempebx) {
4090		tempcx = (tempcx & (~0x4000));
4091		tempeax = pVBInfo->VGAVDE;
4092	} else {
4093		tempeax -= tempebx;
4094	}
4095
4096	templong = (tempeax * 256 * 1024) % tempebx;
4097	tempeax = (tempeax * 256 * 1024) / tempebx;
4098	tempebx = tempeax;
4099
4100	if (templong != 0)
4101		tempebx++;
4102
4103	temp = (unsigned short) (tempebx & 0x000000FF);
4104	xgifb_reg_set(pVBInfo->Part4Port, 0x1B, temp);
4105
4106	temp = (unsigned short) ((tempebx & 0x0000FF00) >> 8);
4107	xgifb_reg_set(pVBInfo->Part4Port, 0x1A, temp);
4108	tempbx = (unsigned short) (tempebx >> 16);
4109	temp = tempbx & 0x00FF;
4110	temp <<= 4;
4111	temp |= ((tempcx & 0xFF00) >> 8);
4112	xgifb_reg_set(pVBInfo->Part4Port, 0x19, temp);
4113
4114	/* 301b */
4115	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4116			| VB_SIS302LV | VB_XGI301C)) {
4117		temp = 0x0028;
4118		xgifb_reg_set(pVBInfo->Part4Port, 0x1C, temp);
4119		tempax = pVBInfo->VGAHDE;
4120		if (modeflag & HalfDCLK)
4121			tempax >>= 1;
4122
4123		if (XGI_IsLCDDualLink(pVBInfo))
4124			tempax >>= 1;
4125
4126		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
4127			if (tempax > 800)
4128				tempax -= 800;
4129		} else if (pVBInfo->VGAHDE > 800) {
4130			if (pVBInfo->VGAHDE == 1024)
4131				tempax = (tempax * 25 / 32) - 1;
4132			else
4133				tempax = (tempax * 20 / 32) - 1;
4134		}
4135		tempax -= 1;
4136
4137		temp = (tempax & 0xFF00) >> 8;
4138		temp = (temp & 0x0003) << 4;
4139		xgifb_reg_set(pVBInfo->Part4Port, 0x1E, temp);
4140		temp = (tempax & 0x00FF);
4141		xgifb_reg_set(pVBInfo->Part4Port, 0x1D, temp);
4142
4143		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVision)) {
4144			if (pVBInfo->VGAHDE > 800)
4145				xgifb_reg_or(pVBInfo->Part4Port, 0x1E, 0x08);
4146
4147		}
4148		temp = 0x0036;
4149
4150		if (pVBInfo->VBInfo & SetCRT2ToTV) {
4151			if (!(pVBInfo->TVInfo & (NTSC1024x768
4152					| TVSetYPbPr525p | TVSetYPbPr750p
4153					| TVSetHiVision))) {
4154				temp |= 0x0001;
4155				if ((pVBInfo->VBInfo & SetInSlaveMode)
4156						&& (!(pVBInfo->TVInfo
4157								& TVSimuMode)))
4158					temp &= (~0x0001);
4159			}
4160		}
4161
4162		xgifb_reg_and_or(pVBInfo->Part4Port, 0x1F, 0x00C0, temp);
4163		tempbx = pVBInfo->HT;
4164		if (XGI_IsLCDDualLink(pVBInfo))
4165			tempbx >>= 1;
4166		tempbx = (tempbx >> 1) - 2;
4167		temp = ((tempbx & 0x0700) >> 8) << 3;
4168		xgifb_reg_and_or(pVBInfo->Part4Port, 0x21, 0x00C0, temp);
4169		temp = tempbx & 0x00FF;
4170		xgifb_reg_set(pVBInfo->Part4Port, 0x22, temp);
4171	}
4172	/* end 301b */
4173
4174	XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
4175}
4176
4177static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo)
4178{
4179	xgifb_reg_and_or(pVBInfo->P3c4, 0x1E, 0xFF, 0x20);
4180}
4181
4182static void XGI_SetGroup5(struct vb_device_info *pVBInfo)
4183{
4184	if (pVBInfo->ModeType == ModeVGA) {
4185		if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag
4186				| DisableCRT2Display))) {
4187			XGINew_EnableCRT2(pVBInfo);
4188		}
4189	}
4190}
4191
4192static void XGI_DisableGatingCRT(struct vb_device_info *pVBInfo)
4193{
4194	xgifb_reg_and_or(pVBInfo->P3d4, 0x63, 0xBF, 0x00);
4195}
4196
4197static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
4198		unsigned short ModeNo, unsigned short ModeIdIndex)
4199{
4200	unsigned short xres, yres, colordepth, modeflag, resindex;
4201
4202	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
4203	xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
4204	yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
4205	/* si+St_ModeFlag */
4206	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
4207
4208	if (!(modeflag & Charx8Dot)) {
4209		xres /= 9;
4210		xres *= 8;
4211	}
4212
4213	if ((ModeNo > 0x13) && (modeflag & HalfDCLK))
4214		xres *= 2;
4215
4216	if ((ModeNo > 0x13) && (modeflag & DoubleScanMode))
4217		yres *= 2;
4218
4219	if (xres > xgifb_info->lvds_data.LVDSHDE)
4220		return 0;
4221
4222	if (yres > xgifb_info->lvds_data.LVDSVDE)
4223		return 0;
4224
4225	if (xres != xgifb_info->lvds_data.LVDSHDE ||
4226	    yres != xgifb_info->lvds_data.LVDSVDE) {
4227		colordepth = XGI_GetColorDepth(ModeIdIndex);
4228		if (colordepth > 2)
4229			return 0;
4230	}
4231	return 1;
4232}
4233
4234static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info,
4235			   int chip_id,
4236			   unsigned short ModeIdIndex,
4237			   struct vb_device_info *pVBInfo)
4238{
4239	unsigned char temp, Miscdata;
4240	unsigned short xres, yres, modeflag, resindex;
4241	unsigned short LVDSHT, LVDSHBS, LVDSHRS, LVDSHRE, LVDSHBE;
4242	unsigned short LVDSVT, LVDSVBS, LVDSVRS, LVDSVRE, LVDSVBE;
4243	unsigned short value;
4244
4245	temp = (unsigned char) ((xgifb_info->lvds_data.LVDS_Capability &
4246				(LCDPolarity << 8)) >> 8);
4247	temp &= LCDPolarity;
4248	Miscdata = inb(pVBInfo->P3cc);
4249
4250	outb((Miscdata & 0x3F) | temp, pVBInfo->P3c2);
4251
4252	temp = xgifb_info->lvds_data.LVDS_Capability & LCDPolarity;
4253	/* SR35[7] FP VSync polarity */
4254	xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x80, temp & 0x80);
4255	/* SR30[5] FP HSync polarity */
4256	xgifb_reg_and_or(pVBInfo->P3c4, 0x30, ~0x20, (temp & 0x40) >> 1);
4257
4258	if (chip_id == XG27)
4259		XGI_SetXG27FPBits(pVBInfo);
4260	else
4261		XGI_SetXG21FPBits(pVBInfo);
4262
4263	resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
4264	xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
4265	yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
4266	/* si+St_ModeFlag */
4267	modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
4268
4269	if (!(modeflag & Charx8Dot))
4270		xres = xres * 8 / 9;
4271
4272	LVDSHT = xgifb_info->lvds_data.LVDSHT;
4273
4274	LVDSHBS = xres + (xgifb_info->lvds_data.LVDSHDE - xres) / 2;
4275
4276	if (LVDSHBS > LVDSHT)
4277		LVDSHBS -= LVDSHT;
4278
4279	LVDSHRS = LVDSHBS + xgifb_info->lvds_data.LVDSHFP;
4280	if (LVDSHRS > LVDSHT)
4281		LVDSHRS -= LVDSHT;
4282
4283	LVDSHRE = LVDSHRS + xgifb_info->lvds_data.LVDSHSYNC;
4284	if (LVDSHRE > LVDSHT)
4285		LVDSHRE -= LVDSHT;
4286
4287	LVDSHBE = LVDSHBS + LVDSHT - xgifb_info->lvds_data.LVDSHDE;
4288
4289	LVDSVT = xgifb_info->lvds_data.LVDSVT;
4290
4291	LVDSVBS = yres + (xgifb_info->lvds_data.LVDSVDE - yres) / 2;
4292	if (modeflag & DoubleScanMode)
4293		LVDSVBS += yres / 2;
4294
4295	if (LVDSVBS > LVDSVT)
4296		LVDSVBS -= LVDSVT;
4297
4298	LVDSVRS = LVDSVBS + xgifb_info->lvds_data.LVDSVFP;
4299	if (LVDSVRS > LVDSVT)
4300		LVDSVRS -= LVDSVT;
4301
4302	LVDSVRE = LVDSVRS + xgifb_info->lvds_data.LVDSVSYNC;
4303	if (LVDSVRE > LVDSVT)
4304		LVDSVRE -= LVDSVT;
4305
4306	LVDSVBE = LVDSVBS + LVDSVT - xgifb_info->lvds_data.LVDSVDE;
4307
4308	temp = xgifb_reg_get(pVBInfo->P3d4, 0x11);
4309	xgifb_reg_set(pVBInfo->P3d4, 0x11, temp & 0x7f); /* Unlock CRTC */
4310
4311	if (!(modeflag & Charx8Dot))
4312		xgifb_reg_or(pVBInfo->P3c4, 0x1, 0x1);
4313
4314	/* HT SR0B[1:0] CR00 */
4315	value = (LVDSHT >> 3) - 5;
4316	xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x03, (value & 0x300) >> 8);
4317	xgifb_reg_set(pVBInfo->P3d4, 0x0, (value & 0xFF));
4318
4319	/* HBS SR0B[5:4] CR02 */
4320	value = (LVDSHBS >> 3) - 1;
4321	xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x30, (value & 0x300) >> 4);
4322	xgifb_reg_set(pVBInfo->P3d4, 0x2, (value & 0xFF));
4323
4324	/* HBE SR0C[1:0] CR05[7] CR03[4:0] */
4325	value = (LVDSHBE >> 3) - 1;
4326	xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x03, (value & 0xC0) >> 6);
4327	xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x80, (value & 0x20) << 2);
4328	xgifb_reg_and_or(pVBInfo->P3d4, 0x03, ~0x1F, value & 0x1F);
4329
4330	/* HRS SR0B[7:6] CR04 */
4331	value = (LVDSHRS >> 3) + 2;
4332	xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0xC0, (value & 0x300) >> 2);
4333	xgifb_reg_set(pVBInfo->P3d4, 0x4, (value & 0xFF));
4334
4335	/* Panel HRS SR2F[1:0] SR2E[7:0]  */
4336	value--;
4337	xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0x03, (value & 0x300) >> 8);
4338	xgifb_reg_set(pVBInfo->P3c4, 0x2E, (value & 0xFF));
4339
4340	/* HRE SR0C[2] CR05[4:0] */
4341	value = (LVDSHRE >> 3) + 2;
4342	xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x04, (value & 0x20) >> 3);
4343	xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x1F, value & 0x1F);
4344
4345	/* Panel HRE SR2F[7:2]  */
4346	value--;
4347	xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0xFC, value << 2);
4348
4349	/* VT SR0A[0] CR07[5][0] CR06 */
4350	value = LVDSVT - 2;
4351	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x01, (value & 0x400) >> 10);
4352	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x20, (value & 0x200) >> 4);
4353	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x01, (value & 0x100) >> 8);
4354	xgifb_reg_set(pVBInfo->P3d4, 0x06, (value & 0xFF));
4355
4356	/* VBS SR0A[2] CR09[5] CR07[3] CR15 */
4357	value = LVDSVBS - 1;
4358	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x04, (value & 0x400) >> 8);
4359	xgifb_reg_and_or(pVBInfo->P3d4, 0x09, ~0x20, (value & 0x200) >> 4);
4360	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x08, (value & 0x100) >> 5);
4361	xgifb_reg_set(pVBInfo->P3d4, 0x15, (value & 0xFF));
4362
4363	/* VBE SR0A[4] CR16 */
4364	value = LVDSVBE - 1;
4365	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x10, (value & 0x100) >> 4);
4366	xgifb_reg_set(pVBInfo->P3d4, 0x16, (value & 0xFF));
4367
4368	/* VRS SR0A[3] CR7[7][2] CR10 */
4369	value = LVDSVRS - 1;
4370	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x08, (value & 0x400) >> 7);
4371	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x80, (value & 0x200) >> 2);
4372	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x04, (value & 0x100) >> 6);
4373	xgifb_reg_set(pVBInfo->P3d4, 0x10, (value & 0xFF));
4374
4375	if (chip_id == XG27) {
4376		/* Panel VRS SR35[2:0] SR34[7:0] */
4377		xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07,
4378					(value & 0x700) >> 8);
4379		xgifb_reg_set(pVBInfo->P3c4, 0x34, value & 0xFF);
4380	} else {
4381		/* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */
4382		xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0x03,
4383					(value & 0x600) >> 9);
4384		xgifb_reg_set(pVBInfo->P3c4, 0x34, (value >> 1) & 0xFF);
4385		xgifb_reg_and_or(pVBInfo->P3d4, 0x33, ~0x01, value & 0x01);
4386	}
4387
4388	/* VRE SR0A[5] CR11[3:0] */
4389	value = LVDSVRE - 1;
4390	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x20, (value & 0x10) << 1);
4391	xgifb_reg_and_or(pVBInfo->P3d4, 0x11, ~0x0F, value & 0x0F);
4392
4393	/* Panel VRE SR3F[7:2] */
4394	if (chip_id == XG27)
4395		xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC,
4396					(value << 2) & 0xFC);
4397	else
4398		/* SR3F[7] has to be 0, h/w bug */
4399		xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC,
4400					(value << 2) & 0x7C);
4401
4402	for (temp = 0, value = 0; temp < 3; temp++) {
4403
4404		xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, value);
4405		xgifb_reg_set(pVBInfo->P3c4,
4406			      0x2B, xgifb_info->lvds_data.VCLKData1);
4407		xgifb_reg_set(pVBInfo->P3c4,
4408			      0x2C, xgifb_info->lvds_data.VCLKData2);
4409		value += 0x10;
4410	}
4411
4412	if (!(modeflag & Charx8Dot)) {
4413		inb(pVBInfo->P3da); /* reset 3da */
4414		outb(0x13, pVBInfo->P3c0); /* set index */
4415		/* set data, panning = 0, shift left 1 dot*/
4416		outb(0x00, pVBInfo->P3c0);
4417
4418		inb(pVBInfo->P3da); /* Enable Attribute */
4419		outb(0x20, pVBInfo->P3c0);
4420
4421		inb(pVBInfo->P3da); /* reset 3da */
4422	}
4423
4424}
4425
4426/* --------------------------------------------------------------------- */
4427/* Function : XGI_IsLCDON */
4428/* Input : */
4429/* Output : 0 : Skip PSC Control */
4430/* 1: Disable PSC */
4431/* Description : */
4432/* --------------------------------------------------------------------- */
4433static unsigned char XGI_IsLCDON(struct vb_device_info *pVBInfo)
4434{
4435	unsigned short tempax;
4436
4437	tempax = pVBInfo->VBInfo;
4438	if (tempax & SetCRT2ToDualEdge)
4439		return 0;
4440	else if (tempax & (DisableCRT2Display | SwitchCRT2 | SetSimuScanMode))
4441		return 1;
4442
4443	return 0;
4444}
4445
4446static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info,
4447		struct xgi_hw_device_info *HwDeviceExtension,
4448		struct vb_device_info *pVBInfo)
4449{
4450	unsigned short tempah = 0;
4451
4452	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4453			| VB_SIS302LV | VB_XGI301C)) {
4454		tempah = 0x3F;
4455		if (!(pVBInfo->VBInfo &
4456		    (DisableCRT2Display | SetSimuScanMode))) {
4457			if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
4458				if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
4459					tempah = 0x7F; /* Disable Channel A */
4460			}
4461		}
4462
4463		/* disable part4_1f */
4464		xgifb_reg_and(pVBInfo->Part4Port, 0x1F, tempah);
4465
4466		if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
4467			if (((pVBInfo->VBInfo &
4468			      (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) ||
4469				(XGI_IsLCDON(pVBInfo)))
4470				/* LVDS Driver power down */
4471				xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x80);
4472		}
4473
4474		if (pVBInfo->VBInfo & (DisableCRT2Display | XGI_SetCRT2ToLCDA |
4475				       SetSimuScanMode))
4476			XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
4477
4478		if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
4479			/* Power down */
4480			xgifb_reg_and(pVBInfo->Part1Port, 0x1e, 0xdf);
4481
4482		/* disable TV as primary VGA swap */
4483		xgifb_reg_and(pVBInfo->P3c4, 0x32, 0xdf);
4484
4485		if ((pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToDualEdge)))
4486			xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xdf);
4487
4488		if ((pVBInfo->VBInfo &
4489			(DisableCRT2Display | SetSimuScanMode)) ||
4490		    ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) &&
4491		    (pVBInfo->VBInfo &
4492			(SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV))))
4493			xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80);
4494
4495		if ((pVBInfo->VBInfo &
4496			(DisableCRT2Display | SetSimuScanMode)) ||
4497		    (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) ||
4498		    (pVBInfo->VBInfo &
4499			(SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV))) {
4500			/* save Part1 index 0 */
4501			tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x00);
4502			/* BTDAC = 1, avoid VB reset */
4503			xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x10);
4504			/* disable CRT2 */
4505			xgifb_reg_and(pVBInfo->Part1Port, 0x1E, 0xDF);
4506			/* restore Part1 index 0 */
4507			xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
4508		}
4509	} else { /* {301} */
4510		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
4511			xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80);
4512			/* Disable CRT2 */
4513			xgifb_reg_and(pVBInfo->Part1Port, 0x1E, 0xDF);
4514			/* Disable TV asPrimary VGA swap */
4515			xgifb_reg_and(pVBInfo->P3c4, 0x32, 0xDF);
4516		}
4517
4518		if (pVBInfo->VBInfo & (DisableCRT2Display | XGI_SetCRT2ToLCDA
4519				| SetSimuScanMode))
4520			XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
4521	}
4522}
4523
4524/* --------------------------------------------------------------------- */
4525/* Function : XGI_GetTVPtrIndex */
4526/* Input : */
4527/* Output : */
4528/* Description : bx 0 : ExtNTSC */
4529/* 1 : StNTSC */
4530/* 2 : ExtPAL */
4531/* 3 : StPAL */
4532/* 4 : ExtHiTV */
4533/* 5 : StHiTV */
4534/* 6 : Ext525i */
4535/* 7 : St525i */
4536/* 8 : Ext525p */
4537/* 9 : St525p */
4538/* A : Ext750p */
4539/* B : St750p */
4540/* --------------------------------------------------------------------- */
4541static unsigned short XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo)
4542{
4543	unsigned short tempbx = 0;
4544
4545	if (pVBInfo->TVInfo & TVSetPAL)
4546		tempbx = 2;
4547	if (pVBInfo->TVInfo & TVSetHiVision)
4548		tempbx = 4;
4549	if (pVBInfo->TVInfo & TVSetYPbPr525i)
4550		tempbx = 6;
4551	if (pVBInfo->TVInfo & TVSetYPbPr525p)
4552		tempbx = 8;
4553	if (pVBInfo->TVInfo & TVSetYPbPr750p)
4554		tempbx = 10;
4555	if (pVBInfo->TVInfo & TVSimuMode)
4556		tempbx++;
4557
4558	return tempbx;
4559}
4560
4561/* --------------------------------------------------------------------- */
4562/* Function : XGI_GetTVPtrIndex2 */
4563/* Input : */
4564/* Output : bx 0 : NTSC */
4565/* 1 : PAL */
4566/* 2 : PALM */
4567/* 3 : PALN */
4568/* 4 : NTSC1024x768 */
4569/* 5 : PAL-M 1024x768 */
4570/* 6-7: reserved */
4571/* cl 0 : YFilter1 */
4572/* 1 : YFilter2 */
4573/* ch 0 : 301A */
4574/* 1 : 301B/302B/301LV/302LV */
4575/* Description : */
4576/* --------------------------------------------------------------------- */
4577static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl,
4578		unsigned char *tempch, struct vb_device_info *pVBInfo)
4579{
4580	*tempbx = 0;
4581	*tempcl = 0;
4582	*tempch = 0;
4583
4584	if (pVBInfo->TVInfo & TVSetPAL)
4585		*tempbx = 1;
4586
4587	if (pVBInfo->TVInfo & TVSetPALM)
4588		*tempbx = 2;
4589
4590	if (pVBInfo->TVInfo & TVSetPALN)
4591		*tempbx = 3;
4592
4593	if (pVBInfo->TVInfo & NTSC1024x768) {
4594		*tempbx = 4;
4595		if (pVBInfo->TVInfo & TVSetPALM)
4596			*tempbx = 5;
4597	}
4598
4599	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4600			| VB_SIS302LV | VB_XGI301C)) {
4601		if ((!(pVBInfo->VBInfo & SetInSlaveMode)) || (pVBInfo->TVInfo
4602				& TVSimuMode)) {
4603			*tempbx += 8;
4604			*tempcl += 1;
4605		}
4606	}
4607
4608	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4609			| VB_SIS302LV | VB_XGI301C))
4610		(*tempch)++;
4611}
4612
4613static void XGI_SetDelayComp(struct vb_device_info *pVBInfo)
4614{
4615	unsigned char tempah, tempbl, tempbh;
4616
4617	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4618			| VB_SIS302LV | VB_XGI301C)) {
4619		if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA
4620				| SetCRT2ToTV | SetCRT2ToRAMDAC)) {
4621			tempbh = 0;
4622			tempbl = XGI301TVDelay;
4623
4624			if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
4625				tempbl >>= 4;
4626			if (pVBInfo->VBInfo &
4627			    (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
4628				tempbh = XGI301LCDDelay;
4629
4630				if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA))
4631					tempbl = tempbh;
4632			}
4633
4634			tempbl &= 0x0F;
4635			tempbh &= 0xF0;
4636			tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2D);
4637
4638			if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD
4639					| SetCRT2ToTV)) { /* Channel B */
4640				tempah &= 0xF0;
4641				tempah |= tempbl;
4642			}
4643
4644			if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
4645				/* Channel A */
4646				tempah &= 0x0F;
4647				tempah |= tempbh;
4648			}
4649			xgifb_reg_set(pVBInfo->Part1Port, 0x2D, tempah);
4650		}
4651	}
4652}
4653
4654static void XGI_SetLCDCap_A(unsigned short tempcx,
4655			    struct vb_device_info *pVBInfo)
4656{
4657	unsigned short temp;
4658
4659	temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
4660
4661	if (temp & LCDRGB18Bit) {
4662		xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F,
4663				/* Enable Dither */
4664				(unsigned short) (0x20 | (tempcx & 0x00C0)));
4665		xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x80);
4666	} else {
4667		xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F,
4668				(unsigned short) (0x30 | (tempcx & 0x00C0)));
4669		xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x00);
4670	}
4671}
4672
4673/* --------------------------------------------------------------------- */
4674/* Function : XGI_SetLCDCap_B */
4675/* Input : cx -> LCD Capability */
4676/* Output : */
4677/* Description : */
4678/* --------------------------------------------------------------------- */
4679static void XGI_SetLCDCap_B(unsigned short tempcx,
4680			    struct vb_device_info *pVBInfo)
4681{
4682	if (tempcx & EnableLCD24bpp) /* 24bits */
4683		xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
4684				(unsigned short) (((tempcx & 0x00ff) >> 6)
4685						| 0x0c));
4686	else
4687		xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
4688				(unsigned short) (((tempcx & 0x00ff) >> 6)
4689						| 0x18)); /* Enable Dither */
4690}
4691
4692static void XGI_LongWait(struct vb_device_info *pVBInfo)
4693{
4694	unsigned short i;
4695
4696	i = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
4697
4698	if (!(i & 0xC0)) {
4699		for (i = 0; i < 0xFFFF; i++) {
4700			if (!(inb(pVBInfo->P3da) & 0x08))
4701				break;
4702		}
4703
4704		for (i = 0; i < 0xFFFF; i++) {
4705			if ((inb(pVBInfo->P3da) & 0x08))
4706				break;
4707		}
4708	}
4709}
4710
4711static void SetSpectrum(struct vb_device_info *pVBInfo)
4712{
4713	unsigned short index;
4714
4715	index = XGI_GetLCDCapPtr(pVBInfo);
4716
4717	/* disable down spectrum D[4] */
4718	xgifb_reg_and(pVBInfo->Part4Port, 0x30, 0x8F);
4719	XGI_LongWait(pVBInfo);
4720	xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x20); /* reset spectrum */
4721	XGI_LongWait(pVBInfo);
4722
4723	xgifb_reg_set(pVBInfo->Part4Port, 0x31,
4724			pVBInfo->LCDCapList[index].Spectrum_31);
4725	xgifb_reg_set(pVBInfo->Part4Port, 0x32,
4726			pVBInfo->LCDCapList[index].Spectrum_32);
4727	xgifb_reg_set(pVBInfo->Part4Port, 0x33,
4728			pVBInfo->LCDCapList[index].Spectrum_33);
4729	xgifb_reg_set(pVBInfo->Part4Port, 0x34,
4730			pVBInfo->LCDCapList[index].Spectrum_34);
4731	XGI_LongWait(pVBInfo);
4732	xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x40); /* enable spectrum */
4733}
4734
4735static void XGI_SetLCDCap(struct vb_device_info *pVBInfo)
4736{
4737	unsigned short tempcx;
4738
4739	tempcx = pVBInfo->LCDCapList[XGI_GetLCDCapPtr(pVBInfo)].LCD_Capability;
4740
4741	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV |
4742		VB_SIS302LV | VB_XGI301C)) {
4743		if (pVBInfo->VBType &
4744		    (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
4745			/* Set 301LV Capability */
4746			xgifb_reg_set(pVBInfo->Part4Port, 0x24,
4747					(unsigned char) (tempcx & 0x1F));
4748		}
4749		/* VB Driving */
4750		xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D,
4751				~((EnableVBCLKDRVLOW | EnablePLLSPLOW) >> 8),
4752				(unsigned short) ((tempcx & (EnableVBCLKDRVLOW
4753						| EnablePLLSPLOW)) >> 8));
4754
4755		if (pVBInfo->VBInfo & SetCRT2ToLCD)
4756			XGI_SetLCDCap_B(tempcx, pVBInfo);
4757		else if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
4758			XGI_SetLCDCap_A(tempcx, pVBInfo);
4759
4760		if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
4761			if (tempcx & EnableSpectrum)
4762				SetSpectrum(pVBInfo);
4763		}
4764	} else {
4765		/* LVDS,CH7017 */
4766		XGI_SetLCDCap_A(tempcx, pVBInfo);
4767	}
4768}
4769
4770/* --------------------------------------------------------------------- */
4771/* Function : XGI_SetAntiFlicker */
4772/* Input : */
4773/* Output : */
4774/* Description : Set TV Customized Param. */
4775/* --------------------------------------------------------------------- */
4776static void XGI_SetAntiFlicker(struct vb_device_info *pVBInfo)
4777{
4778	unsigned short tempbx;
4779
4780	unsigned char tempah;
4781
4782	if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))
4783		return;
4784
4785	tempbx = XGI_GetTVPtrIndex(pVBInfo);
4786	tempbx &= 0xFE;
4787	tempah = TVAntiFlickList[tempbx];
4788	tempah <<= 4;
4789
4790	xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0x8F, tempah);
4791}
4792
4793static void XGI_SetEdgeEnhance(struct vb_device_info *pVBInfo)
4794{
4795	unsigned short tempbx;
4796
4797	unsigned char tempah;
4798
4799	tempbx = XGI_GetTVPtrIndex(pVBInfo);
4800	tempbx &= 0xFE;
4801	tempah = TVEdgeList[tempbx];
4802	tempah <<= 5;
4803
4804	xgifb_reg_and_or(pVBInfo->Part2Port, 0x3A, 0x1F, tempah);
4805}
4806
4807static void XGI_SetPhaseIncr(struct vb_device_info *pVBInfo)
4808{
4809	unsigned short tempbx;
4810
4811	unsigned char tempcl, tempch;
4812
4813	unsigned long tempData;
4814
4815	XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
4816	tempData = TVPhaseList[tempbx];
4817
4818	xgifb_reg_set(pVBInfo->Part2Port, 0x31, (unsigned short) (tempData
4819			& 0x000000FF));
4820	xgifb_reg_set(pVBInfo->Part2Port, 0x32, (unsigned short) ((tempData
4821			& 0x0000FF00) >> 8));
4822	xgifb_reg_set(pVBInfo->Part2Port, 0x33, (unsigned short) ((tempData
4823			& 0x00FF0000) >> 16));
4824	xgifb_reg_set(pVBInfo->Part2Port, 0x34, (unsigned short) ((tempData
4825			& 0xFF000000) >> 24));
4826}
4827
4828static void XGI_SetYFilter(unsigned short ModeIdIndex,
4829			   struct vb_device_info *pVBInfo)
4830{
4831	unsigned short tempbx, index;
4832	unsigned char const *filterPtr;
4833	unsigned char tempcl, tempch, tempal;
4834
4835	XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
4836
4837	switch (tempbx) {
4838	case 0x00:
4839	case 0x04:
4840		filterPtr = NTSCYFilter1;
4841		break;
4842
4843	case 0x01:
4844		filterPtr = PALYFilter1;
4845		break;
4846
4847	case 0x02:
4848	case 0x05:
4849	case 0x0D:
4850	case 0x03:
4851		filterPtr = xgifb_palmn_yfilter1;
4852		break;
4853
4854	case 0x08:
4855	case 0x0C:
4856	case 0x0A:
4857	case 0x0B:
4858	case 0x09:
4859		filterPtr = xgifb_yfilter2;
4860		break;
4861
4862	default:
4863		return;
4864	}
4865
4866	tempal = XGI330_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
4867	if (tempcl == 0)
4868		index = tempal * 4;
4869	else
4870		index = tempal * 7;
4871
4872	if ((tempcl == 0) && (tempch == 1)) {
4873		xgifb_reg_set(pVBInfo->Part2Port, 0x35, 0);
4874		xgifb_reg_set(pVBInfo->Part2Port, 0x36, 0);
4875		xgifb_reg_set(pVBInfo->Part2Port, 0x37, 0);
4876		xgifb_reg_set(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
4877	} else {
4878		xgifb_reg_set(pVBInfo->Part2Port, 0x35, filterPtr[index++]);
4879		xgifb_reg_set(pVBInfo->Part2Port, 0x36, filterPtr[index++]);
4880		xgifb_reg_set(pVBInfo->Part2Port, 0x37, filterPtr[index++]);
4881		xgifb_reg_set(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
4882	}
4883
4884	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4885			| VB_SIS302LV | VB_XGI301C)) {
4886		xgifb_reg_set(pVBInfo->Part2Port, 0x48, filterPtr[index++]);
4887		xgifb_reg_set(pVBInfo->Part2Port, 0x49, filterPtr[index++]);
4888		xgifb_reg_set(pVBInfo->Part2Port, 0x4A, filterPtr[index++]);
4889	}
4890}
4891
4892/* --------------------------------------------------------------------- */
4893/* Function : XGI_OEM310Setting */
4894/* Input : */
4895/* Output : */
4896/* Description : Customized Param. for 301 */
4897/* --------------------------------------------------------------------- */
4898static void XGI_OEM310Setting(unsigned short ModeIdIndex,
4899			      struct vb_device_info *pVBInfo)
4900{
4901	XGI_SetDelayComp(pVBInfo);
4902
4903	if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))
4904		XGI_SetLCDCap(pVBInfo);
4905
4906	if (pVBInfo->VBInfo & SetCRT2ToTV) {
4907		XGI_SetPhaseIncr(pVBInfo);
4908		XGI_SetYFilter(ModeIdIndex, pVBInfo);
4909		XGI_SetAntiFlicker(pVBInfo);
4910
4911		if (pVBInfo->VBType & VB_SIS301)
4912			XGI_SetEdgeEnhance(pVBInfo);
4913	}
4914}
4915
4916/* --------------------------------------------------------------------- */
4917/* Function : XGI_SetCRT2ModeRegs */
4918/* Input : */
4919/* Output : */
4920/* Description : Origin code for crt2group */
4921/* --------------------------------------------------------------------- */
4922static void XGI_SetCRT2ModeRegs(struct vb_device_info *pVBInfo)
4923{
4924	unsigned short tempbl;
4925	short tempcl;
4926
4927	unsigned char tempah;
4928
4929	tempah = 0;
4930	if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
4931		tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x00);
4932		tempah &= ~0x10; /* BTRAMDAC */
4933		tempah |= 0x40; /* BTRAM */
4934
4935		if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV
4936				| SetCRT2ToLCD)) {
4937			tempah = 0x40; /* BTDRAM */
4938			tempcl = pVBInfo->ModeType;
4939			tempcl -= ModeVGA;
4940			if (tempcl >= 0) {
4941				/* BT Color */
4942				tempah = (0x008 >> tempcl);
4943				if (tempah == 0)
4944					tempah = 1;
4945				tempah |= 0x040;
4946			}
4947			if (pVBInfo->VBInfo & SetInSlaveMode)
4948				tempah ^= 0x50; /* BTDAC */
4949		}
4950	}
4951
4952	xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
4953	tempah = 0x08;
4954	tempbl = 0xf0;
4955
4956	if (pVBInfo->VBInfo & DisableCRT2Display)
4957		goto reg_and_or;
4958
4959	tempah = 0x00;
4960	tempbl = 0xff;
4961
4962	if (!(pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV |
4963				 SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
4964		goto reg_and_or;
4965
4966	if ((pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) &&
4967	    (!(pVBInfo->VBInfo & SetSimuScanMode))) {
4968		tempbl &= 0xf7;
4969		tempah |= 0x01;
4970		goto reg_and_or;
4971	}
4972
4973	if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
4974		tempbl &= 0xf7;
4975		tempah |= 0x01;
4976	}
4977
4978	if (!(pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD)))
4979		goto reg_and_or;
4980
4981	tempbl &= 0xf8;
4982	tempah = 0x01;
4983
4984	if (!(pVBInfo->VBInfo & SetInSlaveMode))
4985		tempah |= 0x02;
4986
4987	if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
4988		tempah = tempah ^ 0x05;
4989		if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
4990			tempah = tempah ^ 0x01;
4991	}
4992
4993	if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge))
4994		tempah |= 0x08;
4995
4996reg_and_or:
4997	xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, tempbl, tempah);
4998
4999	if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD
5000			| XGI_SetCRT2ToLCDA)) {
5001		tempah &= (~0x08);
5002		if ((pVBInfo->ModeType == ModeVGA) && (!(pVBInfo->VBInfo
5003				& SetInSlaveMode))) {
5004			tempah |= 0x010;
5005		}
5006		tempah |= 0x080;
5007
5008		if (pVBInfo->VBInfo & SetCRT2ToTV) {
5009			tempah |= 0x020;
5010			if (pVBInfo->VBInfo & DriverMode)
5011				tempah = tempah ^ 0x20;
5012		}
5013
5014		xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D, ~0x0BF, tempah);
5015		tempah = 0;
5016
5017		if (pVBInfo->LCDInfo & SetLCDDualLink)
5018			tempah |= 0x40;
5019
5020		if (pVBInfo->VBInfo & SetCRT2ToTV) {
5021			if (pVBInfo->TVInfo & RPLLDIV2XO)
5022				tempah |= 0x40;
5023		}
5024
5025		if ((pVBInfo->LCDResInfo == Panel_1280x1024)
5026				|| (pVBInfo->LCDResInfo == Panel_1280x1024x75))
5027			tempah |= 0x80;
5028
5029		if (pVBInfo->LCDResInfo == Panel_1280x960)
5030			tempah |= 0x80;
5031
5032		xgifb_reg_set(pVBInfo->Part4Port, 0x0C, tempah);
5033	}
5034
5035	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
5036			| VB_SIS302LV | VB_XGI301C)) {
5037		tempah = 0;
5038		tempbl = 0xfb;
5039
5040		if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
5041			tempbl = 0xff;
5042			if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
5043				tempah |= 0x04; /* shampoo 0129 */
5044		}
5045
5046		xgifb_reg_and_or(pVBInfo->Part1Port, 0x13, tempbl, tempah);
5047		tempah = 0x00;
5048		tempbl = 0xcf;
5049		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
5050			if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
5051				tempah |= 0x30;
5052		}
5053
5054		xgifb_reg_and_or(pVBInfo->Part1Port, 0x2c, tempbl, tempah);
5055		tempah = 0;
5056		tempbl = 0x3f;
5057
5058		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
5059			if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
5060				tempah |= 0xc0;
5061		}
5062		xgifb_reg_and_or(pVBInfo->Part4Port, 0x21, tempbl, tempah);
5063	}
5064
5065	tempah = 0;
5066	tempbl = 0x7f;
5067	if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) {
5068		tempbl = 0xff;
5069		if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge))
5070			tempah |= 0x80;
5071	}
5072
5073	xgifb_reg_and_or(pVBInfo->Part4Port, 0x23, tempbl, tempah);
5074
5075	if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
5076		if (pVBInfo->LCDInfo & SetLCDDualLink) {
5077			xgifb_reg_or(pVBInfo->Part4Port, 0x27, 0x20);
5078			xgifb_reg_or(pVBInfo->Part4Port, 0x34, 0x10);
5079		}
5080	}
5081}
5082
5083
5084void XGI_UnLockCRT2(struct vb_device_info *pVBInfo)
5085{
5086	xgifb_reg_and_or(pVBInfo->Part1Port, 0x2f, 0xFF, 0x01);
5087}
5088
5089void XGI_LockCRT2(struct vb_device_info *pVBInfo)
5090{
5091	xgifb_reg_and_or(pVBInfo->Part1Port, 0x2F, 0xFE, 0x00);
5092}
5093
5094unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
5095		unsigned short ModeNo, unsigned short ModeIdIndex,
5096		struct vb_device_info *pVBInfo)
5097{
5098	const u8 LCDARefreshIndex[] = {
5099		0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00 };
5100
5101	unsigned short RefreshRateTableIndex, i, index, temp;
5102
5103	index = xgifb_reg_get(pVBInfo->P3d4, 0x33);
5104	index >>= pVBInfo->SelectCRT2Rate;
5105	index &= 0x0F;
5106
5107	if (pVBInfo->LCDInfo & LCDNonExpanding)
5108		index = 0;
5109
5110	if (index > 0)
5111		index--;
5112
5113	if (pVBInfo->SetFlag & ProgrammingCRT2) {
5114		if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
5115			temp = LCDARefreshIndex[pVBInfo->LCDResInfo & 0x07];
5116
5117			if (index > temp)
5118				index = temp;
5119		}
5120	}
5121
5122	RefreshRateTableIndex = XGI330_EModeIDTable[ModeIdIndex].REFindex;
5123	ModeNo = XGI330_RefIndex[RefreshRateTableIndex].ModeID;
5124	if (pXGIHWDE->jChipType >= XG20) { /* for XG20, XG21, XG27 */
5125		if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 800) &&
5126		    (XGI330_RefIndex[RefreshRateTableIndex].YRes == 600)) {
5127			index++;
5128		}
5129		/* do the similar adjustment like XGISearchCRT1Rate() */
5130		if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 1024) &&
5131		    (XGI330_RefIndex[RefreshRateTableIndex].YRes == 768)) {
5132			index++;
5133		}
5134		if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
5135		    (XGI330_RefIndex[RefreshRateTableIndex].YRes == 1024)) {
5136			index++;
5137		}
5138	}
5139
5140	i = 0;
5141	do {
5142		if (XGI330_RefIndex[RefreshRateTableIndex + i].
5143			ModeID != ModeNo)
5144			break;
5145		temp = XGI330_RefIndex[RefreshRateTableIndex + i].Ext_InfoFlag;
5146		temp &= ModeTypeMask;
5147		if (temp < pVBInfo->ModeType)
5148			break;
5149		i++;
5150		index--;
5151
5152	} while (index != 0xFFFF);
5153	if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
5154		if (pVBInfo->VBInfo & SetInSlaveMode) {
5155			temp = XGI330_RefIndex[RefreshRateTableIndex + i - 1].
5156				Ext_InfoFlag;
5157			if (temp & InterlaceMode)
5158				i++;
5159		}
5160	}
5161	i--;
5162	if ((pVBInfo->SetFlag & ProgrammingCRT2)) {
5163		temp = XGI_AjustCRT2Rate(ModeIdIndex, RefreshRateTableIndex,
5164					 &i, pVBInfo);
5165	}
5166	return RefreshRateTableIndex + i;
5167}
5168
5169static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,
5170		struct xgi_hw_device_info *HwDeviceExtension,
5171		struct vb_device_info *pVBInfo)
5172{
5173	unsigned short RefreshRateTableIndex;
5174
5175	pVBInfo->SetFlag |= ProgrammingCRT2;
5176	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
5177			ModeIdIndex, pVBInfo);
5178	XGI_GetLVDSResInfo(ModeIdIndex, pVBInfo);
5179	XGI_GetLVDSData(ModeIdIndex, pVBInfo);
5180	XGI_ModCRT1Regs(ModeIdIndex, HwDeviceExtension, pVBInfo);
5181	XGI_SetLVDSRegs(ModeIdIndex, pVBInfo);
5182	XGI_SetCRT2ECLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5183}
5184
5185static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
5186		struct xgi_hw_device_info *HwDeviceExtension,
5187		struct vb_device_info *pVBInfo)
5188{
5189	unsigned short ModeIdIndex, RefreshRateTableIndex;
5190
5191	pVBInfo->SetFlag |= ProgrammingCRT2;
5192	XGI_SearchModeID(ModeNo, &ModeIdIndex);
5193	pVBInfo->SelectCRT2Rate = 4;
5194	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
5195			ModeIdIndex, pVBInfo);
5196	XGI_SaveCRT2Info(ModeNo, pVBInfo);
5197	XGI_GetCRT2ResInfo(ModeIdIndex, pVBInfo);
5198	XGI_GetCRT2Data(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5199	XGI_PreSetGroup1(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5200	XGI_SetGroup1(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5201	XGI_SetLockRegs(ModeNo, ModeIdIndex, pVBInfo);
5202	XGI_SetGroup2(ModeNo, ModeIdIndex, pVBInfo);
5203	XGI_SetLCDRegs(ModeIdIndex, pVBInfo);
5204	XGI_SetTap4Regs(pVBInfo);
5205	XGI_SetGroup3(ModeIdIndex, pVBInfo);
5206	XGI_SetGroup4(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5207	XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5208	XGI_SetGroup5(pVBInfo);
5209	XGI_AutoThreshold(pVBInfo);
5210	return 1;
5211}
5212
5213void XGI_SenseCRT1(struct vb_device_info *pVBInfo)
5214{
5215	unsigned char CRTCData[17] = { 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81,
5216			0x0B, 0x3E, 0xE9, 0x0B, 0xDF, 0xE7, 0x04, 0x00, 0x00,
5217			0x05, 0x00 };
5218
5219	unsigned char SR01 = 0, SR1F = 0, SR07 = 0, SR06 = 0;
5220
5221	unsigned char CR17, CR63, SR31;
5222	unsigned short temp;
5223
5224	int i;
5225
5226	xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
5227
5228	/* to fix XG42 single LCD sense to CRT+LCD */
5229	xgifb_reg_set(pVBInfo->P3d4, 0x57, 0x4A);
5230	xgifb_reg_set(pVBInfo->P3d4, 0x53, (xgifb_reg_get(
5231			pVBInfo->P3d4, 0x53) | 0x02));
5232
5233	SR31 = xgifb_reg_get(pVBInfo->P3c4, 0x31);
5234	CR63 = xgifb_reg_get(pVBInfo->P3d4, 0x63);
5235	SR01 = xgifb_reg_get(pVBInfo->P3c4, 0x01);
5236
5237	xgifb_reg_set(pVBInfo->P3c4, 0x01, (unsigned char) (SR01 & 0xDF));
5238	xgifb_reg_set(pVBInfo->P3d4, 0x63, (unsigned char) (CR63 & 0xBF));
5239
5240	CR17 = xgifb_reg_get(pVBInfo->P3d4, 0x17);
5241	xgifb_reg_set(pVBInfo->P3d4, 0x17, (unsigned char) (CR17 | 0x80));
5242
5243	SR1F = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
5244	xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char) (SR1F | 0x04));
5245
5246	SR07 = xgifb_reg_get(pVBInfo->P3c4, 0x07);
5247	xgifb_reg_set(pVBInfo->P3c4, 0x07, (unsigned char) (SR07 & 0xFB));
5248	SR06 = xgifb_reg_get(pVBInfo->P3c4, 0x06);
5249	xgifb_reg_set(pVBInfo->P3c4, 0x06, (unsigned char) (SR06 & 0xC3));
5250
5251	xgifb_reg_set(pVBInfo->P3d4, 0x11, 0x00);
5252
5253	for (i = 0; i < 8; i++)
5254		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) i, CRTCData[i]);
5255
5256	for (i = 8; i < 11; i++)
5257		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 8),
5258				CRTCData[i]);
5259
5260	for (i = 11; i < 13; i++)
5261		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 4),
5262				CRTCData[i]);
5263
5264	for (i = 13; i < 16; i++)
5265		xgifb_reg_set(pVBInfo->P3c4, (unsigned short) (i - 3),
5266				CRTCData[i]);
5267
5268	xgifb_reg_set(pVBInfo->P3c4, 0x0E, (unsigned char) (CRTCData[16]
5269			& 0xE0));
5270
5271	xgifb_reg_set(pVBInfo->P3c4, 0x31, 0x00);
5272	xgifb_reg_set(pVBInfo->P3c4, 0x2B, 0x1B);
5273	xgifb_reg_set(pVBInfo->P3c4, 0x2C, 0xE1);
5274
5275	outb(0x00, pVBInfo->P3c8);
5276
5277	for (i = 0; i < 256 * 3; i++)
5278		outb(0x0F, (pVBInfo->P3c8 + 1)); /* DAC_TEST_PARMS */
5279
5280	mdelay(1);
5281
5282	XGI_WaitDisply(pVBInfo);
5283	temp = inb(pVBInfo->P3c2);
5284
5285	if (temp & 0x10)
5286		xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xDF, 0x20);
5287	else
5288		xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xDF, 0x00);
5289
5290	/* avoid display something, set BLACK DAC if not restore DAC */
5291	outb(0x00, pVBInfo->P3c8);
5292
5293	for (i = 0; i < 256 * 3; i++)
5294		outb(0, (pVBInfo->P3c8 + 1));
5295
5296	xgifb_reg_set(pVBInfo->P3c4, 0x01, SR01);
5297	xgifb_reg_set(pVBInfo->P3d4, 0x63, CR63);
5298	xgifb_reg_set(pVBInfo->P3c4, 0x31, SR31);
5299
5300	xgifb_reg_set(pVBInfo->P3d4, 0x53, (xgifb_reg_get(
5301			pVBInfo->P3d4, 0x53) & 0xFD));
5302	xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char) SR1F);
5303}
5304
5305static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info,
5306		struct xgi_hw_device_info *HwDeviceExtension,
5307		struct vb_device_info *pVBInfo)
5308{
5309	unsigned short tempah;
5310
5311	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
5312			| VB_SIS302LV | VB_XGI301C)) {
5313		if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
5314			/* Power on */
5315			xgifb_reg_set(pVBInfo->Part1Port, 0x1E, 0x20);
5316
5317		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV |
5318				       SetCRT2ToRAMDAC)) {
5319			tempah = xgifb_reg_get(pVBInfo->P3c4, 0x32);
5320			tempah &= 0xDF;
5321			if (pVBInfo->VBInfo & SetInSlaveMode) {
5322				if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC))
5323					tempah |= 0x20;
5324			}
5325			xgifb_reg_set(pVBInfo->P3c4, 0x32, tempah);
5326			xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x20);
5327
5328			tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2E);
5329
5330			if (!(tempah & 0x80))
5331				xgifb_reg_or(pVBInfo->Part1Port, 0x2E, 0x80);
5332			xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F);
5333		}
5334
5335		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
5336			xgifb_reg_and_or(pVBInfo->Part2Port, 0x00, ~0xE0,
5337					0x20); /* shampoo 0129 */
5338			if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
5339				if (pVBInfo->VBInfo &
5340					(SetCRT2ToLCD | XGI_SetCRT2ToLCDA))
5341					/* LVDS PLL power on */
5342					xgifb_reg_and(pVBInfo->Part4Port, 0x2A,
5343						      0x7F);
5344				/* LVDS Driver power on */
5345				xgifb_reg_and(pVBInfo->Part4Port, 0x30, 0x7F);
5346			}
5347		}
5348
5349		tempah = 0x00;
5350
5351		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
5352			tempah = 0xc0;
5353
5354			if (!(pVBInfo->VBInfo & SetSimuScanMode) &&
5355			    (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) &&
5356			    (pVBInfo->VBInfo & SetCRT2ToDualEdge)) {
5357				tempah = tempah & 0x40;
5358				if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
5359					tempah = tempah ^ 0xC0;
5360			}
5361		}
5362
5363		/* EnablePart4_1F */
5364		xgifb_reg_or(pVBInfo->Part4Port, 0x1F, tempah);
5365
5366		XGI_DisableGatingCRT(pVBInfo);
5367		XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
5368	} /* 301 */
5369	else { /* LVDS */
5370		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD
5371				| XGI_SetCRT2ToLCDA))
5372			/* enable CRT2 */
5373			xgifb_reg_or(pVBInfo->Part1Port, 0x1E, 0x20);
5374
5375		tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2E);
5376		if (!(tempah & 0x80))
5377			xgifb_reg_or(pVBInfo->Part1Port, 0x2E, 0x80);
5378
5379		xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F);
5380		XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
5381	} /* End of VB */
5382}
5383
5384static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
5385		struct xgi_hw_device_info *HwDeviceExtension,
5386		unsigned short ModeNo, unsigned short ModeIdIndex,
5387		struct vb_device_info *pVBInfo)
5388{
5389	unsigned short RefreshRateTableIndex, temp;
5390
5391	XGI_SetSeqRegs(pVBInfo);
5392	outb(XGI330_StandTable.MISC, pVBInfo->P3c2);
5393	XGI_SetCRTCRegs(pVBInfo);
5394	XGI_SetATTRegs(ModeIdIndex, pVBInfo);
5395	XGI_SetGRCRegs(pVBInfo);
5396	XGI_ClearExt1Regs(pVBInfo);
5397
5398	if (HwDeviceExtension->jChipType == XG27) {
5399		if (pVBInfo->IF_DEF_LVDS == 0)
5400			XGI_SetDefaultVCLK(pVBInfo);
5401	}
5402
5403	temp = ~ProgrammingCRT2;
5404	pVBInfo->SetFlag &= temp;
5405	pVBInfo->SelectCRT2Rate = 0;
5406
5407	if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
5408			| VB_SIS302LV | VB_XGI301C)) {
5409		if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA
5410				| SetInSlaveMode)) {
5411			pVBInfo->SetFlag |= ProgrammingCRT2;
5412		}
5413	}
5414
5415	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
5416			ModeIdIndex, pVBInfo);
5417	if (RefreshRateTableIndex != 0xFFFF) {
5418		XGI_SetSync(RefreshRateTableIndex, pVBInfo);
5419		XGI_SetCRT1CRTC(ModeIdIndex, RefreshRateTableIndex,
5420				pVBInfo, HwDeviceExtension);
5421		XGI_SetCRT1DE(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5422		XGI_SetCRT1Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
5423				HwDeviceExtension, pVBInfo);
5424		XGI_SetCRT1VCLK(ModeIdIndex, HwDeviceExtension,
5425				RefreshRateTableIndex, pVBInfo);
5426	}
5427
5428	if (HwDeviceExtension->jChipType >= XG21) {
5429		temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
5430		if (temp & 0xA0) {
5431
5432			if (HwDeviceExtension->jChipType == XG27)
5433				XGI_SetXG27CRTC(RefreshRateTableIndex, pVBInfo);
5434			else
5435				XGI_SetXG21CRTC(RefreshRateTableIndex, pVBInfo);
5436
5437			XGI_UpdateXG21CRTC(ModeNo, pVBInfo,
5438					RefreshRateTableIndex);
5439
5440			xgifb_set_lcd(HwDeviceExtension->jChipType,
5441				      pVBInfo, RefreshRateTableIndex);
5442
5443			if (pVBInfo->IF_DEF_LVDS == 1)
5444				xgifb_set_lvds(xgifb_info,
5445						HwDeviceExtension->jChipType,
5446						ModeIdIndex, pVBInfo);
5447		}
5448	}
5449
5450	pVBInfo->SetFlag &= (~ProgrammingCRT2);
5451	XGI_SetCRT1FIFO(HwDeviceExtension, pVBInfo);
5452	XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeIdIndex,
5453			    RefreshRateTableIndex, pVBInfo);
5454	XGI_LoadDAC(pVBInfo);
5455}
5456
5457unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
5458			struct xgi_hw_device_info *HwDeviceExtension,
5459			unsigned short ModeNo)
5460{
5461	unsigned short ModeIdIndex;
5462	struct vb_device_info VBINF;
5463	struct vb_device_info *pVBInfo = &VBINF;
5464
5465	pVBInfo->IF_DEF_LVDS = 0;
5466
5467	if (HwDeviceExtension->jChipType >= XG20)
5468		pVBInfo->VBType = 0; /*set VBType default 0*/
5469
5470	XGIRegInit(pVBInfo, xgifb_info->vga_base);
5471
5472	/* for x86 Linux, XG21 LVDS */
5473	if (HwDeviceExtension->jChipType == XG21) {
5474		if ((xgifb_reg_get(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0)
5475			pVBInfo->IF_DEF_LVDS = 1;
5476	}
5477	if (HwDeviceExtension->jChipType == XG27) {
5478		if ((xgifb_reg_get(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0) {
5479			if (xgifb_reg_get(pVBInfo->P3d4, 0x30) & 0x20)
5480				pVBInfo->IF_DEF_LVDS = 1;
5481		}
5482	}
5483
5484	InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
5485	if (ModeNo & 0x80)
5486		ModeNo = ModeNo & 0x7F;
5487	xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
5488
5489	if (HwDeviceExtension->jChipType < XG20)
5490		XGI_UnLockCRT2(pVBInfo);
5491
5492	XGI_SearchModeID(ModeNo, &ModeIdIndex);
5493
5494	if (HwDeviceExtension->jChipType < XG20) {
5495		XGI_GetVBInfo(ModeIdIndex, pVBInfo);
5496		XGI_GetTVInfo(ModeIdIndex, pVBInfo);
5497		XGI_GetLCDInfo(ModeIdIndex, pVBInfo);
5498		XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
5499
5500		if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA) ||
5501			(!(pVBInfo->VBInfo & SwitchCRT2))) {
5502			XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo,
5503					ModeIdIndex, pVBInfo);
5504
5505			if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
5506				XGI_SetLCDAGroup(ModeNo, ModeIdIndex,
5507						HwDeviceExtension, pVBInfo);
5508			}
5509		}
5510
5511		if (pVBInfo->VBInfo & (SetSimuScanMode | SwitchCRT2)) {
5512			switch (HwDeviceExtension->ujVBChipID) {
5513			case VB_CHIP_301: /* fall through */
5514			case VB_CHIP_302:
5515				XGI_SetCRT2Group301(ModeNo, HwDeviceExtension,
5516						pVBInfo); /*add for CRT2 */
5517				break;
5518
5519			default:
5520				break;
5521			}
5522		}
5523
5524		XGI_SetCRT2ModeRegs(pVBInfo);
5525		XGI_OEM310Setting(ModeIdIndex, pVBInfo); /*0212*/
5526		XGI_EnableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
5527	} /* !XG20 */
5528	else {
5529		if (pVBInfo->IF_DEF_LVDS == 1)
5530			if (!XGI_XG21CheckLVDSMode(xgifb_info, ModeNo,
5531						   ModeIdIndex))
5532				return 0;
5533
5534		pVBInfo->ModeType = XGI330_EModeIDTable[ModeIdIndex].
5535						Ext_ModeFlag & ModeTypeMask;
5536
5537		pVBInfo->SetFlag = 0;
5538		pVBInfo->VBInfo = DisableCRT2Display;
5539
5540		XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
5541
5542		XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo,
5543				ModeIdIndex, pVBInfo);
5544
5545		XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
5546	}
5547
5548	XGI_UpdateModeInfo(pVBInfo);
5549
5550	if (HwDeviceExtension->jChipType < XG20)
5551		XGI_LockCRT2(pVBInfo);
5552
5553	return 1;
5554}
5555