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