Root/drivers/staging/xgifb/vb_setmode.c

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