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