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