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