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