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