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