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