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