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