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