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