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