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