Merge branch 'stable-4.7' of git://git.infradead.org/users/pcmoore/audit
[cascardo/linux.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
1651         unsigned short index, modeflag;
1652         unsigned char tempal;
1653
1654         /* si+Ext_ResInfo */
1655         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1656
1657         if ((pVBInfo->SetFlag & ProgrammingCRT2) &&
1658             (!(pVBInfo->LCDInfo & EnableScalingLCD))) { /* {LCDA/LCDB} */
1659                 index = XGI_GetLCDCapPtr(pVBInfo);
1660                 tempal = pVBInfo->LCDCapList[index].LCD_VCLK;
1661
1662                 if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))
1663                         return tempal;
1664
1665                 /* {TV} */
1666                 if (pVBInfo->VBType &
1667                     (VB_SIS301B |
1668                      VB_SIS302B |
1669                      VB_SIS301LV |
1670                      VB_SIS302LV |
1671                      VB_XGI301C)) {
1672                         if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
1673                                 tempal = TVCLKBASE_315 + HiTVVCLKDIV2;
1674                                 if (!(pVBInfo->TVInfo & RPLLDIV2XO))
1675                                         tempal = TVCLKBASE_315 + HiTVVCLK;
1676                                 if (pVBInfo->TVInfo & TVSimuMode) {
1677                                         tempal = TVCLKBASE_315 + HiTVSimuVCLK;
1678                                         if (!(modeflag & Charx8Dot))
1679                                                 tempal = TVCLKBASE_315 +
1680                                                                 HiTVTextVCLK;
1681
1682                                 }
1683                                 return tempal;
1684                         }
1685
1686                         if (pVBInfo->TVInfo & TVSetYPbPr750p) {
1687                                 tempal = XGI_YPbPr750pVCLK;
1688                                 return tempal;
1689                         }
1690
1691                         if (pVBInfo->TVInfo & TVSetYPbPr525p) {
1692                                 tempal = YPbPr525pVCLK;
1693                                 return tempal;
1694                         }
1695
1696                         tempal = NTSC1024VCLK;
1697
1698                         if (!(pVBInfo->TVInfo & NTSC1024x768)) {
1699                                 tempal = TVCLKBASE_315 + TVVCLKDIV2;
1700                                 if (!(pVBInfo->TVInfo & RPLLDIV2XO))
1701                                         tempal = TVCLKBASE_315 + TVVCLK;
1702                         }
1703
1704                         if (pVBInfo->VBInfo & SetCRT2ToTV)
1705                                 return tempal;
1706                 }
1707         } /* {End of VB} */
1708
1709         inb((pVBInfo->P3ca + 0x02));
1710         tempal = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
1711         return tempal;
1712 }
1713
1714 static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
1715                 unsigned char *di_1, struct vb_device_info *pVBInfo)
1716 {
1717         if (pVBInfo->VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B
1718                         | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
1719                 if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) &&
1720                     (pVBInfo->SetFlag & ProgrammingCRT2)) {
1721                         *di_0 = XGI_VBVCLKData[tempal].Part4_A;
1722                         *di_1 = XGI_VBVCLKData[tempal].Part4_B;
1723                 }
1724         } else {
1725                 *di_0 = XGI_VCLKData[tempal].SR2B;
1726                 *di_1 = XGI_VCLKData[tempal].SR2C;
1727         }
1728 }
1729
1730 static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex,
1731                 unsigned short RefreshRateTableIndex,
1732                 struct vb_device_info *pVBInfo)
1733 {
1734         unsigned char di_0, di_1, tempal;
1735         int i;
1736
1737         tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo);
1738         XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
1739         XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
1740
1741         for (i = 0; i < 4; i++) {
1742                 xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30,
1743                                 (unsigned short) (0x10 * i));
1744                 if ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA))
1745                                 && (!(pVBInfo->VBInfo & SetInSlaveMode))) {
1746                         xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0);
1747                         xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1);
1748                 } else {
1749                         xgifb_reg_set(pVBInfo->P3c4, 0x2b, di_0);
1750                         xgifb_reg_set(pVBInfo->P3c4, 0x2c, di_1);
1751                 }
1752         }
1753 }
1754
1755 static void XGI_UpdateModeInfo(struct vb_device_info *pVBInfo)
1756 {
1757         unsigned short tempcl, tempch, temp, tempbl, tempax;
1758
1759         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
1760                         | VB_SIS302LV | VB_XGI301C)) {
1761                 tempcl = 0;
1762                 tempch = 0;
1763                 temp = xgifb_reg_get(pVBInfo->P3c4, 0x01);
1764
1765                 if (!(temp & 0x20)) {
1766                         temp = xgifb_reg_get(pVBInfo->P3d4, 0x17);
1767                         if (temp & 0x80) {
1768                                 temp = xgifb_reg_get(pVBInfo->P3d4, 0x53);
1769                                 if (!(temp & 0x40))
1770                                         tempcl |= ActiveCRT1;
1771                         }
1772                 }
1773
1774                 temp = xgifb_reg_get(pVBInfo->Part1Port, 0x2e);
1775                 temp &= 0x0f;
1776
1777                 if (!(temp == 0x08)) {
1778                         /* Check ChannelA */
1779                         tempax = xgifb_reg_get(pVBInfo->Part1Port, 0x13);
1780                         if (tempax & 0x04)
1781                                 tempcl = tempcl | ActiveLCD;
1782
1783                         temp &= 0x05;
1784
1785                         if (!(tempcl & ActiveLCD))
1786                                 if (temp == 0x01)
1787                                         tempcl |= ActiveCRT2;
1788
1789                         if (temp == 0x04)
1790                                 tempcl |= ActiveLCD;
1791
1792                         if (temp == 0x05) {
1793                                 temp = xgifb_reg_get(pVBInfo->Part2Port, 0x00);
1794
1795                                 if (!(temp & 0x08))
1796                                         tempch |= ActiveAVideo;
1797
1798                                 if (!(temp & 0x04))
1799                                         tempch |= ActiveSVideo;
1800
1801                                 if (temp & 0x02)
1802                                         tempch |= ActiveSCART;
1803
1804                                 if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
1805                                         if (temp & 0x01)
1806                                                 tempch |= ActiveHiTV;
1807                                 }
1808
1809                                 if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
1810                                         temp = xgifb_reg_get(
1811                                                         pVBInfo->Part2Port,
1812                                                         0x4d);
1813
1814                                         if (temp & 0x10)
1815                                                 tempch |= ActiveYPbPr;
1816                                 }
1817
1818                                 if (tempch != 0)
1819                                         tempcl |= ActiveTV;
1820                         }
1821                 }
1822
1823                 temp = xgifb_reg_get(pVBInfo->P3d4, 0x3d);
1824                 if (tempcl & ActiveLCD) {
1825                         if ((pVBInfo->SetFlag & ReserveTVOption)) {
1826                                 if (temp & ActiveTV)
1827                                         tempcl |= ActiveTV;
1828                         }
1829                 }
1830                 temp = tempcl;
1831                 tempbl = ~XGI_ModeSwitchStatus;
1832                 xgifb_reg_and_or(pVBInfo->P3d4, 0x3d, tempbl, temp);
1833
1834                 if (!(pVBInfo->SetFlag & ReserveTVOption))
1835                         xgifb_reg_set(pVBInfo->P3d4, 0x3e, tempch);
1836         }
1837 }
1838
1839 void XGI_GetVBType(struct vb_device_info *pVBInfo)
1840 {
1841         unsigned short flag, tempbx, tempah;
1842
1843         tempbx = VB_SIS302B;
1844         flag = xgifb_reg_get(pVBInfo->Part4Port, 0x00);
1845         if (flag == 0x02)
1846                 goto finish;
1847
1848         tempbx = VB_SIS301;
1849         flag = xgifb_reg_get(pVBInfo->Part4Port, 0x01);
1850         if (flag < 0xB0)
1851                 goto finish;
1852
1853         tempbx = VB_SIS301B;
1854         if (flag < 0xC0)
1855                 goto bigger_than_0xB0;
1856
1857         tempbx = VB_XGI301C;
1858         if (flag < 0xD0)
1859                 goto bigger_than_0xB0;
1860
1861         tempbx = VB_SIS301LV;
1862         if (flag < 0xE0)
1863                 goto bigger_than_0xB0;
1864
1865         tempbx = VB_SIS302LV;
1866         tempah = xgifb_reg_get(pVBInfo->Part4Port, 0x39);
1867         if (tempah != 0xFF)
1868                 tempbx = VB_XGI301C;
1869
1870 bigger_than_0xB0:
1871         if (tempbx & (VB_SIS301B | VB_SIS302B)) {
1872                 flag = xgifb_reg_get(pVBInfo->Part4Port, 0x23);
1873                 if (!(flag & 0x02))
1874                         tempbx = tempbx | VB_NoLCD;
1875         }
1876
1877 finish:
1878         pVBInfo->VBType = tempbx;
1879 }
1880
1881 static void XGI_GetVBInfo(unsigned short ModeIdIndex,
1882                 struct vb_device_info *pVBInfo)
1883 {
1884         unsigned short tempax, push, tempbx, temp, modeflag;
1885
1886         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1887         pVBInfo->SetFlag = 0;
1888         pVBInfo->ModeType = modeflag & ModeTypeMask;
1889         tempbx = 0;
1890
1891         if (!(pVBInfo->VBType & 0xFFFF))
1892                 return;
1893
1894         /* Check Display Device */
1895         temp = xgifb_reg_get(pVBInfo->P3d4, 0x30);
1896         tempbx = tempbx | temp;
1897         temp = xgifb_reg_get(pVBInfo->P3d4, 0x31);
1898         push = temp;
1899         push <<= 8;
1900         tempax = temp << 8;
1901         tempbx = tempbx | tempax;
1902         temp = SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | XGI_SetCRT2ToLCDA
1903                 | SetInSlaveMode | DisableCRT2Display;
1904         temp = 0xFFFF ^ temp;
1905         tempbx &= temp;
1906
1907         temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
1908
1909         if (pVBInfo->VBType & (VB_SIS302B | VB_SIS301LV | VB_SIS302LV |
1910                                VB_XGI301C)) {
1911                 if (temp & EnableDualEdge) {
1912                         tempbx |= SetCRT2ToDualEdge;
1913                         if (temp & SetToLCDA)
1914                                 tempbx |= XGI_SetCRT2ToLCDA;
1915                 }
1916         }
1917
1918         if (pVBInfo->VBType & (VB_SIS301LV|VB_SIS302LV|VB_XGI301C)) {
1919                 if (temp & SetYPbPr) {
1920                         /* shampoo add for new scratch */
1921                         temp = xgifb_reg_get(pVBInfo->P3d4, 0x35);
1922                         temp &= YPbPrMode;
1923                         tempbx |= SetCRT2ToHiVision;
1924
1925                         if (temp != YPbPrMode1080i) {
1926                                 tempbx &= (~SetCRT2ToHiVision);
1927                                 tempbx |= SetCRT2ToYPbPr525750;
1928                         }
1929                 }
1930         }
1931
1932         tempax = push; /* restore CR31 */
1933
1934         temp = 0x09FC;
1935
1936         if (!(tempbx & temp)) {
1937                 tempax |= DisableCRT2Display;
1938                 tempbx = 0;
1939         }
1940
1941         if (!(pVBInfo->VBType & VB_NoLCD)) {
1942                 if (tempbx & XGI_SetCRT2ToLCDA) {
1943                         if (tempbx & SetSimuScanMode)
1944                                 tempbx &= (~(SetCRT2ToLCD | SetCRT2ToRAMDAC |
1945                                              SwitchCRT2));
1946                         else
1947                                 tempbx &= (~(SetCRT2ToLCD | SetCRT2ToRAMDAC |
1948                                              SetCRT2ToTV | SwitchCRT2));
1949                 }
1950         }
1951
1952         /* shampoo add */
1953         /* for driver abnormal */
1954         if (!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1955                 if (tempbx & SetCRT2ToRAMDAC) {
1956                         tempbx &= (0xFF00 | SetCRT2ToRAMDAC |
1957                                    SwitchCRT2 | SetSimuScanMode);
1958                         tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750));
1959                 }
1960         }
1961
1962         if (!(pVBInfo->VBType & VB_NoLCD)) {
1963                 if (tempbx & SetCRT2ToLCD) {
1964                         tempbx &= (0xFF00 | SetCRT2ToLCD | SwitchCRT2 |
1965                                    SetSimuScanMode);
1966                         tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750));
1967                 }
1968         }
1969
1970         if (tempbx & SetCRT2ToSCART) {
1971                 tempbx &= (0xFF00 | SetCRT2ToSCART | SwitchCRT2 |
1972                            SetSimuScanMode);
1973                 tempbx &= (0x00FF | (~SetCRT2ToYPbPr525750));
1974         }
1975
1976         if (tempbx & SetCRT2ToYPbPr525750)
1977                 tempbx &= (0xFF00 | SwitchCRT2 | SetSimuScanMode);
1978
1979         if (tempbx & SetCRT2ToHiVision)
1980                 tempbx &= (0xFF00 | SetCRT2ToHiVision | SwitchCRT2 |
1981                            SetSimuScanMode);
1982
1983         if (tempax & DisableCRT2Display) { /* Set Display Device Info */
1984                 if (!(tempbx & (SwitchCRT2 | SetSimuScanMode)))
1985                         tempbx = DisableCRT2Display;
1986         }
1987
1988         if (!(tempbx & DisableCRT2Display)) {
1989                 if ((!(tempbx & DriverMode)) || (!(modeflag & CRT2Mode))) {
1990                         if (!(tempbx & XGI_SetCRT2ToLCDA))
1991                                 tempbx |= (SetInSlaveMode | SetSimuScanMode);
1992                 }
1993
1994                 /* LCD+TV can't support in slave mode
1995                  * (Force LCDA+TV->LCDB) */
1996                 if ((tempbx & SetInSlaveMode) && (tempbx & XGI_SetCRT2ToLCDA)) {
1997                         tempbx ^= (SetCRT2ToLCD | XGI_SetCRT2ToLCDA |
1998                                    SetCRT2ToDualEdge);
1999                         pVBInfo->SetFlag |= ReserveTVOption;
2000                 }
2001         }
2002
2003         pVBInfo->VBInfo = tempbx;
2004 }
2005
2006 static void XGI_GetTVInfo(unsigned short ModeIdIndex,
2007                 struct vb_device_info *pVBInfo)
2008 {
2009         unsigned short tempbx = 0, resinfo = 0, modeflag, index1;
2010
2011         if (pVBInfo->VBInfo & SetCRT2ToTV) {
2012                 modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2013                 resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2014
2015                 tempbx = xgifb_reg_get(pVBInfo->P3d4, 0x35);
2016                 if (tempbx & TVSetPAL) {
2017                         tempbx &= (SetCHTVOverScan |
2018                                    TVSetPALM |
2019                                    TVSetPALN |
2020                                    TVSetPAL);
2021                         if (tempbx & TVSetPALM)
2022                                 /* set to NTSC if PAL-M */
2023                                 tempbx &= ~TVSetPAL;
2024                 } else
2025                         tempbx &= (SetCHTVOverScan |
2026                                    TVSetNTSCJ |
2027                                    TVSetPAL);
2028
2029                 if (pVBInfo->VBInfo & SetCRT2ToSCART)
2030                         tempbx |= TVSetPAL;
2031
2032                 if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
2033                         index1 = xgifb_reg_get(pVBInfo->P3d4, 0x35);
2034                         index1 &= YPbPrMode;
2035
2036                         if (index1 == YPbPrMode525i)
2037                                 tempbx |= TVSetYPbPr525i;
2038
2039                         if (index1 == YPbPrMode525p)
2040                                 tempbx = tempbx | TVSetYPbPr525p;
2041                         if (index1 == YPbPrMode750p)
2042                                 tempbx = tempbx | TVSetYPbPr750p;
2043                 }
2044
2045                 if (pVBInfo->VBInfo & SetCRT2ToHiVision)
2046                         tempbx = tempbx | TVSetHiVision | TVSetPAL;
2047
2048                 if ((pVBInfo->VBInfo & SetInSlaveMode) &&
2049                     (!(pVBInfo->VBInfo & SetNotSimuMode)))
2050                         tempbx |= TVSimuMode;
2051
2052                 if (!(tempbx & TVSetPAL) && (modeflag > 13) && (resinfo == 8))
2053                         /* NTSC 1024x768, */
2054                         tempbx |= NTSC1024x768;
2055
2056                 tempbx |= RPLLDIV2XO;
2057
2058                 if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
2059                         if (pVBInfo->VBInfo & SetInSlaveMode)
2060                                 tempbx &= (~RPLLDIV2XO);
2061                 } else if (tempbx & (TVSetYPbPr525p | TVSetYPbPr750p)) {
2062                         tempbx &= (~RPLLDIV2XO);
2063                 } else if (!(pVBInfo->VBType & (VB_SIS301B | VB_SIS302B |
2064                                                 VB_SIS301LV | VB_SIS302LV |
2065                                                 VB_XGI301C))) {
2066                         if (tempbx & TVSimuMode)
2067                                 tempbx &= (~RPLLDIV2XO);
2068                 }
2069         }
2070         pVBInfo->TVInfo = tempbx;
2071 }
2072
2073 static unsigned char XGI_GetLCDInfo(unsigned short ModeIdIndex,
2074                                     struct vb_device_info *pVBInfo)
2075 {
2076         unsigned short temp, tempax, tempbx, resinfo = 0, LCDIdIndex;
2077
2078         pVBInfo->LCDResInfo = 0;
2079         pVBInfo->LCDTypeInfo = 0;
2080         pVBInfo->LCDInfo = 0;
2081
2082         /* si+Ext_ResInfo // */
2083         resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2084         temp = xgifb_reg_get(pVBInfo->P3d4, 0x36); /* Get LCD Res.Info */
2085         tempbx = temp & 0x0F;
2086
2087         if (tempbx == 0)
2088                 tempbx = Panel_1024x768; /* default */
2089
2090         /* LCD75 */
2091         if ((tempbx == Panel_1024x768) || (tempbx == Panel_1280x1024)) {
2092                 if (pVBInfo->VBInfo & DriverMode) {
2093                         tempax = xgifb_reg_get(pVBInfo->P3d4, 0x33);
2094                         if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
2095                                 tempax &= 0x0F;
2096                         else
2097                                 tempax >>= 4;
2098
2099                         if ((resinfo == 6) || (resinfo == 9)) {
2100                                 if (tempax >= 3)
2101                                         tempbx |= PanelRef75Hz;
2102                         } else if ((resinfo == 7) || (resinfo == 8)) {
2103                                 if (tempax >= 4)
2104                                         tempbx |= PanelRef75Hz;
2105                         }
2106                 }
2107         }
2108
2109         pVBInfo->LCDResInfo = tempbx;
2110
2111         /* End of LCD75 */
2112
2113         if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
2114                 return 0;
2115
2116         tempbx = 0;
2117
2118         temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
2119
2120         temp &= (ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable);
2121
2122         tempbx |= temp;
2123
2124         LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo);
2125
2126         tempax = pVBInfo->LCDCapList[LCDIdIndex].LCD_Capability;
2127
2128         if (((pVBInfo->VBType & VB_SIS302LV) ||
2129              (pVBInfo->VBType & VB_XGI301C)) && (tempax & XGI_LCDDualLink))
2130                 tempbx |= SetLCDDualLink;
2131
2132         if ((pVBInfo->LCDResInfo == Panel_1400x1050) &&
2133             (pVBInfo->VBInfo & SetCRT2ToLCD) && (resinfo == 9) &&
2134             (!(tempbx & EnableScalingLCD)))
2135                 /*
2136                  * set to center in 1280x1024 LCDB
2137                  * for Panel_1400x1050
2138                  */
2139                 tempbx |= SetLCDtoNonExpanding;
2140
2141         if (pVBInfo->VBInfo & SetInSlaveMode) {
2142                 if (pVBInfo->VBInfo & SetNotSimuMode)
2143                         tempbx |= XGI_LCDVESATiming;
2144         } else {
2145                 tempbx |= XGI_LCDVESATiming;
2146         }
2147
2148         pVBInfo->LCDInfo = tempbx;
2149
2150         return 1;
2151 }
2152
2153 unsigned char XGI_SearchModeID(unsigned short ModeNo,
2154                                unsigned short *ModeIdIndex)
2155 {
2156         for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
2157                 if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
2158                         break;
2159                 if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
2160                         return 0;
2161         }
2162
2163         return 1;
2164 }
2165
2166 static unsigned char XG21GPIODataTransfer(unsigned char ujDate)
2167 {
2168         unsigned char ujRet = 0;
2169         unsigned char i = 0;
2170
2171         for (i = 0; i < 8; i++) {
2172                 ujRet <<= 1;
2173                 ujRet |= (ujDate >> i) & 1;
2174         }
2175
2176         return ujRet;
2177 }
2178
2179 /*----------------------------------------------------------------------------*/
2180 /* output                                                                     */
2181 /*      bl[5] : LVDS signal                                                   */
2182 /*      bl[1] : LVDS backlight                                                */
2183 /*      bl[0] : LVDS VDD                                                      */
2184 /*----------------------------------------------------------------------------*/
2185 static unsigned char XGI_XG21GetPSCValue(struct vb_device_info *pVBInfo)
2186 {
2187         unsigned char CR4A, temp;
2188
2189         CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
2190         xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x23); /* enable GPIO write */
2191
2192         temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
2193
2194         temp = XG21GPIODataTransfer(temp);
2195         temp &= 0x23;
2196         xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
2197         return temp;
2198 }
2199
2200 /*----------------------------------------------------------------------------*/
2201 /* output                                                                     */
2202 /*      bl[5] : LVDS signal                                                   */
2203 /*      bl[1] : LVDS backlight                                                */
2204 /*      bl[0] : LVDS VDD                                                      */
2205 /*----------------------------------------------------------------------------*/
2206 static unsigned char XGI_XG27GetPSCValue(struct vb_device_info *pVBInfo)
2207 {
2208         unsigned char CR4A, CRB4, temp;
2209
2210         CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
2211         xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x0C); /* enable GPIO write */
2212
2213         temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
2214
2215         temp &= 0x0C;
2216         temp >>= 2;
2217         xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
2218         CRB4 = xgifb_reg_get(pVBInfo->P3d4, 0xB4);
2219         temp |= ((CRB4 & 0x04) << 3);
2220         return temp;
2221 }
2222
2223 /*----------------------------------------------------------------------------*/
2224 /* input                                                                      */
2225 /*      bl[5] : 1;LVDS signal on                                              */
2226 /*      bl[1] : 1;LVDS backlight on                                           */
2227 /*      bl[0] : 1:LVDS VDD on                                                 */
2228 /*      bh: 100000b : clear bit 5, to set bit5                                */
2229 /*          000010b : clear bit 1, to set bit1                                */
2230 /*          000001b : clear bit 0, to set bit0                                */
2231 /*----------------------------------------------------------------------------*/
2232 static void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
2233                 struct vb_device_info *pVBInfo)
2234 {
2235         unsigned char CR4A, temp;
2236
2237         CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
2238         tempbh &= 0x23;
2239         tempbl &= 0x23;
2240         xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
2241
2242         if (tempbh & 0x20) {
2243                 temp = (tempbl >> 4) & 0x02;
2244
2245                 /* CR B4[1] */
2246                 xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
2247
2248         }
2249
2250         temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
2251
2252         temp = XG21GPIODataTransfer(temp);
2253         temp &= ~tempbh;
2254         temp |= tempbl;
2255         xgifb_reg_set(pVBInfo->P3d4, 0x48, temp);
2256 }
2257
2258 static void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
2259                 struct vb_device_info *pVBInfo)
2260 {
2261         unsigned char CR4A, temp;
2262         unsigned short tempbh0, tempbl0;
2263
2264         tempbh0 = tempbh;
2265         tempbl0 = tempbl;
2266         tempbh0 &= 0x20;
2267         tempbl0 &= 0x20;
2268         tempbh0 >>= 3;
2269         tempbl0 >>= 3;
2270
2271         if (tempbh & 0x20) {
2272                 temp = (tempbl >> 4) & 0x02;
2273
2274                 /* CR B4[1] */
2275                 xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp);
2276
2277         }
2278         xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~tempbh0, tempbl0);
2279
2280         CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
2281         tempbh &= 0x03;
2282         tempbl &= 0x03;
2283         tempbh <<= 2;
2284         tempbl <<= 2; /* GPIOC,GPIOD */
2285         xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
2286         xgifb_reg_and_or(pVBInfo->P3d4, 0x48, ~tempbh, tempbl);
2287 }
2288
2289 static void XGI_DisplayOn(struct xgifb_video_info *xgifb_info,
2290                 struct xgi_hw_device_info *pXGIHWDE,
2291                 struct vb_device_info *pVBInfo)
2292 {
2293
2294         xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x00);
2295         if (pXGIHWDE->jChipType == XG21) {
2296                 if (pVBInfo->IF_DEF_LVDS == 1) {
2297                         if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x1)) {
2298                                 /* LVDS VDD on */
2299                                 XGI_XG21BLSignalVDD(0x01, 0x01, pVBInfo);
2300                                 mdelay(xgifb_info->lvds_data.PSC_S2);
2301                         }
2302                         if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x20))
2303                                 /* LVDS signal on */
2304                                 XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo);
2305                         mdelay(xgifb_info->lvds_data.PSC_S3);
2306                         /* LVDS backlight on */
2307                         XGI_XG21BLSignalVDD(0x02, 0x02, pVBInfo);
2308                 } else {
2309                         /* DVO/DVI signal on */
2310                         XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo);
2311                 }
2312
2313         }
2314
2315         if (pXGIHWDE->jChipType == XG27) {
2316                 if (pVBInfo->IF_DEF_LVDS == 1) {
2317                         if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x1)) {
2318                                 /* LVDS VDD on */
2319                                 XGI_XG27BLSignalVDD(0x01, 0x01, pVBInfo);
2320                                 mdelay(xgifb_info->lvds_data.PSC_S2);
2321                         }
2322                         if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x20))
2323                                 /* LVDS signal on */
2324                                 XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo);
2325                         mdelay(xgifb_info->lvds_data.PSC_S3);
2326                         /* LVDS backlight on */
2327                         XGI_XG27BLSignalVDD(0x02, 0x02, pVBInfo);
2328                 } else {
2329                         /* DVO/DVI signal on */
2330                         XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo);
2331                 }
2332
2333         }
2334 }
2335
2336 void XGI_DisplayOff(struct xgifb_video_info *xgifb_info,
2337                 struct xgi_hw_device_info *pXGIHWDE,
2338                 struct vb_device_info *pVBInfo)
2339 {
2340
2341         if (pXGIHWDE->jChipType == XG21) {
2342                 if (pVBInfo->IF_DEF_LVDS == 1) {
2343                         /* LVDS backlight off */
2344                         XGI_XG21BLSignalVDD(0x02, 0x00, pVBInfo);
2345                         mdelay(xgifb_info->lvds_data.PSC_S3);
2346                 } else {
2347                         /* DVO/DVI signal off */
2348                         XGI_XG21BLSignalVDD(0x20, 0x00, pVBInfo);
2349                 }
2350         }
2351
2352         if (pXGIHWDE->jChipType == XG27) {
2353                 if ((XGI_XG27GetPSCValue(pVBInfo) & 0x2)) {
2354                         /* LVDS backlight off */
2355                         XGI_XG27BLSignalVDD(0x02, 0x00, pVBInfo);
2356                         mdelay(xgifb_info->lvds_data.PSC_S3);
2357                 }
2358
2359                 if (pVBInfo->IF_DEF_LVDS == 0)
2360                         /* DVO/DVI signal off */
2361                         XGI_XG27BLSignalVDD(0x20, 0x00, pVBInfo);
2362         }
2363
2364         xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x20);
2365 }
2366
2367 static void XGI_WaitDisply(struct vb_device_info *pVBInfo)
2368 {
2369         while ((inb(pVBInfo->P3da) & 0x01))
2370                 break;
2371
2372         while (!(inb(pVBInfo->P3da) & 0x01))
2373                 break;
2374 }
2375
2376 static void XGI_AutoThreshold(struct vb_device_info *pVBInfo)
2377 {
2378         xgifb_reg_or(pVBInfo->Part1Port, 0x01, 0x40);
2379 }
2380
2381 static void XGI_SaveCRT2Info(unsigned short ModeNo,
2382                              struct vb_device_info *pVBInfo)
2383 {
2384         unsigned short temp1, temp2;
2385
2386         /* reserve CR34 for CRT1 Mode No */
2387         xgifb_reg_set(pVBInfo->P3d4, 0x34, ModeNo);
2388         temp1 = (pVBInfo->VBInfo & SetInSlaveMode) >> 8;
2389         temp2 = ~(SetInSlaveMode >> 8);
2390         xgifb_reg_and_or(pVBInfo->P3d4, 0x31, temp2, temp1);
2391 }
2392
2393 static void XGI_GetCRT2ResInfo(unsigned short ModeIdIndex,
2394                                struct vb_device_info *pVBInfo)
2395 {
2396         unsigned short xres, yres, modeflag, resindex;
2397
2398         resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2399         xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
2400         yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
2401         /* si+St_ModeFlag */
2402         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2403
2404         if (modeflag & HalfDCLK)
2405                 xres *= 2;
2406
2407         if (modeflag & DoubleScanMode)
2408                 yres *= 2;
2409
2410         if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
2411                 goto exit;
2412
2413         if (pVBInfo->LCDResInfo == Panel_1600x1200) {
2414                 if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
2415                         if (yres == 1024)
2416                                 yres = 1056;
2417                 }
2418         }
2419
2420         if (pVBInfo->LCDResInfo == Panel_1280x1024) {
2421                 if (yres == 400)
2422                         yres = 405;
2423                 else if (yres == 350)
2424                         yres = 360;
2425
2426                 if (pVBInfo->LCDInfo & XGI_LCDVESATiming) {
2427                         if (yres == 360)
2428                                 yres = 375;
2429                 }
2430         }
2431
2432         if (pVBInfo->LCDResInfo == Panel_1024x768) {
2433                 if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
2434                         if (!(pVBInfo->LCDInfo & LCDNonExpanding)) {
2435                                 if (yres == 350)
2436                                         yres = 357;
2437                                 else if (yres == 400)
2438                                         yres = 420;
2439                                 else if (yres == 480)
2440                                         yres = 525;
2441                         }
2442                 }
2443         }
2444
2445         if (xres == 720)
2446                 xres = 640;
2447
2448 exit:
2449         pVBInfo->VGAHDE = xres;
2450         pVBInfo->HDE = xres;
2451         pVBInfo->VGAVDE = yres;
2452         pVBInfo->VDE = yres;
2453 }
2454
2455 static unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo)
2456 {
2457
2458         if ((pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) &&
2459                         (pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */
2460                 return 1;
2461
2462         return 0;
2463 }
2464
2465 static void XGI_GetRAMDAC2DATA(unsigned short ModeIdIndex,
2466                                unsigned short RefreshRateTableIndex,
2467                                struct vb_device_info *pVBInfo)
2468 {
2469         unsigned short tempax, tempbx, temp1, temp2, modeflag = 0, tempcx,
2470                         CRT1Index;
2471
2472         pVBInfo->RVBHCMAX = 1;
2473         pVBInfo->RVBHCFACT = 1;
2474         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2475         CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
2476         CRT1Index &= IndexMask;
2477         temp1 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[0];
2478         temp2 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[5];
2479         tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
2480         tempbx = (unsigned short) XGI_CRT1Table[CRT1Index].CR[8];
2481         tempcx = (unsigned short)
2482                         XGI_CRT1Table[CRT1Index].CR[14] << 8;
2483         tempcx &= 0x0100;
2484         tempcx <<= 2;
2485         tempbx |= tempcx;
2486         temp1 = (unsigned short) XGI_CRT1Table[CRT1Index].CR[9];
2487
2488         if (temp1 & 0x01)
2489                 tempbx |= 0x0100;
2490
2491         if (temp1 & 0x20)
2492                 tempbx |= 0x0200;
2493         tempax += 5;
2494
2495         if (modeflag & Charx8Dot)
2496                 tempax *= 8;
2497         else
2498                 tempax *= 9;
2499
2500         pVBInfo->VGAHT = tempax;
2501         pVBInfo->HT = tempax;
2502         tempbx++;
2503         pVBInfo->VGAVT = tempbx;
2504         pVBInfo->VT = tempbx;
2505 }
2506
2507 static void XGI_GetCRT2Data(unsigned short ModeIdIndex,
2508                 unsigned short RefreshRateTableIndex,
2509                 struct vb_device_info *pVBInfo)
2510 {
2511         unsigned short tempax = 0, tempbx = 0, modeflag, resinfo;
2512
2513         struct SiS_LCDData const *LCDPtr = NULL;
2514
2515         /* si+Ext_ResInfo */
2516         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2517         resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2518         pVBInfo->NewFlickerMode = 0;
2519         pVBInfo->RVBHRS = 50;
2520
2521         if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
2522                 XGI_GetRAMDAC2DATA(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
2523                 return;
2524         }
2525
2526         if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
2527                 LCDPtr = XGI_GetLcdPtr(XGI_LCDDataTable, ModeIdIndex,
2528                                        pVBInfo);
2529
2530                 pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX;
2531                 pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT;
2532                 pVBInfo->VGAHT = LCDPtr->VGAHT;
2533                 pVBInfo->VGAVT = LCDPtr->VGAVT;
2534                 pVBInfo->HT = LCDPtr->LCDHT;
2535                 pVBInfo->VT = LCDPtr->LCDVT;
2536
2537                 if (pVBInfo->LCDResInfo == Panel_1024x768) {
2538                         tempax = 1024;
2539                         tempbx = 768;
2540
2541                         if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
2542                                 if (pVBInfo->VGAVDE == 357)
2543                                         tempbx = 527;
2544                                 else if (pVBInfo->VGAVDE == 420)
2545                                         tempbx = 620;
2546                                 else if (pVBInfo->VGAVDE == 525)
2547                                         tempbx = 775;
2548                                 else if (pVBInfo->VGAVDE == 600)
2549                                         tempbx = 775;
2550                         }
2551                 } else if (pVBInfo->LCDResInfo == Panel_1024x768x75) {
2552                         tempax = 1024;
2553                         tempbx = 768;
2554                 } else if (pVBInfo->LCDResInfo == Panel_1280x1024) {
2555                         tempax = 1280;
2556                         if (pVBInfo->VGAVDE == 360)
2557                                 tempbx = 768;
2558                         else if (pVBInfo->VGAVDE == 375)
2559                                 tempbx = 800;
2560                         else if (pVBInfo->VGAVDE == 405)
2561                                 tempbx = 864;
2562                         else
2563                                 tempbx = 1024;
2564                 } else if (pVBInfo->LCDResInfo == Panel_1280x1024x75) {
2565                         tempax = 1280;
2566                         tempbx = 1024;
2567                 } else if (pVBInfo->LCDResInfo == Panel_1280x960) {
2568                         tempax = 1280;
2569                         if (pVBInfo->VGAVDE == 350)
2570                                 tempbx = 700;
2571                         else if (pVBInfo->VGAVDE == 400)
2572                                 tempbx = 800;
2573                         else if (pVBInfo->VGAVDE == 1024)
2574                                 tempbx = 960;
2575                         else
2576                                 tempbx = 960;
2577                 } else if (pVBInfo->LCDResInfo == Panel_1400x1050) {
2578                         tempax = 1400;
2579                         tempbx = 1050;
2580
2581                         if (pVBInfo->VGAVDE == 1024) {
2582                                 tempax = 1280;
2583                                 tempbx = 1024;
2584                         }
2585                 } else if (pVBInfo->LCDResInfo == Panel_1600x1200) {
2586                         tempax = 1600;
2587                         tempbx = 1200; /* alan 10/14/2003 */
2588                         if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
2589                                 if (pVBInfo->VGAVDE == 350)
2590                                         tempbx = 875;
2591                                 else if (pVBInfo->VGAVDE == 400)
2592                                         tempbx = 1000;
2593                         }
2594                 }
2595
2596                 if (pVBInfo->LCDInfo & LCDNonExpanding) {
2597                         tempax = pVBInfo->VGAHDE;
2598                         tempbx = pVBInfo->VGAVDE;
2599                 }
2600
2601                 pVBInfo->HDE = tempax;
2602                 pVBInfo->VDE = tempbx;
2603                 return;
2604         }
2605
2606         if (pVBInfo->VBInfo & (SetCRT2ToTV)) {
2607                 struct SiS_TVData const *TVPtr;
2608
2609                 TVPtr = XGI_GetTVPtr(ModeIdIndex, RefreshRateTableIndex,
2610                                      pVBInfo);
2611
2612                 pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX;
2613                 pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT;
2614                 pVBInfo->VGAHT = TVPtr->VGAHT;
2615                 pVBInfo->VGAVT = TVPtr->VGAVT;
2616                 pVBInfo->HDE = TVPtr->TVHDE;
2617                 pVBInfo->VDE = TVPtr->TVVDE;
2618                 pVBInfo->RVBHRS = TVPtr->RVBHRS;
2619                 pVBInfo->NewFlickerMode = TVPtr->FlickerMode;
2620
2621                 if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
2622                         if (resinfo == 0x08)
2623                                 pVBInfo->NewFlickerMode = 0x40;
2624                         else if (resinfo == 0x09)
2625                                 pVBInfo->NewFlickerMode = 0x40;
2626                         else if (resinfo == 0x12)
2627                                 pVBInfo->NewFlickerMode = 0x40;
2628
2629                         if (pVBInfo->VGAVDE == 350)
2630                                 pVBInfo->TVInfo |= TVSimuMode;
2631
2632                         tempax = ExtHiTVHT;
2633                         tempbx = ExtHiTVVT;
2634
2635                         if (pVBInfo->VBInfo & SetInSlaveMode) {
2636                                 if (pVBInfo->TVInfo & TVSimuMode) {
2637                                         tempax = StHiTVHT;
2638                                         tempbx = StHiTVVT;
2639
2640                                         if (!(modeflag & Charx8Dot)) {
2641                                                 tempax = StHiTextTVHT;
2642                                                 tempbx = StHiTextTVVT;
2643                                         }
2644                                 }
2645                         }
2646                 } else if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
2647                         if (pVBInfo->TVInfo & TVSetYPbPr750p) {
2648                                 tempax = YPbPrTV750pHT; /* Ext750pTVHT */
2649                                 tempbx = YPbPrTV750pVT; /* Ext750pTVVT */
2650                         }
2651
2652                         if (pVBInfo->TVInfo & TVSetYPbPr525p) {
2653                                 tempax = YPbPrTV525pHT; /* Ext525pTVHT */
2654                                 tempbx = YPbPrTV525pVT; /* Ext525pTVVT */
2655                         } else if (pVBInfo->TVInfo & TVSetYPbPr525i) {
2656                                 tempax = YPbPrTV525iHT; /* Ext525iTVHT */
2657                                 tempbx = YPbPrTV525iVT; /* Ext525iTVVT */
2658                                 if (pVBInfo->TVInfo & NTSC1024x768)
2659                                         tempax = NTSC1024x768HT;
2660                         }
2661                 } else {
2662                         tempax = PALHT;
2663                         tempbx = PALVT;
2664                         if (!(pVBInfo->TVInfo & TVSetPAL)) {
2665                                 tempax = NTSCHT;
2666                                 tempbx = NTSCVT;
2667                                 if (pVBInfo->TVInfo & NTSC1024x768)
2668                                         tempax = NTSC1024x768HT;
2669                         }
2670                 }
2671
2672                 pVBInfo->HT = tempax;
2673                 pVBInfo->VT = tempbx;
2674         }
2675 }
2676
2677 static void XGI_SetCRT2VCLK(unsigned short ModeIdIndex,
2678                 unsigned short RefreshRateTableIndex,
2679                 struct vb_device_info *pVBInfo)
2680 {
2681         unsigned char di_0, di_1, tempal;
2682
2683         tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo);
2684         XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
2685         XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
2686
2687         if (pVBInfo->VBType & VB_SIS301) { /* shampoo 0129 */
2688                 /* 301 */
2689                 xgifb_reg_set(pVBInfo->Part4Port, 0x0A, 0x10);
2690                 xgifb_reg_set(pVBInfo->Part4Port, 0x0B, di_1);
2691                 xgifb_reg_set(pVBInfo->Part4Port, 0x0A, di_0);
2692         } else { /* 301b/302b/301lv/302lv */
2693                 xgifb_reg_set(pVBInfo->Part4Port, 0x0A, di_0);
2694                 xgifb_reg_set(pVBInfo->Part4Port, 0x0B, di_1);
2695         }
2696
2697         xgifb_reg_set(pVBInfo->Part4Port, 0x00, 0x12);
2698
2699         if (pVBInfo->VBInfo & SetCRT2ToRAMDAC)
2700                 xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x28);
2701         else
2702                 xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x08);
2703 }
2704
2705 static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex)
2706 {
2707         unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
2708         short index;
2709         unsigned short modeflag;
2710
2711         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2712         index = (modeflag & ModeTypeMask) - ModeEGA;
2713
2714         if (index < 0)
2715                 index = 0;
2716
2717         return ColorDepth[index];
2718 }
2719
2720 static unsigned short XGI_GetOffset(unsigned short ModeNo,
2721                                     unsigned short ModeIdIndex,
2722                 unsigned short RefreshRateTableIndex)
2723 {
2724         unsigned short temp, colordepth, modeinfo, index, infoflag,
2725                         ColorDepth[] = { 0x01, 0x02, 0x04 };
2726
2727         modeinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
2728         infoflag = XGI330_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
2729
2730         index = (modeinfo >> 8) & 0xFF;
2731
2732         temp = XGI330_ScreenOffset[index];
2733
2734         if (infoflag & InterlaceMode)
2735                 temp <<= 1;
2736
2737         colordepth = XGI_GetColorDepth(ModeIdIndex);
2738
2739         if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) {
2740                 temp = ModeNo - 0x7C;
2741                 colordepth = ColorDepth[temp];
2742                 temp = 0x6B;
2743                 if (infoflag & InterlaceMode)
2744                         temp <<= 1;
2745         }
2746         return temp * colordepth;
2747 }
2748
2749 static void XGI_SetCRT2Offset(unsigned short ModeNo,
2750                 unsigned short ModeIdIndex,
2751                 unsigned short RefreshRateTableIndex,
2752                 struct vb_device_info *pVBInfo)
2753 {
2754         unsigned short offset;
2755         unsigned char temp;
2756
2757         if (pVBInfo->VBInfo & SetInSlaveMode)
2758                 return;
2759
2760         offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex);
2761         temp = (unsigned char) (offset & 0xFF);
2762         xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp);
2763         temp = (unsigned char) ((offset & 0xFF00) >> 8);
2764         xgifb_reg_set(pVBInfo->Part1Port, 0x09, temp);
2765         temp = (unsigned char) (((offset >> 3) & 0xFF) + 1);
2766         xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp);
2767 }
2768
2769 static void XGI_SetCRT2FIFO(struct vb_device_info *pVBInfo)
2770 {
2771         /* threshold high ,disable auto threshold */
2772         xgifb_reg_set(pVBInfo->Part1Port, 0x01, 0x3B);
2773         /* threshold low default 04h */
2774         xgifb_reg_and_or(pVBInfo->Part1Port, 0x02, ~(0x3F), 0x04);
2775 }
2776
2777 static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
2778                 unsigned short RefreshRateTableIndex,
2779                 struct vb_device_info *pVBInfo)
2780 {
2781         u8 tempcx;
2782
2783         XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
2784         XGI_SetCRT2FIFO(pVBInfo);
2785
2786         for (tempcx = 4; tempcx < 7; tempcx++)
2787                 xgifb_reg_set(pVBInfo->Part1Port, tempcx, 0x0);
2788
2789         xgifb_reg_set(pVBInfo->Part1Port, 0x50, 0x00);
2790         xgifb_reg_set(pVBInfo->Part1Port, 0x02, 0x44); /* temp 0206 */
2791 }
2792
2793 static void XGI_SetGroup1(unsigned short ModeIdIndex,
2794                 unsigned short RefreshRateTableIndex,
2795                 struct vb_device_info *pVBInfo)
2796 {
2797         unsigned short temp = 0, tempax = 0, tempbx = 0, tempcx = 0,
2798                         pushbx = 0, CRT1Index, modeflag;
2799
2800         CRT1Index = XGI330_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
2801         CRT1Index &= IndexMask;
2802         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2803
2804         /* bainy change table name */
2805         if (modeflag & HalfDCLK) {
2806                 /* BTVGA2HT 0x08,0x09 */
2807                 temp = (pVBInfo->VGAHT / 2 - 1) & 0x0FF;
2808                 xgifb_reg_set(pVBInfo->Part1Port, 0x08, temp);
2809                 temp = (((pVBInfo->VGAHT / 2 - 1) & 0xFF00) >> 8) << 4;
2810                 xgifb_reg_and_or(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
2811                 /* BTVGA2HDEE 0x0A,0x0C */
2812                 temp = (pVBInfo->VGAHDE / 2 + 16) & 0x0FF;
2813                 xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
2814                 tempcx = ((pVBInfo->VGAHT - pVBInfo->VGAHDE) / 2) >> 2;
2815                 pushbx = pVBInfo->VGAHDE / 2 + 16;
2816                 tempcx >>= 1;
2817                 tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
2818                 tempcx += tempbx;
2819
2820                 if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
2821                         tempbx = XGI_CRT1Table[CRT1Index].CR[4];
2822                         tempbx |= ((XGI_CRT1Table[CRT1Index].CR[14] &
2823                                                 0xC0) << 2);
2824                         tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
2825                         tempcx = XGI_CRT1Table[CRT1Index].CR[5];
2826                         tempcx &= 0x1F;
2827                         temp = XGI_CRT1Table[CRT1Index].CR[15];
2828                         temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
2829                         tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
2830                 }
2831
2832                 tempbx += 4;
2833                 tempcx += 4;
2834
2835                 if (tempcx > (pVBInfo->VGAHT / 2))
2836                         tempcx = pVBInfo->VGAHT / 2;
2837
2838                 temp = tempbx & 0x00FF;
2839
2840                 xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
2841         } else {
2842                 temp = (pVBInfo->VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
2843                 xgifb_reg_set(pVBInfo->Part1Port, 0x08, temp);
2844                 temp = (((pVBInfo->VGAHT - 1) & 0xFF00) >> 8) << 4;
2845                 xgifb_reg_and_or(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
2846                 /* BTVGA2HDEE 0x0A,0x0C */
2847                 temp = (pVBInfo->VGAHDE + 16) & 0x0FF;
2848                 xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
2849                 tempcx = (pVBInfo->VGAHT - pVBInfo->VGAHDE) >> 2; /* cx */
2850                 pushbx = pVBInfo->VGAHDE + 16;
2851                 tempcx >>= 1;
2852                 tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
2853                 tempcx += tempbx;
2854
2855                 if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
2856                         tempbx = XGI_CRT1Table[CRT1Index].CR[3];
2857                         tempbx |= ((XGI_CRT1Table[CRT1Index].CR[5] &
2858                                                 0xC0) << 2);
2859                         tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
2860                         tempcx = XGI_CRT1Table[CRT1Index].CR[4];
2861                         tempcx &= 0x1F;
2862                         temp = XGI_CRT1Table[CRT1Index].CR[6];
2863                         temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
2864                         tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
2865                         tempbx += 16;
2866                         tempcx += 16;
2867                 }
2868
2869                 if (tempcx > pVBInfo->VGAHT)
2870                         tempcx = pVBInfo->VGAHT;
2871
2872                 temp = tempbx & 0x00FF;
2873                 xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
2874         }
2875
2876         tempax = (tempax & 0x00FF) | (tempbx & 0xFF00);
2877         tempbx = pushbx;
2878         tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
2879         tempax |= (tempbx & 0xFF00);
2880         temp = (tempax & 0xFF00) >> 8;
2881         xgifb_reg_set(pVBInfo->Part1Port, 0x0C, temp);
2882         temp = tempcx & 0x00FF;
2883         xgifb_reg_set(pVBInfo->Part1Port, 0x0D, temp);
2884         tempcx = pVBInfo->VGAVT - 1;
2885         temp = tempcx & 0x00FF;
2886
2887         xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp);
2888         tempbx = pVBInfo->VGAVDE - 1;
2889         temp = tempbx & 0x00FF;
2890         xgifb_reg_set(pVBInfo->Part1Port, 0x0F, temp);
2891         temp = ((tempbx & 0xFF00) << 3) >> 8;
2892         temp |= ((tempcx & 0xFF00) >> 8);
2893         xgifb_reg_set(pVBInfo->Part1Port, 0x12, temp);
2894
2895         /* BTVGA2VRS 0x10,0x11 */
2896         tempbx = (pVBInfo->VGAVT + pVBInfo->VGAVDE) >> 1;
2897         /* BTVGA2VRE 0x11 */
2898         tempcx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) >> 4) + tempbx + 1;
2899
2900         if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
2901                 tempbx = XGI_CRT1Table[CRT1Index].CR[10];
2902                 temp = XGI_CRT1Table[CRT1Index].CR[9];
2903
2904                 if (temp & 0x04)
2905                         tempbx |= 0x0100;
2906
2907                 if (temp & 0x080)
2908                         tempbx |= 0x0200;
2909
2910                 temp = XGI_CRT1Table[CRT1Index].CR[14];
2911
2912                 if (temp & 0x08)
2913                         tempbx |= 0x0400;
2914
2915                 temp = XGI_CRT1Table[CRT1Index].CR[11];
2916                 tempcx = (tempcx & 0xFF00) | (temp & 0x00FF);
2917         }
2918
2919         temp = tempbx & 0x00FF;
2920         xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
2921         temp = ((tempbx & 0xFF00) >> 8) << 4;
2922         temp = (tempcx & 0x000F) | (temp);
2923         xgifb_reg_set(pVBInfo->Part1Port, 0x11, temp);
2924         tempax = 0;
2925
2926         if (modeflag & DoubleScanMode)
2927                 tempax |= 0x80;
2928
2929         if (modeflag & HalfDCLK)
2930                 tempax |= 0x40;
2931
2932         xgifb_reg_and_or(pVBInfo->Part1Port, 0x2C, ~0x0C0, tempax);
2933 }
2934
2935 static unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo)
2936 {
2937         unsigned long tempax, tempbx;
2938
2939         tempbx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) * pVBInfo->RVBHCMAX)
2940                         & 0xFFFF;
2941         tempax = (pVBInfo->VT - pVBInfo->VDE) * pVBInfo->RVBHCFACT;
2942         tempax = (tempax * pVBInfo->HT) / tempbx;
2943
2944         return (unsigned short) tempax;
2945 }
2946
2947 static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
2948                 struct vb_device_info *pVBInfo)
2949 {
2950         unsigned short push1, push2, tempax, tempbx = 0, tempcx, temp, resinfo,
2951                         modeflag;
2952
2953         /* si+Ext_ResInfo */
2954         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2955         resinfo = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2956
2957         if (!(pVBInfo->VBInfo & SetInSlaveMode))
2958                 return;
2959
2960         temp = 0xFF; /* set MAX HT */
2961         xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp);
2962         tempcx = 0x08;
2963
2964         if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C))
2965                 modeflag |= Charx8Dot;
2966
2967         tempax = pVBInfo->VGAHDE; /* 0x04 Horizontal Display End */
2968
2969         if (modeflag & HalfDCLK)
2970                 tempax >>= 1;
2971
2972         tempax = (tempax / tempcx) - 1;
2973         tempbx |= ((tempax & 0x00FF) << 8);
2974         temp = tempax & 0x00FF;
2975         xgifb_reg_set(pVBInfo->Part1Port, 0x04, temp);
2976
2977         temp = (tempbx & 0xFF00) >> 8;
2978
2979         if (pVBInfo->VBInfo & SetCRT2ToTV) {
2980                 if (!(pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
2981                                 | VB_SIS302LV | VB_XGI301C)))
2982                         temp += 2;
2983
2984                 if ((pVBInfo->VBInfo & SetCRT2ToHiVision) &&
2985                     !(pVBInfo->VBType & VB_SIS301LV) && (resinfo == 7))
2986                                 temp -= 2;
2987         }
2988
2989         /* 0x05 Horizontal Display Start */
2990         xgifb_reg_set(pVBInfo->Part1Port, 0x05, temp);
2991         /* 0x06 Horizontal Blank end */
2992         xgifb_reg_set(pVBInfo->Part1Port, 0x06, 0x03);
2993
2994         if (!(pVBInfo->VBInfo & DisableCRT2Display)) { /* 030226 bainy */
2995                 if (pVBInfo->VBInfo & SetCRT2ToTV)
2996                         tempax = pVBInfo->VGAHT;
2997                 else
2998                         tempax = XGI_GetVGAHT2(pVBInfo);
2999         }
3000
3001         if (tempax >= pVBInfo->VGAHT)
3002                 tempax = pVBInfo->VGAHT;
3003
3004         if (modeflag & HalfDCLK)
3005                 tempax >>= 1;
3006
3007         tempax = (tempax / tempcx) - 5;
3008         tempcx = tempax; /* 20030401 0x07 horizontal Retrace Start */
3009         if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3010                 temp = (tempbx & 0x00FF) - 1;
3011                 if (!(modeflag & HalfDCLK)) {
3012                         temp -= 6;
3013                         if (pVBInfo->TVInfo & TVSimuMode) {
3014                                 temp -= 4;
3015                                 temp -= 10;
3016                         }
3017                 }
3018         } else {
3019                 tempbx = (tempbx & 0xFF00) >> 8;
3020                 tempcx = (tempcx + tempbx) >> 1;
3021                 temp = (tempcx & 0x00FF) + 2;
3022
3023                 if (pVBInfo->VBInfo & SetCRT2ToTV) {
3024                         temp -= 1;
3025                         if (!(modeflag & HalfDCLK)) {
3026                                 if ((modeflag & Charx8Dot)) {
3027                                         temp += 4;
3028                                         if (pVBInfo->VGAHDE >= 800)
3029                                                 temp -= 6;
3030                                 }
3031                         }
3032                 } else if (!(modeflag & HalfDCLK)) {
3033                         temp -= 4;
3034                         if (pVBInfo->LCDResInfo != Panel_1280x960 &&
3035                             pVBInfo->VGAHDE >= 800) {
3036                                 temp -= 7;
3037                                 if (pVBInfo->VGAHDE >= 1280 &&
3038                                     pVBInfo->LCDResInfo != Panel_1280x960 &&
3039                                     (pVBInfo->LCDInfo & LCDNonExpanding))
3040                                         temp += 28;
3041                         }
3042                 }
3043         }
3044
3045         /* 0x07 Horizontal Retrace Start */
3046         xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp);
3047         /* 0x08 Horizontal Retrace End */
3048         xgifb_reg_set(pVBInfo->Part1Port, 0x08, 0);
3049
3050         if (pVBInfo->VBInfo & SetCRT2ToTV) {
3051                 if (pVBInfo->TVInfo & TVSimuMode) {
3052                         if (ModeNo == 0x50) {
3053                                 if (pVBInfo->TVInfo == SetNTSCTV) {
3054                                         xgifb_reg_set(pVBInfo->Part1Port,
3055                                                         0x07, 0x30);
3056                                         xgifb_reg_set(pVBInfo->Part1Port,
3057                                                         0x08, 0x03);
3058                                 } else {
3059                                         xgifb_reg_set(pVBInfo->Part1Port,
3060                                                         0x07, 0x2f);
3061                                         xgifb_reg_set(pVBInfo->Part1Port,
3062                                                         0x08, 0x02);
3063                                 }
3064                         }
3065                 }
3066         }
3067
3068         xgifb_reg_set(pVBInfo->Part1Port, 0x18, 0x03); /* 0x18 SR0B */
3069         xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0xF0, 0x00);
3070         xgifb_reg_set(pVBInfo->Part1Port, 0x09, 0xFF); /* 0x09 Set Max VT */
3071
3072         tempbx = pVBInfo->VGAVT;
3073         push1 = tempbx;
3074         tempcx = 0x121;
3075         tempbx = pVBInfo->VGAVDE; /* 0x0E Virtical Display End */
3076
3077         if (tempbx == 357)
3078                 tempbx = 350;
3079         if (tempbx == 360)
3080                 tempbx = 350;
3081         if (tempbx == 375)
3082                 tempbx = 350;
3083         if (tempbx == 405)
3084                 tempbx = 400;
3085         if (tempbx == 525)
3086                 tempbx = 480;
3087
3088         push2 = tempbx;
3089
3090         if (pVBInfo->VBInfo & SetCRT2ToLCD) {
3091                 if (pVBInfo->LCDResInfo == Panel_1024x768) {
3092                         if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
3093                                 if (tempbx == 350)
3094                                         tempbx += 5;
3095                                 if (tempbx == 480)
3096                                         tempbx += 5;
3097                         }
3098                 }
3099         }
3100         tempbx--;
3101         tempbx--;
3102         temp = tempbx & 0x00FF;
3103         /* 0x10 vertical Blank Start */
3104         xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
3105         tempbx = push2;
3106         tempbx--;
3107         temp = tempbx & 0x00FF;
3108         xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp);
3109
3110         if (tempbx & 0x0100)
3111                 tempcx |= 0x0002;
3112
3113         tempax = 0x000B;
3114
3115         if (modeflag & DoubleScanMode)
3116                 tempax |= 0x08000;
3117
3118         if (tempbx & 0x0200)
3119                 tempcx |= 0x0040;
3120
3121         temp = (tempax & 0xFF00) >> 8;
3122         xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
3123
3124         if (tempbx & 0x0400)
3125                 tempcx |= 0x0600;
3126
3127         /* 0x11 Vertival Blank End */
3128         xgifb_reg_set(pVBInfo->Part1Port, 0x11, 0x00);
3129
3130         tempax = push1;
3131         tempax -= tempbx; /* 0x0C Vertical Retrace Start */
3132         tempax >>= 2;
3133         push1 = tempax; /* push ax */
3134
3135         if (resinfo != 0x09) {
3136                 tempax <<= 1;
3137                 tempbx += tempax;
3138         }
3139
3140         if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3141                 if ((pVBInfo->VBType & VB_SIS301LV) &&
3142                     !(pVBInfo->TVInfo & TVSetHiVision)) {
3143                         if ((pVBInfo->TVInfo & TVSimuMode) &&
3144                             (pVBInfo->TVInfo & TVSetPAL)) {
3145                                 if (!(pVBInfo->VBType & VB_SIS301LV) ||
3146                                     !(pVBInfo->TVInfo &
3147                                       (TVSetYPbPr525p |
3148                                        TVSetYPbPr750p |
3149                                        TVSetHiVision)))
3150                                         tempbx += 40;
3151                         }
3152                 } else {
3153                         tempbx -= 10;
3154                 }
3155         } else if (pVBInfo->TVInfo & TVSimuMode) {
3156                 if (pVBInfo->TVInfo & TVSetPAL) {
3157                         if (pVBInfo->VBType & VB_SIS301LV) {
3158                                 if (!(pVBInfo->TVInfo &
3159                                     (TVSetYPbPr525p |
3160                                      TVSetYPbPr750p |
3161                                      TVSetHiVision)))
3162                                         tempbx += 40;
3163                         } else {
3164                                 tempbx += 40;
3165                         }
3166                 }
3167         }
3168         tempax = push1;
3169         tempax >>= 2;
3170         tempax++;
3171         tempax += tempbx;
3172         push1 = tempax; /* push ax */
3173
3174         if ((pVBInfo->TVInfo & TVSetPAL)) {
3175                 if (tempbx <= 513) {
3176                         if (tempax >= 513)
3177                                 tempbx = 513;
3178                 }
3179         }
3180
3181         temp = tempbx & 0x00FF;
3182         xgifb_reg_set(pVBInfo->Part1Port, 0x0C, temp);
3183         tempbx--;
3184         temp = tempbx & 0x00FF;
3185         xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
3186
3187         if (tempbx & 0x0100)
3188                 tempcx |= 0x0008;
3189
3190         if (tempbx & 0x0200)
3191                 xgifb_reg_and_or(pVBInfo->Part1Port, 0x0B, 0x0FF, 0x20);
3192
3193         tempbx++;
3194
3195         if (tempbx & 0x0100)
3196                 tempcx |= 0x0004;
3197
3198         if (tempbx & 0x0200)
3199                 tempcx |= 0x0080;
3200
3201         if (tempbx & 0x0400)
3202                 tempcx |= 0x0C00;
3203
3204         tempbx = push1; /* pop ax */
3205         temp = tempbx & 0x00FF;
3206         temp &= 0x0F;
3207         /* 0x0D vertical Retrace End */
3208         xgifb_reg_set(pVBInfo->Part1Port, 0x0D, temp);
3209
3210         if (tempbx & 0x0010)
3211                 tempcx |= 0x2000;
3212
3213         temp = tempcx & 0x00FF;
3214         xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp); /* 0x0A CR07 */
3215         temp = (tempcx & 0x0FF00) >> 8;
3216         xgifb_reg_set(pVBInfo->Part1Port, 0x17, temp); /* 0x17 SR0A */
3217         tempax = modeflag;
3218         temp = (tempax & 0xFF00) >> 8;
3219
3220         temp = (temp >> 1) & 0x09;
3221
3222         if (pVBInfo->VBType & (VB_SIS301LV | VB_SIS302LV | VB_XGI301C))
3223                 temp |= 0x01;
3224
3225         xgifb_reg_set(pVBInfo->Part1Port, 0x16, temp); /* 0x16 SR01 */
3226         xgifb_reg_set(pVBInfo->Part1Port, 0x0F, 0); /* 0x0F CR14 */
3227         xgifb_reg_set(pVBInfo->Part1Port, 0x12, 0); /* 0x12 CR17 */
3228
3229         if (pVBInfo->LCDInfo & LCDRGB18Bit)
3230                 temp = 0x80;
3231         else
3232                 temp = 0x00;
3233
3234         xgifb_reg_set(pVBInfo->Part1Port, 0x1A, temp); /* 0x1A SR0E */
3235 }
3236
3237 static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
3238                 struct vb_device_info *pVBInfo)
3239 {
3240         unsigned short i, j, tempax, tempbx, tempcx, temp, push1, push2,
3241                         modeflag;
3242         unsigned char const *TimingPoint;
3243
3244         unsigned long longtemp, tempeax, tempebx, temp2, tempecx;
3245
3246         /* si+Ext_ResInfo */
3247         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3248
3249         tempax = 0;
3250
3251         if (!(pVBInfo->VBInfo & SetCRT2ToAVIDEO))
3252                 tempax |= 0x0800;
3253
3254         if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
3255                 tempax |= 0x0400;
3256
3257         if (pVBInfo->VBInfo & SetCRT2ToSCART)
3258                 tempax |= 0x0200;
3259
3260         if (!(pVBInfo->TVInfo & TVSetPAL))
3261                 tempax |= 0x1000;
3262
3263         if (pVBInfo->VBInfo & SetCRT2ToHiVision)
3264                 tempax |= 0x0100;
3265
3266         if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))
3267                 tempax &= 0xfe00;
3268
3269         tempax = (tempax & 0xff00) >> 8;
3270
3271         xgifb_reg_set(pVBInfo->Part2Port, 0x0, tempax);
3272         TimingPoint = XGI330_NTSCTiming;
3273
3274         if (pVBInfo->TVInfo & TVSetPAL)
3275                 TimingPoint = XGI330_PALTiming;
3276
3277         if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3278                 TimingPoint = XGI330_HiTVExtTiming;
3279
3280                 if (pVBInfo->VBInfo & SetInSlaveMode)
3281                         TimingPoint = XGI330_HiTVSt2Timing;
3282
3283                 if (pVBInfo->SetFlag & TVSimuMode)
3284                         TimingPoint = XGI330_HiTVSt1Timing;
3285
3286                 if (!(modeflag & Charx8Dot))
3287                         TimingPoint = XGI330_HiTVTextTiming;
3288         }
3289
3290         if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
3291                 if (pVBInfo->TVInfo & TVSetYPbPr525i)
3292                         TimingPoint = XGI330_YPbPr525iTiming;
3293
3294                 if (pVBInfo->TVInfo & TVSetYPbPr525p)
3295                         TimingPoint = XGI330_YPbPr525pTiming;
3296
3297                 if (pVBInfo->TVInfo & TVSetYPbPr750p)
3298                         TimingPoint = XGI330_YPbPr750pTiming;
3299         }
3300
3301         for (i = 0x01, j = 0; i <= 0x2D; i++, j++)
3302                 xgifb_reg_set(pVBInfo->Part2Port, i, TimingPoint[j]);
3303
3304         for (i = 0x39; i <= 0x45; i++, j++)
3305                 /* di->temp2[j] */
3306                 xgifb_reg_set(pVBInfo->Part2Port, i, TimingPoint[j]);
3307
3308         if (pVBInfo->VBInfo & SetCRT2ToTV)
3309                 xgifb_reg_and_or(pVBInfo->Part2Port, 0x3A, 0x1F, 0x00);
3310
3311         temp = pVBInfo->NewFlickerMode;
3312         temp &= 0x80;
3313         xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xFF, temp);
3314
3315         if (pVBInfo->TVInfo & TVSetPAL)
3316                 tempax = 520;
3317         else
3318                 tempax = 440;
3319
3320         if (pVBInfo->VDE <= tempax) {
3321                 tempax -= pVBInfo->VDE;
3322                 tempax >>= 2;
3323                 tempax = (tempax & 0x00FF) | ((tempax & 0x00FF) << 8);
3324                 push1 = tempax;
3325                 temp = (tempax & 0xFF00) >> 8;
3326                 temp += (unsigned short) TimingPoint[0];
3327
3328                 if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3329                                 | VB_SIS302LV | VB_XGI301C)) {
3330                         if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO
3331                                         | SetCRT2ToSVIDEO | SetCRT2ToSCART
3332                                         | SetCRT2ToYPbPr525750)) {
3333                                 tempcx = pVBInfo->VGAHDE;
3334                                 if (tempcx >= 1024) {
3335                                         temp = 0x17; /* NTSC */
3336                                         if (pVBInfo->TVInfo & TVSetPAL)
3337                                                 temp = 0x19; /* PAL */
3338                                 }
3339                         }
3340                 }
3341
3342                 xgifb_reg_set(pVBInfo->Part2Port, 0x01, temp);
3343                 tempax = push1;
3344                 temp = (tempax & 0xFF00) >> 8;
3345                 temp += TimingPoint[1];
3346
3347                 if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3348                                 | VB_SIS302LV | VB_XGI301C)) {
3349                         if ((pVBInfo->VBInfo & (SetCRT2ToAVIDEO
3350                                         | SetCRT2ToSVIDEO | SetCRT2ToSCART
3351                                         | SetCRT2ToYPbPr525750))) {
3352                                 tempcx = pVBInfo->VGAHDE;
3353                                 if (tempcx >= 1024) {
3354                                         temp = 0x1D; /* NTSC */
3355                                         if (pVBInfo->TVInfo & TVSetPAL)
3356                                                 temp = 0x52; /* PAL */
3357                                 }
3358                         }
3359                 }
3360                 xgifb_reg_set(pVBInfo->Part2Port, 0x02, temp);
3361         }
3362
3363         /* 301b */
3364         tempcx = pVBInfo->HT;
3365
3366         if (XGI_IsLCDDualLink(pVBInfo))
3367                 tempcx >>= 1;
3368
3369         tempcx -= 2;
3370         temp = tempcx & 0x00FF;
3371         xgifb_reg_set(pVBInfo->Part2Port, 0x1B, temp);
3372
3373         temp = (tempcx & 0xFF00) >> 8;
3374         xgifb_reg_and_or(pVBInfo->Part2Port, 0x1D, ~0x0F, temp);
3375
3376         tempcx = pVBInfo->HT >> 1;
3377         push1 = tempcx; /* push cx */
3378         tempcx += 7;
3379
3380         if (pVBInfo->VBInfo & SetCRT2ToHiVision)
3381                 tempcx -= 4;
3382
3383         temp = tempcx & 0x00FF;
3384         temp <<= 4;
3385         xgifb_reg_and_or(pVBInfo->Part2Port, 0x22, 0x0F, temp);
3386
3387         tempbx = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
3388         tempbx += tempcx;
3389         push2 = tempbx;
3390         temp = tempbx & 0x00FF;
3391         xgifb_reg_set(pVBInfo->Part2Port, 0x24, temp);
3392         temp = (tempbx & 0xFF00) >> 8;
3393         temp <<= 4;
3394         xgifb_reg_and_or(pVBInfo->Part2Port, 0x25, 0x0F, temp);
3395
3396         tempbx = push2;
3397         tempbx = tempbx + 8;
3398         if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3399                 tempbx = tempbx - 4;
3400                 tempcx = tempbx;
3401         }
3402
3403         temp = (tempbx & 0x00FF) << 4;
3404         xgifb_reg_and_or(pVBInfo->Part2Port, 0x29, 0x0F, temp);
3405
3406         j += 2;
3407         tempcx += (TimingPoint[j] | ((TimingPoint[j + 1]) << 8));
3408         temp = tempcx & 0x00FF;
3409         xgifb_reg_set(pVBInfo->Part2Port, 0x27, temp);
3410         temp = ((tempcx & 0xFF00) >> 8) << 4;
3411         xgifb_reg_and_or(pVBInfo->Part2Port, 0x28, 0x0F, temp);
3412
3413         tempcx += 8;
3414         if (pVBInfo->VBInfo & SetCRT2ToHiVision)
3415                 tempcx -= 4;
3416
3417         temp = tempcx & 0xFF;
3418         temp <<= 4;
3419         xgifb_reg_and_or(pVBInfo->Part2Port, 0x2A, 0x0F, temp);
3420
3421         tempcx = push1; /* pop cx */
3422         j += 2;
3423         temp = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
3424         tempcx -= temp;
3425         temp = tempcx & 0x00FF;
3426         temp <<= 4;
3427         xgifb_reg_and_or(pVBInfo->Part2Port, 0x2D, 0x0F, temp);
3428
3429         tempcx -= 11;
3430
3431         if (!(pVBInfo->VBInfo & SetCRT2ToTV)) {
3432                 tempax = XGI_GetVGAHT2(pVBInfo);
3433                 tempcx = tempax - 1;
3434         }
3435         temp = tempcx & 0x00FF;
3436         xgifb_reg_set(pVBInfo->Part2Port, 0x2E, temp);
3437
3438         tempbx = pVBInfo->VDE;
3439
3440         if (pVBInfo->VGAVDE == 360)
3441                 tempbx = 746;
3442         if (pVBInfo->VGAVDE == 375)
3443                 tempbx = 746;
3444         if (pVBInfo->VGAVDE == 405)
3445                 tempbx = 853;
3446
3447         if (pVBInfo->VBInfo & SetCRT2ToTV) {
3448                 if (pVBInfo->VBType &
3449                     (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
3450                         if (!(pVBInfo->TVInfo &
3451                             (TVSetYPbPr525p | TVSetYPbPr750p)))
3452                                 tempbx >>= 1;
3453                 } else
3454                         tempbx >>= 1;
3455         }
3456
3457         tempbx -= 2;
3458         temp = tempbx & 0x00FF;
3459
3460         if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3461                 if (pVBInfo->VBType & VB_SIS301LV) {
3462                         if (pVBInfo->TVInfo & TVSetHiVision) {
3463                                 if (pVBInfo->VBInfo & SetInSlaveMode) {
3464                                         if (ModeNo == 0x2f)
3465                                                 temp += 1;
3466                                 }
3467                         }
3468                 } else if (pVBInfo->VBInfo & SetInSlaveMode) {
3469                         if (ModeNo == 0x2f)
3470                                 temp += 1;
3471                 }
3472         }
3473
3474         xgifb_reg_set(pVBInfo->Part2Port, 0x2F, temp);
3475
3476         temp = (tempcx & 0xFF00) >> 8;
3477         temp |= ((tempbx & 0xFF00) >> 8) << 6;
3478
3479         if (!(pVBInfo->VBInfo & SetCRT2ToHiVision)) {
3480                 if (pVBInfo->VBType & VB_SIS301LV) {
3481                         if (pVBInfo->TVInfo & TVSetHiVision) {
3482                                 temp |= 0x10;
3483
3484                                 if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
3485                                         temp |= 0x20;
3486                         }
3487                 } else {
3488                         temp |= 0x10;
3489                         if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
3490                                 temp |= 0x20;
3491                 }
3492         }
3493
3494         xgifb_reg_set(pVBInfo->Part2Port, 0x30, temp);
3495
3496         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3497                         | VB_SIS302LV | VB_XGI301C)) { /* TV gatingno */
3498                 tempbx = pVBInfo->VDE;
3499                 tempcx = tempbx - 2;
3500
3501                 if (pVBInfo->VBInfo & SetCRT2ToTV) {
3502                         if (!(pVBInfo->TVInfo & (TVSetYPbPr525p
3503                                         | TVSetYPbPr750p)))
3504                                 tempbx >>= 1;
3505                 }
3506
3507                 if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
3508                         temp = 0;
3509                         if (tempcx & 0x0400)
3510                                 temp |= 0x20;
3511
3512                         if (tempbx & 0x0400)
3513                                 temp |= 0x40;
3514
3515                         xgifb_reg_set(pVBInfo->Part4Port, 0x10, temp);
3516                 }
3517
3518                 temp = (((tempbx - 3) & 0x0300) >> 8) << 5;
3519                 xgifb_reg_set(pVBInfo->Part2Port, 0x46, temp);
3520                 temp = (tempbx - 3) & 0x00FF;
3521                 xgifb_reg_set(pVBInfo->Part2Port, 0x47, temp);
3522         }
3523
3524         tempbx = tempbx & 0x00FF;
3525
3526         if (!(modeflag & HalfDCLK)) {
3527                 tempcx = pVBInfo->VGAHDE;
3528                 if (tempcx >= pVBInfo->HDE) {
3529                         tempbx |= 0x2000;
3530                         tempax &= 0x00FF;
3531                 }
3532         }
3533
3534         tempcx = 0x0101;
3535
3536         if (pVBInfo->VBInfo & SetCRT2ToTV) { /*301b*/
3537                 if (pVBInfo->VGAHDE >= 1024) {
3538                         tempcx = 0x1920;
3539                         if (pVBInfo->VGAHDE >= 1280) {
3540                                 tempcx = 0x1420;
3541                                 tempbx = tempbx & 0xDFFF;
3542                         }
3543                 }
3544         }
3545
3546         if (!(tempbx & 0x2000)) {
3547                 if (modeflag & HalfDCLK)
3548                         tempcx = (tempcx & 0xFF00) | ((tempcx & 0x00FF) << 1);
3549
3550                 push1 = tempbx;
3551                 tempeax = pVBInfo->VGAHDE;
3552                 tempebx = (tempcx & 0xFF00) >> 8;
3553                 longtemp = tempeax * tempebx;
3554                 tempecx = tempcx & 0x00FF;
3555                 longtemp = longtemp / tempecx;
3556
3557                 /* 301b */
3558                 tempecx = 8 * 1024;
3559
3560                 if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3561                                 | VB_SIS302LV | VB_XGI301C)) {
3562                         tempecx = tempecx * 8;
3563                 }
3564
3565                 longtemp = longtemp * tempecx;
3566                 tempecx = pVBInfo->HDE;
3567                 temp2 = longtemp % tempecx;
3568                 tempeax = longtemp / tempecx;
3569                 if (temp2 != 0)
3570                         tempeax += 1;
3571
3572                 tempax = (unsigned short) tempeax;
3573
3574                 /* 301b */
3575                 if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
3576                                 | VB_SIS302LV | VB_XGI301C)) {
3577                         tempcx = ((tempax & 0xFF00) >> 5) >> 8;
3578                 }
3579                 /* end 301b */
3580
3581                 tempbx = push1;
3582                 tempbx = (unsigned short) (((tempeax & 0x0000FF00) & 0x1F00)
3583                                 | (tempbx & 0x00FF));
3584                 tempax = (unsigned short) (((tempeax & 0x000000FF) << 8)
3585                                 | (tempax & 0x00FF));
3586                 temp = (tempax & 0xFF00) >> 8;
3587         } else {
3588                 temp = (tempax & 0x00FF) >> 8;
3589         }
3590
3591         xgifb_reg_set(pVBInfo->Part2Port, 0x44, temp);
3592         temp = (tempbx & 0xFF00) >> 8;
3593         xgifb_reg_and_or(pVBInfo->Part2Port, 0x45, ~0x03F, temp);
3594         temp = tempcx & 0x00FF;
3595
3596         if (tempbx & 0x2000)
3597                 temp = 0;
3598
3599         if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
3600                 temp |= 0x18;
3601
3602         xgifb_reg_and_or(pVBInfo->Part2Port, 0x46, ~0x1F, temp);
3603         if (pVBInfo->TVInfo & TVSetPAL) {
3604                 tempbx = 0x0382;
3605                 tempcx = 0x007e;
3606         } else {
3607                 tempbx = 0x0369;
3608                 tempcx = 0x0061;
3609         }
3610
3611         temp = tempbx & 0x00FF;
3612         xgifb_reg_set(pVBInfo->Part2Port, 0x4b, temp);
3613         temp = tempcx & 0x00FF;
3614         xgifb_reg_set(pVBInfo->Part2Port, 0x4c, temp);
3615
3616         temp = ((tempcx & 0xFF00) >> 8) & 0x03;
3617         temp <<= 2;
3618         temp |= ((tempbx & 0xFF00) >> 8) & 0x03;
3619
3620         if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
3621                 temp |= 0x10;
3622
3623                 if (pVBInfo->TVInfo & TVSetYPbPr525p)
3624                         temp |= 0x20;
3625
3626                 if (pVBInfo->TVInfo & TVSetYPbPr750p)
3627                         temp |= 0x60;
3628         }
3629
3630         xgifb_reg_set(pVBInfo->Part2Port, 0x4d, temp);
3631         temp = xgifb_reg_get(pVBInfo->Part2Port, 0x43); /* 301b change */
3632         xgifb_reg_set(pVBInfo->Part2Port, 0x43, (unsigned short) (temp - 3));
3633
3634         if (!(pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))) {
3635                 if (pVBInfo->TVInfo & NTSC1024x768) {
3636                         TimingPoint = XGI_NTSC1024AdjTime;
3637                         for (i = 0x1c, j = 0; i <= 0x30; i++, j++) {
3638                                 xgifb_reg_set(pVBInfo->Part2Port, i,
3639                                                 TimingPoint[j]);
3640                         }
3641                         xgifb_reg_set(pVBInfo->Part2Port, 0x43, 0x72);
3642                 }
3643         }
3644
3645         /* Modify for 301C PALM Support */
3646         if (pVBInfo->VBType & VB_XGI301C) {
3647                 if (pVBInfo->TVInfo & TVSetPALM)
3648                         xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x08,
3649                                         0x08); /* PALM Mode */
3650         }
3651
3652         if (pVBInfo->TVInfo & TVSetPALM) {
3653                 tempax = xgifb_reg_get(pVBInfo->Part2Port, 0x01);
3654                 tempax--;
3655                 xgifb_reg_and(pVBInfo->Part2Port, 0x01, tempax);
3656
3657                 xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xEF);
3658         }
3659
3660         if (pVBInfo->VBInfo & SetCRT2ToHiVision) {
3661                 if (!(pVBInfo->VBInfo & SetInSlaveMode))
3662                         xgifb_reg_set(pVBInfo->Part2Port, 0x0B, 0x00);
3663         }
3664 }
3665
3666 static void XGI_SetLCDRegs(unsigned short ModeIdIndex,
3667                 struct vb_device_info *pVBInfo)
3668 {
3669         unsigned short pushbx, tempax, tempbx, tempcx, temp, tempah,
3670                         tempbh, tempch;
3671
3672         struct XGI_LCDDesStruct const *LCDBDesPtr = NULL;
3673
3674         /* si+Ext_ResInfo */
3675         if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
3676                 return;
3677
3678         tempbx = pVBInfo->HDE; /* RHACTE=HDE-1 */
3679
3680         if (XGI_IsLCDDualLink(pVBInfo))
3681                 tempbx >>= 1;
3682
3683         tempbx -= 1;
3684         temp = tempbx & 0x00FF;
3685         xgifb_reg_set(pVBInfo->Part2Port, 0x2C, temp);
3686         temp = (tempbx & 0xFF00) >> 8;
3687         temp <<= 4;
3688         xgifb_reg_and_or(pVBInfo->Part2Port, 0x2B, 0x0F, temp);
3689         temp = 0x01;
3690
3691         xgifb_reg_set(pVBInfo->Part2Port, 0x0B, temp);
3692         tempbx = pVBInfo->VDE; /* RTVACTEO=(VDE-1)&0xFF */
3693         tempbx--;
3694         temp = tempbx & 0x00FF;
3695         xgifb_reg_set(pVBInfo->Part2Port, 0x03, temp);
3696         temp = ((tempbx & 0xFF00) >> 8) & 0x07;
3697         xgifb_reg_and_or(pVBInfo->Part2Port, 0x0C, ~0x07, temp);
3698
3699         tempcx = pVBInfo->VT - 1;
3700         temp = tempcx & 0x00FF; /* RVTVT=VT-1 */
3701         xgifb_reg_set(pVBInfo->Part2Port, 0x19, temp);
3702         temp = (tempcx & 0xFF00) >> 8;
3703         temp <<= 5;
3704         xgifb_reg_set(pVBInfo->Part2Port, 0x1A, temp);
3705         xgifb_reg_and_or(pVBInfo->Part2Port, 0x09, 0xF0, 0x00);
3706         xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xF0, 0x00);
3707         xgifb_reg_and_or(pVBInfo->Part2Port, 0x17, 0xFB, 0x00);
3708         xgifb_reg_and_or(pVBInfo->Part2Port, 0x18, 0xDF, 0x00);
3709
3710         /* Customized LCDB Does not add */
3711         if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV))
3712                 LCDBDesPtr = XGI_GetLcdPtr(xgifb_lcddldes, ModeIdIndex,
3713                                            pVBInfo);
3714         else
3715                 LCDBDesPtr = XGI_GetLcdPtr(XGI_LCDDesDataTable, ModeIdIndex,
3716                                            pVBInfo);
3717
3718         tempah = pVBInfo->LCDResInfo;
3719         tempah &= PanelResInfo;
3720
3721         if ((tempah == Panel_1024x768) || (tempah == Panel_1024x768x75)) {
3722                 tempbx = 1024;
3723                 tempcx = 768;
3724         } else if ((tempah == Panel_1280x1024) ||
3725                    (tempah == Panel_1280x1024x75)) {
3726                 tempbx = 1280;
3727                 tempcx = 1024;
3728         } else if (tempah == Panel_1400x1050) {
3729                 tempbx = 1400;
3730                 tempcx = 1050;
3731         } else {
3732                 tempbx = 1600;
3733                 tempcx = 1200;
3734         }
3735
3736         if (pVBInfo->LCDInfo & EnableScalingLCD) {
3737                 tempbx = pVBInfo->HDE;
3738                 tempcx = pVBInfo->VDE;
3739         }
3740
3741         pushbx = tempbx;
3742         tempax = pVBInfo->VT;
3743         pVBInfo->LCDHDES = LCDBDesPtr->LCDHDES;
3744         pVBInfo->LCDHRS = LCDBDesPtr->LCDHRS;
3745         pVBInfo->LCDVDES = LCDBDesPtr->LCDVDES;
3746         pVBInfo->LCDVRS = LCDBDesPtr->LCDVRS;
3747         tempbx = pVBInfo->LCDVDES;
3748         tempcx += tempbx;
3749
3750         if (tempcx >= tempax)
3751                 tempcx -= tempax; /* lcdvdes */
3752
3753         temp = tempbx & 0x00FF; /* RVEQ1EQ=lcdvdes */
3754         xgifb_reg_set(pVBInfo->Part2Port, 0x05, temp);
3755         temp = tempcx & 0x00FF;
3756         xgifb_reg_set(pVBInfo->Part2Port, 0x06, temp);
3757         tempch = ((tempcx & 0xFF00) >> 8) & 0x07;
3758         tempbh = ((tempbx & 0xFF00) >> 8) & 0x07;
3759         tempah = tempch;
3760         tempah <<= 3;
3761         tempah |= tempbh;
3762         xgifb_reg_set(pVBInfo->Part2Port, 0x02, tempah);
3763
3764         /* getlcdsync() */
3765         XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
3766         tempcx = tempbx;
3767         tempax = pVBInfo->VT;
3768         tempbx = pVBInfo->LCDVRS;
3769
3770         tempcx += tempbx;
3771         if (tempcx >= tempax)
3772                 tempcx -= tempax;
3773
3774         temp = tempbx & 0x00FF; /* RTVACTEE=lcdvrs */
3775         xgifb_reg_set(pVBInfo->Part2Port, 0x04, temp);
3776         temp = (tempbx & 0xFF00) >> 8;
3777         temp <<= 4;
3778         temp |= (tempcx & 0x000F);
3779         xgifb_reg_set(pVBInfo->Part2Port, 0x01, temp);
3780         tempcx = pushbx;
3781         tempax = pVBInfo->HT;
3782         tempbx = pVBInfo->LCDHDES;
3783         tempbx &= 0x0FFF;
3784
3785         if (XGI_IsLCDDualLink(pVBInfo)) {
3786                 tempax >>= 1;
3787                 tempbx >>= 1;
3788                 tempcx >>= 1;
3789         }
3790
3791         if (pVBInfo->VBType & VB_SIS302LV)
3792                 tempbx += 1;
3793
3794         if (pVBInfo->VBType & VB_XGI301C) /* tap4 */
3795                 tempbx += 1;
3796
3797         tempcx += tempbx;
3798
3799         if (tempcx >= tempax)
3800                 tempcx -= tempax;
3801
3802         temp = tempbx & 0x00FF;
3803         xgifb_reg_set(pVBInfo->Part2Port, 0x1F, temp); /* RHBLKE=lcdhdes */
3804         temp = ((tempbx & 0xFF00) >> 8) << 4;
3805         xgifb_reg_set(pVBInfo->Part2Port, 0x20, temp);
3806         temp = tempcx & 0x00FF;
3807         xgifb_reg_set(pVBInfo->Part2Port, 0x23, temp); /* RHEQPLE=lcdhdee */
3808         temp = (tempcx & 0xFF00) >> 8;
3809         xgifb_reg_set(pVBInfo->Part2Port, 0x25, temp);
3810
3811         XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
3812         tempcx = tempax;
3813         tempax = pVBInfo->HT;
3814         tempbx = pVBInfo->LCDHRS;
3815         if (XGI_IsLCDDualLink(pVBInfo)) {
3816                 tempax >>= 1;
3817                 tempbx >>= 1;
3818                 tempcx >>= 1;
3819         }
3820
3821         if (pVBInfo->VBType & VB_SIS302LV)
3822                 tempbx += 1;
3823
3824         tempcx += tempbx;
3825
3826         if (tempcx >= tempax)
3827                 tempcx -= tempax;
3828
3829         temp = tempbx & 0x00FF; /* RHBURSTS=lcdhrs */
3830         xgifb_reg_set(pVBInfo->Part2Port, 0x1C, temp);
3831
3832         temp = (tempbx & 0xFF00) >> 8;
3833         temp <<= 4;
3834         xgifb_reg_and_or(pVBInfo->Part2Port, 0x1D, ~0x0F0, temp);
3835         temp = tempcx & 0x00FF; /* RHSYEXP2S=lcdhre */
3836         xgifb_reg_set(pVBInfo->Part2Port, 0x21, temp);
3837
3838         if (!(pVBInfo->LCDInfo & XGI_LCDVESATiming)) {
3839                 if (pVBInfo->VGAVDE == 525) {
3840                         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B
3841                                         | VB_SIS301LV | VB_SIS302LV
3842                                         | VB_XGI301C)) {
3843                                 temp = 0xC6;
3844                         } else
3845                                 temp = 0xC4;
3846
3847                         xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp);
3848                         xgifb_reg_set(pVBInfo->Part2Port, 0x30, 0xB3);
3849                 }
3850
3851                 if (pVBInfo->VGAVDE == 420) {
3852                         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B
3853                                         | VB_SIS301LV | VB_SIS302LV
3854                                         | VB_XGI301C)) {
3855                                 temp = 0x4F;
3856                         } else
3857                                 temp = 0x4E;
3858                         xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp);
3859                 }
3860         }
3861 }
3862
3863 /* --------------------------------------------------------------------- */
3864 /* Function : XGI_GetTap4Ptr */
3865 /* Input : */
3866 /* Output : di -> Tap4 Reg. Setting Pointer */
3867 /* Description : */
3868 /* --------------------------------------------------------------------- */
3869 static struct XGI301C_Tap4TimingStruct const
3870 *XGI_GetTap4Ptr(unsigned short tempcx, struct vb_device_info *pVBInfo)
3871 {
3872         unsigned short tempax, tempbx, i;
3873         struct XGI301C_Tap4TimingStruct const *Tap4TimingPtr;
3874
3875         if (tempcx == 0) {
3876                 tempax = pVBInfo->VGAHDE;
3877                 tempbx = pVBInfo->HDE;
3878         } else {
3879                 tempax = pVBInfo->VGAVDE;
3880                 tempbx = pVBInfo->VDE;
3881         }
3882
3883         if (tempax <= tempbx)
3884                 return &xgifb_tap4_timing[0];
3885         Tap4TimingPtr = xgifb_ntsc_525_tap4_timing; /* NTSC */
3886
3887         if (pVBInfo->TVInfo & TVSetPAL)
3888                 Tap4TimingPtr = PALTap4Timing;
3889
3890         if (pVBInfo->VBInfo & SetCRT2ToYPbPr525750) {
3891                 if ((pVBInfo->TVInfo & TVSetYPbPr525i) ||
3892                         (pVBInfo->TVInfo & TVSetYPbPr525p))
3893                         Tap4TimingPtr = xgifb_ntsc_525_tap4_timing;
3894                 if (pVBInfo->TVInfo & TVSetYPbPr750p)
3895                         Tap4TimingPtr = YPbPr750pTap4Timing;
3896         }
3897
3898         if (pVBInfo->VBInfo & SetCRT2ToHiVision)
3899                 Tap4TimingPtr = xgifb_tap4_timing;
3900
3901         i = 0;
3902         while (Tap4TimingPtr[i].DE != 0xFFFF) {
3903                 if (Tap4TimingPtr[i].DE == tempax)
3904                         break;
3905                 i++;
3906         }
3907         return &Tap4TimingPtr[i];
3908 }
3909
3910 static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
3911 {
3912         unsigned short i, j;
3913         struct XGI301C_Tap4TimingStruct const *Tap4TimingPtr;
3914
3915         if (!(pVBInfo->VBType & VB_XGI301C))
3916                 return;
3917
3918         Tap4TimingPtr = XGI_GetTap4Ptr(0, pVBInfo); /* Set Horizontal Scaling */
3919         for (i = 0x80, j = 0; i <= 0xBF; i++, j++)
3920                 xgifb_reg_set(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]);
3921
3922         if ((pVBInfo->VBInfo & SetCRT2ToTV) &&
3923             (!(pVBInfo->VBInfo & SetCRT2ToHiVision))) {
3924                 /* Set Vertical Scaling */
3925                 Tap4TimingPtr = XGI_GetTap4Ptr(1, pVBInfo);
3926                 for (i = 0xC0, j = 0; i < 0xFF; i++, j++)
3927                         xgifb_reg_set(pVBInfo->Part2Port,
3928                                       i,
3929                                       Tap4TimingPtr->Reg[j]);
3930         }
3931
3932         if ((pVBInfo->VBInfo & SetCRT2ToTV) &&
3933             (!(pVBInfo->VBInfo & SetCRT2ToHiVision)))
3934                 /* Enable V.Scaling */
3935                 xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x04);
3936         else
3937                 /* Enable H.Scaling */
3938                 xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x10);
3939 }
3940
3941 static void XGI_SetGroup3(unsigned short ModeIdIndex,
3942                           struct vb_device_info *pVBInfo)
3943 {
3944         unsigned short i;
3945         unsigned char const *tempdi;
3946         unsigned short modeflag;
3947
3948         /* si+Ext_ResInfo */
3949         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3950
3951         xgifb_reg_set(pVBInfo->Part3Port, 0x00, 0x00);
3952         if (pVBInfo->TVInfo & TVSetPAL) {
3953                 xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA);
3954                 xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8);
3955         } else {
3956                 xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xF5);
3957                 xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xB7);
3958         }
3959
3960         if (!(pVBInfo->VBInfo & SetCRT2ToTV))
3961                 return;
3962
3963         if (pVBInfo->TVInfo & TVSetPALM) {
3964                 xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA);
3965                 xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8);
3966                 xgifb_reg_set(pVBInfo->Part3Port, 0x3D, 0xA8);
3967         }
3968
3969         if ((pVBInfo->VBInfo & SetCRT2ToHiVision) || (pVBInfo->VBInfo
3970                         & SetCRT2ToYPbPr525750)) {
3971                 if (pVBInfo->TVInfo & TVSetYPbPr525i)
3972                         return;
3973
3974                 tempdi = XGI330_HiTVGroup3Data;
3975                 if (pVBInfo->SetFlag & TVSimuMode) {
3976                         tempdi = XGI330_HiTVGroup3Simu;
3977                         if (!(modeflag & Charx8Dot))
3978                                 tempdi = XGI330_HiTVGroup3Text;
3979                 }
3980
3981                 if (pVBInfo->TVInfo & TVSetYPbPr525p)
3982                         tempdi = XGI330_Ren525pGroup3;
3983
3984                 if (pVBInfo->TVInfo & TVSetYPbPr750p)
3985                         tempdi = XGI330_Ren750pGroup3;
3986
3987                 for (i = 0; i <= 0x3E; i++)
3988                         xgifb_reg_set(pVBInfo->Part3Port, i, tempdi[i]);
3989
3990                 if (pVBInfo->VBType & VB_XGI301C) { /* Marcovision */
3991                         if (pVBInfo->TVInfo & TVSetYPbPr525p)
3992                                 xgifb_reg_set(pVBInfo->Part3Port, 0x28, 0x3f);
3993                 }
3994         }
3995 }
3996
3997 static void XGI_SetGroup4(unsigned short ModeIdIndex,
3998                 unsigned short RefreshRateTableIndex,
3999                 struct vb_device_info *pVBInfo)
4000 {
4001         unsigned short tempax, tempcx, tempbx, modeflag, temp, temp2;
4002
4003         unsigned long tempebx, tempeax, templong;
4004
4005         /* si+Ext_ResInfo */
4006         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
4007         temp = pVBInfo->RVBHCFACT;
4008         xgifb_reg_set(pVBInfo->Part4Port, 0x13, temp);
4009
4010         tempbx = pVBInfo->RVBHCMAX;
4011         temp = tempbx & 0x00FF;
4012         xgifb_reg_set(pVBInfo->Part4Port, 0x14, temp);
4013         temp2 = ((tempbx & 0xFF00) >> 8) << 7;
4014         tempcx = pVBInfo->VGAHT - 1;
4015         temp = tempcx & 0x00FF;
4016         xgifb_reg_set(pVBInfo->Part4Port, 0x16, temp);
4017
4018         temp = ((tempcx & 0xFF00) >> 8) << 3;
4019         temp2 |= temp;
4020
4021         tempcx = pVBInfo->VGAVT - 1;
4022         if (!(pVBInfo->VBInfo & SetCRT2ToTV))
4023                 tempcx -= 5;
4024
4025         temp = tempcx & 0x00FF;
4026         xgifb_reg_set(pVBInfo->Part4Port, 0x17, temp);
4027         temp = temp2 | ((tempcx & 0xFF00) >> 8);
4028         xgifb_reg_set(pVBInfo->Part4Port, 0x15, temp);
4029         xgifb_reg_or(pVBInfo->Part4Port, 0x0D, 0x08);
4030         tempcx = pVBInfo->VBInfo;
4031         tempbx = pVBInfo->VGAHDE;
4032
4033         if (modeflag & HalfDCLK)
4034                 tempbx >>= 1;
4035
4036         if (XGI_IsLCDDualLink(pVBInfo))
4037                 tempbx >>= 1;
4038
4039         if (tempcx & SetCRT2ToHiVision) {
4040                 temp = 0;
4041                 if (tempbx <= 1024)
4042                         temp = 0xA0;
4043                 if (tempbx == 1280)
4044                         temp = 0xC0;
4045         } else if (tempcx & SetCRT2ToTV) {
4046                 temp = 0xA0;
4047                 if (tempbx <= 800)
4048                         temp = 0x80;
4049         } else {
4050                 temp = 0x80;
4051                 if (pVBInfo->VBInfo & SetCRT2ToLCD) {
4052                         temp = 0;
4053                         if (tempbx > 800)
4054                                 temp = 0x60;
4055                 }
4056         }
4057
4058         if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p)) {
4059                 temp = 0x00;
4060                 if (pVBInfo->VGAHDE == 1280)
4061                         temp = 0x40;
4062                 if (pVBInfo->VGAHDE == 1024)
4063                         temp = 0x20;
4064         }
4065         xgifb_reg_and_or(pVBInfo->Part4Port, 0x0E, ~0xEF, temp);
4066
4067         tempebx = pVBInfo->VDE;
4068
4069         tempcx = pVBInfo->RVBHRS;
4070         temp = tempcx & 0x00FF;
4071         xgifb_reg_set(pVBInfo->Part4Port, 0x18, temp);
4072
4073         tempeax = pVBInfo->VGAVDE;
4074         tempcx |= 0x04000;
4075
4076         if (tempeax <= tempebx) {
4077                 tempcx = tempcx & (~0x4000);
4078                 tempeax = pVBInfo->VGAVDE;
4079         } else {
4080                 tempeax -= tempebx;
4081         }
4082
4083         templong = (tempeax * 256 * 1024) % tempebx;
4084         tempeax = (tempeax * 256 * 1024) / tempebx;
4085         tempebx = tempeax;
4086
4087         if (templong != 0)
4088                 tempebx++;
4089
4090         temp = (unsigned short) (tempebx & 0x000000FF);
4091         xgifb_reg_set(pVBInfo->Part4Port, 0x1B, temp);
4092
4093         temp = (unsigned short) ((tempebx & 0x0000FF00) >> 8);
4094         xgifb_reg_set(pVBInfo->Part4Port, 0x1A, temp);
4095         tempbx = (unsigned short) (tempebx >> 16);
4096         temp = tempbx & 0x00FF;
4097         temp <<= 4;
4098         temp |= ((tempcx & 0xFF00) >> 8);
4099         xgifb_reg_set(pVBInfo->Part4Port, 0x19, temp);
4100
4101         /* 301b */
4102         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4103                         | VB_SIS302LV | VB_XGI301C)) {
4104                 temp = 0x0028;
4105                 xgifb_reg_set(pVBInfo->Part4Port, 0x1C, temp);
4106                 tempax = pVBInfo->VGAHDE;
4107                 if (modeflag & HalfDCLK)
4108                         tempax >>= 1;
4109
4110                 if (XGI_IsLCDDualLink(pVBInfo))
4111                         tempax >>= 1;
4112
4113                 if (pVBInfo->VBInfo & SetCRT2ToLCD) {
4114                         if (tempax > 800)
4115                                 tempax -= 800;
4116                 } else if (pVBInfo->VGAHDE > 800) {
4117                         if (pVBInfo->VGAHDE == 1024)
4118                                 tempax = (tempax * 25 / 32) - 1;
4119                         else
4120                                 tempax = (tempax * 20 / 32) - 1;
4121                 }
4122                 tempax -= 1;
4123
4124                 temp = (tempax & 0xFF00) >> 8;
4125                 temp = (temp & 0x0003) << 4;
4126                 xgifb_reg_set(pVBInfo->Part4Port, 0x1E, temp);
4127                 temp = tempax & 0x00FF;
4128                 xgifb_reg_set(pVBInfo->Part4Port, 0x1D, temp);
4129
4130                 if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVision)) {
4131                         if (pVBInfo->VGAHDE > 800)
4132                                 xgifb_reg_or(pVBInfo->Part4Port, 0x1E, 0x08);
4133
4134                 }
4135                 temp = 0x0036;
4136
4137                 if (pVBInfo->VBInfo & SetCRT2ToTV) {
4138                         if (!(pVBInfo->TVInfo & (NTSC1024x768
4139                                         | TVSetYPbPr525p | TVSetYPbPr750p
4140                                         | TVSetHiVision))) {
4141                                 temp |= 0x0001;
4142                                 if ((pVBInfo->VBInfo & SetInSlaveMode)
4143                                                 && (!(pVBInfo->TVInfo
4144                                                                 & TVSimuMode)))
4145                                         temp &= (~0x0001);
4146                         }
4147                 }
4148
4149                 xgifb_reg_and_or(pVBInfo->Part4Port, 0x1F, 0x00C0, temp);
4150                 tempbx = pVBInfo->HT;
4151                 if (XGI_IsLCDDualLink(pVBInfo))
4152                         tempbx >>= 1;
4153                 tempbx = (tempbx >> 1) - 2;
4154                 temp = ((tempbx & 0x0700) >> 8) << 3;
4155                 xgifb_reg_and_or(pVBInfo->Part4Port, 0x21, 0x00C0, temp);
4156                 temp = tempbx & 0x00FF;
4157                 xgifb_reg_set(pVBInfo->Part4Port, 0x22, temp);
4158         }
4159         /* end 301b */
4160
4161         XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
4162 }
4163
4164 static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo)
4165 {
4166         xgifb_reg_and_or(pVBInfo->P3c4, 0x1E, 0xFF, 0x20);
4167 }
4168
4169 static void XGI_SetGroup5(struct vb_device_info *pVBInfo)
4170 {
4171         if (pVBInfo->ModeType == ModeVGA) {
4172                 if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag
4173                                 | DisableCRT2Display))) {
4174                         XGINew_EnableCRT2(pVBInfo);
4175                 }
4176         }
4177 }
4178
4179 static void XGI_DisableGatingCRT(struct vb_device_info *pVBInfo)
4180 {
4181         xgifb_reg_and_or(pVBInfo->P3d4, 0x63, 0xBF, 0x00);
4182 }
4183
4184 static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info,
4185                 unsigned short ModeNo, unsigned short ModeIdIndex)
4186 {
4187         unsigned short xres, yres, colordepth, modeflag, resindex;
4188
4189         resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
4190         xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
4191         yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
4192         /* si+St_ModeFlag */
4193         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
4194
4195         if (!(modeflag & Charx8Dot)) {
4196                 xres /= 9;
4197                 xres *= 8;
4198         }
4199
4200         if ((ModeNo > 0x13) && (modeflag & HalfDCLK))
4201                 xres *= 2;
4202
4203         if ((ModeNo > 0x13) && (modeflag & DoubleScanMode))
4204                 yres *= 2;
4205
4206         if (xres > xgifb_info->lvds_data.LVDSHDE)
4207                 return 0;
4208
4209         if (yres > xgifb_info->lvds_data.LVDSVDE)
4210                 return 0;
4211
4212         if (xres != xgifb_info->lvds_data.LVDSHDE ||
4213             yres != xgifb_info->lvds_data.LVDSVDE) {
4214                 colordepth = XGI_GetColorDepth(ModeIdIndex);
4215                 if (colordepth > 2)
4216                         return 0;
4217         }
4218         return 1;
4219 }
4220
4221 static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info,
4222                            int chip_id,
4223                            unsigned short ModeIdIndex,
4224                            struct vb_device_info *pVBInfo)
4225 {
4226         unsigned char temp, Miscdata;
4227         unsigned short xres, yres, modeflag, resindex;
4228         unsigned short LVDSHT, LVDSHBS, LVDSHRS, LVDSHRE, LVDSHBE;
4229         unsigned short LVDSVT, LVDSVBS, LVDSVRS, LVDSVRE, LVDSVBE;
4230         unsigned short value;
4231
4232         temp = (unsigned char) ((xgifb_info->lvds_data.LVDS_Capability &
4233                                 (LCDPolarity << 8)) >> 8);
4234         temp &= LCDPolarity;
4235         Miscdata = inb(pVBInfo->P3cc);
4236
4237         outb((Miscdata & 0x3F) | temp, pVBInfo->P3c2);
4238
4239         temp = xgifb_info->lvds_data.LVDS_Capability & LCDPolarity;
4240         /* SR35[7] FP VSync polarity */
4241         xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x80, temp & 0x80);
4242         /* SR30[5] FP HSync polarity */
4243         xgifb_reg_and_or(pVBInfo->P3c4, 0x30, ~0x20, (temp & 0x40) >> 1);
4244
4245         if (chip_id == XG27)
4246                 XGI_SetXG27FPBits(pVBInfo);
4247         else
4248                 XGI_SetXG21FPBits(pVBInfo);
4249
4250         resindex = XGI330_EModeIDTable[ModeIdIndex].Ext_RESINFO;
4251         xres = XGI330_ModeResInfo[resindex].HTotal; /* xres->ax */
4252         yres = XGI330_ModeResInfo[resindex].VTotal; /* yres->bx */
4253         /* si+St_ModeFlag */
4254         modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
4255
4256         if (!(modeflag & Charx8Dot))
4257                 xres = xres * 8 / 9;
4258
4259         LVDSHT = xgifb_info->lvds_data.LVDSHT;
4260
4261         LVDSHBS = xres + (xgifb_info->lvds_data.LVDSHDE - xres) / 2;
4262
4263         if (LVDSHBS > LVDSHT)
4264                 LVDSHBS -= LVDSHT;
4265
4266         LVDSHRS = LVDSHBS + xgifb_info->lvds_data.LVDSHFP;
4267         if (LVDSHRS > LVDSHT)
4268                 LVDSHRS -= LVDSHT;
4269
4270         LVDSHRE = LVDSHRS + xgifb_info->lvds_data.LVDSHSYNC;
4271         if (LVDSHRE > LVDSHT)
4272                 LVDSHRE -= LVDSHT;
4273
4274         LVDSHBE = LVDSHBS + LVDSHT - xgifb_info->lvds_data.LVDSHDE;
4275
4276         LVDSVT = xgifb_info->lvds_data.LVDSVT;
4277
4278         LVDSVBS = yres + (xgifb_info->lvds_data.LVDSVDE - yres) / 2;
4279         if (modeflag & DoubleScanMode)
4280                 LVDSVBS += yres / 2;
4281
4282         if (LVDSVBS > LVDSVT)
4283                 LVDSVBS -= LVDSVT;
4284
4285         LVDSVRS = LVDSVBS + xgifb_info->lvds_data.LVDSVFP;
4286         if (LVDSVRS > LVDSVT)
4287                 LVDSVRS -= LVDSVT;
4288
4289         LVDSVRE = LVDSVRS + xgifb_info->lvds_data.LVDSVSYNC;
4290         if (LVDSVRE > LVDSVT)
4291                 LVDSVRE -= LVDSVT;
4292
4293         LVDSVBE = LVDSVBS + LVDSVT - xgifb_info->lvds_data.LVDSVDE;
4294
4295         temp = xgifb_reg_get(pVBInfo->P3d4, 0x11);
4296         xgifb_reg_set(pVBInfo->P3d4, 0x11, temp & 0x7f); /* Unlock CRTC */
4297
4298         if (!(modeflag & Charx8Dot))
4299                 xgifb_reg_or(pVBInfo->P3c4, 0x1, 0x1);
4300
4301         /* HT SR0B[1:0] CR00 */
4302         value = (LVDSHT >> 3) - 5;
4303         xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x03, (value & 0x300) >> 8);
4304         xgifb_reg_set(pVBInfo->P3d4, 0x0, (value & 0xFF));
4305
4306         /* HBS SR0B[5:4] CR02 */
4307         value = (LVDSHBS >> 3) - 1;
4308         xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x30, (value & 0x300) >> 4);
4309         xgifb_reg_set(pVBInfo->P3d4, 0x2, (value & 0xFF));
4310
4311         /* HBE SR0C[1:0] CR05[7] CR03[4:0] */
4312         value = (LVDSHBE >> 3) - 1;
4313         xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x03, (value & 0xC0) >> 6);
4314         xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x80, (value & 0x20) << 2);
4315         xgifb_reg_and_or(pVBInfo->P3d4, 0x03, ~0x1F, value & 0x1F);
4316
4317         /* HRS SR0B[7:6] CR04 */
4318         value = (LVDSHRS >> 3) + 2;
4319         xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0xC0, (value & 0x300) >> 2);
4320         xgifb_reg_set(pVBInfo->P3d4, 0x4, (value & 0xFF));
4321
4322         /* Panel HRS SR2F[1:0] SR2E[7:0]  */
4323         value--;
4324         xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0x03, (value & 0x300) >> 8);
4325         xgifb_reg_set(pVBInfo->P3c4, 0x2E, (value & 0xFF));
4326
4327         /* HRE SR0C[2] CR05[4:0] */
4328         value = (LVDSHRE >> 3) + 2;
4329         xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x04, (value & 0x20) >> 3);
4330         xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x1F, value & 0x1F);
4331
4332         /* Panel HRE SR2F[7:2]  */
4333         value--;
4334         xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0xFC, value << 2);
4335
4336         /* VT SR0A[0] CR07[5][0] CR06 */
4337         value = LVDSVT - 2;
4338         xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x01, (value & 0x400) >> 10);
4339         xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x20, (value & 0x200) >> 4);
4340         xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x01, (value & 0x100) >> 8);
4341         xgifb_reg_set(pVBInfo->P3d4, 0x06, (value & 0xFF));
4342
4343         /* VBS SR0A[2] CR09[5] CR07[3] CR15 */
4344         value = LVDSVBS - 1;
4345         xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x04, (value & 0x400) >> 8);
4346         xgifb_reg_and_or(pVBInfo->P3d4, 0x09, ~0x20, (value & 0x200) >> 4);
4347         xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x08, (value & 0x100) >> 5);
4348         xgifb_reg_set(pVBInfo->P3d4, 0x15, (value & 0xFF));
4349
4350         /* VBE SR0A[4] CR16 */
4351         value = LVDSVBE - 1;
4352         xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x10, (value & 0x100) >> 4);
4353         xgifb_reg_set(pVBInfo->P3d4, 0x16, (value & 0xFF));
4354
4355         /* VRS SR0A[3] CR7[7][2] CR10 */
4356         value = LVDSVRS - 1;
4357         xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x08, (value & 0x400) >> 7);
4358         xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x80, (value & 0x200) >> 2);
4359         xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x04, (value & 0x100) >> 6);
4360         xgifb_reg_set(pVBInfo->P3d4, 0x10, (value & 0xFF));
4361
4362         if (chip_id == XG27) {
4363                 /* Panel VRS SR35[2:0] SR34[7:0] */
4364                 xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07,
4365                                         (value & 0x700) >> 8);
4366                 xgifb_reg_set(pVBInfo->P3c4, 0x34, value & 0xFF);
4367         } else {
4368                 /* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */
4369                 xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0x03,
4370                                         (value & 0x600) >> 9);
4371                 xgifb_reg_set(pVBInfo->P3c4, 0x34, (value >> 1) & 0xFF);
4372                 xgifb_reg_and_or(pVBInfo->P3d4, 0x33, ~0x01, value & 0x01);
4373         }
4374
4375         /* VRE SR0A[5] CR11[3:0] */
4376         value = LVDSVRE - 1;
4377         xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x20, (value & 0x10) << 1);
4378         xgifb_reg_and_or(pVBInfo->P3d4, 0x11, ~0x0F, value & 0x0F);
4379
4380         /* Panel VRE SR3F[7:2] */
4381         if (chip_id == XG27)
4382                 xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC,
4383                                         (value << 2) & 0xFC);
4384         else
4385                 /* SR3F[7] has to be 0, h/w bug */
4386                 xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC,
4387                                         (value << 2) & 0x7C);
4388
4389         for (temp = 0, value = 0; temp < 3; temp++) {
4390
4391                 xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, value);
4392                 xgifb_reg_set(pVBInfo->P3c4,
4393                               0x2B, xgifb_info->lvds_data.VCLKData1);
4394                 xgifb_reg_set(pVBInfo->P3c4,
4395                               0x2C, xgifb_info->lvds_data.VCLKData2);
4396                 value += 0x10;
4397         }
4398
4399         if (!(modeflag & Charx8Dot)) {
4400                 inb(pVBInfo->P3da); /* reset 3da */
4401                 outb(0x13, pVBInfo->P3c0); /* set index */
4402                 /* set data, panning = 0, shift left 1 dot*/
4403                 outb(0x00, pVBInfo->P3c0);
4404
4405                 inb(pVBInfo->P3da); /* Enable Attribute */
4406                 outb(0x20, pVBInfo->P3c0);
4407
4408                 inb(pVBInfo->P3da); /* reset 3da */
4409         }
4410
4411 }
4412
4413 /* --------------------------------------------------------------------- */
4414 /* Function : XGI_IsLCDON */
4415 /* Input : */
4416 /* Output : 0 : Skip PSC Control */
4417 /* 1: Disable PSC */
4418 /* Description : */
4419 /* --------------------------------------------------------------------- */
4420 static unsigned char XGI_IsLCDON(struct vb_device_info *pVBInfo)
4421 {
4422         unsigned short tempax;
4423
4424         tempax = pVBInfo->VBInfo;
4425         if (tempax & SetCRT2ToDualEdge)
4426                 return 0;
4427         else if (tempax & (DisableCRT2Display | SwitchCRT2 | SetSimuScanMode))
4428                 return 1;
4429
4430         return 0;
4431 }
4432
4433 static void XGI_DisableBridge(struct xgifb_video_info *xgifb_info,
4434                 struct xgi_hw_device_info *HwDeviceExtension,
4435                 struct vb_device_info *pVBInfo)
4436 {
4437         unsigned short tempah = 0;
4438
4439         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4440                         | VB_SIS302LV | VB_XGI301C)) {
4441                 tempah = 0x3F;
4442                 if (!(pVBInfo->VBInfo &
4443                     (DisableCRT2Display | SetSimuScanMode))) {
4444                         if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
4445                                 if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
4446                                         tempah = 0x7F; /* Disable Channel A */
4447                         }
4448                 }
4449
4450                 /* disable part4_1f */
4451                 xgifb_reg_and(pVBInfo->Part4Port, 0x1F, tempah);
4452
4453                 if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
4454                         if (((pVBInfo->VBInfo &
4455                               (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) ||
4456                                 (XGI_IsLCDON(pVBInfo)))
4457                                 /* LVDS Driver power down */
4458                                 xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x80);
4459                 }
4460
4461                 if (pVBInfo->VBInfo & (DisableCRT2Display | XGI_SetCRT2ToLCDA |
4462                                        SetSimuScanMode))
4463                         XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
4464
4465                 if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
4466                         /* Power down */
4467                         xgifb_reg_and(pVBInfo->Part1Port, 0x1e, 0xdf);
4468
4469                 /* disable TV as primary VGA swap */
4470                 xgifb_reg_and(pVBInfo->P3c4, 0x32, 0xdf);
4471
4472                 if ((pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToDualEdge)))
4473                         xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xdf);
4474
4475                 if ((pVBInfo->VBInfo &
4476                         (DisableCRT2Display | SetSimuScanMode)) ||
4477                     ((!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) &&
4478                     (pVBInfo->VBInfo &
4479                         (SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV))))
4480                         xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80);
4481
4482                 if ((pVBInfo->VBInfo &
4483                         (DisableCRT2Display | SetSimuScanMode)) ||
4484                     (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) ||
4485                     (pVBInfo->VBInfo &
4486                         (SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV))) {
4487                         /* save Part1 index 0 */
4488                         tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x00);
4489                         /* BTDAC = 1, avoid VB reset */
4490                         xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x10);
4491                         /* disable CRT2 */
4492                         xgifb_reg_and(pVBInfo->Part1Port, 0x1E, 0xDF);
4493                         /* restore Part1 index 0 */
4494                         xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
4495                 }
4496         } else { /* {301} */
4497                 if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
4498                         xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80);
4499                         /* Disable CRT2 */
4500                         xgifb_reg_and(pVBInfo->Part1Port, 0x1E, 0xDF);
4501                         /* Disable TV asPrimary VGA swap */
4502                         xgifb_reg_and(pVBInfo->P3c4, 0x32, 0xDF);
4503                 }
4504
4505                 if (pVBInfo->VBInfo & (DisableCRT2Display | XGI_SetCRT2ToLCDA
4506                                 | SetSimuScanMode))
4507                         XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
4508         }
4509 }
4510
4511 /* --------------------------------------------------------------------- */
4512 /* Function : XGI_GetTVPtrIndex */
4513 /* Input : */
4514 /* Output : */
4515 /* Description : bx 0 : ExtNTSC */
4516 /* 1 : StNTSC */
4517 /* 2 : ExtPAL */
4518 /* 3 : StPAL */
4519 /* 4 : ExtHiTV */
4520 /* 5 : StHiTV */
4521 /* 6 : Ext525i */
4522 /* 7 : St525i */
4523 /* 8 : Ext525p */
4524 /* 9 : St525p */
4525 /* A : Ext750p */
4526 /* B : St750p */
4527 /* --------------------------------------------------------------------- */
4528 static unsigned short XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo)
4529 {
4530         unsigned short tempbx = 0;
4531
4532         if (pVBInfo->TVInfo & TVSetPAL)
4533                 tempbx = 2;
4534         if (pVBInfo->TVInfo & TVSetHiVision)
4535                 tempbx = 4;
4536         if (pVBInfo->TVInfo & TVSetYPbPr525i)
4537                 tempbx = 6;
4538         if (pVBInfo->TVInfo & TVSetYPbPr525p)
4539                 tempbx = 8;
4540         if (pVBInfo->TVInfo & TVSetYPbPr750p)
4541                 tempbx = 10;
4542         if (pVBInfo->TVInfo & TVSimuMode)
4543                 tempbx++;
4544
4545         return tempbx;
4546 }
4547
4548 /* --------------------------------------------------------------------- */
4549 /* Function : XGI_GetTVPtrIndex2 */
4550 /* Input : */
4551 /* Output : bx 0 : NTSC */
4552 /* 1 : PAL */
4553 /* 2 : PALM */
4554 /* 3 : PALN */
4555 /* 4 : NTSC1024x768 */
4556 /* 5 : PAL-M 1024x768 */
4557 /* 6-7: reserved */
4558 /* cl 0 : YFilter1 */
4559 /* 1 : YFilter2 */
4560 /* ch 0 : 301A */
4561 /* 1 : 301B/302B/301LV/302LV */
4562 /* Description : */
4563 /* --------------------------------------------------------------------- */
4564 static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl,
4565                 unsigned char *tempch, struct vb_device_info *pVBInfo)
4566 {
4567         *tempbx = 0;
4568         *tempcl = 0;
4569         *tempch = 0;
4570
4571         if (pVBInfo->TVInfo & TVSetPAL)
4572                 *tempbx = 1;
4573
4574         if (pVBInfo->TVInfo & TVSetPALM)
4575                 *tempbx = 2;
4576
4577         if (pVBInfo->TVInfo & TVSetPALN)
4578                 *tempbx = 3;
4579
4580         if (pVBInfo->TVInfo & NTSC1024x768) {
4581                 *tempbx = 4;
4582                 if (pVBInfo->TVInfo & TVSetPALM)
4583                         *tempbx = 5;
4584         }
4585
4586         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4587                         | VB_SIS302LV | VB_XGI301C)) {
4588                 if ((!(pVBInfo->VBInfo & SetInSlaveMode)) || (pVBInfo->TVInfo
4589                                 & TVSimuMode)) {
4590                         *tempbx += 8;
4591                         *tempcl += 1;
4592                 }
4593         }
4594
4595         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4596                         | VB_SIS302LV | VB_XGI301C))
4597                 (*tempch)++;
4598 }
4599
4600 static void XGI_SetDelayComp(struct vb_device_info *pVBInfo)
4601 {
4602         unsigned char tempah, tempbl, tempbh;
4603
4604         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4605                         | VB_SIS302LV | VB_XGI301C)) {
4606                 if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA
4607                                 | SetCRT2ToTV | SetCRT2ToRAMDAC)) {
4608                         tempbh = 0;
4609                         tempbl = XGI301TVDelay;
4610
4611                         if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
4612                                 tempbl >>= 4;
4613                         if (pVBInfo->VBInfo &
4614                             (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
4615                                 tempbh = XGI301LCDDelay;
4616
4617                                 if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA))
4618                                         tempbl = tempbh;
4619                         }
4620
4621                         tempbl &= 0x0F;
4622                         tempbh &= 0xF0;
4623                         tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2D);
4624
4625                         if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD
4626                                         | SetCRT2ToTV)) { /* Channel B */
4627                                 tempah &= 0xF0;
4628                                 tempah |= tempbl;
4629                         }
4630
4631                         if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
4632                                 /* Channel A */
4633                                 tempah &= 0x0F;
4634                                 tempah |= tempbh;
4635                         }
4636                         xgifb_reg_set(pVBInfo->Part1Port, 0x2D, tempah);
4637                 }
4638         }
4639 }
4640
4641 static void XGI_SetLCDCap_A(unsigned short tempcx,
4642                             struct vb_device_info *pVBInfo)
4643 {
4644         unsigned short temp;
4645
4646         temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
4647
4648         if (temp & LCDRGB18Bit) {
4649                 xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F,
4650                                 /* Enable Dither */
4651                                 (unsigned short) (0x20 | (tempcx & 0x00C0)));
4652                 xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x80);
4653         } else {
4654                 xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F,
4655                                 (unsigned short) (0x30 | (tempcx & 0x00C0)));
4656                 xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x00);
4657         }
4658 }
4659
4660 /* --------------------------------------------------------------------- */
4661 /* Function : XGI_SetLCDCap_B */
4662 /* Input : cx -> LCD Capability */
4663 /* Output : */
4664 /* Description : */
4665 /* --------------------------------------------------------------------- */
4666 static void XGI_SetLCDCap_B(unsigned short tempcx,
4667                             struct vb_device_info *pVBInfo)
4668 {
4669         if (tempcx & EnableLCD24bpp) /* 24bits */
4670                 xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
4671                                 (unsigned short) (((tempcx & 0x00ff) >> 6)
4672                                                 | 0x0c));
4673         else
4674                 xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
4675                                 (unsigned short) (((tempcx & 0x00ff) >> 6)
4676                                                 | 0x18)); /* Enable Dither */
4677 }
4678
4679 static void XGI_LongWait(struct vb_device_info *pVBInfo)
4680 {
4681         unsigned short i;
4682
4683         i = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
4684
4685         if (!(i & 0xC0)) {
4686                 for (i = 0; i < 0xFFFF; i++) {
4687                         if (!(inb(pVBInfo->P3da) & 0x08))
4688                                 break;
4689                 }
4690
4691                 for (i = 0; i < 0xFFFF; i++) {
4692                         if ((inb(pVBInfo->P3da) & 0x08))
4693                                 break;
4694                 }
4695         }
4696 }
4697
4698 static void SetSpectrum(struct vb_device_info *pVBInfo)
4699 {
4700         unsigned short index;
4701
4702         index = XGI_GetLCDCapPtr(pVBInfo);
4703
4704         /* disable down spectrum D[4] */
4705         xgifb_reg_and(pVBInfo->Part4Port, 0x30, 0x8F);
4706         XGI_LongWait(pVBInfo);
4707         xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x20); /* reset spectrum */
4708         XGI_LongWait(pVBInfo);
4709
4710         xgifb_reg_set(pVBInfo->Part4Port, 0x31,
4711                         pVBInfo->LCDCapList[index].Spectrum_31);
4712         xgifb_reg_set(pVBInfo->Part4Port, 0x32,
4713                         pVBInfo->LCDCapList[index].Spectrum_32);
4714         xgifb_reg_set(pVBInfo->Part4Port, 0x33,
4715                         pVBInfo->LCDCapList[index].Spectrum_33);
4716         xgifb_reg_set(pVBInfo->Part4Port, 0x34,
4717                         pVBInfo->LCDCapList[index].Spectrum_34);
4718         XGI_LongWait(pVBInfo);
4719         xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x40); /* enable spectrum */
4720 }
4721
4722 static void XGI_SetLCDCap(struct vb_device_info *pVBInfo)
4723 {
4724         unsigned short tempcx;
4725
4726         tempcx = pVBInfo->LCDCapList[XGI_GetLCDCapPtr(pVBInfo)].LCD_Capability;
4727
4728         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV |
4729                 VB_SIS302LV | VB_XGI301C)) {
4730                 if (pVBInfo->VBType &
4731                     (VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) {
4732                         /* Set 301LV Capability */
4733                         xgifb_reg_set(pVBInfo->Part4Port, 0x24,
4734                                         (unsigned char) (tempcx & 0x1F));
4735                 }
4736                 /* VB Driving */
4737                 xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D,
4738                                 ~((EnableVBCLKDRVLOW | EnablePLLSPLOW) >> 8),
4739                                 (unsigned short) ((tempcx & (EnableVBCLKDRVLOW
4740                                                 | EnablePLLSPLOW)) >> 8));
4741
4742                 if (pVBInfo->VBInfo & SetCRT2ToLCD)
4743                         XGI_SetLCDCap_B(tempcx, pVBInfo);
4744                 else if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
4745                         XGI_SetLCDCap_A(tempcx, pVBInfo);
4746
4747                 if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
4748                         if (tempcx & EnableSpectrum)
4749                                 SetSpectrum(pVBInfo);
4750                 }
4751         } else {
4752                 /* LVDS,CH7017 */
4753                 XGI_SetLCDCap_A(tempcx, pVBInfo);
4754         }
4755 }
4756
4757 /* --------------------------------------------------------------------- */
4758 /* Function : XGI_SetAntiFlicker */
4759 /* Input : */
4760 /* Output : */
4761 /* Description : Set TV Customized Param. */
4762 /* --------------------------------------------------------------------- */
4763 static void XGI_SetAntiFlicker(struct vb_device_info *pVBInfo)
4764 {
4765         unsigned short tempbx;
4766
4767         unsigned char tempah;
4768
4769         if (pVBInfo->TVInfo & (TVSetYPbPr525p | TVSetYPbPr750p))
4770                 return;
4771
4772         tempbx = XGI_GetTVPtrIndex(pVBInfo);
4773         tempbx &= 0xFE;
4774         tempah = TVAntiFlickList[tempbx];
4775         tempah <<= 4;
4776
4777         xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0x8F, tempah);
4778 }
4779
4780 static void XGI_SetEdgeEnhance(struct vb_device_info *pVBInfo)
4781 {
4782         unsigned short tempbx;
4783
4784         unsigned char tempah;
4785
4786         tempbx = XGI_GetTVPtrIndex(pVBInfo);
4787         tempbx &= 0xFE;
4788         tempah = TVEdgeList[tempbx];
4789         tempah <<= 5;
4790
4791         xgifb_reg_and_or(pVBInfo->Part2Port, 0x3A, 0x1F, tempah);
4792 }
4793
4794 static void XGI_SetPhaseIncr(struct vb_device_info *pVBInfo)
4795 {
4796         unsigned short tempbx;
4797
4798         unsigned char tempcl, tempch;
4799
4800         unsigned long tempData;
4801
4802         XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
4803         tempData = TVPhaseList[tempbx];
4804
4805         xgifb_reg_set(pVBInfo->Part2Port, 0x31, (unsigned short) (tempData
4806                         & 0x000000FF));
4807         xgifb_reg_set(pVBInfo->Part2Port, 0x32, (unsigned short) ((tempData
4808                         & 0x0000FF00) >> 8));
4809         xgifb_reg_set(pVBInfo->Part2Port, 0x33, (unsigned short) ((tempData
4810                         & 0x00FF0000) >> 16));
4811         xgifb_reg_set(pVBInfo->Part2Port, 0x34, (unsigned short) ((tempData
4812                         & 0xFF000000) >> 24));
4813 }
4814
4815 static void XGI_SetYFilter(unsigned short ModeIdIndex,
4816                            struct vb_device_info *pVBInfo)
4817 {
4818         unsigned short tempbx, index;
4819         unsigned char const *filterPtr;
4820         unsigned char tempcl, tempch, tempal;
4821
4822         XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
4823
4824         switch (tempbx) {
4825         case 0x00:
4826         case 0x04:
4827                 filterPtr = NTSCYFilter1;
4828                 break;
4829
4830         case 0x01:
4831                 filterPtr = PALYFilter1;
4832                 break;
4833
4834         case 0x02:
4835         case 0x05:
4836         case 0x0D:
4837         case 0x03:
4838                 filterPtr = xgifb_palmn_yfilter1;
4839                 break;
4840
4841         case 0x08:
4842         case 0x0C:
4843         case 0x0A:
4844         case 0x0B:
4845         case 0x09:
4846                 filterPtr = xgifb_yfilter2;
4847                 break;
4848
4849         default:
4850                 return;
4851         }
4852
4853         tempal = XGI330_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
4854         if (tempcl == 0)
4855                 index = tempal * 4;
4856         else
4857                 index = tempal * 7;
4858
4859         if ((tempcl == 0) && (tempch == 1)) {
4860                 xgifb_reg_set(pVBInfo->Part2Port, 0x35, 0);
4861                 xgifb_reg_set(pVBInfo->Part2Port, 0x36, 0);
4862                 xgifb_reg_set(pVBInfo->Part2Port, 0x37, 0);
4863                 xgifb_reg_set(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
4864         } else {
4865                 xgifb_reg_set(pVBInfo->Part2Port, 0x35, filterPtr[index++]);
4866                 xgifb_reg_set(pVBInfo->Part2Port, 0x36, filterPtr[index++]);
4867                 xgifb_reg_set(pVBInfo->Part2Port, 0x37, filterPtr[index++]);
4868                 xgifb_reg_set(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
4869         }
4870
4871         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
4872                         | VB_SIS302LV | VB_XGI301C)) {
4873                 xgifb_reg_set(pVBInfo->Part2Port, 0x48, filterPtr[index++]);
4874                 xgifb_reg_set(pVBInfo->Part2Port, 0x49, filterPtr[index++]);
4875                 xgifb_reg_set(pVBInfo->Part2Port, 0x4A, filterPtr[index++]);
4876         }
4877 }
4878
4879 /* --------------------------------------------------------------------- */
4880 /* Function : XGI_OEM310Setting */
4881 /* Input : */
4882 /* Output : */
4883 /* Description : Customized Param. for 301 */
4884 /* --------------------------------------------------------------------- */
4885 static void XGI_OEM310Setting(unsigned short ModeIdIndex,
4886                               struct vb_device_info *pVBInfo)
4887 {
4888         XGI_SetDelayComp(pVBInfo);
4889
4890         if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))
4891                 XGI_SetLCDCap(pVBInfo);
4892
4893         if (pVBInfo->VBInfo & SetCRT2ToTV) {
4894                 XGI_SetPhaseIncr(pVBInfo);
4895                 XGI_SetYFilter(ModeIdIndex, pVBInfo);
4896                 XGI_SetAntiFlicker(pVBInfo);
4897
4898                 if (pVBInfo->VBType & VB_SIS301)
4899                         XGI_SetEdgeEnhance(pVBInfo);
4900         }
4901 }
4902
4903 /* --------------------------------------------------------------------- */
4904 /* Function : XGI_SetCRT2ModeRegs */
4905 /* Input : */
4906 /* Output : */
4907 /* Description : Origin code for crt2group */
4908 /* --------------------------------------------------------------------- */
4909 static void XGI_SetCRT2ModeRegs(struct vb_device_info *pVBInfo)
4910 {
4911         unsigned short tempbl;
4912         short tempcl;
4913
4914         unsigned char tempah;
4915
4916         tempah = 0;
4917         if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
4918                 tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x00);
4919                 tempah &= ~0x10; /* BTRAMDAC */
4920                 tempah |= 0x40; /* BTRAM */
4921
4922                 if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV
4923                                 | SetCRT2ToLCD)) {
4924                         tempah = 0x40; /* BTDRAM */
4925                         tempcl = pVBInfo->ModeType;
4926                         tempcl -= ModeVGA;
4927                         if (tempcl >= 0) {
4928                                 /* BT Color */
4929                                 tempah = 0x008 >> tempcl;
4930                                 if (tempah == 0)
4931                                         tempah = 1;
4932                                 tempah |= 0x040;
4933                         }
4934                         if (pVBInfo->VBInfo & SetInSlaveMode)
4935                                 tempah ^= 0x50; /* BTDAC */
4936                 }
4937         }
4938
4939         xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
4940         tempah = 0x08;
4941         tempbl = 0xf0;
4942
4943         if (pVBInfo->VBInfo & DisableCRT2Display)
4944                 goto reg_and_or;
4945
4946         tempah = 0x00;
4947         tempbl = 0xff;
4948
4949         if (!(pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV |
4950                                  SetCRT2ToLCD | XGI_SetCRT2ToLCDA)))
4951                 goto reg_and_or;
4952
4953         if ((pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) &&
4954             (!(pVBInfo->VBInfo & SetSimuScanMode))) {
4955                 tempbl &= 0xf7;
4956                 tempah |= 0x01;
4957                 goto reg_and_or;
4958         }
4959
4960         if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
4961                 tempbl &= 0xf7;
4962                 tempah |= 0x01;
4963         }
4964
4965         if (!(pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD)))
4966                 goto reg_and_or;
4967
4968         tempbl &= 0xf8;
4969         tempah = 0x01;
4970
4971         if (!(pVBInfo->VBInfo & SetInSlaveMode))
4972                 tempah |= 0x02;
4973
4974         if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
4975                 tempah = tempah ^ 0x05;
4976                 if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
4977                         tempah = tempah ^ 0x01;
4978         }
4979
4980         if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge))
4981                 tempah |= 0x08;
4982
4983 reg_and_or:
4984         xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, tempbl, tempah);
4985
4986         if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD
4987                         | XGI_SetCRT2ToLCDA)) {
4988                 tempah &= (~0x08);
4989                 if ((pVBInfo->ModeType == ModeVGA) && (!(pVBInfo->VBInfo
4990                                 & SetInSlaveMode))) {
4991                         tempah |= 0x010;
4992                 }
4993                 tempah |= 0x080;
4994
4995                 if (pVBInfo->VBInfo & SetCRT2ToTV) {
4996                         tempah |= 0x020;
4997                         if (pVBInfo->VBInfo & DriverMode)
4998                                 tempah = tempah ^ 0x20;
4999                 }
5000
5001                 xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D, ~0x0BF, tempah);
5002                 tempah = 0;
5003
5004                 if (pVBInfo->LCDInfo & SetLCDDualLink)
5005                         tempah |= 0x40;
5006
5007                 if (pVBInfo->VBInfo & SetCRT2ToTV) {
5008                         if (pVBInfo->TVInfo & RPLLDIV2XO)
5009                                 tempah |= 0x40;
5010                 }
5011
5012                 if ((pVBInfo->LCDResInfo == Panel_1280x1024)
5013                                 || (pVBInfo->LCDResInfo == Panel_1280x1024x75))
5014                         tempah |= 0x80;
5015
5016                 if (pVBInfo->LCDResInfo == Panel_1280x960)
5017                         tempah |= 0x80;
5018
5019                 xgifb_reg_set(pVBInfo->Part4Port, 0x0C, tempah);
5020         }
5021
5022         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
5023                         | VB_SIS302LV | VB_XGI301C)) {
5024                 tempah = 0;
5025                 tempbl = 0xfb;
5026
5027                 if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
5028                         tempbl = 0xff;
5029                         if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
5030                                 tempah |= 0x04; /* shampoo 0129 */
5031                 }
5032
5033                 xgifb_reg_and_or(pVBInfo->Part1Port, 0x13, tempbl, tempah);
5034                 tempah = 0x00;
5035                 tempbl = 0xcf;
5036                 if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
5037                         if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
5038                                 tempah |= 0x30;
5039                 }
5040
5041                 xgifb_reg_and_or(pVBInfo->Part1Port, 0x2c, tempbl, tempah);
5042                 tempah = 0;
5043                 tempbl = 0x3f;
5044
5045                 if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
5046                         if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
5047                                 tempah |= 0xc0;
5048                 }
5049                 xgifb_reg_and_or(pVBInfo->Part4Port, 0x21, tempbl, tempah);
5050         }
5051
5052         tempah = 0;
5053         tempbl = 0x7f;
5054         if (!(pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) {
5055                 tempbl = 0xff;
5056                 if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge))
5057                         tempah |= 0x80;
5058         }
5059
5060         xgifb_reg_and_or(pVBInfo->Part4Port, 0x23, tempbl, tempah);
5061
5062         if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
5063                 if (pVBInfo->LCDInfo & SetLCDDualLink) {
5064                         xgifb_reg_or(pVBInfo->Part4Port, 0x27, 0x20);
5065                         xgifb_reg_or(pVBInfo->Part4Port, 0x34, 0x10);
5066                 }
5067         }
5068 }
5069
5070 void XGI_UnLockCRT2(struct vb_device_info *pVBInfo)
5071 {
5072         xgifb_reg_and_or(pVBInfo->Part1Port, 0x2f, 0xFF, 0x01);
5073 }
5074
5075 void XGI_LockCRT2(struct vb_device_info *pVBInfo)
5076 {
5077         xgifb_reg_and_or(pVBInfo->Part1Port, 0x2F, 0xFE, 0x00);
5078 }
5079
5080 unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
5081                 unsigned short ModeNo, unsigned short ModeIdIndex,
5082                 struct vb_device_info *pVBInfo)
5083 {
5084         const u8 LCDARefreshIndex[] = {
5085                 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00 };
5086
5087         unsigned short RefreshRateTableIndex, i, index, temp;
5088
5089         index = xgifb_reg_get(pVBInfo->P3d4, 0x33);
5090         index >>= pVBInfo->SelectCRT2Rate;
5091         index &= 0x0F;
5092
5093         if (pVBInfo->LCDInfo & LCDNonExpanding)
5094                 index = 0;
5095
5096         if (index > 0)
5097                 index--;
5098
5099         if (pVBInfo->SetFlag & ProgrammingCRT2) {
5100                 if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) {
5101                         temp = LCDARefreshIndex[pVBInfo->LCDResInfo & 0x07];
5102
5103                         if (index > temp)
5104                                 index = temp;
5105                 }
5106         }
5107
5108         RefreshRateTableIndex = XGI330_EModeIDTable[ModeIdIndex].REFindex;
5109         ModeNo = XGI330_RefIndex[RefreshRateTableIndex].ModeID;
5110         if (pXGIHWDE->jChipType >= XG20) { /* for XG20, XG21, XG27 */
5111                 if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 800) &&
5112                     (XGI330_RefIndex[RefreshRateTableIndex].YRes == 600)) {
5113                         index++;
5114                 }
5115                 /* do the similar adjustment like XGISearchCRT1Rate() */
5116                 if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 1024) &&
5117                     (XGI330_RefIndex[RefreshRateTableIndex].YRes == 768)) {
5118                         index++;
5119                 }
5120                 if ((XGI330_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
5121                     (XGI330_RefIndex[RefreshRateTableIndex].YRes == 1024)) {
5122                         index++;
5123                 }
5124         }
5125
5126         i = 0;
5127         do {
5128                 if (XGI330_RefIndex[RefreshRateTableIndex + i].
5129                         ModeID != ModeNo)
5130                         break;
5131                 temp = XGI330_RefIndex[RefreshRateTableIndex + i].Ext_InfoFlag;
5132                 temp &= ModeTypeMask;
5133                 if (temp < pVBInfo->ModeType)
5134                         break;
5135                 i++;
5136                 index--;
5137
5138         } while (index != 0xFFFF);
5139         if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
5140                 if (pVBInfo->VBInfo & SetInSlaveMode) {
5141                         temp = XGI330_RefIndex[RefreshRateTableIndex + i - 1].
5142                                 Ext_InfoFlag;
5143                         if (temp & InterlaceMode)
5144                                 i++;
5145                 }
5146         }
5147         i--;
5148         if ((pVBInfo->SetFlag & ProgrammingCRT2)) {
5149                 temp = XGI_AjustCRT2Rate(ModeIdIndex, RefreshRateTableIndex,
5150                                          &i, pVBInfo);
5151         }
5152         return RefreshRateTableIndex + i;
5153 }
5154
5155 static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,
5156                 struct xgi_hw_device_info *HwDeviceExtension,
5157                 struct vb_device_info *pVBInfo)
5158 {
5159         unsigned short RefreshRateTableIndex;
5160
5161         pVBInfo->SetFlag |= ProgrammingCRT2;
5162         RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
5163                         ModeIdIndex, pVBInfo);
5164         XGI_GetLVDSResInfo(ModeIdIndex, pVBInfo);
5165         XGI_GetLVDSData(ModeIdIndex, pVBInfo);
5166         XGI_ModCRT1Regs(ModeIdIndex, HwDeviceExtension, pVBInfo);
5167         XGI_SetLVDSRegs(ModeIdIndex, pVBInfo);
5168         XGI_SetCRT2ECLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5169 }
5170
5171 static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
5172                 struct xgi_hw_device_info *HwDeviceExtension,
5173                 struct vb_device_info *pVBInfo)
5174 {
5175         unsigned short ModeIdIndex, RefreshRateTableIndex;
5176
5177         pVBInfo->SetFlag |= ProgrammingCRT2;
5178         XGI_SearchModeID(ModeNo, &ModeIdIndex);
5179         pVBInfo->SelectCRT2Rate = 4;
5180         RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
5181                         ModeIdIndex, pVBInfo);
5182         XGI_SaveCRT2Info(ModeNo, pVBInfo);
5183         XGI_GetCRT2ResInfo(ModeIdIndex, pVBInfo);
5184         XGI_GetCRT2Data(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5185         XGI_PreSetGroup1(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5186         XGI_SetGroup1(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5187         XGI_SetLockRegs(ModeNo, ModeIdIndex, pVBInfo);
5188         XGI_SetGroup2(ModeNo, ModeIdIndex, pVBInfo);
5189         XGI_SetLCDRegs(ModeIdIndex, pVBInfo);
5190         XGI_SetTap4Regs(pVBInfo);
5191         XGI_SetGroup3(ModeIdIndex, pVBInfo);
5192         XGI_SetGroup4(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5193         XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5194         XGI_SetGroup5(pVBInfo);
5195         XGI_AutoThreshold(pVBInfo);
5196         return 1;
5197 }
5198
5199 void XGI_SenseCRT1(struct vb_device_info *pVBInfo)
5200 {
5201         unsigned char CRTCData[17] = { 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81,
5202                         0x0B, 0x3E, 0xE9, 0x0B, 0xDF, 0xE7, 0x04, 0x00, 0x00,
5203                         0x05, 0x00 };
5204
5205         unsigned char SR01 = 0, SR1F = 0, SR07 = 0, SR06 = 0;
5206
5207         unsigned char CR17, CR63, SR31;
5208         unsigned short temp;
5209
5210         int i;
5211
5212         xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
5213
5214         /* to fix XG42 single LCD sense to CRT+LCD */
5215         xgifb_reg_set(pVBInfo->P3d4, 0x57, 0x4A);
5216         xgifb_reg_set(pVBInfo->P3d4, 0x53, (xgifb_reg_get(
5217                         pVBInfo->P3d4, 0x53) | 0x02));
5218
5219         SR31 = xgifb_reg_get(pVBInfo->P3c4, 0x31);
5220         CR63 = xgifb_reg_get(pVBInfo->P3d4, 0x63);
5221         SR01 = xgifb_reg_get(pVBInfo->P3c4, 0x01);
5222
5223         xgifb_reg_set(pVBInfo->P3c4, 0x01, (unsigned char) (SR01 & 0xDF));
5224         xgifb_reg_set(pVBInfo->P3d4, 0x63, (unsigned char) (CR63 & 0xBF));
5225
5226         CR17 = xgifb_reg_get(pVBInfo->P3d4, 0x17);
5227         xgifb_reg_set(pVBInfo->P3d4, 0x17, (unsigned char) (CR17 | 0x80));
5228
5229         SR1F = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
5230         xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char) (SR1F | 0x04));
5231
5232         SR07 = xgifb_reg_get(pVBInfo->P3c4, 0x07);
5233         xgifb_reg_set(pVBInfo->P3c4, 0x07, (unsigned char) (SR07 & 0xFB));
5234         SR06 = xgifb_reg_get(pVBInfo->P3c4, 0x06);
5235         xgifb_reg_set(pVBInfo->P3c4, 0x06, (unsigned char) (SR06 & 0xC3));
5236
5237         xgifb_reg_set(pVBInfo->P3d4, 0x11, 0x00);
5238
5239         for (i = 0; i < 8; i++)
5240                 xgifb_reg_set(pVBInfo->P3d4, (unsigned short) i, CRTCData[i]);
5241
5242         for (i = 8; i < 11; i++)
5243                 xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 8),
5244                                 CRTCData[i]);
5245
5246         for (i = 11; i < 13; i++)
5247                 xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 4),
5248                                 CRTCData[i]);
5249
5250         for (i = 13; i < 16; i++)
5251                 xgifb_reg_set(pVBInfo->P3c4, (unsigned short) (i - 3),
5252                                 CRTCData[i]);
5253
5254         xgifb_reg_set(pVBInfo->P3c4, 0x0E, (unsigned char) (CRTCData[16]
5255                         & 0xE0));
5256
5257         xgifb_reg_set(pVBInfo->P3c4, 0x31, 0x00);
5258         xgifb_reg_set(pVBInfo->P3c4, 0x2B, 0x1B);
5259         xgifb_reg_set(pVBInfo->P3c4, 0x2C, 0xE1);
5260
5261         outb(0x00, pVBInfo->P3c8);
5262
5263         for (i = 0; i < 256 * 3; i++)
5264                 outb(0x0F, (pVBInfo->P3c8 + 1)); /* DAC_TEST_PARMS */
5265
5266         mdelay(1);
5267
5268         XGI_WaitDisply(pVBInfo);
5269         temp = inb(pVBInfo->P3c2);
5270
5271         if (temp & 0x10)
5272                 xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xDF, 0x20);
5273         else
5274                 xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xDF, 0x00);
5275
5276         /* avoid display something, set BLACK DAC if not restore DAC */
5277         outb(0x00, pVBInfo->P3c8);
5278
5279         for (i = 0; i < 256 * 3; i++)
5280                 outb(0, (pVBInfo->P3c8 + 1));
5281
5282         xgifb_reg_set(pVBInfo->P3c4, 0x01, SR01);
5283         xgifb_reg_set(pVBInfo->P3d4, 0x63, CR63);
5284         xgifb_reg_set(pVBInfo->P3c4, 0x31, SR31);
5285
5286         xgifb_reg_set(pVBInfo->P3d4, 0x53, (xgifb_reg_get(
5287                         pVBInfo->P3d4, 0x53) & 0xFD));
5288         xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char) SR1F);
5289 }
5290
5291 static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info,
5292                 struct xgi_hw_device_info *HwDeviceExtension,
5293                 struct vb_device_info *pVBInfo)
5294 {
5295         unsigned short tempah;
5296
5297         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
5298                         | VB_SIS302LV | VB_XGI301C)) {
5299                 if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
5300                         /* Power on */
5301                         xgifb_reg_set(pVBInfo->Part1Port, 0x1E, 0x20);
5302
5303                 if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV |
5304                                        SetCRT2ToRAMDAC)) {
5305                         tempah = xgifb_reg_get(pVBInfo->P3c4, 0x32);
5306                         tempah &= 0xDF;
5307                         if (pVBInfo->VBInfo & SetInSlaveMode) {
5308                                 if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC))
5309                                         tempah |= 0x20;
5310                         }
5311                         xgifb_reg_set(pVBInfo->P3c4, 0x32, tempah);
5312                         xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x20);
5313
5314                         tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2E);
5315
5316                         if (!(tempah & 0x80))
5317                                 xgifb_reg_or(pVBInfo->Part1Port, 0x2E, 0x80);
5318                         xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F);
5319                 }
5320
5321                 if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
5322                         xgifb_reg_and_or(pVBInfo->Part2Port, 0x00, ~0xE0,
5323                                         0x20); /* shampoo 0129 */
5324                         if (pVBInfo->VBType & (VB_SIS302LV | VB_XGI301C)) {
5325                                 if (pVBInfo->VBInfo &
5326                                         (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))
5327                                         /* LVDS PLL power on */
5328                                         xgifb_reg_and(pVBInfo->Part4Port, 0x2A,
5329                                                       0x7F);
5330                                 /* LVDS Driver power on */
5331                                 xgifb_reg_and(pVBInfo->Part4Port, 0x30, 0x7F);
5332                         }
5333                 }
5334
5335                 tempah = 0x00;
5336
5337                 if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
5338                         tempah = 0xc0;
5339
5340                         if (!(pVBInfo->VBInfo & SetSimuScanMode) &&
5341                             (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) &&
5342                             (pVBInfo->VBInfo & SetCRT2ToDualEdge)) {
5343                                 tempah = tempah & 0x40;
5344                                 if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)
5345                                         tempah = tempah ^ 0xC0;
5346                         }
5347                 }
5348
5349                 /* EnablePart4_1F */
5350                 xgifb_reg_or(pVBInfo->Part4Port, 0x1F, tempah);
5351
5352                 XGI_DisableGatingCRT(pVBInfo);
5353                 XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
5354         } /* 301 */
5355         else { /* LVDS */
5356                 if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD
5357                                 | XGI_SetCRT2ToLCDA))
5358                         /* enable CRT2 */
5359                         xgifb_reg_or(pVBInfo->Part1Port, 0x1E, 0x20);
5360
5361                 tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2E);
5362                 if (!(tempah & 0x80))
5363                         xgifb_reg_or(pVBInfo->Part1Port, 0x2E, 0x80);
5364
5365                 xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F);
5366                 XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
5367         } /* End of VB */
5368 }
5369
5370 static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info,
5371                 struct xgi_hw_device_info *HwDeviceExtension,
5372                 unsigned short ModeNo, unsigned short ModeIdIndex,
5373                 struct vb_device_info *pVBInfo)
5374 {
5375         unsigned short RefreshRateTableIndex, temp;
5376
5377         XGI_SetSeqRegs(pVBInfo);
5378         outb(XGI330_StandTable.MISC, pVBInfo->P3c2);
5379         XGI_SetCRTCRegs(pVBInfo);
5380         XGI_SetATTRegs(ModeIdIndex, pVBInfo);
5381         XGI_SetGRCRegs(pVBInfo);
5382         XGI_ClearExt1Regs(pVBInfo);
5383
5384         if (HwDeviceExtension->jChipType == XG27) {
5385                 if (pVBInfo->IF_DEF_LVDS == 0)
5386                         XGI_SetDefaultVCLK(pVBInfo);
5387         }
5388
5389         temp = ~ProgrammingCRT2;
5390         pVBInfo->SetFlag &= temp;
5391         pVBInfo->SelectCRT2Rate = 0;
5392
5393         if (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV
5394                         | VB_SIS302LV | VB_XGI301C)) {
5395                 if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA
5396                                 | SetInSlaveMode)) {
5397                         pVBInfo->SetFlag |= ProgrammingCRT2;
5398                 }
5399         }
5400
5401         RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
5402                         ModeIdIndex, pVBInfo);
5403         if (RefreshRateTableIndex != 0xFFFF) {
5404                 XGI_SetSync(RefreshRateTableIndex, pVBInfo);
5405                 XGI_SetCRT1CRTC(ModeIdIndex, RefreshRateTableIndex,
5406                                 pVBInfo, HwDeviceExtension);
5407                 XGI_SetCRT1DE(ModeIdIndex, RefreshRateTableIndex, pVBInfo);
5408                 XGI_SetCRT1Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
5409                                 HwDeviceExtension, pVBInfo);
5410                 XGI_SetCRT1VCLK(ModeIdIndex, HwDeviceExtension,
5411                                 RefreshRateTableIndex, pVBInfo);
5412         }
5413
5414         if (HwDeviceExtension->jChipType >= XG21) {
5415                 temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
5416                 if (temp & 0xA0) {
5417
5418                         if (HwDeviceExtension->jChipType == XG27)
5419                                 XGI_SetXG27CRTC(RefreshRateTableIndex, pVBInfo);
5420                         else
5421                                 XGI_SetXG21CRTC(RefreshRateTableIndex, pVBInfo);
5422
5423                         XGI_UpdateXG21CRTC(ModeNo, pVBInfo,
5424                                         RefreshRateTableIndex);
5425
5426                         xgifb_set_lcd(HwDeviceExtension->jChipType,
5427                                       pVBInfo, RefreshRateTableIndex);
5428
5429                         if (pVBInfo->IF_DEF_LVDS == 1)
5430                                 xgifb_set_lvds(xgifb_info,
5431                                                 HwDeviceExtension->jChipType,
5432                                                 ModeIdIndex, pVBInfo);
5433                 }
5434         }
5435
5436         pVBInfo->SetFlag &= (~ProgrammingCRT2);
5437         XGI_SetCRT1FIFO(HwDeviceExtension, pVBInfo);
5438         XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeIdIndex,
5439                             RefreshRateTableIndex, pVBInfo);
5440         XGI_LoadDAC(pVBInfo);
5441 }
5442
5443 unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
5444                         struct xgi_hw_device_info *HwDeviceExtension,
5445                         unsigned short ModeNo)
5446 {
5447         unsigned short ModeIdIndex;
5448         struct vb_device_info VBINF;
5449         struct vb_device_info *pVBInfo = &VBINF;
5450
5451         pVBInfo->IF_DEF_LVDS = 0;
5452
5453         if (HwDeviceExtension->jChipType >= XG20)
5454                 pVBInfo->VBType = 0; /*set VBType default 0*/
5455
5456         XGIRegInit(pVBInfo, xgifb_info->vga_base);
5457
5458         /* for x86 Linux, XG21 LVDS */
5459         if (HwDeviceExtension->jChipType == XG21) {
5460                 if ((xgifb_reg_get(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0)
5461                         pVBInfo->IF_DEF_LVDS = 1;
5462         }
5463         if (HwDeviceExtension->jChipType == XG27) {
5464                 if ((xgifb_reg_get(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0) {
5465                         if (xgifb_reg_get(pVBInfo->P3d4, 0x30) & 0x20)
5466                                 pVBInfo->IF_DEF_LVDS = 1;
5467                 }
5468         }
5469
5470         InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
5471         if (ModeNo & 0x80)
5472                 ModeNo = ModeNo & 0x7F;
5473         xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
5474
5475         if (HwDeviceExtension->jChipType < XG20)
5476                 XGI_UnLockCRT2(pVBInfo);
5477
5478         XGI_SearchModeID(ModeNo, &ModeIdIndex);
5479
5480         if (HwDeviceExtension->jChipType < XG20) {
5481                 XGI_GetVBInfo(ModeIdIndex, pVBInfo);
5482                 XGI_GetTVInfo(ModeIdIndex, pVBInfo);
5483                 XGI_GetLCDInfo(ModeIdIndex, pVBInfo);
5484                 XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
5485
5486                 if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA) ||
5487                         (!(pVBInfo->VBInfo & SwitchCRT2))) {
5488                         XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo,
5489                                         ModeIdIndex, pVBInfo);
5490
5491                         if (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA) {
5492                                 XGI_SetLCDAGroup(ModeNo, ModeIdIndex,
5493                                                 HwDeviceExtension, pVBInfo);
5494                         }
5495                 }
5496
5497                 if (pVBInfo->VBInfo & (SetSimuScanMode | SwitchCRT2)) {
5498                         switch (HwDeviceExtension->ujVBChipID) {
5499                         case VB_CHIP_301: /* fall through */
5500                         case VB_CHIP_302:
5501                                 XGI_SetCRT2Group301(ModeNo, HwDeviceExtension,
5502                                                 pVBInfo); /*add for CRT2 */
5503                                 break;
5504
5505                         default:
5506                                 break;
5507                         }
5508                 }
5509
5510                 XGI_SetCRT2ModeRegs(pVBInfo);
5511                 XGI_OEM310Setting(ModeIdIndex, pVBInfo); /*0212*/
5512                 XGI_EnableBridge(xgifb_info, HwDeviceExtension, pVBInfo);
5513         } /* !XG20 */
5514         else {
5515                 if (pVBInfo->IF_DEF_LVDS == 1)
5516                         if (!XGI_XG21CheckLVDSMode(xgifb_info, ModeNo,
5517                                                    ModeIdIndex))
5518                                 return 0;
5519
5520                 pVBInfo->ModeType = XGI330_EModeIDTable[ModeIdIndex].
5521                                                 Ext_ModeFlag & ModeTypeMask;
5522
5523                 pVBInfo->SetFlag = 0;
5524                 pVBInfo->VBInfo = DisableCRT2Display;
5525
5526                 XGI_DisplayOff(xgifb_info, HwDeviceExtension, pVBInfo);
5527
5528                 XGI_SetCRT1Group(xgifb_info, HwDeviceExtension, ModeNo,
5529                                 ModeIdIndex, pVBInfo);
5530
5531                 XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo);
5532         }
5533
5534         XGI_UpdateModeInfo(pVBInfo);
5535
5536         if (HwDeviceExtension->jChipType < XG20)
5537                 XGI_LockCRT2(pVBInfo);
5538
5539         return 1;
5540 }