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