linux/drivers/video/fbdev/sis/init301.c
<<
>>
Prefs
   1/* $XFree86$ */
   2/* $XdotOrg$ */
   3/*
   4 * Mode initializing code (CRT2 section)
   5 * for SiS 300/305/540/630/730,
   6 *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
   7 *     XGI V3XT/V5/V8, Z7
   8 * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
   9 *
  10 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  11 *
  12 * If distributed as part of the Linux kernel, the following license terms
  13 * apply:
  14 *
  15 * * This program is free software; you can redistribute it and/or modify
  16 * * it under the terms of the GNU General Public License as published by
  17 * * the Free Software Foundation; either version 2 of the named License,
  18 * * or any later version.
  19 * *
  20 * * This program is distributed in the hope that it will be useful,
  21 * * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23 * * GNU General Public License for more details.
  24 * *
  25 * * You should have received a copy of the GNU General Public License
  26 * * along with this program; if not, write to the Free Software
  27 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  28 *
  29 * Otherwise, the following license terms apply:
  30 *
  31 * * Redistribution and use in source and binary forms, with or without
  32 * * modification, are permitted provided that the following conditions
  33 * * are met:
  34 * * 1) Redistributions of source code must retain the above copyright
  35 * *    notice, this list of conditions and the following disclaimer.
  36 * * 2) Redistributions in binary form must reproduce the above copyright
  37 * *    notice, this list of conditions and the following disclaimer in the
  38 * *    documentation and/or other materials provided with the distribution.
  39 * * 3) The name of the author may not be used to endorse or promote products
  40 * *    derived from this software without specific prior written permission.
  41 * *
  42 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  43 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  44 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  45 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  46 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  47 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  48 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  49 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  50 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  51 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  52 *
  53 * Author:      Thomas Winischhofer <thomas@winischhofer.net>
  54 *
  55 * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
  56 * Used by permission.
  57 *
  58 */
  59
  60#if 1
  61#define SET_EMI         /* 302LV/ELV: Set EMI values */
  62#endif
  63
  64#if 1
  65#define SET_PWD         /* 301/302LV: Set PWD */
  66#endif
  67
  68#define COMPAL_HACK     /* Needed for Compal 1400x1050 (EMI) */
  69#define COMPAQ_HACK     /* Needed for Inventec/Compaq 1280x1024 (EMI) */
  70#define ASUS_HACK       /* Needed for Asus A2H 1024x768 (EMI) */
  71
  72#include "init301.h"
  73
  74#ifdef CONFIG_FB_SIS_300
  75#include "oem300.h"
  76#endif
  77
  78#ifdef CONFIG_FB_SIS_315
  79#include "oem310.h"
  80#endif
  81
  82#define SiS_I2CDELAY      1000
  83#define SiS_I2CDELAYSHORT  150
  84
  85static unsigned short   SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
  86static void             SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
  87
  88/*********************************************/
  89/*         HELPER: Lock/Unlock CRT2          */
  90/*********************************************/
  91
  92void
  93SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
  94{
  95   if(SiS_Pr->ChipType == XGI_20)
  96      return;
  97   else if(SiS_Pr->ChipType >= SIS_315H)
  98      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
  99   else
 100      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
 101}
 102
 103static
 104void
 105SiS_LockCRT2(struct SiS_Private *SiS_Pr)
 106{
 107   if(SiS_Pr->ChipType == XGI_20)
 108      return;
 109   else if(SiS_Pr->ChipType >= SIS_315H)
 110      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
 111   else
 112      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
 113}
 114
 115/*********************************************/
 116/*            HELPER: Write SR11             */
 117/*********************************************/
 118
 119static void
 120SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
 121{
 122   if(SiS_Pr->ChipType >= SIS_661) {
 123      DataAND &= 0x0f;
 124      DataOR  &= 0x0f;
 125   }
 126   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
 127}
 128
 129/*********************************************/
 130/*    HELPER: Get Pointer to LCD structure   */
 131/*********************************************/
 132
 133#ifdef CONFIG_FB_SIS_315
 134static unsigned char *
 135GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
 136{
 137   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 138   unsigned char  *myptr = NULL;
 139   unsigned short romindex = 0, reg = 0, idx = 0;
 140
 141   /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
 142    * due to the variaty of panels the BIOS doesn't know about.
 143    * Exception: If the BIOS has better knowledge (such as in case
 144    * of machines with a 301C and a panel that does not support DDC)
 145    * use the BIOS data as well.
 146    */
 147
 148   if((SiS_Pr->SiS_ROMNew) &&
 149      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
 150
 151      if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
 152      else                           reg = 0x7d;
 153
 154      idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
 155
 156      if(idx < (8*26)) {
 157         myptr = (unsigned char *)&SiS_LCDStruct661[idx];
 158      }
 159      romindex = SISGETROMW(0x100);
 160      if(romindex) {
 161         romindex += idx;
 162         myptr = &ROMAddr[romindex];
 163      }
 164   }
 165   return myptr;
 166}
 167
 168static unsigned short
 169GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
 170{
 171   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 172   unsigned short romptr = 0;
 173
 174   /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
 175    * due to the variaty of panels the BIOS doesn't know about.
 176    * Exception: If the BIOS has better knowledge (such as in case
 177    * of machines with a 301C and a panel that does not support DDC)
 178    * use the BIOS data as well.
 179    */
 180
 181   if((SiS_Pr->SiS_ROMNew) &&
 182      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
 183      romptr = SISGETROMW(0x102);
 184      romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
 185   }
 186
 187   return romptr;
 188}
 189#endif
 190
 191/*********************************************/
 192/*           Adjust Rate for CRT2            */
 193/*********************************************/
 194
 195static bool
 196SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
 197                unsigned short RRTI, unsigned short *i)
 198{
 199   unsigned short checkmask=0, modeid, infoflag;
 200
 201   modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
 202
 203   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 204
 205      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
 206
 207         checkmask |= SupportRAMDAC2;
 208         if(SiS_Pr->ChipType >= SIS_315H) {
 209            checkmask |= SupportRAMDAC2_135;
 210            if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 211               checkmask |= SupportRAMDAC2_162;
 212               if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
 213                  checkmask |= SupportRAMDAC2_202;
 214               }
 215            }
 216         }
 217
 218      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 219
 220         checkmask |= SupportLCD;
 221         if(SiS_Pr->ChipType >= SIS_315H) {
 222            if(SiS_Pr->SiS_VBType & VB_SISVB) {
 223               if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 224                  if(modeid == 0x2e) checkmask |= Support64048060Hz;
 225               }
 226            }
 227         }
 228
 229      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 230
 231         checkmask |= SupportHiVision;
 232
 233      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
 234
 235         checkmask |= SupportTV;
 236         if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 237            checkmask |= SupportTV1024;
 238            if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
 239               if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
 240                  checkmask |= SupportYPbPr750p;
 241               }
 242            }
 243         }
 244
 245      }
 246
 247   } else {     /* LVDS */
 248
 249      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 250         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 251            checkmask |= SupportCHTV;
 252         }
 253      }
 254
 255      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 256         checkmask |= SupportLCD;
 257      }
 258
 259   }
 260
 261   /* Look backwards in table for matching CRT2 mode */
 262   for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
 263      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
 264      if(infoflag & checkmask) return true;
 265      if((*i) == 0) break;
 266   }
 267
 268   /* Look through the whole mode-section of the table from the beginning
 269    * for a matching CRT2 mode if no mode was found yet.
 270    */
 271   for((*i) = 0; ; (*i)++) {
 272      if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
 273      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
 274      if(infoflag & checkmask) return true;
 275   }
 276   return false;
 277}
 278
 279/*********************************************/
 280/*              Get rate index               */
 281/*********************************************/
 282
 283unsigned short
 284SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 285{
 286   unsigned short RRTI,i,backup_i;
 287   unsigned short modeflag,index,temp,backupindex;
 288   static const unsigned short LCDRefreshIndex[] = {
 289                0x00, 0x00, 0x01, 0x01,
 290                0x01, 0x01, 0x01, 0x01,
 291                0x01, 0x01, 0x01, 0x01,
 292                0x01, 0x01, 0x01, 0x01,
 293                0x00, 0x00, 0x00, 0x00
 294   };
 295
 296   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
 297   if(ModeNo == 0xfe) return 0;
 298
 299   if(ModeNo <= 0x13) {
 300      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
 301   } else {
 302      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 303   }
 304
 305   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 306      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 307         if(modeflag & HalfDCLK) return 0;
 308      }
 309   }
 310
 311   if(ModeNo < 0x14) return 0xFFFF;
 312
 313   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
 314   backupindex = index;
 315
 316   if(index > 0) index--;
 317
 318   if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 319      if(SiS_Pr->SiS_VBType & VB_SISVB) {
 320         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 321            if(SiS_Pr->SiS_VBType & VB_NoLCD)            index = 0;
 322            else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
 323         }
 324         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 325            if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
 326               temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
 327               if(index > temp) index = temp;
 328            }
 329         }
 330      } else {
 331         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
 332         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 333            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
 334         }
 335      }
 336   }
 337
 338   RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
 339   ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
 340
 341   if(SiS_Pr->ChipType >= SIS_315H) {
 342      if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
 343         if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
 344             (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
 345            if(backupindex <= 1) RRTI++;
 346         }
 347      }
 348   }
 349
 350   i = 0;
 351   do {
 352      if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
 353      temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
 354      temp &= ModeTypeMask;
 355      if(temp < SiS_Pr->SiS_ModeType) break;
 356      i++;
 357      index--;
 358   } while(index != 0xFFFF);
 359
 360   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
 361      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
 362         temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
 363         if(temp & InterlaceMode) i++;
 364      }
 365   }
 366
 367   i--;
 368
 369   if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
 370      backup_i = i;
 371      if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
 372         i = backup_i;
 373      }
 374   }
 375
 376   return (RRTI + i);
 377}
 378
 379/*********************************************/
 380/*            STORE CRT2 INFO in CR34        */
 381/*********************************************/
 382
 383static void
 384SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 385{
 386   unsigned short temp1, temp2;
 387
 388   /* Store CRT1 ModeNo in CR34 */
 389   SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
 390   temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
 391   temp2 = ~(SetInSlaveMode >> 8);
 392   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
 393}
 394
 395/*********************************************/
 396/*    HELPER: GET SOME DATA FROM BIOS ROM    */
 397/*********************************************/
 398
 399#ifdef CONFIG_FB_SIS_300
 400static bool
 401SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
 402{
 403   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 404   unsigned short temp,temp1;
 405
 406   if(SiS_Pr->SiS_UseROM) {
 407      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 408         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
 409         temp1 = SISGETROMW(0x23b);
 410         if(temp1 & temp) return true;
 411      }
 412   }
 413   return false;
 414}
 415
 416static bool
 417SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
 418{
 419   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 420   unsigned short temp,temp1;
 421
 422   if(SiS_Pr->SiS_UseROM) {
 423      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 424         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
 425         temp1 = SISGETROMW(0x23d);
 426         if(temp1 & temp) return true;
 427      }
 428   }
 429   return false;
 430}
 431#endif
 432
 433/*********************************************/
 434/*          HELPER: DELAY FUNCTIONS          */
 435/*********************************************/
 436
 437void
 438SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
 439{
 440   while (delaytime-- > 0)
 441      SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
 442}
 443
 444#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 445static void
 446SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 447{
 448   SiS_DDC2Delay(SiS_Pr, delay * 36);
 449}
 450#endif
 451
 452#ifdef CONFIG_FB_SIS_315
 453static void
 454SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 455{
 456   while(delay--) {
 457      SiS_GenericDelay(SiS_Pr, 6623);
 458   }
 459}
 460#endif
 461
 462#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 463static void
 464SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 465{
 466   while(delay--) {
 467      SiS_GenericDelay(SiS_Pr, 66);
 468   }
 469}
 470#endif
 471
 472static void
 473SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
 474{
 475#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 476   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 477   unsigned short PanelID, DelayIndex, Delay=0;
 478#endif
 479
 480   if(SiS_Pr->ChipType < SIS_315H) {
 481
 482#ifdef CONFIG_FB_SIS_300
 483
 484      PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
 485      if(SiS_Pr->SiS_VBType & VB_SISVB) {
 486         if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
 487         if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
 488      }
 489      DelayIndex = PanelID >> 4;
 490      if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
 491         Delay = 3;
 492      } else {
 493         if(DelayTime >= 2) DelayTime -= 2;
 494         if(!(DelayTime & 0x01)) {
 495            Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
 496         } else {
 497            Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
 498         }
 499         if(SiS_Pr->SiS_UseROM) {
 500            if(ROMAddr[0x220] & 0x40) {
 501               if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
 502               else                    Delay = (unsigned short)ROMAddr[0x226];
 503            }
 504         }
 505      }
 506      SiS_ShortDelay(SiS_Pr, Delay);
 507
 508#endif  /* CONFIG_FB_SIS_300 */
 509
 510   } else {
 511
 512#ifdef CONFIG_FB_SIS_315
 513
 514      if((SiS_Pr->ChipType >= SIS_661)    ||
 515         (SiS_Pr->ChipType <= SIS_315PRO) ||
 516         (SiS_Pr->ChipType == SIS_330)    ||
 517         (SiS_Pr->SiS_ROMNew)) {
 518
 519         if(!(DelayTime & 0x01)) {
 520            SiS_DDC2Delay(SiS_Pr, 0x1000);
 521         } else {
 522            SiS_DDC2Delay(SiS_Pr, 0x4000);
 523         }
 524
 525      } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
 526         (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
 527         (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) {                  /* 315 series, LVDS; Special */
 528
 529         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
 530            PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
 531            if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
 532               if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
 533            }
 534            if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
 535               DelayIndex = PanelID & 0x0f;
 536            } else {
 537               DelayIndex = PanelID >> 4;
 538            }
 539            if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
 540               Delay = 3;
 541            } else {
 542               if(DelayTime >= 2) DelayTime -= 2;
 543               if(!(DelayTime & 0x01)) {
 544                  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
 545                } else {
 546                  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
 547               }
 548               if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
 549                  if(ROMAddr[0x13c] & 0x40) {
 550                     if(!(DelayTime & 0x01)) {
 551                        Delay = (unsigned short)ROMAddr[0x17e];
 552                     } else {
 553                        Delay = (unsigned short)ROMAddr[0x17f];
 554                     }
 555                  }
 556               }
 557            }
 558            SiS_ShortDelay(SiS_Pr, Delay);
 559         }
 560
 561      } else if(SiS_Pr->SiS_VBType & VB_SISVB) {                        /* 315 series, all bridges */
 562
 563         DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
 564         if(!(DelayTime & 0x01)) {
 565            Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
 566         } else {
 567            Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
 568         }
 569         Delay <<= 8;
 570         SiS_DDC2Delay(SiS_Pr, Delay);
 571
 572      }
 573
 574#endif /* CONFIG_FB_SIS_315 */
 575
 576   }
 577}
 578
 579#ifdef CONFIG_FB_SIS_315
 580static void
 581SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
 582{
 583   int i;
 584   for(i = 0; i < DelayLoop; i++) {
 585      SiS_PanelDelay(SiS_Pr, DelayTime);
 586   }
 587}
 588#endif
 589
 590/*********************************************/
 591/*    HELPER: WAIT-FOR-RETRACE FUNCTIONS     */
 592/*********************************************/
 593
 594void
 595SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
 596{
 597   unsigned short watchdog;
 598
 599   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
 600   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
 601
 602   watchdog = 65535;
 603   while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
 604   watchdog = 65535;
 605   while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
 606}
 607
 608#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 609static void
 610SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
 611{
 612   unsigned short watchdog;
 613
 614   watchdog = 65535;
 615   while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
 616   watchdog = 65535;
 617   while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
 618}
 619#endif
 620
 621static void
 622SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
 623{
 624   if(SiS_Pr->ChipType < SIS_315H) {
 625#ifdef CONFIG_FB_SIS_300
 626      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 627         if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
 628      }
 629      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
 630         SiS_WaitRetrace1(SiS_Pr);
 631      } else {
 632         SiS_WaitRetrace2(SiS_Pr, 0x25);
 633      }
 634#endif
 635   } else {
 636#ifdef CONFIG_FB_SIS_315
 637      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
 638         SiS_WaitRetrace1(SiS_Pr);
 639      } else {
 640         SiS_WaitRetrace2(SiS_Pr, 0x30);
 641      }
 642#endif
 643   }
 644}
 645
 646static void
 647SiS_VBWait(struct SiS_Private *SiS_Pr)
 648{
 649   unsigned short tempal,temp,i,j;
 650
 651   temp = 0;
 652   for(i = 0; i < 3; i++) {
 653     for(j = 0; j < 100; j++) {
 654        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
 655        if(temp & 0x01) {
 656           if((tempal & 0x08))  continue;
 657           else break;
 658        } else {
 659           if(!(tempal & 0x08)) continue;
 660           else break;
 661        }
 662     }
 663     temp ^= 0x01;
 664   }
 665}
 666
 667static void
 668SiS_VBLongWait(struct SiS_Private *SiS_Pr)
 669{
 670   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 671      SiS_VBWait(SiS_Pr);
 672   } else {
 673      SiS_WaitRetrace1(SiS_Pr);
 674   }
 675}
 676
 677/*********************************************/
 678/*               HELPER: MISC                */
 679/*********************************************/
 680
 681#ifdef CONFIG_FB_SIS_300
 682static bool
 683SiS_Is301B(struct SiS_Private *SiS_Pr)
 684{
 685   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
 686   return false;
 687}
 688#endif
 689
 690static bool
 691SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
 692{
 693   if(SiS_Pr->ChipType == SIS_730) {
 694      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
 695   }
 696   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
 697   return false;
 698}
 699
 700bool
 701SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
 702{
 703#ifdef CONFIG_FB_SIS_315
 704   if(SiS_Pr->ChipType >= SIS_315H) {
 705      if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
 706         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
 707      }
 708   }
 709#endif
 710   return false;
 711}
 712
 713bool
 714SiS_IsVAMode(struct SiS_Private *SiS_Pr)
 715{
 716#ifdef CONFIG_FB_SIS_315
 717   unsigned short flag;
 718
 719   if(SiS_Pr->ChipType >= SIS_315H) {
 720      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
 721      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
 722   }
 723#endif
 724   return false;
 725}
 726
 727#ifdef CONFIG_FB_SIS_315
 728static bool
 729SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
 730{
 731   if(SiS_IsVAMode(SiS_Pr))  return true;
 732   if(SiS_CRT2IsLCD(SiS_Pr)) return true;
 733   return false;
 734}
 735#endif
 736
 737static bool
 738SiS_IsDualLink(struct SiS_Private *SiS_Pr)
 739{
 740#ifdef CONFIG_FB_SIS_315
 741   if(SiS_Pr->ChipType >= SIS_315H) {
 742      if((SiS_CRT2IsLCD(SiS_Pr)) ||
 743         (SiS_IsVAMode(SiS_Pr))) {
 744         if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
 745      }
 746   }
 747#endif
 748   return false;
 749}
 750
 751#ifdef CONFIG_FB_SIS_315
 752static bool
 753SiS_TVEnabled(struct SiS_Private *SiS_Pr)
 754{
 755   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
 756   if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
 757      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
 758   }
 759   return false;
 760}
 761#endif
 762
 763#ifdef CONFIG_FB_SIS_315
 764static bool
 765SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
 766{
 767   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
 768   return false;
 769}
 770#endif
 771
 772#ifdef CONFIG_FB_SIS_315
 773static bool
 774SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
 775{
 776   if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
 777      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
 778   }
 779   return false;
 780}
 781#endif
 782
 783#ifdef CONFIG_FB_SIS_315
 784static bool
 785SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
 786{
 787   unsigned short flag;
 788
 789   if(SiS_Pr->ChipType == SIS_650) {
 790      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
 791      /* Check for revision != A0 only */
 792      if((flag == 0xe0) || (flag == 0xc0) ||
 793         (flag == 0xb0) || (flag == 0x90)) return false;
 794   } else if(SiS_Pr->ChipType >= SIS_661) return false;
 795   return true;
 796}
 797#endif
 798
 799#ifdef CONFIG_FB_SIS_315
 800static bool
 801SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
 802{
 803   if(SiS_Pr->ChipType >= SIS_315H) {
 804      /* YPrPb = 0x08 */
 805      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
 806   }
 807   return false;
 808}
 809#endif
 810
 811#ifdef CONFIG_FB_SIS_315
 812static bool
 813SiS_IsChScart(struct SiS_Private *SiS_Pr)
 814{
 815   if(SiS_Pr->ChipType >= SIS_315H) {
 816      /* Scart = 0x04 */
 817      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
 818   }
 819   return false;
 820}
 821#endif
 822
 823#ifdef CONFIG_FB_SIS_315
 824static bool
 825SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
 826{
 827   unsigned short flag;
 828
 829   if(SiS_Pr->ChipType >= SIS_315H) {
 830      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 831      if(flag & SetCRT2ToTV)        return true;
 832      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
 833      if(flag & EnableCHYPbPr)      return true;  /* = YPrPb = 0x08 */
 834      if(flag & EnableCHScart)      return true;  /* = Scart = 0x04 - TW */
 835   } else {
 836      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 837      if(flag & SetCRT2ToTV)        return true;
 838   }
 839   return false;
 840}
 841#endif
 842
 843#ifdef CONFIG_FB_SIS_315
 844static bool
 845SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
 846{
 847   unsigned short flag;
 848
 849   if(SiS_Pr->ChipType >= SIS_315H) {
 850      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 851      if(flag & SetCRT2ToLCD) return true;
 852      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
 853      if(flag & SetToLCDA)    return true;
 854   } else {
 855      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 856      if(flag & SetCRT2ToLCD) return true;
 857   }
 858   return false;
 859}
 860#endif
 861
 862static bool
 863SiS_HaveBridge(struct SiS_Private *SiS_Pr)
 864{
 865   unsigned short flag;
 866
 867   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 868      return true;
 869   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
 870      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
 871      if((flag == 1) || (flag == 2)) return true;
 872   }
 873   return false;
 874}
 875
 876static bool
 877SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
 878{
 879   unsigned short flag;
 880
 881   if(SiS_HaveBridge(SiS_Pr)) {
 882      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
 883      if(SiS_Pr->ChipType < SIS_315H) {
 884        flag &= 0xa0;
 885        if((flag == 0x80) || (flag == 0x20)) return true;
 886      } else {
 887        flag &= 0x50;
 888        if((flag == 0x40) || (flag == 0x10)) return true;
 889      }
 890   }
 891   return false;
 892}
 893
 894static bool
 895SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
 896{
 897   unsigned short flag1;
 898
 899   flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
 900   if(flag1 & (SetInSlaveMode >> 8)) return true;
 901   return false;
 902}
 903
 904/*********************************************/
 905/*       GET VIDEO BRIDGE CONFIG INFO        */
 906/*********************************************/
 907
 908/* Setup general purpose IO for Chrontel communication */
 909#ifdef CONFIG_FB_SIS_300
 910void
 911SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
 912{
 913   unsigned int   acpibase;
 914   unsigned short temp;
 915
 916   if(!(SiS_Pr->SiS_ChSW)) return;
 917
 918   acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
 919   acpibase &= 0xFFFF;
 920   if(!acpibase) return;
 921   temp = SiS_GetRegShort((acpibase + 0x3c));   /* ACPI register 0x3c: GP Event 1 I/O mode select */
 922   temp &= 0xFEFF;
 923   SiS_SetRegShort((acpibase + 0x3c), temp);
 924   temp = SiS_GetRegShort((acpibase + 0x3c));
 925   temp = SiS_GetRegShort((acpibase + 0x3a));   /* ACPI register 0x3a: GP Pin Level (low/high) */
 926   temp &= 0xFEFF;
 927   if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
 928   SiS_SetRegShort((acpibase + 0x3a), temp);
 929   temp = SiS_GetRegShort((acpibase + 0x3a));
 930}
 931#endif
 932
 933void
 934SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 935                unsigned short ModeIdIndex, int checkcrt2mode)
 936{
 937   unsigned short tempax, tempbx, temp;
 938   unsigned short modeflag, resinfo = 0;
 939
 940   SiS_Pr->SiS_SetFlag = 0;
 941
 942   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
 943
 944   SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
 945
 946   if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
 947      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
 948   }
 949
 950   tempbx = 0;
 951
 952   if(SiS_HaveBridge(SiS_Pr)) {
 953
 954        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 955        tempbx |= temp;
 956        tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
 957        tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
 958        tempbx |= tempax;
 959
 960#ifdef CONFIG_FB_SIS_315
 961        if(SiS_Pr->ChipType >= SIS_315H) {
 962           if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
 963              if(ModeNo == 0x03) {
 964                 /* Mode 0x03 is never in driver mode */
 965                 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
 966              }
 967              if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
 968                 /* Reset LCDA setting if not driver mode */
 969                 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
 970              }
 971              if(IS_SIS650) {
 972                 if(SiS_Pr->SiS_UseLCDA) {
 973                    if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
 974                       if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
 975                          SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
 976                       }
 977                    }
 978                 }
 979              }
 980              temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
 981              if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
 982                 tempbx |= SetCRT2ToLCDA;
 983              }
 984           }
 985
 986           if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
 987              tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
 988              if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
 989                 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
 990                 if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
 991                 else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
 992                    tempbx |= SetCRT2ToYPbPr525750;
 993                 }
 994              }
 995           }
 996
 997           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 998              temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
 999              if(temp & SetToLCDA) {
1000                 tempbx |= SetCRT2ToLCDA;
1001              }
1002              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1003                 if(temp & EnableCHYPbPr) {
1004                    tempbx |= SetCRT2ToCHYPbPr;
1005                 }
1006              }
1007           }
1008        }
1009
1010#endif  /* CONFIG_FB_SIS_315 */
1011
1012        if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
1013           tempbx &= ~(SetCRT2ToRAMDAC);
1014        }
1015
1016        if(SiS_Pr->SiS_VBType & VB_SISVB) {
1017           temp = SetCRT2ToSVIDEO   |
1018                  SetCRT2ToAVIDEO   |
1019                  SetCRT2ToSCART    |
1020                  SetCRT2ToLCDA     |
1021                  SetCRT2ToLCD      |
1022                  SetCRT2ToRAMDAC   |
1023                  SetCRT2ToHiVision |
1024                  SetCRT2ToYPbPr525750;
1025        } else {
1026           if(SiS_Pr->ChipType >= SIS_315H) {
1027              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1028                 temp = SetCRT2ToAVIDEO |
1029                        SetCRT2ToSVIDEO |
1030                        SetCRT2ToSCART  |
1031                        SetCRT2ToLCDA   |
1032                        SetCRT2ToLCD    |
1033                        SetCRT2ToCHYPbPr;
1034              } else {
1035                 temp = SetCRT2ToLCDA   |
1036                        SetCRT2ToLCD;
1037              }
1038           } else {
1039              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1040                 temp = SetCRT2ToTV | SetCRT2ToLCD;
1041              } else {
1042                 temp = SetCRT2ToLCD;
1043              }
1044           }
1045        }
1046
1047        if(!(tempbx & temp)) {
1048           tempax = DisableCRT2Display;
1049           tempbx = 0;
1050        }
1051
1052        if(SiS_Pr->SiS_VBType & VB_SISVB) {
1053
1054           unsigned short clearmask = ( DriverMode |
1055                                DisableCRT2Display |
1056                                LoadDACFlag        |
1057                                SetNotSimuMode     |
1058                                SetInSlaveMode     |
1059                                SetPALTV           |
1060                                SwitchCRT2         |
1061                                SetSimuScanMode );
1062
1063           if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
1064           if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
1065           if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
1066           if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
1067           if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
1068           if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
1069
1070        } else {
1071
1072           if(SiS_Pr->ChipType >= SIS_315H) {
1073              if(tempbx & SetCRT2ToLCDA) {
1074                 tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
1075              }
1076           }
1077           if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1078              if(tempbx & SetCRT2ToTV) {
1079                 tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
1080              }
1081           }
1082           if(tempbx & SetCRT2ToLCD) {
1083              tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
1084           }
1085           if(SiS_Pr->ChipType >= SIS_315H) {
1086              if(tempbx & SetCRT2ToLCDA) {
1087                 tempbx |= SetCRT2ToLCD;
1088              }
1089           }
1090
1091        }
1092
1093        if(tempax & DisableCRT2Display) {
1094           if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1095              tempbx = SetSimuScanMode | DisableCRT2Display;
1096           }
1097        }
1098
1099        if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
1100
1101        /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
1102        if(SiS_Pr->SiS_ModeType <= ModeVGA) {
1103           if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
1104               ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
1105              modeflag &= (~CRT2Mode);
1106           }
1107        }
1108
1109        if(!(tempbx & SetSimuScanMode)) {
1110           if(tempbx & SwitchCRT2) {
1111              if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1112                 if(resinfo != SIS_RI_1600x1200) {
1113                    tempbx |= SetSimuScanMode;
1114                 }
1115              }
1116           } else {
1117              if(SiS_BridgeIsEnabled(SiS_Pr)) {
1118                 if(!(tempbx & DriverMode)) {
1119                    if(SiS_BridgeInSlavemode(SiS_Pr)) {
1120                       tempbx |= SetSimuScanMode;
1121                    }
1122                 }
1123              }
1124           }
1125        }
1126
1127        if(!(tempbx & DisableCRT2Display)) {
1128           if(tempbx & DriverMode) {
1129              if(tempbx & SetSimuScanMode) {
1130                 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1131                    if(resinfo != SIS_RI_1600x1200) {
1132                       tempbx |= SetInSlaveMode;
1133                    }
1134                 }
1135              }
1136           } else {
1137              tempbx |= SetInSlaveMode;
1138           }
1139        }
1140
1141   }
1142
1143   SiS_Pr->SiS_VBInfo = tempbx;
1144
1145#ifdef CONFIG_FB_SIS_300
1146   if(SiS_Pr->ChipType == SIS_630) {
1147      SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1148   }
1149#endif
1150
1151#if 0
1152   printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
1153      SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1154#endif
1155}
1156
1157/*********************************************/
1158/*           DETERMINE YPbPr MODE            */
1159/*********************************************/
1160
1161void
1162SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
1163{
1164
1165   unsigned char temp;
1166
1167   /* Note: This variable is only used on 30xLV systems.
1168    * CR38 has a different meaning on LVDS/CH7019 systems.
1169    * On 661 and later, these bits moved to CR35.
1170    *
1171    * On 301, 301B, only HiVision 1080i is supported.
1172    * On 30xLV, 301C, only YPbPr 1080i is supported.
1173    */
1174
1175   SiS_Pr->SiS_YPbPr = 0;
1176   if(SiS_Pr->ChipType >= SIS_661) return;
1177
1178   if(SiS_Pr->SiS_VBType) {
1179      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1180         SiS_Pr->SiS_YPbPr = YPbPrHiVision;
1181      }
1182   }
1183
1184   if(SiS_Pr->ChipType >= SIS_315H) {
1185      if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1186         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1187         if(temp & 0x08) {
1188            switch((temp >> 4)) {
1189            case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
1190            case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
1191            case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
1192            case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
1193            }
1194         }
1195      }
1196   }
1197
1198}
1199
1200/*********************************************/
1201/*           DETERMINE TVMode flag           */
1202/*********************************************/
1203
1204void
1205SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1206{
1207   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
1208   unsigned short temp, temp1, resinfo = 0, romindex = 0;
1209   unsigned char  OutputSelect = *SiS_Pr->pSiS_OutputSelect;
1210
1211   SiS_Pr->SiS_TVMode = 0;
1212
1213   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
1214   if(SiS_Pr->UseCustomMode) return;
1215
1216   if(ModeNo > 0x13) {
1217      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1218   }
1219
1220   if(SiS_Pr->ChipType < SIS_661) {
1221
1222      if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
1223
1224      if(SiS_Pr->SiS_VBType & VB_SISVB) {
1225         temp = 0;
1226         if((SiS_Pr->ChipType == SIS_630) ||
1227            (SiS_Pr->ChipType == SIS_730)) {
1228            temp = 0x35;
1229            romindex = 0xfe;
1230         } else if(SiS_Pr->ChipType >= SIS_315H) {
1231            temp = 0x38;
1232            if(SiS_Pr->ChipType < XGI_20) {
1233               romindex = 0xf3;
1234               if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
1235            }
1236         }
1237         if(temp) {
1238            if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
1239               OutputSelect = ROMAddr[romindex];
1240               if(!(OutputSelect & EnablePALMN)) {
1241                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
1242               }
1243            }
1244            temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
1245            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1246               if(temp1 & EnablePALM) {         /* 0x40 */
1247                  SiS_Pr->SiS_TVMode |= TVSetPALM;
1248                  SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1249               } else if(temp1 & EnablePALN) {  /* 0x80 */
1250                  SiS_Pr->SiS_TVMode |= TVSetPALN;
1251               }
1252            } else {
1253               if(temp1 & EnableNTSCJ) {        /* 0x40 */
1254                  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1255               }
1256            }
1257         }
1258         /* Translate HiVision/YPbPr to our new flags */
1259         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1260            if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1261            else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1262            else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
1263            else                                        SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1264            if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
1265               SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
1266               SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
1267            } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
1268               SiS_Pr->SiS_TVMode |= TVSetPAL;
1269            }
1270         }
1271      } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1272         if(SiS_Pr->SiS_CHOverScan) {
1273            if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
1274               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1275               if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
1276                  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1277               }
1278            } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1279               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
1280               if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
1281                  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1282               }
1283            }
1284            if(SiS_Pr->SiS_CHSOverScan) {
1285               SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1286            }
1287         }
1288         if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1289            temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1290            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1291               if(temp & EnablePALM)      SiS_Pr->SiS_TVMode |= TVSetPALM;
1292               else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
1293            } else {
1294               if(temp & EnableNTSCJ) {
1295                  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1296               }
1297            }
1298         }
1299      }
1300
1301   } else {  /* 661 and later */
1302
1303      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1304      if(temp1 & 0x01) {
1305         SiS_Pr->SiS_TVMode |= TVSetPAL;
1306         if(temp1 & 0x08) {
1307            SiS_Pr->SiS_TVMode |= TVSetPALN;
1308         } else if(temp1 & 0x04) {
1309            if(SiS_Pr->SiS_VBType & VB_SISVB) {
1310               SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1311            }
1312            SiS_Pr->SiS_TVMode |= TVSetPALM;
1313         }
1314      } else {
1315         if(temp1 & 0x02) {
1316            SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1317         }
1318      }
1319      if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1320         if(SiS_Pr->SiS_CHOverScan) {
1321            if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
1322               SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1323            }
1324         }
1325      }
1326      if(SiS_Pr->SiS_VBType & VB_SISVB) {
1327         if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1328            temp1 &= 0xe0;
1329            if(temp1 == 0x00)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1330            else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1331            else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1332         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1333            SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
1334         }
1335         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
1336            if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
1337               SiS_Pr->SiS_TVMode |= TVAspect169;
1338            } else {
1339               temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
1340               if(temp1 & 0x02) {
1341                  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
1342                     SiS_Pr->SiS_TVMode |= TVAspect169;
1343                  } else {
1344                     SiS_Pr->SiS_TVMode |= TVAspect43LB;
1345                  }
1346               } else {
1347                  SiS_Pr->SiS_TVMode |= TVAspect43;
1348               }
1349            }
1350         }
1351      }
1352   }
1353
1354   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
1355
1356   if(SiS_Pr->SiS_VBType & VB_SISVB) {
1357
1358      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1359         SiS_Pr->SiS_TVMode |= TVSetPAL;
1360         SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
1361      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1362         if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
1363            SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
1364         }
1365      }
1366
1367      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1368         if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
1369            SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1370         }
1371      }
1372
1373      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
1374         if(resinfo == SIS_RI_1024x768) {
1375            if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
1376               SiS_Pr->SiS_TVMode |= TVSet525p1024;
1377            } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
1378               SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
1379            }
1380         }
1381      }
1382
1383      SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
1384      if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
1385         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
1386         SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1387      } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
1388         SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1389      } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
1390         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
1391            SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1392         }
1393      }
1394
1395   }
1396
1397   SiS_Pr->SiS_VBInfo &= ~SetPALTV;
1398}
1399
1400/*********************************************/
1401/*               GET LCD INFO                */
1402/*********************************************/
1403
1404static unsigned short
1405SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
1406{
1407   unsigned short temp = SiS_Pr->SiS_LCDResInfo;
1408   /* Translate my LCDResInfo to BIOS value */
1409   switch(temp) {
1410   case Panel_1280x768_2: temp = Panel_1280x768;    break;
1411   case Panel_1280x800_2: temp = Panel_1280x800;    break;
1412   case Panel_1280x854:   temp = Panel661_1280x854; break;
1413   }
1414   return temp;
1415}
1416
1417static void
1418SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
1419{
1420#ifdef CONFIG_FB_SIS_315
1421   unsigned char  *ROMAddr;
1422   unsigned short temp;
1423
1424   if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
1425      if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
1426         SiS_Pr->SiS_NeedRomModeData = true;
1427         SiS_Pr->PanelHT  = temp;
1428      }
1429      if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
1430         SiS_Pr->SiS_NeedRomModeData = true;
1431         SiS_Pr->PanelVT  = temp;
1432      }
1433      SiS_Pr->PanelHRS = SISGETROMW(10);
1434      SiS_Pr->PanelHRE = SISGETROMW(12);
1435      SiS_Pr->PanelVRS = SISGETROMW(14);
1436      SiS_Pr->PanelVRE = SISGETROMW(16);
1437      SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1438      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
1439         SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
1440      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
1441         SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
1442      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
1443         SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
1444
1445   }
1446#endif
1447}
1448
1449static void
1450SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
1451                        const unsigned char *nonscalingmodes)
1452{
1453   int i = 0;
1454   while(nonscalingmodes[i] != 0xff) {
1455      if(nonscalingmodes[i++] == resinfo) {
1456         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
1457            (SiS_Pr->UsePanelScaler == -1)) {
1458            SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1459         }
1460         break;
1461      }
1462   }
1463}
1464
1465void
1466SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1467{
1468  unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
1469  bool panelcanscale = false;
1470#ifdef CONFIG_FB_SIS_300
1471  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1472  static const unsigned char SiS300SeriesLCDRes[] =
1473          { 0,  1,  2,  3,  7,  4,  5,  8,
1474            0,  0, 10,  0,  0,  0,  0, 15 };
1475#endif
1476#ifdef CONFIG_FB_SIS_315
1477  unsigned char   *myptr = NULL;
1478#endif
1479
1480  SiS_Pr->SiS_LCDResInfo  = 0;
1481  SiS_Pr->SiS_LCDTypeInfo = 0;
1482  SiS_Pr->SiS_LCDInfo     = 0;
1483  SiS_Pr->PanelHRS        = 999; /* HSync start */
1484  SiS_Pr->PanelHRE        = 999; /* HSync end */
1485  SiS_Pr->PanelVRS        = 999; /* VSync start */
1486  SiS_Pr->PanelVRE        = 999; /* VSync end */
1487  SiS_Pr->SiS_NeedRomModeData = false;
1488
1489  /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
1490  SiS_Pr->Alternate1600x1200 = false;
1491
1492  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
1493
1494  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1495
1496  if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
1497     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1498     modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
1499     modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
1500  }
1501
1502  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
1503
1504  /* For broken BIOSes: Assume 1024x768 */
1505  if(temp == 0) temp = 0x02;
1506
1507  if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
1508     SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
1509  } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
1510     SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
1511  } else {
1512     SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1513  }
1514  temp &= 0x0f;
1515#ifdef CONFIG_FB_SIS_300
1516  if(SiS_Pr->ChipType < SIS_315H) {
1517     /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
1518     if(SiS_Pr->SiS_VBType & VB_SIS301) {
1519        if(temp < 0x0f) temp &= 0x07;
1520     }
1521     /* Translate 300 series LCDRes to 315 series for unified usage */
1522     temp = SiS300SeriesLCDRes[temp];
1523  }
1524#endif
1525
1526  /* Translate to our internal types */
1527#ifdef CONFIG_FB_SIS_315
1528  if(SiS_Pr->ChipType == SIS_550) {
1529     if     (temp == Panel310_1152x768)  temp = Panel_320x240_2; /* Verified working */
1530     else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
1531     else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
1532  } else if(SiS_Pr->ChipType >= SIS_661) {
1533     if(temp == Panel661_1280x854)       temp = Panel_1280x854;
1534  }
1535#endif
1536
1537  if(SiS_Pr->SiS_VBType & VB_SISLVDS) {         /* SiS LVDS */
1538     if(temp == Panel310_1280x768) {
1539        temp = Panel_1280x768_2;
1540     }
1541     if(SiS_Pr->SiS_ROMNew) {
1542        if(temp == Panel661_1280x800) {
1543           temp = Panel_1280x800_2;
1544        }
1545     }
1546  }
1547
1548  SiS_Pr->SiS_LCDResInfo = temp;
1549
1550#ifdef CONFIG_FB_SIS_300
1551  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1552     if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
1553        SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
1554     } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
1555        SiS_Pr->SiS_LCDResInfo = Panel_848x480;
1556     } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
1557        SiS_Pr->SiS_LCDResInfo = Panel_856x480;
1558     }
1559  }
1560#endif
1561
1562  if(SiS_Pr->SiS_VBType & VB_SISVB) {
1563     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
1564        SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
1565  } else {
1566     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
1567        SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
1568  }
1569
1570  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
1571  SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
1572  /* Need temp below! */
1573
1574  /* These must/can't scale no matter what */
1575  switch(SiS_Pr->SiS_LCDResInfo) {
1576  case Panel_320x240_1:
1577  case Panel_320x240_2:
1578  case Panel_320x240_3:
1579  case Panel_1280x960:
1580      SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1581      break;
1582  case Panel_640x480:
1583      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1584  }
1585
1586  panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
1587
1588  if(!SiS_Pr->UsePanelScaler)          SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1589  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1590
1591  /* Dual link, Pass 1:1 BIOS default, etc. */
1592#ifdef CONFIG_FB_SIS_315
1593  if(SiS_Pr->ChipType >= SIS_661) {
1594     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1595        if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1596     }
1597     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1598        if(SiS_Pr->SiS_ROMNew) {
1599           if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1600        } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
1601           if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1602        }
1603     }
1604  } else if(SiS_Pr->ChipType >= SIS_315H) {
1605     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1606        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1607     }
1608     if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
1609        SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
1610        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1611        if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
1612        if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1613           if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1614        }
1615     } else if(!(SiS_Pr->SiS_ROMNew)) {
1616        if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1617           if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
1618              (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
1619              SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1620           }
1621           if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
1622              (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
1623              (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
1624              (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
1625              SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1626           }
1627        }
1628     }
1629  }
1630#endif
1631
1632  /* Pass 1:1 */
1633  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
1634     /* Always center screen on LVDS (if scaling is disabled) */
1635     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1636  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1637     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1638        /* Always center screen on SiS LVDS (if scaling is disabled) */
1639        SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1640     } else {
1641        /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
1642        if(panelcanscale)             SiS_Pr->SiS_LCDInfo |= LCDPass11;
1643        if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1644     }
1645  }
1646
1647  SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1648  SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1649
1650  switch(SiS_Pr->SiS_LCDResInfo) {
1651     case Panel_320x240_1:
1652     case Panel_320x240_2:
1653     case Panel_320x240_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
1654                            SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
1655                            SiS_Pr->PanelVCLKIdx300 = VCLK28;
1656                            SiS_Pr->PanelVCLKIdx315 = VCLK28;
1657                            break;
1658     case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
1659                                                      SiS_Pr->PanelVRE  =    3;
1660                            SiS_Pr->PanelVCLKIdx300 = VCLK28;
1661                            SiS_Pr->PanelVCLKIdx315 = VCLK28;
1662                            break;
1663     case Panel_800x600:    SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600;
1664                            SiS_Pr->PanelHT   = 1056; SiS_Pr->PanelVT   =  628;
1665                            SiS_Pr->PanelHRS  =   40; SiS_Pr->PanelHRE  =  128;
1666                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    4;
1667                            SiS_Pr->PanelVCLKIdx300 = VCLK40;
1668                            SiS_Pr->PanelVCLKIdx315 = VCLK40;
1669                            break;
1670     case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
1671                            SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
1672                            SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
1673                            SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
1674                            SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1675                            SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
1676                            break;
1677     case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
1678                            SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
1679                            SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
1680                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1681                            if(SiS_Pr->ChipType < SIS_315H) {
1682                               SiS_Pr->PanelHRS = 23;
1683                                                      SiS_Pr->PanelVRE  =    5;
1684                            }
1685                            SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1686                            SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
1687                            SiS_GetLCDInfoBIOS(SiS_Pr);
1688                            break;
1689     case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
1690                            SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
1691                            SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
1692                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1693                            if(SiS_Pr->ChipType < SIS_315H) {
1694                               SiS_Pr->PanelHRS = 23;
1695                                                      SiS_Pr->PanelVRE  =    5;
1696                            }
1697                            SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1698                            SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
1699                            break;
1700     case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
1701                            break;
1702     case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
1703                            SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
1704                            SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
1705                            SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
1706                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
1707                            /* Data above for TMDS (projector); get from BIOS for LVDS */
1708                            SiS_GetLCDInfoBIOS(SiS_Pr);
1709                            break;
1710     case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
1711                            if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1712                               SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
1713                               SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
1714                               SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
1715                            } else {
1716                               SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
1717                               SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRS  =  112;
1718                               SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1719                               SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
1720                               SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
1721                            }
1722                            break;
1723     case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
1724                            SiS_Pr->PanelHT   = 1660; SiS_Pr->PanelVT   =  806;
1725                            SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
1726                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1727                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
1728                            SiS_GetLCDInfoBIOS(SiS_Pr);
1729                            break;
1730     case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
1731                            SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
1732                            SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
1733                            SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
1734                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
1735                            SiS_GetLCDInfoBIOS(SiS_Pr);
1736                            break;
1737     case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
1738                            SiS_Pr->PanelHT   = 1552; SiS_Pr->PanelVT   =  812;
1739                            SiS_Pr->PanelHRS   =  48; SiS_Pr->PanelHRE  =  112;
1740                            SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
1741                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
1742                            SiS_GetLCDInfoBIOS(SiS_Pr);
1743                            break;
1744     case Panel_1280x854:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  854;
1745                            SiS_Pr->PanelHT   = 1664; SiS_Pr->PanelVT   =  861;
1746                            SiS_Pr->PanelHRS   =  16; SiS_Pr->PanelHRE  =  112;
1747                            SiS_Pr->PanelVRS   =   1; SiS_Pr->PanelVRE  =    3;
1748                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
1749                            SiS_GetLCDInfoBIOS(SiS_Pr);
1750                            break;
1751     case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
1752                            SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
1753                            SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1754                            SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
1755                            if(resinfo == SIS_RI_1280x1024) {
1756                               SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
1757                               SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
1758                            }
1759                            break;
1760     case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
1761                            SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
1762                            SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
1763                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
1764                            SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1765                            SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1766                            SiS_GetLCDInfoBIOS(SiS_Pr);
1767                            break;
1768     case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
1769                            SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
1770                            SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
1771                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
1772                            SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1773                            SiS_GetLCDInfoBIOS(SiS_Pr);
1774                            break;
1775     case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
1776                            SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
1777                            SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
1778                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
1779                            SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
1780                            if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
1781                               if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1782                                  SiS_Pr->PanelHT  = 1760; SiS_Pr->PanelVT  = 1235;
1783                                  SiS_Pr->PanelHRS =   48; SiS_Pr->PanelHRE =   32;
1784                                  SiS_Pr->PanelVRS =    2; SiS_Pr->PanelVRE =    4;
1785                                  SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
1786                                  SiS_Pr->Alternate1600x1200 = true;
1787                               }
1788                            } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
1789                               SiS_Pr->PanelHT  = 2048; SiS_Pr->PanelVT  = 1320;
1790                               SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
1791                               SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
1792                            }
1793                            SiS_GetLCDInfoBIOS(SiS_Pr);
1794                            break;
1795     case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
1796                            SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
1797                            SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
1798                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1799                            SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
1800                            SiS_GetLCDInfoBIOS(SiS_Pr);
1801                            break;
1802     case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
1803                            SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
1804                            break;
1805     case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
1806                            SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
1807                            break;
1808     case Panel_856x480:    SiS_Pr->PanelXRes =  856; SiS_Pr->PanelYRes =  480;
1809                            SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
1810                            break;
1811     case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
1812                            SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
1813                            SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
1814                            SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
1815                            if(SiS_Pr->CP_PreferredIndex != -1) {
1816                               SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
1817                               SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
1818                               SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
1819                               SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
1820                               SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
1821                               SiS_Pr->PanelHRE  = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
1822                               SiS_Pr->PanelVRS  = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
1823                               SiS_Pr->PanelVRE  = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
1824                               SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
1825                               SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
1826                               SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
1827                               SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
1828                               if(SiS_Pr->CP_PrefClock) {
1829                                  int idx;
1830                                  SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1831                                  SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
1832                                  if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
1833                                  else                             idx = VCLK_CUSTOM_315;
1834                                  SiS_Pr->SiS_VCLKData[idx].CLOCK =
1835                                     SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
1836                                  SiS_Pr->SiS_VCLKData[idx].SR2B =
1837                                     SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
1838                                  SiS_Pr->SiS_VCLKData[idx].SR2C =
1839                                     SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
1840                               }
1841                            }
1842                            break;
1843     default:               SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
1844                            SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
1845                            break;
1846  }
1847
1848  /* Special cases */
1849  if( (SiS_Pr->SiS_IF_DEF_FSTN)              ||
1850      (SiS_Pr->SiS_IF_DEF_DSTN)              ||
1851      (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1852      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
1853      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
1854      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
1855     SiS_Pr->PanelHRS = 999;
1856     SiS_Pr->PanelHRE = 999;
1857  }
1858
1859  if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1860      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
1861      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
1862      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
1863     SiS_Pr->PanelVRS = 999;
1864     SiS_Pr->PanelVRE = 999;
1865  }
1866
1867  /* DontExpand overrule */
1868  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
1869
1870     if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
1871        /* No scaling for this mode on any panel (LCD=CRT2)*/
1872        SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1873     }
1874
1875     switch(SiS_Pr->SiS_LCDResInfo) {
1876
1877     case Panel_Custom:
1878     case Panel_1152x864:
1879     case Panel_1280x768:       /* TMDS only */
1880        SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1881        break;
1882
1883     case Panel_800x600: {
1884        static const unsigned char nonscalingmodes[] = {
1885           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
1886        };
1887        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1888        break;
1889     }
1890     case Panel_1024x768: {
1891        static const unsigned char nonscalingmodes[] = {
1892           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1893           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1894           0xff
1895        };
1896        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1897        break;
1898     }
1899     case Panel_1280x720: {
1900        static const unsigned char nonscalingmodes[] = {
1901           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1902           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1903           0xff
1904        };
1905        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1906        if(SiS_Pr->PanelHT == 1650) {
1907           SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1908        }
1909        break;
1910     }
1911     case Panel_1280x768_2: {  /* LVDS only */
1912        static const unsigned char nonscalingmodes[] = {
1913           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1914           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1915           SIS_RI_1152x768,0xff
1916        };
1917        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1918        switch(resinfo) {
1919        case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
1920                                  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1921                               }
1922                               break;
1923        }
1924        break;
1925     }
1926     case Panel_1280x800: {     /* SiS TMDS special (Averatec 6200 series) */
1927        static const unsigned char nonscalingmodes[] = {
1928           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1929           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1930           SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
1931        };
1932        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1933        break;
1934     }
1935     case Panel_1280x800_2:  {  /* SiS LVDS */
1936        static const unsigned char nonscalingmodes[] = {
1937           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1938           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1939           SIS_RI_1152x768,0xff
1940        };
1941        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1942        switch(resinfo) {
1943        case SIS_RI_1280x720:
1944        case SIS_RI_1280x768:  if(SiS_Pr->UsePanelScaler == -1) {
1945                                  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1946                               }
1947                               break;
1948        }
1949        break;
1950     }
1951     case Panel_1280x854: {     /* SiS LVDS */
1952        static const unsigned char nonscalingmodes[] = {
1953           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1954           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1955           SIS_RI_1152x768,0xff
1956        };
1957        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1958        switch(resinfo) {
1959        case SIS_RI_1280x720:
1960        case SIS_RI_1280x768:
1961        case SIS_RI_1280x800:  if(SiS_Pr->UsePanelScaler == -1) {
1962                                  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1963                               }
1964                               break;
1965        }
1966        break;
1967     }
1968     case Panel_1280x960: {
1969        static const unsigned char nonscalingmodes[] = {
1970           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1971           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1972           SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
1973           SIS_RI_1280x854,0xff
1974        };
1975        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1976        break;
1977     }
1978     case Panel_1280x1024: {
1979        static const unsigned char nonscalingmodes[] = {
1980           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1981           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1982           SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
1983           SIS_RI_1280x854,SIS_RI_1280x960,0xff
1984        };
1985        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1986        break;
1987     }
1988     case Panel_1400x1050: {
1989        static const unsigned char nonscalingmodes[] = {
1990             SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1991             SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1992             SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
1993             SIS_RI_1280x960,0xff
1994        };
1995        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1996        switch(resinfo) {
1997        case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
1998                                  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1999                               }
2000                               break;
2001        case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2002                               break;
2003        }
2004        break;
2005     }
2006     case Panel_1600x1200: {
2007        static const unsigned char nonscalingmodes[] = {
2008             SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2009             SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2010             SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2011             SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
2012        };
2013        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2014        break;
2015     }
2016     case Panel_1680x1050: {
2017        static const unsigned char nonscalingmodes[] = {
2018             SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2019             SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2020             SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
2021             SIS_RI_1360x1024,0xff
2022        };
2023        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2024        break;
2025     }
2026     }
2027  }
2028
2029#ifdef CONFIG_FB_SIS_300
2030  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2031     if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2032        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
2033     }
2034  }
2035
2036  if(SiS_Pr->ChipType < SIS_315H) {
2037     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2038        if(SiS_Pr->SiS_UseROM) {
2039           if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
2040              if(!(ROMAddr[0x235] & 0x02)) {
2041                 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2042              }
2043           }
2044        }
2045     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2046        if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
2047           SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2048        }
2049     }
2050  }
2051#endif
2052
2053  /* Special cases */
2054
2055  if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
2056     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2057  }
2058
2059  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
2060     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2061  }
2062
2063  switch(SiS_Pr->SiS_LCDResInfo) {
2064  case Panel_640x480:
2065     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2066     break;
2067  case Panel_1280x800:
2068     /* Don't pass 1:1 by default (TMDS special) */
2069     if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2070     break;
2071  case Panel_1280x960:
2072     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2073     break;
2074  case Panel_Custom:
2075     if((!SiS_Pr->CP_PrefClock) ||
2076        (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
2077        SiS_Pr->SiS_LCDInfo |= LCDPass11;
2078     }
2079     break;
2080  }
2081
2082  if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
2083     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2084  }
2085
2086  /* (In)validate LCDPass11 flag */
2087  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2088     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2089  }
2090
2091  /* LVDS DDA */
2092  if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
2093
2094     if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
2095        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
2096           if(ModeNo == 0x12) {
2097              if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
2098                 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2099              }
2100           } else if(ModeNo > 0x13) {
2101              if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
2102                 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2103                    if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
2104                       SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2105                    }
2106                 }
2107              }
2108           }
2109        }
2110     }
2111
2112     if(modeflag & HalfDCLK) {
2113        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
2114           SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2115        } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
2116           SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2117        } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
2118           SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2119        } else if(ModeNo > 0x13) {
2120           if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
2121              if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2122           } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
2123              if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2124           }
2125        }
2126     }
2127
2128  }
2129
2130  /* VESA timing */
2131  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2132     if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
2133        SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2134     }
2135  } else {
2136     SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2137  }
2138
2139#if 0
2140  printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
2141        SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
2142#endif
2143}
2144
2145/*********************************************/
2146/*                 GET VCLK                  */
2147/*********************************************/
2148
2149unsigned short
2150SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2151                unsigned short RefreshRateTableIndex)
2152{
2153  unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
2154  unsigned short modeflag, resinfo, tempbx;
2155  const unsigned char *CHTVVCLKPtr = NULL;
2156
2157  if(ModeNo <= 0x13) {
2158     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2159     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
2160     CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2161     VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
2162     VCLKIndexGENCRT = VCLKIndexGEN;
2163  } else {
2164     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2165     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2166     CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2167     VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
2168     VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
2169                (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
2170  }
2171
2172  if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
2173
2174     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2175
2176        CRT2Index >>= 6;
2177        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {       /*  LCD */
2178
2179           if(SiS_Pr->ChipType < SIS_315H) {
2180              VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2181              if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2182                 VCLKIndex = VCLKIndexGEN;
2183              }
2184           } else {
2185              VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2186              if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2187                 switch(resinfo) {
2188                 /* Correct those whose IndexGEN doesn't match VBVCLK array */
2189                 case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
2190                 case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
2191                 case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
2192                 case SIS_RI_848x480:  VCLKIndex = VCLK_848x480;  break;
2193                 case SIS_RI_856x480:  VCLKIndex = VCLK_856x480;  break;
2194                 case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
2195                 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
2196                 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
2197                 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
2198                 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
2199                 default:              VCLKIndex = VCLKIndexGEN;
2200                 }
2201
2202                 if(ModeNo <= 0x13) {
2203                    if(SiS_Pr->ChipType <= SIS_315PRO) {
2204                       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
2205                    } else {
2206                       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
2207                    }
2208                 }
2209                 if(SiS_Pr->ChipType <= SIS_315PRO) {
2210                    if(VCLKIndex == 0) VCLKIndex = 0x41;
2211                    if(VCLKIndex == 1) VCLKIndex = 0x43;
2212                    if(VCLKIndex == 4) VCLKIndex = 0x44;
2213                 }
2214              }
2215           }
2216
2217        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                   /*  TV */
2218
2219           if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2220              if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)        VCLKIndex = HiTVVCLKDIV2;
2221              else                                         VCLKIndex = HiTVVCLK;
2222              if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     VCLKIndex = HiTVSimuVCLK;
2223           } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  VCLKIndex = YPbPr750pVCLK;
2224           else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)    VCLKIndex = TVVCLKDIV2;
2225           else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)      VCLKIndex = TVVCLKDIV2;
2226           else                                            VCLKIndex = TVVCLK;
2227
2228           if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
2229           else                            VCLKIndex += TVCLKBASE_315;
2230
2231        } else {                                                        /* VGA2 */
2232
2233           VCLKIndex = VCLKIndexGENCRT;
2234           if(SiS_Pr->ChipType < SIS_315H) {
2235              if(ModeNo > 0x13) {
2236                 if( (SiS_Pr->ChipType == SIS_630) &&
2237                     (SiS_Pr->ChipRevision >= 0x30)) {
2238                    if(VCLKIndex == 0x14) VCLKIndex = 0x34;
2239                 }
2240                 /* Better VGA2 clock for 1280x1024@75 */
2241                 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
2242              }
2243           }
2244        }
2245
2246     } else {   /* If not programming CRT2 */
2247
2248        VCLKIndex = VCLKIndexGENCRT;
2249        if(SiS_Pr->ChipType < SIS_315H) {
2250           if(ModeNo > 0x13) {
2251              if( (SiS_Pr->ChipType != SIS_630) &&
2252                  (SiS_Pr->ChipType != SIS_300) ) {
2253                 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2254              }
2255           }
2256        }
2257     }
2258
2259  } else {       /*   LVDS  */
2260
2261     VCLKIndex = CRT2Index;
2262
2263     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2264
2265        if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
2266
2267           VCLKIndex &= 0x1f;
2268           tempbx = 0;
2269           if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2270           if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2271              tempbx += 2;
2272              if(SiS_Pr->SiS_ModeType > ModeVGA) {
2273                 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
2274              }
2275              if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2276                 tempbx = 4;
2277                 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2278              } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2279                 tempbx = 6;
2280                 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2281              }
2282           }
2283           switch(tempbx) {
2284             case  0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC;  break;
2285             case  1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC;  break;
2286             case  2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL;   break;
2287             case  3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
2288             case  4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM;  break;
2289             case  5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM;  break;
2290             case  6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN;  break;
2291             case  7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN;  break;
2292             case  8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL;  break;
2293             default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
2294           }
2295           VCLKIndex = CHTVVCLKPtr[VCLKIndex];
2296
2297        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2298
2299           if(SiS_Pr->ChipType < SIS_315H) {
2300              VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2301           } else {
2302              VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2303           }
2304
2305#ifdef CONFIG_FB_SIS_300
2306           /* Special Timing: Barco iQ Pro R series */
2307           if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2308
2309           /* Special Timing: 848x480 and 856x480 parallel lvds panels */
2310           if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2311              if(SiS_Pr->ChipType < SIS_315H) {
2312                 VCLKIndex = VCLK34_300;
2313                 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2314              } else {
2315                 VCLKIndex = VCLK34_315;
2316                 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2317              }
2318           }
2319#endif
2320
2321        } else {
2322
2323           VCLKIndex = VCLKIndexGENCRT;
2324           if(SiS_Pr->ChipType < SIS_315H) {
2325              if(ModeNo > 0x13) {
2326                 if( (SiS_Pr->ChipType == SIS_630) &&
2327                     (SiS_Pr->ChipRevision >= 0x30) ) {
2328                    if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
2329                 }
2330              }
2331           }
2332        }
2333
2334     } else {  /* if not programming CRT2 */
2335
2336        VCLKIndex = VCLKIndexGENCRT;
2337        if(SiS_Pr->ChipType < SIS_315H) {
2338           if(ModeNo > 0x13) {
2339              if( (SiS_Pr->ChipType != SIS_630) &&
2340                  (SiS_Pr->ChipType != SIS_300) ) {
2341                 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2342              }
2343#if 0
2344              if(SiS_Pr->ChipType == SIS_730) {
2345                 if(VCLKIndex == 0x0b) VCLKIndex = 0x40;   /* 1024x768-70 */
2346                 if(VCLKIndex == 0x0d) VCLKIndex = 0x41;   /* 1024x768-75 */
2347              }
2348#endif
2349           }
2350        }
2351
2352     }
2353
2354  }
2355
2356  return VCLKIndex;
2357}
2358
2359/*********************************************/
2360/*        SET CRT2 MODE TYPE REGISTERS       */
2361/*********************************************/
2362
2363static void
2364SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2365{
2366  unsigned short i, j, modeflag, tempah=0;
2367  short tempcl;
2368#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2369  unsigned short tempbl;
2370#endif
2371#ifdef CONFIG_FB_SIS_315
2372  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
2373  unsigned short tempah2, tempbl2;
2374#endif
2375
2376  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2377
2378  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2379
2380     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
2381     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
2382
2383  } else {
2384
2385     for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
2386     if(SiS_Pr->ChipType >= SIS_315H) {
2387        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
2388     }
2389
2390     tempcl = SiS_Pr->SiS_ModeType;
2391
2392     if(SiS_Pr->ChipType < SIS_315H) {
2393
2394#ifdef CONFIG_FB_SIS_300    /* ---- 300 series ---- */
2395
2396        /* For 301BDH: (with LCD via LVDS) */
2397        if(SiS_Pr->SiS_VBType & VB_NoLCD) {
2398           tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
2399           tempbl &= 0xef;
2400           tempbl |= 0x02;
2401           if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2402              tempbl |= 0x10;
2403              tempbl &= 0xfd;
2404           }
2405           SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
2406        }
2407
2408        if(ModeNo > 0x13) {
2409           tempcl -= ModeVGA;
2410           if(tempcl >= 0) {
2411              tempah = ((0x10 >> tempcl) | 0x80);
2412           }
2413        } else tempah = 0x80;
2414
2415        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  tempah ^= 0xA0;
2416
2417#endif  /* CONFIG_FB_SIS_300 */
2418
2419     } else {
2420
2421#ifdef CONFIG_FB_SIS_315    /* ------- 315/330 series ------ */
2422
2423        if(ModeNo > 0x13) {
2424           tempcl -= ModeVGA;
2425           if(tempcl >= 0) {
2426              tempah = (0x08 >> tempcl);
2427              if (tempah == 0) tempah = 1;
2428              tempah |= 0x40;
2429           }
2430        } else tempah = 0x40;
2431
2432        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
2433
2434#endif  /* CONFIG_FB_SIS_315 */
2435
2436     }
2437
2438     if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2439
2440     if(SiS_Pr->ChipType < SIS_315H) {
2441        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2442     } else {
2443#ifdef CONFIG_FB_SIS_315
2444        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2445           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2446        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2447           if(IS_SIS740) {
2448              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2449           } else {
2450              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2451           }
2452        }
2453#endif
2454     }
2455
2456     if(SiS_Pr->SiS_VBType & VB_SISVB) {
2457
2458        tempah = 0x01;
2459        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2460           tempah |= 0x02;
2461        }
2462        if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2463           tempah ^= 0x05;
2464           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
2465              tempah ^= 0x01;
2466           }
2467        }
2468
2469        if(SiS_Pr->ChipType < SIS_315H) {
2470
2471           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
2472
2473           tempah = (tempah << 5) & 0xFF;
2474           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2475           tempah = (tempah >> 5) & 0xFF;
2476
2477        } else {
2478
2479           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0x08;
2480           else if(!(SiS_IsDualEdge(SiS_Pr)))           tempah |= 0x08;
2481           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
2482           tempah &= ~0x08;
2483
2484        }
2485
2486        if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
2487           tempah |= 0x10;
2488        }
2489
2490        tempah |= 0x80;
2491        if(SiS_Pr->SiS_VBType & VB_SIS301) {
2492           if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
2493        }
2494
2495        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2496           if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
2497              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2498                 tempah |= 0x20;
2499              }
2500           }
2501        }
2502
2503        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
2504
2505        tempah = 0x80;
2506        if(SiS_Pr->SiS_VBType & VB_SIS301) {
2507           if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
2508        }
2509
2510        if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
2511
2512        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2513           if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
2514              tempah |= 0x40;
2515           }
2516        }
2517
2518        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
2519
2520     } else {  /* LVDS */
2521
2522        if(SiS_Pr->ChipType >= SIS_315H) {
2523
2524#ifdef CONFIG_FB_SIS_315
2525           /* LVDS can only be slave in 8bpp modes */
2526           tempah = 0x80;
2527           if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
2528              if(SiS_Pr->SiS_VBInfo & DriverMode) {
2529                 tempah |= 0x02;
2530              }
2531           }
2532
2533           if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  tempah |= 0x02;
2534
2535           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)        tempah ^= 0x01;
2536
2537           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
2538
2539           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
2540#endif
2541
2542        } else {
2543
2544#ifdef CONFIG_FB_SIS_300
2545           tempah = 0;
2546           if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
2547              tempah |= 0x02;
2548           }
2549           tempah <<= 5;
2550
2551           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2552
2553           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2554#endif
2555
2556        }
2557
2558     }
2559
2560  }  /* LCDA */
2561
2562  if(SiS_Pr->SiS_VBType & VB_SISVB) {
2563
2564     if(SiS_Pr->ChipType >= SIS_315H) {
2565
2566#ifdef CONFIG_FB_SIS_315
2567        /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
2568
2569        /* The following is nearly unpreditable and varies from machine
2570         * to machine. Especially the 301DH seems to be a real trouble
2571         * maker. Some BIOSes simply set the registers (like in the
2572         * NoLCD-if-statements here), some set them according to the
2573         * LCDA stuff. It is very likely that some machines are not
2574         * treated correctly in the following, very case-orientated
2575         * code. What do I do then...?
2576         */
2577
2578        /* 740 variants match for 30xB, 301B-DH, 30xLV */
2579
2580        if(!(IS_SIS740)) {
2581           tempah = 0x04;                                                  /* For all bridges */
2582           tempbl = 0xfb;
2583           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2584              tempah = 0x00;
2585              if(SiS_IsDualEdge(SiS_Pr)) {
2586                 tempbl = 0xff;
2587              }
2588           }
2589           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2590        }
2591
2592        /* The following two are responsible for eventually wrong colors
2593         * in TV output. The DH (VB_NoLCD) conditions are unknown; the
2594         * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
2595         * in a 650 box (Jake). What is the criteria?
2596         * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
2597         * treatment like the 651+301B-DH(b0) case. Seems more to be the
2598         * chipset than the bridge revision.
2599         */
2600
2601        if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
2602           tempah = 0x30;
2603           tempbl = 0xc0;
2604           if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2605              ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
2606              tempah = 0x00;
2607              tempbl = 0x00;
2608           }
2609           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
2610           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
2611        } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
2612           /* Fixes "TV-blue-bug" on 315+301 */
2613           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf);      /* For 301   */
2614           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
2615        } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
2616           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);       /* For 30xLV */
2617           SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
2618        } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {              /* For 301B-DH */
2619           tempah = 0x30; tempah2 = 0xc0;
2620           tempbl = 0xcf; tempbl2 = 0x3f;
2621           if(SiS_Pr->SiS_TVBlue == 0) {
2622                 tempah = tempah2 = 0x00;
2623           } else if(SiS_Pr->SiS_TVBlue == -1) {
2624              /* Set on 651/M650, clear on 315/650 */
2625              if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
2626                 tempah = tempah2 = 0x00;
2627              }
2628           }
2629           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2630           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2631        } else {
2632           tempah = 0x30; tempah2 = 0xc0;                      /* For 30xB, 301C */
2633           tempbl = 0xcf; tempbl2 = 0x3f;
2634           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2635              tempah = tempah2 = 0x00;
2636              if(SiS_IsDualEdge(SiS_Pr)) {
2637                 tempbl = tempbl2 = 0xff;
2638              }
2639           }
2640           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2641           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2642        }
2643
2644        if(IS_SIS740) {
2645           tempah = 0x80;
2646           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
2647           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
2648        } else {
2649           tempah = 0x00;
2650           tempbl = 0x7f;
2651           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2652              tempbl = 0xff;
2653              if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
2654           }
2655           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
2656        }
2657
2658#endif /* CONFIG_FB_SIS_315 */
2659
2660     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2661
2662#ifdef CONFIG_FB_SIS_300
2663        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
2664
2665        if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2666           ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
2667            (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
2668           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
2669        } else {
2670           SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
2671        }
2672#endif
2673
2674     }
2675
2676     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2677        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
2678        if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
2679           SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
2680        }
2681     }
2682
2683  } else {  /* LVDS */
2684
2685#ifdef CONFIG_FB_SIS_315
2686     if(SiS_Pr->ChipType >= SIS_315H) {
2687
2688        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
2689
2690           tempah = 0x04;
2691           tempbl = 0xfb;
2692           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2693              tempah = 0x00;
2694              if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
2695           }
2696           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2697
2698           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2699              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2700           }
2701
2702           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2703
2704        } else if(SiS_Pr->ChipType == SIS_550) {
2705
2706           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2707           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2708
2709        }
2710
2711     }
2712#endif
2713
2714  }
2715
2716}
2717
2718/*********************************************/
2719/*            GET RESOLUTION DATA            */
2720/*********************************************/
2721
2722unsigned short
2723SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2724{
2725   if(ModeNo <= 0x13)
2726      return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
2727   else
2728      return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
2729}
2730
2731static void
2732SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2733{
2734   unsigned short xres, yres, modeflag=0, resindex;
2735
2736   if(SiS_Pr->UseCustomMode) {
2737      xres = SiS_Pr->CHDisplay;
2738      if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
2739      SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2740      /* DoubleScanMode-check done in CheckCalcCustomMode()! */
2741      SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
2742      return;
2743   }
2744
2745   resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
2746
2747   if(ModeNo <= 0x13) {
2748      xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
2749      yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
2750   } else {
2751      xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
2752      yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
2753      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2754   }
2755
2756   if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
2757
2758      if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
2759         if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
2760            if(yres == 350) yres = 400;
2761         }
2762         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
2763            if(ModeNo == 0x12) yres = 400;
2764         }
2765      }
2766
2767      if(modeflag & HalfDCLK)       xres <<= 1;
2768      if(modeflag & DoubleScanMode) yres <<= 1;
2769
2770   }
2771
2772   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
2773
2774      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2775         switch(SiS_Pr->SiS_LCDResInfo) {
2776           case Panel_1024x768:
2777              if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
2778                 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2779                    if(yres == 350) yres = 357;
2780                    if(yres == 400) yres = 420;
2781                    if(yres == 480) yres = 525;
2782                 }
2783              }
2784              break;
2785           case Panel_1280x1024:
2786              if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2787                 /* BIOS bug - does this regardless of scaling */
2788                 if(yres == 400) yres = 405;
2789              }
2790              if(yres == 350) yres = 360;
2791              if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
2792                 if(yres == 360) yres = 375;
2793              }
2794              break;
2795           case Panel_1600x1200:
2796              if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
2797                 if(yres == 1024) yres = 1056;
2798              }
2799              break;
2800         }
2801      }
2802
2803   } else {
2804
2805      if(SiS_Pr->SiS_VBType & VB_SISVB) {
2806         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
2807            if(xres == 720) xres = 640;
2808         }
2809      } else if(xres == 720) xres = 640;
2810
2811      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
2812         yres = 400;
2813         if(SiS_Pr->ChipType >= SIS_315H) {
2814            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
2815         } else {
2816            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
2817         }
2818         if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
2819      }
2820
2821   }
2822   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2823   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
2824}
2825
2826/*********************************************/
2827/*           GET CRT2 TIMING DATA            */
2828/*********************************************/
2829
2830static void
2831SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2832               unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
2833               unsigned short *ResIndex)
2834{
2835  unsigned short tempbx=0, tempal=0, resinfo=0;
2836
2837  if(ModeNo <= 0x13) {
2838     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2839  } else {
2840     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2841     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2842  }
2843
2844  if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
2845
2846     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
2847
2848        tempbx = SiS_Pr->SiS_LCDResInfo;
2849        if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
2850
2851        /* patch index */
2852        if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
2853           if     (resinfo == SIS_RI_1280x800)  tempal =  9;
2854           else if(resinfo == SIS_RI_1400x1050) tempal = 11;
2855        } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
2856                  (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
2857                  (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
2858           if     (resinfo == SIS_RI_1280x768)  tempal =  9;
2859        }
2860
2861        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
2862           /* Pass 1:1 only (center-screen handled outside) */
2863           /* This is never called for the panel's native resolution */
2864           /* since Pass1:1 will not be set in this case */
2865           tempbx = 100;
2866           if(ModeNo >= 0x13) {
2867              tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
2868           }
2869        }
2870
2871#ifdef CONFIG_FB_SIS_315
2872        if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
2873           if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
2874              if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2875                 tempbx = 200;
2876                 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
2877              }
2878           }
2879        }
2880#endif
2881
2882     } else {                                                   /* TV */
2883
2884        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2885           /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
2886           tempbx = 2;
2887           if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2888              tempbx = 13;
2889              if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
2890           }
2891        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2892           if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      tempbx = 7;
2893           else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
2894           else                                         tempbx = 5;
2895           if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
2896        } else {
2897           if(SiS_Pr->SiS_TVMode & TVSetPAL)            tempbx = 3;
2898           else                                         tempbx = 4;
2899           if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
2900        }
2901
2902     }
2903
2904     tempal &= 0x3F;
2905
2906     if(ModeNo > 0x13) {
2907        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
2908           switch(resinfo) {
2909           case SIS_RI_720x480:
2910              tempal = 6;
2911              if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN))   tempal = 9;
2912              break;
2913           case SIS_RI_720x576:
2914           case SIS_RI_768x576:
2915           case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
2916              tempal = 6;
2917              if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2918                 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)        tempal = 8;
2919              }
2920              break;
2921           case SIS_RI_800x480:
2922              tempal = 4;
2923              break;
2924           case SIS_RI_512x384:
2925           case SIS_RI_1024x768:
2926              tempal = 7;
2927              if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2928                 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)        tempal = 8;
2929              }
2930              break;
2931           case SIS_RI_1280x720:
2932              if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2933                 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)        tempal = 9;
2934              }
2935              break;
2936           }
2937        }
2938     }
2939
2940     *CRT2Index = tempbx;
2941     *ResIndex = tempal;
2942
2943  } else {   /* LVDS, 301B-DH (if running on LCD) */
2944
2945     tempbx = 0;
2946     if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
2947
2948        tempbx = 90;
2949        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2950           tempbx = 92;
2951           if(SiS_Pr->SiS_ModeType > ModeVGA) {
2952              if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
2953           }
2954           if(SiS_Pr->SiS_TVMode & TVSetPALM)      tempbx = 94;
2955           else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
2956        }
2957        if(tempbx != 99) {
2958           if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
2959        }
2960
2961     } else {
2962
2963        switch(SiS_Pr->SiS_LCDResInfo) {
2964        case Panel_640x480:   tempbx = 12; break;
2965        case Panel_320x240_1: tempbx = 10; break;
2966        case Panel_320x240_2:
2967        case Panel_320x240_3: tempbx = 14; break;
2968        case Panel_800x600:   tempbx = 16; break;
2969        case Panel_1024x600:  tempbx = 18; break;
2970        case Panel_1152x768:
2971        case Panel_1024x768:  tempbx = 20; break;
2972        case Panel_1280x768:  tempbx = 22; break;
2973        case Panel_1280x1024: tempbx = 24; break;
2974        case Panel_1400x1050: tempbx = 26; break;
2975        case Panel_1600x1200: tempbx = 28; break;
2976#ifdef CONFIG_FB_SIS_300
2977        case Panel_Barco1366: tempbx = 80; break;
2978#endif
2979        }
2980
2981        switch(SiS_Pr->SiS_LCDResInfo) {
2982        case Panel_320x240_1:
2983        case Panel_320x240_2:
2984        case Panel_320x240_3:
2985        case Panel_640x480:
2986           break;
2987        default:
2988           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
2989        }
2990
2991        if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
2992
2993#ifdef CONFIG_FB_SIS_300
2994        if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
2995           tempbx = 82;
2996           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
2997        } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2998           tempbx = 84;
2999           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3000        }
3001#endif
3002
3003     }
3004
3005     (*CRT2Index) = tempbx;
3006     (*ResIndex) = tempal & 0x1F;
3007  }
3008}
3009
3010static void
3011SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3012                unsigned short RefreshRateTableIndex)
3013{
3014  unsigned short tempax=0, tempbx=0, index, dotclock;
3015  unsigned short temp1=0, modeflag=0, tempcx=0;
3016
3017  SiS_Pr->SiS_RVBHCMAX  = 1;
3018  SiS_Pr->SiS_RVBHCFACT = 1;
3019
3020  if(ModeNo <= 0x13) {
3021
3022     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3023     index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
3024
3025     tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
3026     tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
3027     temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
3028
3029     dotclock = (modeflag & Charx8Dot) ? 8 : 9;
3030
3031  } else {
3032
3033     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3034     index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
3035
3036     tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
3037     tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
3038     tempax &= 0x03FF;
3039     tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
3040     tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
3041     tempcx &= 0x0100;
3042     tempcx <<= 2;
3043     tempbx |= tempcx;
3044     temp1  = SiS_Pr->SiS_CRT1Table[index].CR[7];
3045
3046     dotclock = 8;
3047
3048  }
3049
3050  if(temp1 & 0x01) tempbx |= 0x0100;
3051  if(temp1 & 0x20) tempbx |= 0x0200;
3052
3053  tempax += 5;
3054  tempax *= dotclock;
3055  if(modeflag & HalfDCLK) tempax <<= 1;
3056
3057  tempbx++;
3058
3059  SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3060  SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
3061}
3062
3063static void
3064SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3065                unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
3066{
3067   unsigned short ResIndex;
3068
3069   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3070      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3071         if(SiS_Pr->UseCustomMode) {
3072            ResIndex = SiS_Pr->CHTotal;
3073            if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
3074            SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
3075            SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3076         } else {
3077            if(ModeNo < 0x13) {
3078               ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3079            } else {
3080               ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3081            }
3082            if(ResIndex == 0x09) {
3083               if(SiS_Pr->Alternate1600x1200)        ResIndex = 0x20; /* 1600x1200 LCDA */
3084               else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
3085            }
3086            SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
3087            SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
3088            SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
3089            SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
3090         }
3091      } else {
3092         SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3093         SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3094      }
3095   } else {
3096      /* This handles custom modes and custom panels */
3097      SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3098      SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3099      SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
3100      SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
3101      SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
3102      SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
3103   }
3104}
3105
3106static void
3107SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3108                    unsigned short RefreshRateTableIndex)
3109{
3110   unsigned short CRT2Index, ResIndex, backup;
3111   const struct SiS_LVDSData *LVDSData = NULL;
3112
3113   SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3114
3115   if(SiS_Pr->SiS_VBType & VB_SISVB) {
3116      SiS_Pr->SiS_RVBHCMAX  = 1;
3117      SiS_Pr->SiS_RVBHCFACT = 1;
3118      SiS_Pr->SiS_NewFlickerMode = 0;
3119      SiS_Pr->SiS_RVBHRS = 50;
3120      SiS_Pr->SiS_RY1COE = 0;
3121      SiS_Pr->SiS_RY2COE = 0;
3122      SiS_Pr->SiS_RY3COE = 0;
3123      SiS_Pr->SiS_RY4COE = 0;
3124      SiS_Pr->SiS_RVBHRS2 = 0;
3125   }
3126
3127   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3128
3129#ifdef CONFIG_FB_SIS_315
3130      SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3131      SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
3132#endif
3133
3134   } else {
3135
3136      /* 301BDH needs LVDS Data */
3137      backup = SiS_Pr->SiS_IF_DEF_LVDS;
3138      if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3139         SiS_Pr->SiS_IF_DEF_LVDS = 1;
3140      }
3141
3142      SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
3143                                            &CRT2Index, &ResIndex);
3144
3145      SiS_Pr->SiS_IF_DEF_LVDS = backup;
3146
3147      switch(CRT2Index) {
3148         case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1;    break;
3149         case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2;    break;
3150         case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
3151         case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
3152         case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
3153         case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
3154#ifdef CONFIG_FB_SIS_300
3155         case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
3156         case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
3157         case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
3158         case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
3159         case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
3160#endif
3161         case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
3162         case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
3163         case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
3164         case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
3165         case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
3166         case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
3167         case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
3168         case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
3169         case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;        break;
3170      }
3171
3172      if(LVDSData) {
3173         SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
3174         SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
3175         SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
3176         SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
3177      } else {
3178         SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3179      }
3180
3181      if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
3182          (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
3183          (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
3184         if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
3185             (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
3186            SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3187            SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3188#ifdef CONFIG_FB_SIS_300
3189            if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3190               if(ResIndex < 0x08) {
3191                  SiS_Pr->SiS_HDE = 1280;
3192                  SiS_Pr->SiS_VDE = 1024;
3193               }
3194            }
3195#endif
3196         }
3197      }
3198   }
3199}
3200
3201static void
3202SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3203                unsigned short RefreshRateTableIndex)
3204{
3205  unsigned char  *ROMAddr = NULL;
3206  unsigned short tempax, tempbx, modeflag, romptr=0;
3207  unsigned short resinfo, CRT2Index, ResIndex;
3208  const struct SiS_LCDData *LCDPtr = NULL;
3209  const struct SiS_TVData  *TVPtr  = NULL;
3210#ifdef CONFIG_FB_SIS_315
3211  short resinfo661;
3212#endif
3213
3214  if(ModeNo <= 0x13) {
3215     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3216     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
3217  } else if(SiS_Pr->UseCustomMode) {
3218     modeflag = SiS_Pr->CModeFlag;
3219     resinfo = 0;
3220  } else {
3221     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3222     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
3223#ifdef CONFIG_FB_SIS_315
3224     resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3225     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
3226         (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
3227         (resinfo661 >= 0)                     &&
3228         (SiS_Pr->SiS_NeedRomModeData) ) {
3229        if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
3230           if((romptr = (SISGETROMW(21)))) {
3231              romptr += (resinfo661 * 10);
3232              ROMAddr = SiS_Pr->VirtualRomBase;
3233           }
3234        }
3235     }
3236#endif
3237  }
3238
3239  SiS_Pr->SiS_NewFlickerMode = 0;
3240  SiS_Pr->SiS_RVBHRS = 50;
3241  SiS_Pr->SiS_RY1COE = 0;
3242  SiS_Pr->SiS_RY2COE = 0;
3243  SiS_Pr->SiS_RY3COE = 0;
3244  SiS_Pr->SiS_RY4COE = 0;
3245  SiS_Pr->SiS_RVBHRS2 = 0;
3246
3247  SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
3248
3249  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
3250
3251     if(SiS_Pr->UseCustomMode) {
3252
3253        SiS_Pr->SiS_RVBHCMAX  = 1;
3254        SiS_Pr->SiS_RVBHCFACT = 1;
3255        SiS_Pr->SiS_HDE       = SiS_Pr->SiS_VGAHDE;
3256        SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
3257
3258        tempax = SiS_Pr->CHTotal;
3259        if(modeflag & HalfDCLK) tempax <<= 1;
3260        SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3261        SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3262
3263     } else {
3264
3265        SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3266
3267     }
3268
3269  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3270
3271     SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3272                    &CRT2Index,&ResIndex);
3273
3274     switch(CRT2Index) {
3275        case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
3276        case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
3277        case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
3278        case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
3279        case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
3280        case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
3281        case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
3282        case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
3283        case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
3284        case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
3285        case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
3286        case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
3287        case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
3288        default: TVPtr = SiS_Pr->SiS_StPALData;     break;
3289     }
3290
3291     SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
3292     SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
3293     SiS_Pr->SiS_VGAHT     = (TVPtr+ResIndex)->VGAHT;
3294     SiS_Pr->SiS_VGAVT     = (TVPtr+ResIndex)->VGAVT;
3295     SiS_Pr->SiS_HDE       = (TVPtr+ResIndex)->TVHDE;
3296     SiS_Pr->SiS_VDE       = (TVPtr+ResIndex)->TVVDE;
3297     SiS_Pr->SiS_RVBHRS2   = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
3298     if(modeflag & HalfDCLK) {
3299        SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
3300        if(SiS_Pr->SiS_RVBHRS2) {
3301           SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3302           tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
3303           if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
3304           else                                   SiS_Pr->SiS_RVBHRS2 += tempax;
3305        }
3306     } else {
3307        SiS_Pr->SiS_RVBHRS    = (TVPtr+ResIndex)->RVBHRS;
3308     }
3309     SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
3310
3311     if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3312
3313        if((resinfo == SIS_RI_960x600)   ||
3314           (resinfo == SIS_RI_1024x768)  ||
3315           (resinfo == SIS_RI_1280x1024) ||
3316           (resinfo == SIS_RI_1280x720)) {
3317           SiS_Pr->SiS_NewFlickerMode = 0x40;
3318        }
3319
3320        if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
3321
3322        SiS_Pr->SiS_HT = ExtHiTVHT;
3323        SiS_Pr->SiS_VT = ExtHiTVVT;
3324        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3325           if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
3326              SiS_Pr->SiS_HT = StHiTVHT;
3327              SiS_Pr->SiS_VT = StHiTVVT;
3328           }
3329        }
3330
3331     } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3332
3333        if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3334           SiS_Pr->SiS_HT = 1650;
3335           SiS_Pr->SiS_VT = 750;
3336        } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3337           SiS_Pr->SiS_HT = NTSCHT;
3338           if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
3339           SiS_Pr->SiS_VT = NTSCVT;
3340        } else {
3341           SiS_Pr->SiS_HT = NTSCHT;
3342           if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
3343           SiS_Pr->SiS_VT = NTSCVT;
3344        }
3345
3346     } else {
3347
3348        SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
3349        SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
3350        SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
3351        SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
3352
3353        if(modeflag & HalfDCLK) {
3354           SiS_Pr->SiS_RY1COE = 0x00;
3355           SiS_Pr->SiS_RY2COE = 0xf4;
3356           SiS_Pr->SiS_RY3COE = 0x10;
3357           SiS_Pr->SiS_RY4COE = 0x38;
3358        }
3359
3360        if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
3361           SiS_Pr->SiS_HT = NTSCHT;
3362           if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
3363           SiS_Pr->SiS_VT = NTSCVT;
3364        } else {
3365           SiS_Pr->SiS_HT = PALHT;
3366           SiS_Pr->SiS_VT = PALVT;
3367        }
3368
3369     }
3370
3371  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3372
3373     SiS_Pr->SiS_RVBHCMAX  = 1;
3374     SiS_Pr->SiS_RVBHCFACT = 1;
3375
3376     if(SiS_Pr->UseCustomMode) {
3377
3378        SiS_Pr->SiS_HDE   = SiS_Pr->SiS_VGAHDE;
3379        SiS_Pr->SiS_VDE   = SiS_Pr->SiS_VGAVDE;
3380
3381        tempax = SiS_Pr->CHTotal;
3382        if(modeflag & HalfDCLK) tempax <<= 1;
3383        SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3384        SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3385
3386     } else {
3387
3388        bool gotit = false;
3389
3390        if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
3391
3392           SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
3393           SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3394           SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
3395           SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
3396           gotit = true;
3397
3398        } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3399
3400#ifdef CONFIG_FB_SIS_315
3401           SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
3402           SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3403           SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
3404           SiS_Pr->SiS_VGAVT     = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
3405           SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
3406           SiS_Pr->SiS_VT        = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
3407           SiS_Pr->SiS_RVBHRS2   = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
3408           if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
3409              SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3410              tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
3411              if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
3412              else                         SiS_Pr->SiS_RVBHRS2 += tempax;
3413           }
3414           if(SiS_Pr->SiS_VGAHT) gotit = true;
3415           else {
3416              SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
3417              SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
3418              SiS_Pr->SiS_RVBHCMAX  = 1;
3419              SiS_Pr->SiS_RVBHCFACT = 1;
3420              SiS_Pr->SiS_VGAHT   = SiS_Pr->PanelHT;
3421              SiS_Pr->SiS_VGAVT   = SiS_Pr->PanelVT;
3422              SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
3423              SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
3424              SiS_Pr->SiS_RVBHRS2 = 0;
3425              gotit = true;
3426           }
3427#endif
3428
3429        }
3430
3431        if(!gotit) {
3432
3433           SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3434                          &CRT2Index,&ResIndex);
3435
3436           switch(CRT2Index) {
3437              case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
3438              case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
3439              case Panel_1280x720      :
3440              case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
3441              case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
3442              case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
3443              case Panel_1280x800      :
3444              case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
3445              case Panel_1280x800_2    :
3446              case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data;    break;
3447              case Panel_1280x854      :
3448              case Panel_1280x854  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data;      break;
3449              case Panel_1280x960      :
3450              case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
3451              case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
3452              case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
3453              case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
3454              case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
3455              case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
3456              case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
3457              case Panel_1680x1050     :
3458              case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
3459              case 100                 : LCDPtr = SiS_Pr->SiS_NoScaleData;          break;
3460#ifdef CONFIG_FB_SIS_315
3461              case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
3462              case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
3463#endif
3464              default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
3465           }
3466
3467           SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
3468           SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3469           SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
3470           SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
3471           SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
3472           SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
3473
3474        }
3475
3476        tempax = SiS_Pr->PanelXRes;
3477        tempbx = SiS_Pr->PanelYRes;
3478
3479        switch(SiS_Pr->SiS_LCDResInfo) {
3480        case Panel_1024x768:
3481           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3482              if(SiS_Pr->ChipType < SIS_315H) {
3483                 if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3484                 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3485              }
3486           } else {
3487              if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
3488              else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
3489              else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
3490              else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
3491              else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3492              else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3493           }
3494           break;
3495        case Panel_1280x960:
3496           if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
3497           else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
3498           else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
3499           break;
3500        case Panel_1280x1024:
3501           if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
3502           else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
3503           else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
3504           break;
3505        case Panel_1600x1200:
3506           if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
3507              if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
3508              else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
3509           }
3510           break;
3511        }
3512
3513        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3514           tempax = SiS_Pr->SiS_VGAHDE;
3515           tempbx = SiS_Pr->SiS_VGAVDE;
3516        }
3517
3518        SiS_Pr->SiS_HDE = tempax;
3519        SiS_Pr->SiS_VDE = tempbx;
3520     }
3521  }
3522}
3523
3524static void
3525SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3526                unsigned short RefreshRateTableIndex)
3527{
3528
3529   if(SiS_Pr->SiS_VBType & VB_SISVB) {
3530
3531      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3532         SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3533      } else {
3534         if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3535            /* Need LVDS Data for LCD on 301B-DH */
3536            SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3537         } else {
3538            SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3539         }
3540      }
3541
3542   } else {
3543
3544      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3545
3546   }
3547}
3548
3549/*********************************************/
3550/*         GET LVDS DES (SKEW) DATA          */
3551/*********************************************/
3552
3553static const struct SiS_LVDSDes *
3554SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
3555{
3556   const struct SiS_LVDSDes *PanelDesPtr = NULL;
3557
3558#ifdef CONFIG_FB_SIS_300
3559   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3560
3561      if(SiS_Pr->ChipType < SIS_315H) {
3562         if(SiS_Pr->SiS_LCDTypeInfo == 4) {
3563            if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3564               PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
3565               if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3566                  PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
3567               }
3568            } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3569               PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
3570               if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3571                  PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
3572               }
3573            }
3574         }
3575      }
3576   }
3577#endif
3578   return PanelDesPtr;
3579}
3580
3581static void
3582SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3583                   unsigned short RefreshRateTableIndex)
3584{
3585  unsigned short modeflag, ResIndex;
3586  const struct SiS_LVDSDes *PanelDesPtr = NULL;
3587
3588  SiS_Pr->SiS_LCDHDES = 0;
3589  SiS_Pr->SiS_LCDVDES = 0;
3590
3591  /* Some special cases */
3592  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3593
3594     /* Trumpion */
3595     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
3596        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3597           if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3598              SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3599           }
3600        }
3601        return;
3602     }
3603
3604     /* 640x480 on LVDS */
3605     if(SiS_Pr->ChipType < SIS_315H) {
3606        if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
3607           SiS_Pr->SiS_LCDHDES = 8;
3608           if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3609           else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3610           else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3611           return;
3612        }
3613     }
3614
3615  } /* LCD */
3616
3617  if( (SiS_Pr->UseCustomMode)                    ||
3618      (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
3619      (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
3620      (SiS_Pr->SiS_CustomT == CUT_PANEL856)      ||
3621      (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
3622     return;
3623  }
3624
3625  if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3626  else               ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3627
3628  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3629
3630#ifdef CONFIG_FB_SIS_315
3631     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3632        /* non-pass 1:1 only, see above */
3633        if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3634           SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3635        }
3636        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3637           SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3638        }
3639     }
3640     if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3641        switch(SiS_Pr->SiS_CustomT) {
3642        case CUT_UNIWILL1024:
3643        case CUT_UNIWILL10242:
3644        case CUT_CLEVO1400:
3645           if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3646              SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3647           }
3648           break;
3649        }
3650        switch(SiS_Pr->SiS_LCDResInfo) {
3651        case Panel_1280x1024:
3652           if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
3653              SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3654           }
3655           break;
3656        case Panel_1280x800:    /* Verified for Averatec 6240 */
3657        case Panel_1280x800_2:  /* Verified for Asus A4L */
3658        case Panel_1280x854:    /* Not verified yet FIXME */
3659           SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3660           break;
3661        }
3662     }
3663#endif
3664
3665  } else {
3666
3667     if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
3668
3669        if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
3670           if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
3671        }
3672
3673     } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
3674
3675        SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
3676        SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
3677
3678     } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3679
3680        if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3681           SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3682        }
3683        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3684           SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3685        } else {
3686           if(SiS_Pr->ChipType < SIS_315H) {
3687              SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3688           } else {
3689              switch(SiS_Pr->SiS_LCDResInfo) {
3690              case Panel_800x600:
3691              case Panel_1024x768:
3692              case Panel_1280x1024:
3693                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3694                 break;
3695              case Panel_1400x1050:
3696                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3697                 break;
3698              }
3699           }
3700        }
3701
3702     } else {
3703
3704        if(SiS_Pr->ChipType < SIS_315H) {
3705#ifdef CONFIG_FB_SIS_300
3706           switch(SiS_Pr->SiS_LCDResInfo) {
3707           case Panel_800x600:
3708              if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3709                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3710              } else {
3711                 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
3712                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3713                 if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
3714                 else                          SiS_Pr->SiS_LCDVDES -= 4;
3715              }
3716              break;
3717           case Panel_1024x768:
3718              if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3719                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3720              } else {
3721                 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3722                 if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
3723                 if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
3724              }
3725              break;
3726           case Panel_1024x600:
3727           default:
3728              if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
3729                  (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
3730                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3731              } else {
3732                 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3733              }
3734              break;
3735           }
3736
3737           switch(SiS_Pr->SiS_LCDTypeInfo) {
3738           case 1:
3739              SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
3740              break;
3741           case 3: /* 640x480 only? */
3742              SiS_Pr->SiS_LCDHDES = 8;
3743              if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3744              else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3745              else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3746              break;
3747           }
3748#endif
3749        } else {
3750#ifdef CONFIG_FB_SIS_315
3751           switch(SiS_Pr->SiS_LCDResInfo) {
3752           case Panel_1024x768:
3753           case Panel_1280x1024:
3754              if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3755                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3756              }
3757              break;
3758           case Panel_320x240_1:
3759           case Panel_320x240_2:
3760           case Panel_320x240_3:
3761              SiS_Pr->SiS_LCDVDES = 524;
3762              break;
3763           }
3764#endif
3765        }
3766     }
3767
3768     if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
3769        modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3770        if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3771           if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
3772        } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3773           if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
3774              if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
3775                 if(SiS_Pr->ChipType < SIS_315H) {
3776                    if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
3777                 } else {
3778#ifdef CONFIG_FB_SIS_315
3779                    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
3780                    if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
3781                    if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
3782                    if(!(modeflag & HalfDCLK)) {
3783                       SiS_Pr->SiS_LCDHDES = 320;
3784                       if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
3785                       if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
3786                    }
3787#endif
3788                 }
3789              }
3790           }
3791        }
3792     }
3793  }
3794}
3795
3796/*********************************************/
3797/*           DISABLE VIDEO BRIDGE            */
3798/*********************************************/
3799
3800#ifdef CONFIG_FB_SIS_315
3801static int
3802SiS_HandlePWD(struct SiS_Private *SiS_Pr)
3803{
3804   int ret = 0;
3805#ifdef SET_PWD
3806   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3807   unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
3808   unsigned char  drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
3809   unsigned short temp;
3810
3811   if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
3812       (romptr)                         &&
3813       (SiS_Pr->SiS_PWDOffset) ) {
3814      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
3815      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
3816      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
3817      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
3818      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
3819      temp = 0x00;
3820      if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
3821         temp = 0x80;
3822         ret = 1;
3823      }
3824      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
3825   }
3826#endif
3827   return ret;
3828}
3829#endif
3830
3831/* NEVER use any variables (VBInfo), this will be called
3832 * from outside the context of modeswitch!
3833 * MUST call getVBType before calling this
3834 */
3835void
3836SiS_DisableBridge(struct SiS_Private *SiS_Pr)
3837{
3838#ifdef CONFIG_FB_SIS_315
3839  unsigned short tempah, pushax=0, modenum;
3840#endif
3841  unsigned short temp=0;
3842
3843  if(SiS_Pr->SiS_VBType & VB_SISVB) {
3844
3845     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {            /* ===== For 30xB/C/LV ===== */
3846
3847        if(SiS_Pr->ChipType < SIS_315H) {
3848
3849#ifdef CONFIG_FB_SIS_300           /* 300 series */
3850
3851           if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
3852              if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3853                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
3854              } else {
3855                 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
3856              }
3857              SiS_PanelDelay(SiS_Pr, 3);
3858           }
3859           if(SiS_Is301B(SiS_Pr)) {
3860              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
3861              SiS_ShortDelay(SiS_Pr,1);
3862           }
3863           SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
3864           SiS_DisplayOff(SiS_Pr);
3865           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3866           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
3867           SiS_UnLockCRT2(SiS_Pr);
3868           if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
3869              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
3870              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
3871           }
3872           if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
3873               (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
3874              SiS_PanelDelay(SiS_Pr, 2);
3875              if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3876                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
3877              } else {
3878                 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
3879              }
3880           }
3881
3882#endif  /* CONFIG_FB_SIS_300 */
3883
3884        } else {
3885
3886#ifdef CONFIG_FB_SIS_315           /* 315 series */
3887
3888           int didpwd = 0;
3889           bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
3890                          (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
3891
3892           modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
3893
3894           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3895
3896#ifdef SET_EMI
3897              if(SiS_Pr->SiS_VBType & VB_SISEMI) {
3898                 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
3899                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
3900                 }
3901              }
3902#endif
3903
3904              didpwd = SiS_HandlePWD(SiS_Pr);
3905
3906              if( (modenum <= 0x13)           ||
3907                  (SiS_IsVAMode(SiS_Pr))      ||
3908                  (!(SiS_IsDualEdge(SiS_Pr))) ) {
3909                 if(!didpwd) {
3910                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
3911                    if(custom1) SiS_PanelDelay(SiS_Pr, 3);
3912                 } else {
3913                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
3914                 }
3915              }
3916
3917              if(!custom1) {
3918                 SiS_DDC2Delay(SiS_Pr,0xff00);
3919                 SiS_DDC2Delay(SiS_Pr,0xe000);
3920                 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
3921                 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
3922                 if(IS_SIS740) {
3923                    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
3924                 }
3925                 SiS_PanelDelay(SiS_Pr, 3);
3926              }
3927
3928           }
3929
3930           if(!(SiS_IsNotM650orLater(SiS_Pr))) {
3931              /* if(SiS_Pr->ChipType < SIS_340) {*/
3932                 tempah = 0xef;
3933                 if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
3934                 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
3935              /*}*/
3936           }
3937
3938           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3939              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
3940           }
3941
3942           tempah = 0x3f;
3943           if(SiS_IsDualEdge(SiS_Pr)) {
3944              tempah = 0x7f;
3945              if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
3946           }
3947           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
3948
3949           if((SiS_IsVAMode(SiS_Pr)) ||
3950              ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
3951
3952              SiS_DisplayOff(SiS_Pr);
3953              if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3954                 SiS_PanelDelay(SiS_Pr, 2);
3955              }
3956              SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3957              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
3958
3959           }
3960
3961           if((!(SiS_IsVAMode(SiS_Pr))) ||
3962              ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
3963
3964              if(!(SiS_IsDualEdge(SiS_Pr))) {
3965                 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
3966                 SiS_DisplayOff(SiS_Pr);
3967              }
3968              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
3969
3970              if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3971                 SiS_PanelDelay(SiS_Pr, 2);
3972              }
3973
3974              SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3975              temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
3976              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
3977              SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
3978              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
3979
3980           }
3981
3982           if(SiS_IsNotM650orLater(SiS_Pr)) {
3983              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
3984           }
3985
3986           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3987
3988              if( (!(SiS_IsVAMode(SiS_Pr)))  &&
3989                  (!(SiS_CRT2IsLCD(SiS_Pr))) &&
3990                  (!(SiS_IsDualEdge(SiS_Pr))) ) {
3991
3992                 if(custom1) SiS_PanelDelay(SiS_Pr, 2);
3993                 if(!didpwd) {
3994                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
3995                 }
3996                 if(custom1) SiS_PanelDelay(SiS_Pr, 4);
3997              }
3998
3999              if(!custom1) {
4000                 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4001                 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4002                    if(SiS_IsVAorLCD(SiS_Pr)) {
4003                       SiS_PanelDelayLoop(SiS_Pr, 3, 20);
4004                    }
4005                 }
4006              }
4007
4008           }
4009
4010#endif /* CONFIG_FB_SIS_315 */
4011
4012        }
4013
4014     } else {     /* ============ For 301 ================ */
4015
4016        if(SiS_Pr->ChipType < SIS_315H) {
4017#ifdef CONFIG_FB_SIS_300
4018           if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4019              SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4020              SiS_PanelDelay(SiS_Pr, 3);
4021           }
4022#endif
4023        }
4024
4025        SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
4026        SiS_DisplayOff(SiS_Pr);
4027
4028        if(SiS_Pr->ChipType >= SIS_315H) {
4029           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4030        }
4031
4032        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);                /* disable lock mode */
4033
4034        if(SiS_Pr->ChipType >= SIS_315H) {
4035            temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4036            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
4037            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4038            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4039        } else {
4040#ifdef CONFIG_FB_SIS_300
4041            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
4042            if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4043                (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4044                SiS_PanelDelay(SiS_Pr, 2);
4045                SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
4046            }
4047#endif
4048        }
4049
4050      }
4051
4052  } else {     /* ============ For LVDS =============*/
4053
4054    if(SiS_Pr->ChipType < SIS_315H) {
4055
4056#ifdef CONFIG_FB_SIS_300        /* 300 series */
4057
4058        if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
4059           SiS_SetCH700x(SiS_Pr,0x0E,0x09);
4060        }
4061
4062        if(SiS_Pr->ChipType == SIS_730) {
4063           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4064              SiS_WaitVBRetrace(SiS_Pr);
4065           }
4066           if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4067              SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4068              SiS_PanelDelay(SiS_Pr, 3);
4069           }
4070        } else {
4071           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4072              if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4073                 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4074                    SiS_WaitVBRetrace(SiS_Pr);
4075                    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
4076                       SiS_DisplayOff(SiS_Pr);
4077                    }
4078                    SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4079                    SiS_PanelDelay(SiS_Pr, 3);
4080                 }
4081              }
4082           }
4083        }
4084
4085        SiS_DisplayOff(SiS_Pr);
4086
4087        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4088
4089        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4090        SiS_UnLockCRT2(SiS_Pr);
4091        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4092        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4093
4094        if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4095            (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4096           SiS_PanelDelay(SiS_Pr, 2);
4097           SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
4098        }
4099
4100#endif  /* CONFIG_FB_SIS_300 */
4101
4102    } else {
4103
4104#ifdef CONFIG_FB_SIS_315        /* 315 series */
4105
4106        if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4107           /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
4108              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
4109           /* } */
4110        }
4111
4112        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4113
4114           if(SiS_Pr->ChipType == SIS_740) {
4115              temp = SiS_GetCH701x(SiS_Pr,0x61);
4116              if(temp < 1) {
4117                 SiS_SetCH701x(SiS_Pr,0x76,0xac);
4118                 SiS_SetCH701x(SiS_Pr,0x66,0x00);
4119              }
4120
4121              if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4122                  (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4123                 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
4124              }
4125           }
4126
4127           if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4128               (SiS_IsVAMode(SiS_Pr)) ) {
4129              SiS_Chrontel701xBLOff(SiS_Pr);
4130              SiS_Chrontel701xOff(SiS_Pr);
4131           }
4132
4133           if(SiS_Pr->ChipType != SIS_740) {
4134              if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4135                  (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4136                 SiS_SetCH701x(SiS_Pr,0x49,0x01);
4137              }
4138           }
4139
4140        }
4141
4142        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4143           SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4144           SiS_PanelDelay(SiS_Pr, 3);
4145        }
4146
4147        if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4148            (!(SiS_IsDualEdge(SiS_Pr))) ||
4149            (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
4150           SiS_DisplayOff(SiS_Pr);
4151        }
4152
4153        if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4154            (!(SiS_IsDualEdge(SiS_Pr))) ||
4155            (!(SiS_IsVAMode(SiS_Pr))) ) {
4156           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4157        }
4158
4159        if(SiS_Pr->ChipType == SIS_740) {
4160           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4161        }
4162
4163        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4164
4165        if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4166            (!(SiS_IsDualEdge(SiS_Pr))) ||
4167            (!(SiS_IsVAMode(SiS_Pr))) ) {
4168           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4169        }
4170
4171        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4172           if(SiS_CRT2IsLCD(SiS_Pr)) {
4173              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4174              if(SiS_Pr->ChipType == SIS_550) {
4175                 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
4176                 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
4177              }
4178           }
4179        } else {
4180           if(SiS_Pr->ChipType == SIS_740) {
4181              if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4182                 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4183              }
4184           } else if(SiS_IsVAMode(SiS_Pr)) {
4185              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4186           }
4187        }
4188
4189        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4190           if(SiS_IsDualEdge(SiS_Pr)) {
4191              /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
4192           } else {
4193              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
4194           }
4195        }
4196
4197        SiS_UnLockCRT2(SiS_Pr);
4198
4199        if(SiS_Pr->ChipType == SIS_550) {
4200           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
4201           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
4202        } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4203                   (!(SiS_IsDualEdge(SiS_Pr))) ||
4204                   (!(SiS_IsVAMode(SiS_Pr))) ) {
4205           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4206        }
4207
4208        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4209           if(SiS_CRT2IsLCD(SiS_Pr)) {
4210              if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4211                 SiS_PanelDelay(SiS_Pr, 2);
4212                 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
4213              }
4214           }
4215        }
4216
4217#endif  /* CONFIG_FB_SIS_315 */
4218
4219    }  /* 315 series */
4220
4221  }  /* LVDS */
4222
4223}
4224
4225/*********************************************/
4226/*            ENABLE VIDEO BRIDGE            */
4227/*********************************************/
4228
4229/* NEVER use any variables (VBInfo), this will be called
4230 * from outside the context of a mode switch!
4231 * MUST call getVBType before calling this
4232 */
4233static
4234void
4235SiS_EnableBridge(struct SiS_Private *SiS_Pr)
4236{
4237  unsigned short temp=0, tempah;
4238#ifdef CONFIG_FB_SIS_315
4239  unsigned short temp1, pushax=0;
4240  bool delaylong = false;
4241#endif
4242
4243  if(SiS_Pr->SiS_VBType & VB_SISVB) {
4244
4245    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {             /* ====== For 301B et al  ====== */
4246
4247      if(SiS_Pr->ChipType < SIS_315H) {
4248
4249#ifdef CONFIG_FB_SIS_300     /* 300 series */
4250
4251         if(SiS_CRT2IsLCD(SiS_Pr)) {
4252            if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4253               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4254            } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4255               SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4256            }
4257            if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
4258               if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4259                  SiS_PanelDelay(SiS_Pr, 0);
4260               }
4261            }
4262         }
4263
4264         if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
4265            (SiS_CRT2IsLCD(SiS_Pr))) {
4266
4267            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* Enable CRT2 */
4268            SiS_DisplayOn(SiS_Pr);
4269            SiS_UnLockCRT2(SiS_Pr);
4270            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4271            if(SiS_BridgeInSlavemode(SiS_Pr)) {
4272               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4273            } else {
4274               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4275            }
4276            if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4277               if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4278                  if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4279                     SiS_PanelDelay(SiS_Pr, 1);
4280                  }
4281                  SiS_WaitVBRetrace(SiS_Pr);
4282                  SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4283               }
4284            }
4285
4286         } else {
4287
4288            temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
4289            if(SiS_BridgeInSlavemode(SiS_Pr)) {
4290               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4291               if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4292            }
4293            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4294            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4295            SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
4296            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
4297            SiS_DisplayOn(SiS_Pr);
4298            if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4299               if(SiS_CRT2IsLCD(SiS_Pr)) {
4300                  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4301                     if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4302                        SiS_PanelDelay(SiS_Pr, 1);
4303                     }
4304                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4305                  }
4306               }
4307            }
4308
4309         }
4310
4311
4312#endif /* CONFIG_FB_SIS_300 */
4313
4314      } else {
4315
4316#ifdef CONFIG_FB_SIS_315    /* 315 series */
4317
4318#ifdef SET_EMI
4319         unsigned char   r30=0, r31=0, r32=0, r33=0, cr36=0;
4320         int didpwd = 0;
4321         /* unsigned short  emidelay=0; */
4322#endif
4323
4324         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4325            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
4326#ifdef SET_EMI
4327            if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4328               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4329            }
4330#endif
4331         }
4332
4333         if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4334            /*if(SiS_Pr->ChipType < SIS_340) { */
4335               tempah = 0x10;
4336               if(SiS_LCDAEnabled(SiS_Pr)) {
4337                  if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
4338                  else                      tempah = 0x08;
4339               }
4340               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
4341            /*}*/
4342         }
4343
4344         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4345
4346            SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4347            SiS_DisplayOff(SiS_Pr);
4348            pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4349            if(IS_SIS740) {
4350               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4351            }
4352
4353            didpwd = SiS_HandlePWD(SiS_Pr);
4354
4355            if(SiS_IsVAorLCD(SiS_Pr)) {
4356               if(!didpwd) {
4357                  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
4358                     SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4359                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4360                     SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4361                     if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4362                        SiS_GenericDelay(SiS_Pr, 17664);
4363                     }
4364                  }
4365               } else {
4366                  SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4367                  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4368                     SiS_GenericDelay(SiS_Pr, 17664);
4369                  }
4370               }
4371            }
4372
4373            if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
4374               SiS_PanelDelayLoop(SiS_Pr, 3, 10);
4375               delaylong = true;
4376            }
4377
4378         }
4379
4380         if(!(SiS_IsVAMode(SiS_Pr))) {
4381
4382            temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
4383            if(SiS_BridgeInSlavemode(SiS_Pr)) {
4384               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4385               if(!(tempah & SetCRT2ToRAMDAC)) {
4386                  if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
4387               }
4388            }
4389            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4390
4391            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
4392
4393            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4394            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4395
4396            if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4397               SiS_PanelDelay(SiS_Pr, 2);
4398            }
4399
4400         } else {
4401
4402            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
4403
4404         }
4405
4406         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
4407         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4408
4409         if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
4410            if( (SiS_LCDAEnabled(SiS_Pr)) ||
4411                (SiS_CRT2IsLCD(SiS_Pr)) ) {
4412               /* Enable "LVDS PLL power on" (even on 301C) */
4413               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
4414               /* Enable "LVDS Driver Power on" (even on 301C) */
4415               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
4416            }
4417         }
4418
4419         tempah = 0xc0;
4420         if(SiS_IsDualEdge(SiS_Pr)) {
4421            tempah = 0x80;
4422            if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
4423         }
4424         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
4425
4426         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4427
4428            SiS_PanelDelay(SiS_Pr, 2);
4429
4430            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
4431            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4432
4433            if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4434#ifdef SET_EMI
4435               if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4436                  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4437                  SiS_GenericDelay(SiS_Pr, 2048);
4438               }
4439#endif
4440               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
4441
4442               if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4443#ifdef SET_EMI
4444                  cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
4445
4446                  if(SiS_Pr->SiS_ROMNew) {
4447                     unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
4448                     unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
4449                     if(romptr) {
4450                        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
4451                        SiS_Pr->EMI_30 = 0;
4452                        SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
4453                        SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
4454                        SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
4455                        if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
4456                        /* emidelay = SISGETROMW((romptr + 0x22)); */
4457                        SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
4458                     }
4459                  }
4460
4461                  /*                                              (P4_30|0x40)  */
4462                  /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
4463                  /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
4464                  /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
4465                  /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
4466                  /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
4467                  /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
4468                  /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
4469                  /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
4470                  /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
4471
4472                  if(SiS_Pr->HaveEMI) {
4473                     r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
4474                     r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
4475                  } else {
4476                     r30 = 0;
4477                  }
4478
4479                  /* EMI_30 is read at driver start; however, the BIOS sets this
4480                   * (if it is used) only if the LCD is in use. In case we caught
4481                   * the machine while on TV output, this bit is not set and we
4482                   * don't know if it should be set - hence our detection is wrong.
4483                   * Work-around this here:
4484                   */
4485
4486                  if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
4487                     switch((cr36 & 0x0f)) {
4488                     case 2:
4489                        r30 |= 0x40;
4490                        if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
4491                        if(!SiS_Pr->HaveEMI) {
4492                           r31 = 0x05; r32 = 0x60; r33 = 0x33;
4493                           if((cr36 & 0xf0) == 0x30) {
4494                              r31 = 0x0d; r32 = 0x70; r33 = 0x40;
4495                           }
4496                        }
4497                        break;
4498                     case 3:  /* 1280x1024 */
4499                        if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
4500                        if(!SiS_Pr->HaveEMI) {
4501                           r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4502                           if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4503                              r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
4504                           }
4505                        }
4506                        break;
4507                     case 9:  /* 1400x1050 */
4508                        r30 |= 0x40;
4509                        if(!SiS_Pr->HaveEMI) {
4510                           r31 = 0x05; r32 = 0x60; r33 = 0x00;
4511                           if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4512                              r31 = 0x0d; r32 = 0x70; r33 = 0x40;  /* BIOS values */
4513                           }
4514                        }
4515                        break;
4516                     case 11: /* 1600x1200 - unknown */
4517                        r30 |= 0x40;
4518                        if(!SiS_Pr->HaveEMI) {
4519                           r31 = 0x05; r32 = 0x60; r33 = 0x00;
4520                        }
4521                     }
4522                  }
4523
4524                  /* BIOS values don't work so well sometimes */
4525                  if(!SiS_Pr->OverruleEMI) {
4526#ifdef COMPAL_HACK
4527                     if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4528                        if((cr36 & 0x0f) == 0x09) {
4529                           r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
4530                        }
4531                     }
4532#endif
4533#ifdef COMPAQ_HACK
4534                     if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4535                        if((cr36 & 0x0f) == 0x03) {
4536                           r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4537                        }
4538                     }
4539#endif
4540#ifdef ASUS_HACK
4541                     if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
4542                        if((cr36 & 0x0f) == 0x02) {
4543                           /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
4544                           /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
4545                           /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
4546                           /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
4547                        }
4548                     }
4549#endif
4550                  }
4551
4552                  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
4553                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
4554                     SiS_GenericDelay(SiS_Pr, 2048);
4555                  }
4556                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
4557                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
4558                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
4559#endif  /* SET_EMI */
4560
4561                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
4562
4563#ifdef SET_EMI
4564                  if( (SiS_LCDAEnabled(SiS_Pr)) ||
4565                      (SiS_CRT2IsLCD(SiS_Pr)) ) {
4566                     if(r30 & 0x40) {
4567                        /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
4568                        SiS_PanelDelayLoop(SiS_Pr, 3, 5);
4569                        if(delaylong) {
4570                           SiS_PanelDelayLoop(SiS_Pr, 3, 5);
4571                           delaylong = false;
4572                        }
4573                        SiS_WaitVBRetrace(SiS_Pr);
4574                        SiS_WaitVBRetrace(SiS_Pr);
4575                        if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
4576                           SiS_GenericDelay(SiS_Pr, 1280);
4577                        }
4578                        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   /* Enable */
4579                        /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
4580                     }
4581                  }
4582#endif
4583               }
4584            }
4585
4586            if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4587               if(SiS_IsVAorLCD(SiS_Pr)) {
4588                  SiS_PanelDelayLoop(SiS_Pr, 3, 10);
4589                  if(delaylong) {
4590                     SiS_PanelDelayLoop(SiS_Pr, 3, 10);
4591                  }
4592                  SiS_WaitVBRetrace(SiS_Pr);
4593                  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4594                     SiS_GenericDelay(SiS_Pr, 2048);
4595                     SiS_WaitVBRetrace(SiS_Pr);
4596                  }
4597                  if(!didpwd) {
4598                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4599                  } else {
4600                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
4601                  }
4602               }
4603            }
4604
4605            SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4606            SiS_DisplayOn(SiS_Pr);
4607            SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
4608
4609         }
4610
4611         if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4612            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4613         }
4614
4615#endif /* CONFIG_FB_SIS_315 */
4616
4617      }
4618
4619    } else {    /* ============  For 301 ================ */
4620
4621       if(SiS_Pr->ChipType < SIS_315H) {
4622          if(SiS_CRT2IsLCD(SiS_Pr)) {
4623             SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4624             SiS_PanelDelay(SiS_Pr, 0);
4625          }
4626       }
4627
4628       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
4629       if(SiS_BridgeInSlavemode(SiS_Pr)) {
4630          tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4631          if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4632       }
4633       SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4634
4635       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                  /* enable CRT2 */
4636
4637       if(SiS_Pr->ChipType >= SIS_315H) {
4638          temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4639          if(!(temp & 0x80)) {
4640             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);         /* BVBDOENABLE=1 */
4641          }
4642       }
4643
4644       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);     /* enable VB processor */
4645
4646       SiS_VBLongWait(SiS_Pr);
4647       SiS_DisplayOn(SiS_Pr);
4648       if(SiS_Pr->ChipType >= SIS_315H) {
4649          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4650       }
4651       SiS_VBLongWait(SiS_Pr);
4652
4653       if(SiS_Pr->ChipType < SIS_315H) {
4654          if(SiS_CRT2IsLCD(SiS_Pr)) {
4655             SiS_PanelDelay(SiS_Pr, 1);
4656             SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4657          }
4658       }
4659
4660    }
4661
4662  } else {   /* =================== For LVDS ================== */
4663
4664    if(SiS_Pr->ChipType < SIS_315H) {
4665
4666#ifdef CONFIG_FB_SIS_300    /* 300 series */
4667
4668       if(SiS_CRT2IsLCD(SiS_Pr)) {
4669          if(SiS_Pr->ChipType == SIS_730) {
4670             SiS_PanelDelay(SiS_Pr, 1);
4671             SiS_PanelDelay(SiS_Pr, 1);
4672             SiS_PanelDelay(SiS_Pr, 1);
4673          }
4674          SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4675          if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4676             SiS_PanelDelay(SiS_Pr, 0);
4677          }
4678       }
4679
4680       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4681       SiS_DisplayOn(SiS_Pr);
4682       SiS_UnLockCRT2(SiS_Pr);
4683       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4684       if(SiS_BridgeInSlavemode(SiS_Pr)) {
4685          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4686       } else {
4687          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4688       }
4689
4690       if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
4691          if(!(SiS_CRT2IsLCD(SiS_Pr))) {
4692             SiS_WaitVBRetrace(SiS_Pr);
4693             SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
4694          }
4695       }
4696
4697       if(SiS_CRT2IsLCD(SiS_Pr)) {
4698          if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4699             if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4700                if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4701                   SiS_PanelDelay(SiS_Pr, 1);
4702                   SiS_PanelDelay(SiS_Pr, 1);
4703                }
4704                SiS_WaitVBRetrace(SiS_Pr);
4705                SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4706             }
4707          }
4708       }
4709
4710#endif  /* CONFIG_FB_SIS_300 */
4711
4712    } else {
4713
4714#ifdef CONFIG_FB_SIS_315    /* 315 series */
4715
4716       if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4717          /*if(SiS_Pr->ChipType < SIS_340) {*/  /* XGI needs this */
4718             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
4719          /*}*/
4720       }
4721
4722       if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4723          if(SiS_CRT2IsLCD(SiS_Pr)) {
4724             SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4725             SiS_PanelDelay(SiS_Pr, 0);
4726          }
4727       }
4728
4729       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4730       SiS_UnLockCRT2(SiS_Pr);
4731
4732       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4733
4734       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4735          temp = SiS_GetCH701x(SiS_Pr,0x66);
4736          temp &= 0x20;
4737          SiS_Chrontel701xBLOff(SiS_Pr);
4738       }
4739
4740       if(SiS_Pr->ChipType != SIS_550) {
4741          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4742       }
4743
4744       if(SiS_Pr->ChipType == SIS_740) {
4745          if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4746             if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4747                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
4748             }
4749          }
4750       }
4751
4752       temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4753       if(!(temp1 & 0x80)) {
4754          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
4755       }
4756
4757       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4758          if(temp) {
4759             SiS_Chrontel701xBLOn(SiS_Pr);
4760          }
4761       }
4762
4763       if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4764          if(SiS_CRT2IsLCD(SiS_Pr)) {
4765             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
4766             if(SiS_Pr->ChipType == SIS_550) {
4767                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
4768                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
4769             }
4770          }
4771       } else if(SiS_IsVAMode(SiS_Pr)) {
4772          if(SiS_Pr->ChipType != SIS_740) {
4773             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
4774          }
4775       }
4776
4777       if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4778          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4779       }
4780
4781       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4782          if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
4783             SiS_Chrontel701xOn(SiS_Pr);
4784          }
4785          if( (SiS_IsVAMode(SiS_Pr)) ||
4786              (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4787             SiS_ChrontelDoSomething1(SiS_Pr);
4788          }
4789       }
4790
4791       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4792          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4793             if( (SiS_IsVAMode(SiS_Pr)) ||
4794                 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4795                SiS_Chrontel701xBLOn(SiS_Pr);
4796                SiS_ChrontelInitTVVSync(SiS_Pr);
4797             }
4798          }
4799       } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4800          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4801             if(SiS_CRT2IsLCD(SiS_Pr)) {
4802                SiS_PanelDelay(SiS_Pr, 1);
4803                SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4804             }
4805          }
4806       }
4807
4808#endif  /* CONFIG_FB_SIS_315 */
4809
4810    } /* 310 series */
4811
4812  }  /* LVDS */
4813
4814}
4815
4816/*********************************************/
4817/*         SET PART 1 REGISTER GROUP         */
4818/*********************************************/
4819
4820/* Set CRT2 OFFSET / PITCH */
4821static void
4822SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
4823                unsigned short RRTI)
4824{
4825   unsigned short offset;
4826   unsigned char  temp;
4827
4828   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
4829
4830   offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
4831
4832   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
4833   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
4834
4835   temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
4836   if(offset & 0x07) temp++;
4837   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
4838}
4839
4840/* Set CRT2 sync and PanelLink mode */
4841static void
4842SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
4843{
4844   unsigned short tempah=0, tempbl, infoflag;
4845
4846   tempbl = 0xC0;
4847
4848   if(SiS_Pr->UseCustomMode) {
4849      infoflag = SiS_Pr->CInfoFlag;
4850   } else {
4851      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
4852   }
4853
4854   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {                                   /* LVDS */
4855
4856      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4857         tempah = 0;
4858      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
4859         tempah = SiS_Pr->SiS_LCDInfo;
4860      } else tempah = infoflag >> 8;
4861      tempah &= 0xC0;
4862      tempah |= 0x20;
4863      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4864      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4865         if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
4866            (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
4867            tempah |= 0xf0;
4868         }
4869         if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4870             (SiS_Pr->SiS_IF_DEF_DSTN) ||
4871             (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
4872             (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
4873             (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
4874            tempah |= 0x30;
4875         }
4876         if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4877             (SiS_Pr->SiS_IF_DEF_DSTN) ) {
4878            tempah &= ~0xc0;
4879         }
4880      }
4881      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4882         if(SiS_Pr->ChipType >= SIS_315H) {
4883            tempah >>= 3;
4884            tempah &= 0x18;
4885            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
4886            /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
4887         } else {
4888            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
4889         }
4890      } else {
4891         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4892      }
4893
4894   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
4895
4896      if(SiS_Pr->ChipType < SIS_315H) {
4897
4898#ifdef CONFIG_FB_SIS_300  /* ---- 300 series --- */
4899
4900         if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {                        /* 630 - 301B(-DH) */
4901
4902            tempah = infoflag >> 8;
4903            tempbl = 0;
4904            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4905               if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4906                  tempah = SiS_Pr->SiS_LCDInfo;
4907                  tempbl = (tempah >> 6) & 0x03;
4908               }
4909            }
4910            tempah &= 0xC0;
4911            tempah |= 0x20;
4912            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4913            tempah |= 0xc0;
4914            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4915            if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
4916               SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4917            }
4918
4919         } else {                                                       /* 630 - 301 */
4920
4921            tempah = ((infoflag >> 8) & 0xc0) | 0x20;
4922            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4923            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4924
4925         }
4926
4927#endif /* CONFIG_FB_SIS_300 */
4928
4929      } else {
4930
4931#ifdef CONFIG_FB_SIS_315  /* ------- 315 series ------ */
4932
4933         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {                  /* 315 - LVDS */
4934
4935            tempbl = 0;
4936            if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
4937               (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
4938               tempah = infoflag >> 8;
4939               if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4940                 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
4941               }
4942            } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
4943                      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
4944               tempah = infoflag >> 8;
4945               tempbl = 0x03;
4946            } else {
4947               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
4948               tempbl = (tempah >> 6) & 0x03;
4949               tempbl |= 0x08;
4950               if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
4951            }
4952            tempah &= 0xC0;
4953            tempah |= 0x20;
4954            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4955            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
4956            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4957            if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
4958               if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4959                  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4960               }
4961            }
4962
4963         } else {                                                       /* 315 - TMDS */
4964
4965            tempah = tempbl = infoflag >> 8;
4966            if(!SiS_Pr->UseCustomMode) {
4967               tempbl = 0;
4968               if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4969                  if(ModeNo <= 0x13) {
4970                     tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
4971                  }
4972               }
4973               if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
4974                  if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
4975                    if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4976                       tempah = SiS_Pr->SiS_LCDInfo;
4977                       tempbl = (tempah >> 6) & 0x03;
4978                    }
4979                  }
4980               }
4981            }
4982            tempah &= 0xC0;
4983            tempah |= 0x20;
4984            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4985            if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4986               /* Imitate BIOS bug */
4987               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
4988            }
4989            if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4990               tempah >>= 3;
4991               tempah &= 0x18;
4992               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
4993            } else {
4994               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4995               if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
4996                  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4997                     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4998                  }
4999               }
5000            }
5001
5002         }
5003#endif  /* CONFIG_FB_SIS_315 */
5004      }
5005   }
5006}
5007
5008/* Set CRT2 FIFO on 300/540/630/730 */
5009#ifdef CONFIG_FB_SIS_300
5010static void
5011SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
5012{
5013  unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
5014  unsigned short temp, index, modeidindex, refreshratetableindex;
5015  unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
5016  unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
5017  unsigned int   data, pci50, pciA0;
5018  static const unsigned char colortharray[] = {
5019        1, 1, 2, 2, 3, 4
5020  };
5021
5022  SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
5023
5024  if(!SiS_Pr->CRT1UsesCustomMode) {
5025
5026     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 /* get CRT1 ModeNo */
5027     SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
5028     SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
5029     SiS_Pr->SiS_SelectCRT2Rate = 0;
5030     refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
5031
5032     if(CRT1ModeNo >= 0x13) {
5033        /* Get VCLK */
5034        index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
5035        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
5036
5037        /* Get colordepth */
5038        colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
5039        if(!colorth) colorth++;
5040     }
5041
5042  } else {
5043
5044     CRT1ModeNo = 0xfe;
5045
5046     /* Get VCLK */
5047     VCLK = SiS_Pr->CSRClock_CRT1;
5048
5049     /* Get color depth */
5050     colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
5051
5052  }
5053
5054  if(CRT1ModeNo >= 0x13) {
5055     /* Get MCLK */
5056     if(SiS_Pr->ChipType == SIS_300) {
5057        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
5058     } else {
5059        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
5060     }
5061     index &= 0x07;
5062     MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
5063
5064     temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
5065     if(!temp) temp++;
5066     temp <<= 2;
5067
5068     data2 = temp - ((colorth * VCLK) / MCLK);
5069
5070     temp = (28 * 16) % data2;
5071     data2 = (28 * 16) / data2;
5072     if(temp) data2++;
5073
5074     if(SiS_Pr->ChipType == SIS_300) {
5075
5076        SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
5077        data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
5078
5079     } else {
5080
5081        pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
5082        pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
5083
5084        if(SiS_Pr->ChipType == SIS_730) {
5085
5086           index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
5087           index += (unsigned short)(((pci50 >> 9)) & 0x03);
5088
5089           /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
5090           index = 0;  /* -- do it like the BIOS anyway... */
5091
5092        } else {
5093
5094           pci50 >>= 24;
5095           pciA0 >>= 24;
5096
5097           index = (pci50 >> 1) & 0x07;
5098
5099           if(pci50 & 0x01)    index += 6;
5100           if(!(pciA0 & 0x01)) index += 24;
5101
5102           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
5103
5104        }
5105
5106        data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
5107        if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
5108
5109     }
5110
5111     data += data2;                                             /* CRT1 Request Period */
5112
5113     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5114     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
5115
5116     if(!SiS_Pr->UseCustomMode) {
5117
5118        CRT2ModeNo = ModeNo;
5119        SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
5120
5121        refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
5122
5123        /* Get VCLK  */
5124        index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
5125        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
5126
5127        if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5128           if(SiS_Pr->SiS_UseROM) {
5129              if(ROMAddr[0x220] & 0x01) {
5130                 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
5131              }
5132           }
5133        }
5134
5135     } else {
5136
5137        /* Get VCLK */
5138        CRT2ModeNo = 0xfe;
5139        VCLK = SiS_Pr->CSRClock;
5140
5141     }
5142
5143     /* Get colordepth */
5144     colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
5145     if(!colorth) colorth++;
5146
5147     data = data * VCLK * colorth;
5148     temp = data % (MCLK << 4);
5149     data = data / (MCLK << 4);
5150     if(temp) data++;
5151
5152     if(data < 6) data = 6;
5153     else if(data > 0x14) data = 0x14;
5154
5155     if(SiS_Pr->ChipType == SIS_300) {
5156        temp = 0x16;
5157        if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
5158           temp = 0x13;
5159     } else {
5160        temp = 0x16;
5161        if(( (SiS_Pr->ChipType == SIS_630) ||
5162             (SiS_Pr->ChipType == SIS_730) )  &&
5163           (SiS_Pr->ChipRevision >= 0x30))
5164           temp = 0x1b;
5165     }
5166     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
5167
5168     if((SiS_Pr->ChipType == SIS_630) &&
5169        (SiS_Pr->ChipRevision >= 0x30)) {
5170        if(data > 0x13) data = 0x13;
5171     }
5172     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
5173
5174  } else {  /* If mode <= 0x13, we just restore everything */
5175
5176     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5177     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
5178
5179  }
5180}
5181#endif
5182
5183/* Set CRT2 FIFO on 315/330 series */
5184#ifdef CONFIG_FB_SIS_315
5185static void
5186SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
5187{
5188  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
5189  if( (SiS_Pr->ChipType == SIS_760)      &&
5190      (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
5191      (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
5192      (SiS_Pr->SiS_VGAHDE >= 1280)        &&
5193      (SiS_Pr->SiS_VGAVDE >= 1024) ) {
5194     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
5195     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
5196     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5197     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
5198     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5199     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
5200  } else {
5201     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
5202  }
5203
5204}
5205#endif
5206
5207static unsigned short
5208SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
5209{
5210  unsigned int tempax,tempbx;
5211
5212  tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
5213  tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
5214  tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
5215  return (unsigned short)tempax;
5216}
5217
5218/* Set Part 1 / SiS bridge slave mode */
5219static void
5220SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
5221                  unsigned short RefreshRateTableIndex)
5222{
5223  unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
5224  static const unsigned short CRTranslation[] = {
5225       /* CR0   CR1   CR2   CR3   CR4   CR5   CR6   CR7   */
5226          0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
5227       /* CR8   CR9   SR0A  SR0B  SR0C  SR0D  SR0E  CR0F  */
5228          0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
5229       /* CR10  CR11  CR12  CR13  CR14  CR15  CR16  CR17  */
5230          0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
5231  };
5232
5233  if(ModeNo <= 0x13) {
5234     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5235  } else if(SiS_Pr->UseCustomMode) {
5236     modeflag = SiS_Pr->CModeFlag;
5237     xres = SiS_Pr->CHDisplay;
5238  } else {
5239     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5240     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
5241  }
5242
5243  /* The following is only done if bridge is in slave mode: */
5244
5245  if(SiS_Pr->ChipType >= SIS_315H) {
5246     if(xres >= 1600) {  /* BIOS: == 1600 */
5247        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
5248     }
5249  }
5250
5251  SiS_Pr->CHTotal = 8224;  /* Max HT, 0x2020, results in 0x3ff in registers */
5252
5253  SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
5254  if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
5255
5256  SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
5257  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5258     SiS_Pr->CHBlankStart += 16;
5259  }
5260
5261  SiS_Pr->CHBlankEnd = 32;
5262  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5263     if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
5264  }
5265
5266  temp = SiS_Pr->SiS_VGAHT - 96;
5267  if(!(modeflag & HalfDCLK)) temp -= 32;
5268  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
5269     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
5270     temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
5271     temp -= 3;
5272     temp <<= 3;
5273  } else {
5274     if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
5275  }
5276  SiS_Pr->CHSyncStart = temp;
5277
5278  SiS_Pr->CHSyncEnd = 0xffe8;   /* results in 0x2000 in registers */
5279
5280  SiS_Pr->CVTotal = 2049;       /* Max VT, 0x0801, results in 0x7ff in registers */
5281
5282  VGAVDE = SiS_Pr->SiS_VGAVDE;
5283  if     (VGAVDE ==  357) VGAVDE =  350;
5284  else if(VGAVDE ==  360) VGAVDE =  350;
5285  else if(VGAVDE ==  375) VGAVDE =  350;
5286  else if(VGAVDE ==  405) VGAVDE =  400;
5287  else if(VGAVDE ==  420) VGAVDE =  400;
5288  else if(VGAVDE ==  525) VGAVDE =  480;
5289  else if(VGAVDE == 1056) VGAVDE = 1024;
5290  SiS_Pr->CVDisplay = VGAVDE;
5291
5292  SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
5293
5294  SiS_Pr->CVBlankEnd = 1;
5295  if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
5296
5297  temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
5298  SiS_Pr->CVSyncStart = VGAVDE + temp;
5299
5300  temp >>= 3;
5301  SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
5302
5303  SiS_CalcCRRegisters(SiS_Pr, 0);
5304  SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
5305
5306  for(i = 0; i <= 7; i++) {
5307     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
5308  }
5309  for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
5310     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5311  }
5312  for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
5313     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5314  }
5315  for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
5316     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5317  }
5318
5319  temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
5320  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
5321
5322  temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
5323  if(modeflag & DoubleScanMode) temp |= 0x80;
5324  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
5325
5326  temp = 0;
5327  temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
5328  if(modeflag & HalfDCLK) temp |= 0x08;
5329  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                  /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
5330
5331  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00);                  /* CR14: (text mode: underline location) */
5332  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00);                  /* CR17: n/a */
5333
5334  temp = 0;
5335  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5336     temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
5337  }
5338  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                  /* SR0E, dither[7] */
5339
5340  temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
5341  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);                  /* ? */
5342}
5343
5344/* Setup panel link
5345 * This is used for LVDS, LCDA and Chrontel TV output
5346 * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
5347 */
5348static void
5349SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5350                unsigned short RefreshRateTableIndex)
5351{
5352  unsigned short modeflag, resinfo = 0;
5353  unsigned short push2, tempax, tempbx, tempcx, temp;
5354  unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 0;
5355  bool islvds = false, issis  = false, chkdclkfirst = false;
5356#ifdef CONFIG_FB_SIS_300
5357  unsigned short crt2crtc = 0;
5358#endif
5359#ifdef CONFIG_FB_SIS_315
5360  unsigned short pushcx;
5361#endif
5362
5363  if(ModeNo <= 0x13) {
5364     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5365     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
5366#ifdef CONFIG_FB_SIS_300
5367     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5368#endif
5369  } else if(SiS_Pr->UseCustomMode) {
5370     modeflag = SiS_Pr->CModeFlag;
5371  } else {
5372     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5373     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5374#ifdef CONFIG_FB_SIS_300
5375     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
5376#endif
5377  }
5378
5379  /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
5380  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
5381     islvds = true;
5382  }
5383
5384  /* is really sis if sis bridge, but not 301B-DH */
5385  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
5386     issis = true;
5387  }
5388
5389  if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
5390     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
5391        chkdclkfirst = true;
5392     }
5393  }
5394
5395#ifdef CONFIG_FB_SIS_315
5396  if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
5397     if(IS_SIS330) {
5398        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5399     } else if(IS_SIS740) {
5400        if(islvds) {
5401           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5402           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
5403        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5404           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5405        }
5406     } else {
5407        if(islvds) {
5408           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5409           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
5410        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5411           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
5412           if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
5413              if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
5414                 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5415                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
5416              }
5417           }
5418        }
5419     }
5420  }
5421#endif
5422
5423  /* Horizontal */
5424
5425  tempax = SiS_Pr->SiS_LCDHDES;
5426  if(islvds) {
5427     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5428        if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
5429           if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
5430              (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
5431              tempax -= 8;
5432           }
5433        }
5434     }
5435  }
5436
5437  temp = (tempax & 0x0007);
5438  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                  /* BPLHDESKEW[2:0]   */
5439  temp = (tempax >> 3) & 0x00FF;
5440  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                  /* BPLHDESKEW[10:3]  */
5441
5442  tempbx = SiS_Pr->SiS_HDE;
5443  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5444     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5445        tempbx = SiS_Pr->PanelXRes;
5446     }
5447     if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
5448        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
5449        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
5450        tempbx >>= 1;
5451     }
5452  }
5453
5454  tempax += tempbx;
5455  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
5456
5457  temp = tempax;
5458  if(temp & 0x07) temp += 8;
5459  temp >>= 3;
5460  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                  /* BPLHDEE  */
5461
5462  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
5463
5464  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5465     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5466        if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
5467     }
5468  }
5469
5470  tempcx += tempax;
5471  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
5472
5473  temp = (tempcx >> 3) & 0x00FF;
5474  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5475     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5476        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5477           switch(ModeNo) {
5478           case 0x04:
5479           case 0x05:
5480           case 0x0d: temp = 0x56; break;
5481           case 0x10: temp = 0x60; break;
5482           case 0x13: temp = 0x5f; break;
5483           case 0x40:
5484           case 0x41:
5485           case 0x4f:
5486           case 0x43:
5487           case 0x44:
5488           case 0x62:
5489           case 0x56:
5490           case 0x53:
5491           case 0x5d:
5492           case 0x5e: temp = 0x54; break;
5493           }
5494        }
5495     }
5496  }
5497  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);                  /* BPLHRS */
5498
5499  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5500     temp += 2;
5501     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5502        temp += 8;
5503        if(SiS_Pr->PanelHRE != 999) {
5504           temp = tempcx + SiS_Pr->PanelHRE;
5505           if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
5506           temp >>= 3;
5507        }
5508     }
5509  } else {
5510     temp += 10;
5511  }
5512
5513  temp &= 0x1F;
5514  temp |= ((tempcx & 0x07) << 5);
5515  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);                  /* BPLHRE */
5516
5517  /* Vertical */
5518
5519  tempax = SiS_Pr->SiS_VGAVDE;
5520  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5521     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5522        tempax = SiS_Pr->PanelYRes;
5523     }
5524  }
5525
5526  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
5527  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5528
5529  push2 = tempbx;
5530
5531  tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
5532  if(SiS_Pr->ChipType < SIS_315H) {
5533     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5534        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5535           tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
5536        }
5537     }
5538  }
5539  if(islvds) tempcx >>= 1;
5540  else       tempcx >>= 2;
5541
5542  if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
5543      (!(SiS_Pr->SiS_LCDInfo & LCDPass11))                  &&
5544      (SiS_Pr->PanelVRS != 999) ) {
5545     tempcx = SiS_Pr->PanelVRS;
5546     tempbx += tempcx;
5547     if(issis) tempbx++;
5548  } else {
5549     tempbx += tempcx;
5550     if(SiS_Pr->ChipType < SIS_315H) tempbx++;
5551     else if(issis)                   tempbx++;
5552  }
5553
5554  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5555
5556  temp = tempbx & 0x00FF;
5557  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5558     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5559        if(ModeNo == 0x10) temp = 0xa9;
5560     }
5561  }
5562  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);                  /* BPLVRS */
5563
5564  tempcx >>= 3;
5565  tempcx++;
5566
5567  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5568     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5569        if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
5570     }
5571  }
5572
5573  tempcx += tempbx;
5574  temp = tempcx & 0x000F;
5575  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);        /* BPLVRE  */
5576
5577  temp = ((tempbx >> 8) & 0x07) << 3;
5578  if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5579     if(SiS_Pr->SiS_HDE != 640) {
5580        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
5581     }
5582  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5583  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
5584  tempbx = 0x87;
5585  if((SiS_Pr->ChipType >= SIS_315H) ||
5586     (SiS_Pr->ChipRevision >= 0x30)) {
5587     tempbx = 0x07;
5588     if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
5589        if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
5590     }
5591     /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
5592     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5593        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5594           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
5595        } else {
5596           if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
5597        }
5598     }
5599  }
5600  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
5601
5602  tempbx = push2;                                               /* BPLVDEE */
5603
5604  tempcx = SiS_Pr->SiS_LCDVDES;                                 /* BPLVDES */
5605
5606  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5607     switch(SiS_Pr->SiS_LCDResInfo) {
5608     case Panel_640x480:
5609        tempbx = SiS_Pr->SiS_VGAVDE - 1;
5610        tempcx = SiS_Pr->SiS_VGAVDE;
5611        break;
5612     case Panel_800x600:
5613        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5614           if(resinfo == SIS_RI_800x600) tempcx++;
5615        }
5616        break;
5617     case Panel_1024x600:
5618        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5619           if(resinfo == SIS_RI_1024x600) tempcx++;
5620           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
5621              if(resinfo == SIS_RI_800x600) tempcx++;
5622           }
5623        }
5624        break;
5625     case Panel_1024x768:
5626        if(SiS_Pr->ChipType < SIS_315H) {
5627           if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5628              if(resinfo == SIS_RI_1024x768) tempcx++;
5629           }
5630        }
5631        break;
5632     }
5633  }
5634
5635  temp = ((tempbx >> 8) & 0x07) << 3;
5636  temp |= ((tempcx >> 8) & 0x07);
5637  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
5638  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
5639  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
5640
5641  /* Vertical scaling */
5642
5643  if(SiS_Pr->ChipType < SIS_315H) {
5644
5645#ifdef CONFIG_FB_SIS_300      /* 300 series */
5646     tempeax = SiS_Pr->SiS_VGAVDE << 6;
5647     temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
5648     tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
5649     if(temp) tempeax++;
5650
5651     if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
5652
5653     temp = (unsigned short)(tempeax & 0x00FF);
5654     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);       /* BPLVCFACT */
5655     tempvcfact = temp;
5656#endif /* CONFIG_FB_SIS_300 */
5657
5658  } else {
5659
5660#ifdef CONFIG_FB_SIS_315  /* 315 series */
5661     tempeax = SiS_Pr->SiS_VGAVDE << 18;
5662     tempebx = SiS_Pr->SiS_VDE;
5663     temp = (tempeax % tempebx);
5664     tempeax = tempeax / tempebx;
5665     if(temp) tempeax++;
5666     tempvcfact = tempeax;
5667
5668     temp = (unsigned short)(tempeax & 0x00FF);
5669     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
5670     temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
5671     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
5672     temp = (unsigned short)((tempeax & 0x00030000) >> 16);
5673     if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
5674     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
5675
5676     if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
5677        temp = (unsigned short)(tempeax & 0x00FF);
5678        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
5679        temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
5680        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
5681        temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
5682        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
5683        temp = 0;
5684        if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
5685        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
5686     }
5687#endif
5688
5689  }
5690
5691  /* Horizontal scaling */
5692
5693  tempeax = SiS_Pr->SiS_VGAHDE;         /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
5694  if(chkdclkfirst) {
5695     if(modeflag & HalfDCLK) tempeax >>= 1;
5696  }
5697  tempebx = tempeax << 16;
5698  if(SiS_Pr->SiS_HDE == tempeax) {
5699     tempecx = 0xFFFF;
5700  } else {
5701     tempecx = tempebx / SiS_Pr->SiS_HDE;
5702     if(SiS_Pr->ChipType >= SIS_315H) {
5703        if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
5704     }
5705  }
5706
5707  if(SiS_Pr->ChipType >= SIS_315H) {
5708     tempeax = (tempebx / tempecx) - 1;
5709  } else {
5710     tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
5711  }
5712  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
5713  temp = (unsigned short)(tempecx & 0x00FF);
5714  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
5715
5716  if(SiS_Pr->ChipType >= SIS_315H) {
5717     tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
5718     tempbx = (unsigned short)(tempeax & 0xFFFF);
5719  } else {
5720     tempeax = SiS_Pr->SiS_VGAVDE << 6;
5721     tempbx = tempvcfact & 0x3f;
5722     if(tempbx == 0) tempbx = 64;
5723     tempeax /= tempbx;
5724     tempbx = (unsigned short)(tempeax & 0xFFFF);
5725  }
5726  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
5727  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
5728     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
5729     else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480)             tempbx = 1;
5730  }
5731
5732  temp = ((tempbx >> 8) & 0x07) << 3;
5733  temp = temp | ((tempecx >> 8) & 0x07);
5734  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
5735  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
5736
5737  tempecx >>= 16;                                               /* BPLHCFACT  */
5738  if(!chkdclkfirst) {
5739     if(modeflag & HalfDCLK) tempecx >>= 1;
5740  }
5741  temp = (unsigned short)((tempecx & 0xFF00) >> 8);
5742  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
5743  temp = (unsigned short)(tempecx & 0x00FF);
5744  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
5745
5746#ifdef CONFIG_FB_SIS_315
5747  if(SiS_Pr->ChipType >= SIS_315H) {
5748     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5749        if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
5750           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
5751        }
5752     } else {
5753        if(islvds) {
5754           if(SiS_Pr->ChipType == SIS_740) {
5755              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
5756           } else {
5757              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
5758           }
5759        }
5760     }
5761  }
5762#endif
5763
5764#ifdef CONFIG_FB_SIS_300
5765  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5766     unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5767     unsigned char *trumpdata;
5768     int   i, j = crt2crtc;
5769     unsigned char TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
5770     unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
5771     unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
5772
5773     if(SiS_Pr->SiS_UseROM) {
5774        trumpdata = &ROMAddr[0x8001 + (j * 80)];
5775     } else {
5776        if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
5777        trumpdata = &SiS300_TrumpionData[j][0];
5778     }
5779
5780     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
5781     for(i=0; i<5; i++) {
5782        SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
5783     }
5784     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5785        if(ModeNo == 0x13) {
5786           for(i=0; i<4; i++) {
5787              SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
5788           }
5789        } else if(ModeNo == 0x10) {
5790           for(i=0; i<4; i++) {
5791              SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
5792              SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
5793           }
5794        }
5795     }
5796     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
5797  }
5798#endif
5799
5800#ifdef CONFIG_FB_SIS_315
5801  if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5802     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
5803     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
5804     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
5805     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
5806     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
5807     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
5808     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
5809     tempax = SiS_Pr->SiS_HDE;                                  /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
5810     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5811        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5812        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5813     tempax += 64;
5814     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
5815     temp = (tempax >> 8) << 3;
5816     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
5817     tempax += 32;                                              /* Blpe = lBlps+32 */
5818     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
5819     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00);               /* Bflml = 0 */
5820     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
5821
5822     tempax = SiS_Pr->SiS_VDE;
5823     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5824        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5825        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5826     tempax >>= 1;
5827     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
5828     temp = (tempax >> 8) << 3;
5829     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
5830
5831     tempeax = SiS_Pr->SiS_HDE;
5832     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5833        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5834        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
5835     tempeax <<= 2;                                             /* BDxFIFOSTOP = (HDE*4)/128 */
5836     temp = tempeax & 0x7f;
5837     tempeax >>= 7;
5838     if(temp) tempeax++;
5839     temp = tempeax & 0x3f;
5840     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
5841     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00);               /* BDxWadrst0 */
5842     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
5843     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
5844     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
5845
5846     tempax = SiS_Pr->SiS_HDE;
5847     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5848        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5849        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5850     tempax >>= 4;                                              /* BDxWadroff = HDE*4/8/8 */
5851     pushcx = tempax;
5852     temp = tempax & 0x00FF;
5853     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
5854     temp = ((tempax & 0xFF00) >> 8) << 3;
5855     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x44, 0x07, temp);
5856
5857     tempax = SiS_Pr->SiS_VDE;                                  /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
5858     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5859        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5860        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5861     tempeax = tempax * pushcx;
5862     temp = tempeax & 0xFF;
5863     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
5864     temp = (tempeax & 0xFF00) >> 8;
5865     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
5866     temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
5867     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
5868     temp = ((tempeax & 0x01000000) >> 24) << 7;
5869     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x3C, 0x7F, temp);
5870
5871     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
5872     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
5873     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
5874     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
5875     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
5876
5877     if(SiS_Pr->SiS_IF_DEF_FSTN) {
5878        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
5879        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
5880        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
5881        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
5882        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
5883        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
5884        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
5885        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
5886        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
5887        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
5888        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
5889        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
5890        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
5891        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
5892        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
5893        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
5894        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
5895        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
5896        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
5897        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
5898     }
5899  }
5900#endif  /* CONFIG_FB_SIS_315 */
5901}
5902
5903/* Set Part 1 */
5904static void
5905SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5906                unsigned short RefreshRateTableIndex)
5907{
5908#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
5909  unsigned char   *ROMAddr = SiS_Pr->VirtualRomBase;
5910#endif
5911  unsigned short  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
5912  unsigned short  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
5913#ifdef CONFIG_FB_SIS_315
5914  unsigned short  tempbl=0;
5915#endif
5916
5917  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5918     SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
5919     return;
5920  }
5921
5922  if(ModeNo <= 0x13) {
5923     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5924  } else if(SiS_Pr->UseCustomMode) {
5925     modeflag = SiS_Pr->CModeFlag;
5926  } else {
5927     CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
5928     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5929     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5930  }
5931
5932  SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
5933
5934  if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
5935         (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
5936         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
5937
5938     if(SiS_Pr->ChipType < SIS_315H ) {
5939#ifdef CONFIG_FB_SIS_300
5940        SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
5941#endif
5942     } else {
5943#ifdef CONFIG_FB_SIS_315
5944        SiS_SetCRT2FIFO_310(SiS_Pr);
5945#endif
5946     }
5947
5948     /* 1. Horizontal setup */
5949
5950     if(SiS_Pr->ChipType < SIS_315H ) {
5951
5952#ifdef CONFIG_FB_SIS_300   /* ------------- 300 series --------------*/
5953
5954        temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;                   /* BTVGA2HT 0x08,0x09 */
5955        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
5956
5957        temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
5958        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
5959
5960        temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
5961        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
5962
5963        pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
5964        tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
5965        tempbx = pushbx + tempcx;
5966        tempcx <<= 1;
5967        tempcx += tempbx;
5968
5969        bridgeadd = 12;
5970
5971#endif /* CONFIG_FB_SIS_300 */
5972
5973     } else {
5974
5975#ifdef CONFIG_FB_SIS_315  /* ------------------- 315/330 series --------------- */
5976
5977        tempcx = SiS_Pr->SiS_VGAHT;                               /* BTVGA2HT 0x08,0x09 */
5978        if(modeflag & HalfDCLK) {
5979           if(SiS_Pr->SiS_VBType & VB_SISVB) {
5980              tempcx >>= 1;
5981           } else {
5982              tempax = SiS_Pr->SiS_VGAHDE >> 1;
5983              tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
5984              if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
5985                 tempcx = SiS_Pr->SiS_HT - tempax;
5986              }
5987           }
5988        }
5989        tempcx--;
5990        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx);            /* CRT2 Horizontal Total */
5991        temp = (tempcx >> 4) & 0xF0;
5992        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
5993
5994        tempcx = SiS_Pr->SiS_VGAHT;                               /* BTVGA2HDEE 0x0A,0x0C */
5995        tempbx = SiS_Pr->SiS_VGAHDE;
5996        tempcx -= tempbx;
5997        tempcx >>= 2;
5998        if(modeflag & HalfDCLK) {
5999           tempbx >>= 1;
6000           tempcx >>= 1;
6001        }
6002        tempbx += 16;
6003
6004        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx);            /* CRT2 Horizontal Display Enable End */
6005
6006        pushbx = tempbx;
6007        tempcx >>= 1;
6008        tempbx += tempcx;
6009        tempcx += tempbx;
6010
6011        bridgeadd = 16;
6012
6013        if(SiS_Pr->SiS_VBType & VB_SISVB) {
6014           if(SiS_Pr->ChipType >= SIS_661) {
6015              if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
6016                 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
6017                 if(resinfo == SIS_RI_1280x1024) {
6018                    tempcx = (tempcx & 0xff00) | 0x30;
6019                 } else if(resinfo == SIS_RI_1600x1200) {
6020                    tempcx = (tempcx & 0xff00) | 0xff;
6021                 }
6022              }
6023           }
6024        }
6025
6026#endif  /* CONFIG_FB_SIS_315 */
6027
6028     }  /* 315/330 series */
6029
6030     if(SiS_Pr->SiS_VBType & VB_SISVB) {
6031
6032        if(SiS_Pr->UseCustomMode) {
6033           tempbx = SiS_Pr->CHSyncStart + bridgeadd;
6034           tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
6035           tempax = SiS_Pr->SiS_VGAHT;
6036           if(modeflag & HalfDCLK) tempax >>= 1;
6037           tempax--;
6038           if(tempcx > tempax) tempcx = tempax;
6039        }
6040
6041        if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6042           unsigned char cr4, cr14, cr5, cr15;
6043           if(SiS_Pr->UseCustomMode) {
6044              cr4  = SiS_Pr->CCRT1CRTC[4];
6045              cr14 = SiS_Pr->CCRT1CRTC[14];
6046              cr5  = SiS_Pr->CCRT1CRTC[5];
6047              cr15 = SiS_Pr->CCRT1CRTC[15];
6048           } else {
6049              cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
6050              cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
6051              cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
6052              cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
6053           }
6054           tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3;                /* (VGAHRS-3)*8 */
6055           tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
6056           tempcx &= 0x00FF;
6057           tempcx |= (tempbx & 0xFF00);
6058           tempbx += bridgeadd;
6059           tempcx += bridgeadd;
6060           tempax = SiS_Pr->SiS_VGAHT;
6061           if(modeflag & HalfDCLK) tempax >>= 1;
6062           tempax--;
6063           if(tempcx > tempax) tempcx = tempax;
6064        }
6065
6066        if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
6067           tempbx = 1040;
6068           tempcx = 1044;   /* HWCursor bug! */
6069        }
6070
6071     }
6072
6073     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx);               /* CRT2 Horizontal Retrace Start */
6074
6075     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx);               /* CRT2 Horizontal Retrace End */
6076
6077     temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
6078     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                 /* Overflow */
6079
6080     /* 2. Vertical setup */
6081
6082     tempcx = SiS_Pr->SiS_VGAVT - 1;
6083     temp = tempcx & 0x00FF;
6084
6085     if(SiS_Pr->ChipType < SIS_661) {
6086        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6087           if(SiS_Pr->ChipType < SIS_315H) {
6088              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6089                 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6090                    temp--;
6091                 }
6092              }
6093           } else {
6094              temp--;
6095           }
6096        } else if(SiS_Pr->ChipType >= SIS_315H) {
6097           temp--;
6098        }
6099     }
6100     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
6101
6102     tempbx = SiS_Pr->SiS_VGAVDE - 1;
6103     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx);               /* CRT2 Vertical Display Enable End */
6104
6105     temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
6106     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
6107
6108     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
6109        tempbx++;
6110        tempax = tempbx;
6111        tempcx++;
6112        tempcx -= tempax;
6113        tempcx >>= 2;
6114        tempbx += tempcx;
6115        if(tempcx < 4) tempcx = 4;
6116        tempcx >>= 2;
6117        tempcx += tempbx;
6118        tempcx++;
6119     } else {
6120        tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
6121        tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
6122     }
6123
6124     if(SiS_Pr->SiS_VBType & VB_SISVB) {
6125        if(SiS_Pr->UseCustomMode) {
6126           tempbx = SiS_Pr->CVSyncStart;
6127           tempcx = SiS_Pr->CVSyncEnd;
6128        }
6129        if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6130           unsigned char cr8, cr7, cr13;
6131           if(SiS_Pr->UseCustomMode) {
6132              cr8    = SiS_Pr->CCRT1CRTC[8];
6133              cr7    = SiS_Pr->CCRT1CRTC[7];
6134              cr13   = SiS_Pr->CCRT1CRTC[13];
6135              tempcx = SiS_Pr->CCRT1CRTC[9];
6136           } else {
6137              cr8    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
6138              cr7    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
6139              cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
6140              tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
6141           }
6142           tempbx = cr8;
6143           if(cr7  & 0x04) tempbx |= 0x0100;
6144           if(cr7  & 0x80) tempbx |= 0x0200;
6145           if(cr13 & 0x08) tempbx |= 0x0400;
6146        }
6147     }
6148     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
6149
6150     temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
6151     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow */
6152
6153     /* 3. Panel delay compensation */
6154
6155     if(SiS_Pr->ChipType < SIS_315H) {
6156
6157#ifdef CONFIG_FB_SIS_300  /* ---------- 300 series -------------- */
6158
6159        if(SiS_Pr->SiS_VBType & VB_SISVB) {
6160           temp = 0x20;
6161           if(SiS_Pr->ChipType == SIS_300) {
6162              temp = 0x10;
6163              if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
6164              if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6165           }
6166           if(SiS_Pr->SiS_VBType & VB_SIS301) {
6167              if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6168           }
6169           if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
6170           if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
6171           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)             temp = 0x08;
6172           if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6173              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)       temp = 0x2c;
6174              else                                          temp = 0x20;
6175           }
6176           if(SiS_Pr->SiS_UseROM) {
6177              if(ROMAddr[0x220] & 0x80) {
6178                 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
6179                    temp = ROMAddr[0x221];
6180                 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
6181                    temp = ROMAddr[0x222];
6182                 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
6183                    temp = ROMAddr[0x223];
6184                 else
6185                    temp = ROMAddr[0x224];
6186              }
6187           }
6188           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6189              if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC;
6190           }
6191
6192        } else {
6193           temp = 0x20;
6194           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6195              if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
6196           }
6197           if(SiS_Pr->SiS_UseROM) {
6198              if(ROMAddr[0x220] & 0x80) {
6199                 temp = ROMAddr[0x220];
6200              }
6201           }
6202           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6203              if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
6204           }
6205        }
6206
6207        temp &= 0x3c;
6208
6209        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
6210
6211#endif  /* CONFIG_FB_SIS_300 */
6212
6213     } else {
6214
6215#ifdef CONFIG_FB_SIS_315   /* --------------- 315/330 series ---------------*/
6216
6217        if(SiS_Pr->ChipType < SIS_661) {
6218
6219           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6220
6221              if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
6222              else                            temp = 0x00;
6223
6224              if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
6225              tempbl = 0xF0;
6226              if(SiS_Pr->ChipType == SIS_650) {
6227                 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6228                    if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
6229                 }
6230              }
6231
6232              if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
6233                 temp = 0x08;
6234                 tempbl = 0;
6235                 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
6236                    if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
6237                 }
6238              }
6239
6240              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp);      /* Panel Link Delay Compensation */
6241           }
6242
6243        } /* < 661 */
6244
6245        tempax = 0;
6246        if(modeflag & DoubleScanMode) tempax |= 0x80;
6247        if(modeflag & HalfDCLK)       tempax |= 0x40;
6248        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
6249
6250#endif  /* CONFIG_FB_SIS_315 */
6251
6252     }
6253
6254  }  /* Slavemode */
6255
6256  if(SiS_Pr->SiS_VBType & VB_SISVB) {
6257     if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
6258        /* For 301BDH with LCD, we set up the Panel Link */
6259        SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
6260     } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6261        SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
6262     }
6263  } else {
6264     if(SiS_Pr->ChipType < SIS_315H) {
6265        SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
6266     } else {
6267        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6268           if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6269              SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
6270           }
6271        } else {
6272           SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
6273        }
6274     }
6275  }
6276}
6277
6278/*********************************************/
6279/*         SET PART 2 REGISTER GROUP         */
6280/*********************************************/
6281
6282#ifdef CONFIG_FB_SIS_315
6283static unsigned char *
6284SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
6285{
6286   const unsigned char *tableptr = NULL;
6287   unsigned short      a, b, p = 0;
6288
6289   a = SiS_Pr->SiS_VGAHDE;
6290   b = SiS_Pr->SiS_HDE;
6291   if(tabletype) {
6292      a = SiS_Pr->SiS_VGAVDE;
6293      b = SiS_Pr->SiS_VDE;
6294   }
6295
6296   if(a < b) {
6297      tableptr = SiS_Part2CLVX_1;
6298   } else if(a == b) {
6299      tableptr = SiS_Part2CLVX_2;
6300   } else {
6301      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6302         tableptr = SiS_Part2CLVX_4;
6303      } else {
6304         tableptr = SiS_Part2CLVX_3;
6305      }
6306      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6307         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)        tableptr = SiS_Part2CLVX_3;
6308         else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   tableptr = SiS_Part2CLVX_3;
6309         else                                           tableptr = SiS_Part2CLVX_5;
6310      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6311         tableptr = SiS_Part2CLVX_6;
6312      }
6313      do {
6314         if((tableptr[p] | tableptr[p+1] << 8) == a) break;
6315         p += 0x42;
6316      } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
6317      if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
6318   }
6319   p += 2;
6320   return ((unsigned char *)&tableptr[p]);
6321}
6322
6323static void
6324SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6325                    unsigned short RefreshRateTableIndex)
6326{
6327   unsigned char *tableptr;
6328   unsigned char temp;
6329   int i, j;
6330
6331   if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
6332
6333   tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
6334   for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
6335      SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6336   }
6337   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6338      tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
6339      for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
6340         SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6341      }
6342   }
6343   temp = 0x10;
6344   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
6345   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
6346}
6347
6348static bool
6349SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
6350                    unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
6351                    unsigned short *ResIndex)
6352{
6353
6354  if(SiS_Pr->ChipType < SIS_315H) return false;
6355
6356  if(ModeNo <= 0x13)
6357     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6358  else
6359     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6360
6361  (*ResIndex) &= 0x3f;
6362  (*CRT2Index) = 0;
6363
6364  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6365     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6366        (*CRT2Index) = 200;
6367     }
6368  }
6369
6370  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
6371     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6372        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
6373     }
6374  }
6375  return (((*CRT2Index) != 0));
6376}
6377#endif
6378
6379#ifdef CONFIG_FB_SIS_300
6380static void
6381SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
6382{
6383   unsigned short tempcx;
6384   static const unsigned char atable[] = {
6385       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
6386       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
6387   };
6388
6389   if(!SiS_Pr->UseCustomMode) {
6390      if( ( ( (SiS_Pr->ChipType == SIS_630) ||
6391              (SiS_Pr->ChipType == SIS_730) ) &&
6392            (SiS_Pr->ChipRevision > 2) )  &&
6393          (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
6394          (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
6395          (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
6396         if(ModeNo == 0x13) {
6397            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
6398            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
6399            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
6400         } else if((crt2crtc & 0x3F) == 4) {
6401            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
6402            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
6403            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
6404            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
6405            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
6406         }
6407      }
6408
6409      if(SiS_Pr->ChipType < SIS_315H) {
6410         if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
6411            crt2crtc &= 0x1f;
6412            tempcx = 0;
6413            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6414               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6415                  tempcx += 7;
6416               }
6417            }
6418            tempcx += crt2crtc;
6419            if(crt2crtc >= 4) {
6420               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
6421            }
6422
6423            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6424               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6425                  if(crt2crtc == 4) {
6426                     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
6427                  }
6428               }
6429            }
6430            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
6431            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
6432         }
6433      }
6434   }
6435}
6436
6437/* For ECS A907. Highly preliminary. */
6438static void
6439SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
6440                    unsigned short ModeNo)
6441{
6442  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6443  unsigned short crt2crtc, resindex;
6444  int i, j;
6445
6446  if(SiS_Pr->ChipType != SIS_300) return;
6447  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
6448  if(SiS_Pr->UseCustomMode) return;
6449
6450  if(ModeNo <= 0x13) {
6451     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6452  } else {
6453     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6454  }
6455
6456  resindex = crt2crtc & 0x3F;
6457  if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6458  else                                    CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
6459
6460  /* The BIOS code (1.16.51,56) is obviously a fragment! */
6461  if(ModeNo > 0x13) {
6462     CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6463     resindex = 4;
6464  }
6465
6466  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6467  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6468  for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
6469     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6470  }
6471  for(j = 0x1c; j <= 0x1d; i++, j++ ) {
6472     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6473  }
6474  for(j = 0x1f; j <= 0x21; i++, j++ ) {
6475     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6476  }
6477  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6478  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6479}
6480#endif
6481
6482static void
6483SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
6484{
6485  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
6486  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
6487  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
6488
6489  if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6490     if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6491        const unsigned char specialtv[] = {
6492                0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
6493                0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
6494                0x58,0xe4,0x73,0xda,0x13
6495        };
6496        int i, j;
6497        for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
6498           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
6499        }
6500        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
6501        if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
6502           if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6503              SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
6504              SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
6505           } else {
6506              SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);  /* 15 */
6507              SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a);  /* 1b */
6508           }
6509        }
6510     }
6511  } else {
6512     if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
6513        (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
6514        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 21 */
6515        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 5a */
6516     } else {
6517        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a);  /* 21 */
6518        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53);  /* 5a */
6519     }
6520  }
6521}
6522
6523static void
6524SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
6525{
6526  unsigned short temp;
6527
6528  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6529     if(SiS_Pr->SiS_VGAVDE == 525) {
6530        temp = 0xc3;
6531        if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6532           temp++;
6533           if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
6534        }
6535        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6536        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
6537     } else if(SiS_Pr->SiS_VGAVDE == 420) {
6538        temp = 0x4d;
6539        if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6540           temp++;
6541           if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
6542        }
6543        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6544     }
6545  }
6546
6547  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6548     if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
6549        if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
6550           SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
6551           /* Not always for LV, see SetGrp2 */
6552        }
6553        temp = 1;
6554        if(ModeNo <= 0x13) temp = 3;
6555        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
6556     }
6557#if 0
6558     /* 651+301C, for 1280x768 - do I really need that? */
6559     if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
6560        if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
6561           if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
6562              ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
6563              SiS_SetReg(SiS_Part2Port,0x01,0x2b);
6564              SiS_SetReg(SiS_Part2Port,0x02,0x13);
6565              SiS_SetReg(SiS_Part2Port,0x04,0xe5);
6566              SiS_SetReg(SiS_Part2Port,0x05,0x08);
6567              SiS_SetReg(SiS_Part2Port,0x06,0xe2);
6568              SiS_SetReg(SiS_Part2Port,0x1c,0x21);
6569              SiS_SetReg(SiS_Part2Port,0x1d,0x45);
6570              SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
6571              SiS_SetReg(SiS_Part2Port,0x20,0x00);
6572              SiS_SetReg(SiS_Part2Port,0x21,0xa9);
6573              SiS_SetReg(SiS_Part2Port,0x23,0x0b);
6574              SiS_SetReg(SiS_Part2Port,0x25,0x04);
6575           }
6576        }
6577     }
6578#endif
6579  }
6580}
6581
6582static void
6583SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6584                unsigned short RefreshRateTableIndex)
6585{
6586  unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
6587  unsigned short push2, modeflag, crt2crtc, bridgeoffset;
6588  unsigned int   longtemp, PhaseIndex;
6589  bool           newtvphase;
6590  const unsigned char *TimingPoint;
6591#ifdef CONFIG_FB_SIS_315
6592  unsigned short resindex, CRT2Index;
6593  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6594
6595  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
6596#endif
6597
6598  if(ModeNo <= 0x13) {
6599     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6600     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6601  } else if(SiS_Pr->UseCustomMode) {
6602     modeflag = SiS_Pr->CModeFlag;
6603     crt2crtc = 0;
6604  } else {
6605     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6606     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6607  }
6608
6609  temp = 0;
6610  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
6611  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
6612  if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)     temp |= 0x02;
6613  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)  temp |= 0x01;
6614
6615  if(!(SiS_Pr->SiS_TVMode & TVSetPAL))        temp |= 0x10;
6616
6617  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
6618
6619  PhaseIndex  = 0x01; /* SiS_PALPhase */
6620  TimingPoint = SiS_Pr->SiS_PALTiming;
6621
6622  newtvphase = false;
6623  if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
6624      ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6625        (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6626     newtvphase = true;
6627  }
6628
6629  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6630
6631     TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
6632     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6633        TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
6634        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6635           TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
6636        }
6637     }
6638
6639  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6640
6641     i = 0;
6642     if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      i = 2;
6643     else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
6644
6645     TimingPoint = &SiS_YPbPrTable[i][0];
6646
6647     PhaseIndex = 0x00; /* SiS_NTSCPhase */
6648
6649  } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6650
6651     if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
6652
6653  } else {
6654
6655     TimingPoint = SiS_Pr->SiS_NTSCTiming;
6656     PhaseIndex  = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00;     /* SiS_PALPhase : SiS_NTSCPhase */
6657     if(newtvphase) PhaseIndex += 8;                                    /* SiS_PALPhase2 : SiS_NTSCPhase2 */
6658
6659  }
6660
6661  if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
6662     PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03;       /* SiS_PALMPhase : SiS_PALNPhase */
6663     if(newtvphase) PhaseIndex += 8;                                    /* SiS_PALMPhase2 : SiS_PALNPhase2 */
6664  }
6665
6666  if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6667     if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6668        PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
6669     } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
6670        PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
6671     } else {
6672        PhaseIndex = 0x10; /* SiS_SpecialPhase */
6673     }
6674  }
6675
6676  for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
6677     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
6678  }
6679
6680  for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
6681     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6682  }
6683  for(i = 0x39; i <= 0x45; i++, j++) {
6684     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6685  }
6686
6687  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6688     if(SiS_Pr->SiS_ModeType != ModeText) {
6689        SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
6690     }
6691  }
6692
6693  SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
6694
6695  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
6696  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
6697  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
6698  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
6699
6700  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)    tempax = 950;
6701  else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  tempax = 680;
6702  else if(SiS_Pr->SiS_TVMode & TVSetPAL)        tempax = 520;
6703  else                                          tempax = 440; /* NTSC, YPbPr 525 */
6704
6705  if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
6706      ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
6707        ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
6708
6709     tempax -= SiS_Pr->SiS_VDE;
6710     tempax >>= 1;
6711     if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
6712        tempax >>= 1;
6713     }
6714     tempax &= 0x00ff;
6715
6716     temp = tempax + (unsigned short)TimingPoint[0];
6717     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
6718
6719     temp = tempax + (unsigned short)TimingPoint[1];
6720     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
6721
6722     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
6723        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6724           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
6725           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
6726        } else {
6727           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
6728           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
6729        }
6730     }
6731
6732  }
6733
6734  tempcx = SiS_Pr->SiS_HT;
6735  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
6736  tempcx--;
6737  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
6738  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
6739  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
6740
6741  tempcx = SiS_Pr->SiS_HT >> 1;
6742  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
6743  tempcx += 7;
6744  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6745  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
6746
6747  tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
6748  tempbx += tempcx;
6749  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
6750  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
6751
6752  tempbx += 8;
6753  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6754     tempbx -= 4;
6755     tempcx = tempbx;
6756  }
6757  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
6758
6759  j += 2;
6760  tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
6761  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
6762  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
6763
6764  tempcx += 8;
6765  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6766  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
6767
6768  tempcx = SiS_Pr->SiS_HT >> 1;
6769  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
6770  j += 2;
6771  tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
6772  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
6773
6774  tempcx -= 11;
6775  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6776     tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
6777  }
6778  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
6779
6780  tempbx = SiS_Pr->SiS_VDE;
6781  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6782     if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
6783     if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
6784     if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
6785  } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6786             (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
6787     tempbx >>= 1;
6788     if(SiS_Pr->ChipType >= SIS_315H) {
6789        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6790           if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
6791        } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6792           if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6793              if(crt2crtc == 4) tempbx++;
6794           }
6795        }
6796     }
6797     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6798        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6799           if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
6800        }
6801        if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6802           if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
6803        }
6804     }
6805  }
6806  tempbx -= 2;
6807  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
6808
6809  temp = (tempcx >> 8) & 0x0F;
6810  temp |= ((tempbx >> 2) & 0xC0);
6811  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6812     temp |= 0x10;
6813     if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
6814  }
6815  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
6816
6817  if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
6818     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
6819  }
6820
6821  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
6822     tempbx = SiS_Pr->SiS_VDE;
6823     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6824         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
6825        tempbx >>= 1;
6826     }
6827     tempbx -= 3;
6828     temp = ((tempbx >> 3) & 0x60) | 0x18;
6829     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
6830     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
6831
6832     if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
6833        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
6834     }
6835  }
6836
6837  tempbx = 0;
6838  if(!(modeflag & HalfDCLK)) {
6839     if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
6840        tempax = 0;
6841        tempbx |= 0x20;
6842     }
6843  }
6844
6845  tempch = tempcl = 0x01;
6846  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6847     if(SiS_Pr->SiS_VGAHDE >= 960) {
6848        if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
6849           tempcl = 0x20;
6850           if(SiS_Pr->SiS_VGAHDE >= 1280) {
6851              tempch = 20;
6852              tempbx &= ~0x20;
6853           } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
6854              tempch = 25;
6855           } else {
6856              tempch = 25; /* OK */
6857           }
6858        }
6859     }
6860  }
6861
6862  if(!(tempbx & 0x20)) {
6863     if(modeflag & HalfDCLK) tempcl <<= 1;
6864     longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
6865     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
6866     tempax = longtemp / SiS_Pr->SiS_HDE;
6867     if(longtemp % SiS_Pr->SiS_HDE) tempax++;
6868     tempbx |= ((tempax >> 8) & 0x1F);
6869     tempcx = tempax >> 13;
6870  }
6871
6872  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
6873  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
6874
6875  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
6876
6877     tempcx &= 0x07;
6878     if(tempbx & 0x20) tempcx = 0;
6879     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
6880
6881     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6882        tempbx = 0x0382;
6883        tempcx = 0x007e;
6884     } else {
6885        tempbx = 0x0369;
6886        tempcx = 0x0061;
6887     }
6888     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
6889     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
6890     temp = (tempcx & 0x0300) >> 6;
6891     temp |= ((tempbx >> 8) & 0x03);
6892     if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6893        temp |= 0x10;
6894        if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)      temp |= 0x20;
6895        else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
6896     }
6897     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
6898
6899     temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
6900     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
6901
6902     SiS_SetTVSpecial(SiS_Pr, ModeNo);
6903
6904     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
6905        temp = 0;
6906        if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
6907        SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
6908     }
6909
6910  }
6911
6912  if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6913     if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
6914        temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
6915        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
6916     }
6917     SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
6918  }
6919
6920  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6921     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6922        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
6923     }
6924  }
6925
6926  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
6927
6928  /* From here: Part2 LCD setup */
6929
6930  tempbx = SiS_Pr->SiS_HDE;
6931  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
6932  tempbx--;                                     /* RHACTE = HDE - 1 */
6933  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
6934  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
6935
6936  temp = 0x01;
6937  if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
6938     if(SiS_Pr->SiS_ModeType == ModeEGA) {
6939        if(SiS_Pr->SiS_VGAHDE >= 1024) {
6940           temp = 0x02;
6941           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
6942              temp = 0x01;
6943           }
6944        }
6945     }
6946  }
6947  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
6948
6949  tempbx = SiS_Pr->SiS_VDE - 1;
6950  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
6951  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
6952
6953  tempcx = SiS_Pr->SiS_VT - 1;
6954  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
6955  temp = (tempcx >> 3) & 0xE0;
6956  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
6957     /* Enable dithering; only do this for 32bpp mode */
6958     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
6959        temp |= 0x10;
6960     }
6961  }
6962  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
6963
6964  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
6965  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
6966
6967  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
6968  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
6969
6970#ifdef CONFIG_FB_SIS_315
6971  if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
6972                                                &CRT2Index, &resindex)) {
6973      switch(CRT2Index) {
6974        case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
6975        default:
6976        case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
6977      }
6978
6979      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6980      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6981      for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
6982        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6983      }
6984      for(j = 0x1c; j <= 0x1d; i++, j++ ) {
6985        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6986      }
6987      for(j = 0x1f; j <= 0x21; i++, j++ ) {
6988        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6989      }
6990      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6991      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6992
6993      SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
6994
6995  } else {
6996#endif
6997
6998    /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
6999    /*             Clevo dual-link 1024x768 */
7000    /*             Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
7001    /*             Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
7002
7003    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7004       if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7005          tempbx = SiS_Pr->SiS_VDE - 1;
7006          tempcx = SiS_Pr->SiS_VT - 1;
7007       } else {
7008          tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7009          tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7010       }
7011    } else {
7012       tempbx = SiS_Pr->PanelYRes;
7013       tempcx = SiS_Pr->SiS_VT;
7014       tempax = 1;
7015       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7016          tempax = SiS_Pr->PanelYRes;
7017          /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
7018          if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7019             tempax = tempcx = 0;
7020          } else {
7021             tempax -= SiS_Pr->SiS_VDE;
7022          }
7023          tempax >>= 1;
7024       }
7025       tempcx -= tempax; /* lcdvdes */
7026       tempbx -= tempax; /* lcdvdee */
7027    }
7028
7029    /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7030
7031    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);      /* lcdvdes  */
7032    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);      /* lcdvdee  */
7033
7034    temp = (tempbx >> 5) & 0x38;
7035    temp |= ((tempcx >> 8) & 0x07);
7036    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7037
7038    tempax = SiS_Pr->SiS_VDE;
7039    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7040       tempax = SiS_Pr->PanelYRes;
7041    }
7042    tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7043    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7044       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7045          tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7046       }
7047    }
7048
7049    tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7050    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7051       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7052          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7053             tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7054             if(tempax % 4) { tempax >>= 2; tempax++; }
7055             else           { tempax >>= 2;           }
7056             tempbx -= (tempax - 1);
7057          } else {
7058             tempbx -= 10;
7059             if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7060          }
7061       }
7062    }
7063    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7064       tempbx++;
7065       if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7066          if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7067             tempbx = 770;
7068             tempcx = 3;
7069          }
7070       }
7071    }
7072
7073    /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7074
7075    if(SiS_Pr->UseCustomMode) {
7076       tempbx = SiS_Pr->CVSyncStart;
7077    }
7078
7079    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);          /* lcdvrs */
7080
7081    temp = (tempbx >> 4) & 0xF0;
7082    tempbx += (tempcx + 1);
7083    temp |= (tempbx & 0x0F);
7084
7085    if(SiS_Pr->UseCustomMode) {
7086       temp &= 0xf0;
7087       temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7088    }
7089
7090    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7091
7092#ifdef CONFIG_FB_SIS_300
7093    SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
7094#endif
7095
7096    bridgeoffset = 7;
7097    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)       bridgeoffset += 2;
7098    if(SiS_Pr->SiS_VBType & VB_SIS30xCLV)       bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
7099    if(SiS_IsDualLink(SiS_Pr))                  bridgeoffset++;
7100    else if(SiS_Pr->SiS_VBType & VB_SIS302LV)   bridgeoffset++;    /* OK for Asus A4L 1280x800 */
7101    /* Higher bridgeoffset shifts to the LEFT */
7102
7103    temp = 0;
7104    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7105       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7106          temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7107          if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
7108       }
7109    }
7110    temp += bridgeoffset;
7111    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);             /* lcdhdes */
7112    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7113
7114    tempcx = SiS_Pr->SiS_HT;
7115    tempax = tempbx = SiS_Pr->SiS_HDE;
7116    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7117       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7118          tempax = SiS_Pr->PanelXRes;
7119          tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7120       }
7121    }
7122    if(SiS_IsDualLink(SiS_Pr)) {
7123       tempcx >>= 1;
7124       tempbx >>= 1;
7125       tempax >>= 1;
7126    }
7127
7128    tempbx += bridgeoffset;
7129
7130    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);          /* lcdhdee */
7131    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7132
7133    tempcx = (tempcx - tempax) >> 2;
7134
7135    tempbx += tempcx;
7136    push2 = tempbx;
7137
7138    if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7139       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7140          if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7141             if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7142          }
7143       }
7144    }
7145
7146    if(SiS_Pr->UseCustomMode) {
7147       tempbx = SiS_Pr->CHSyncStart;
7148       if(modeflag & HalfDCLK) tempbx <<= 1;
7149       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7150       tempbx += bridgeoffset;
7151    }
7152
7153    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);          /* lcdhrs */
7154    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7155
7156    tempbx = push2;
7157
7158    tempcx <<= 1;
7159    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7160       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7161    }
7162    tempbx += tempcx;
7163
7164    if(SiS_Pr->UseCustomMode) {
7165       tempbx = SiS_Pr->CHSyncEnd;
7166       if(modeflag & HalfDCLK) tempbx <<= 1;
7167       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7168       tempbx += bridgeoffset;
7169    }
7170
7171    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);          /* lcdhre */
7172
7173    SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7174
7175#ifdef CONFIG_FB_SIS_300
7176    SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
7177#endif
7178#ifdef CONFIG_FB_SIS_315
7179  } /* CRT2-LCD from table */
7180#endif
7181}
7182
7183/*********************************************/
7184/*         SET PART 3 REGISTER GROUP         */
7185/*********************************************/
7186
7187static void
7188SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
7189{
7190  unsigned short i;
7191  const unsigned char *tempdi;
7192
7193  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7194
7195#ifndef SIS_CP
7196  SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7197#else
7198  SIS_CP_INIT301_CP
7199#endif
7200
7201  if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7202     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7203     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7204  } else {
7205     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7206     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7207  }
7208
7209  if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7210     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7211     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7212     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7213  }
7214
7215  tempdi = NULL;
7216  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7217     tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7218     if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7219        tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7220     }
7221  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7222     if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7223        tempdi = SiS_HiTVGroup3_1;
7224        if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7225     }
7226  }
7227  if(tempdi) {
7228     for(i=0; i<=0x3E; i++) {
7229        SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7230     }
7231     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
7232        if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7233           SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7234        }
7235     }
7236  }
7237
7238#ifdef SIS_CP
7239  SIS_CP_INIT301_CP2
7240#endif
7241}
7242
7243/*********************************************/
7244/*         SET PART 4 REGISTER GROUP         */
7245/*********************************************/
7246
7247#ifdef CONFIG_FB_SIS_315
7248#if 0
7249static void
7250SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
7251{
7252   unsigned short temp, temp1, temp2;
7253
7254   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7255   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
7256   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7257   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7258   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7259   temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
7260   temp = (unsigned short)((int)(temp) + shift);
7261   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7262   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7263   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
7264   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7265   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7266   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7267}
7268#endif
7269
7270static void
7271SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
7272{
7273   unsigned short temp, temp1, resinfo = 0;
7274   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
7275
7276   if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
7277   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7278
7279   if(SiS_Pr->ChipType >= XGI_20) return;
7280
7281   if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
7282      if(!(ROMAddr[0x61] & 0x04)) return;
7283   }
7284
7285   if(ModeNo > 0x13) {
7286      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7287   }
7288
7289   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7290   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7291   if(!(temp & 0x01)) {
7292      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7293      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
7294      if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
7295         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7296      }
7297      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7298      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
7299      else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7300      else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
7301      else                                         temp = 0x0402;
7302      if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
7303         temp1 = 0;
7304         if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7305         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7306         if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7307         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
7308         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7309         if(ModeNo > 0x13) {
7310            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
7311         }
7312      } else {
7313         temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7314         if(temp1 == 0x01) temp |= 0x01;
7315         if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
7316         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
7317         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7318         if(ModeNo > 0x13) {
7319            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7320         }
7321      }
7322
7323#if 0
7324      if(SiS_Pr->ChipType >= SIS_661) {                 /* ? */
7325         if(SiS_Pr->SiS_TVMode & TVAspect43) {
7326            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7327               if(resinfo == SIS_RI_1024x768) {
7328                  SiS_ShiftXPos(SiS_Pr, 97);
7329               } else {
7330                  SiS_ShiftXPos(SiS_Pr, 111);
7331               }
7332            } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7333               SiS_ShiftXPos(SiS_Pr, 136);
7334            }
7335         }
7336      }
7337#endif
7338
7339   }
7340
7341}
7342#endif
7343
7344static void
7345SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7346                 unsigned short RefreshRateTableIndex)
7347{
7348  unsigned short vclkindex, temp, reg1, reg2;
7349
7350  if(SiS_Pr->UseCustomMode) {
7351     reg1 = SiS_Pr->CSR2B;
7352     reg2 = SiS_Pr->CSR2C;
7353  } else {
7354     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
7355     reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7356     reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7357  }
7358
7359  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7360     if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
7361        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7362        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7363        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7364     } else {
7365        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7366        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7367     }
7368  } else {
7369     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7370     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7371     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7372  }
7373  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7374  temp = 0x08;
7375  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7376  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7377}
7378
7379static void
7380SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
7381{
7382  if(SiS_Pr->ChipType >= SIS_315H) {
7383     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
7384        if((SiS_CRT2IsLCD(SiS_Pr)) ||
7385           (SiS_IsVAMode(SiS_Pr))) {
7386           if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
7387              SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7388           } else {
7389              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7390           }
7391        }
7392     }
7393  }
7394  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
7395     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7396#ifdef SET_EMI
7397     SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7398#endif
7399     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7400  }
7401}
7402
7403static void
7404SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7405                unsigned short RefreshRateTableIndex)
7406{
7407  unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
7408  unsigned int   tempebx, tempeax, templong;
7409
7410  if(ModeNo <= 0x13) {
7411     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7412     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7413  } else if(SiS_Pr->UseCustomMode) {
7414     modeflag = SiS_Pr->CModeFlag;
7415     resinfo = 0;
7416  } else {
7417     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7418     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7419  }
7420
7421  if(SiS_Pr->ChipType >= SIS_315H) {
7422     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7423        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7424           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7425        }
7426     }
7427  }
7428
7429  if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
7430     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7431        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
7432     }
7433  }
7434
7435  if(SiS_Pr->ChipType >= SIS_315H) {
7436     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7437        SiS_SetDualLinkEtc(SiS_Pr);
7438        return;
7439     }
7440  }
7441
7442  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7443
7444  tempbx = SiS_Pr->SiS_RVBHCMAX;
7445  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7446
7447  temp = (tempbx >> 1) & 0x80;
7448
7449  tempcx = SiS_Pr->SiS_VGAHT - 1;
7450  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7451
7452  temp |= ((tempcx >> 5) & 0x78);
7453
7454  tempcx = SiS_Pr->SiS_VGAVT - 1;
7455  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7456  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7457
7458  temp |= ((tempcx >> 8) & 0x07);
7459  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7460
7461  tempbx = SiS_Pr->SiS_VGAHDE;
7462  if(modeflag & HalfDCLK)    tempbx >>= 1;
7463  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7464
7465  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7466     temp = 0;
7467     if(tempbx > 800)        temp = 0x60;
7468  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7469     temp = 0;
7470     if(tempbx > 1024)       temp = 0xC0;
7471     else if(tempbx >= 960)  temp = 0xA0;
7472  } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7473     temp = 0;
7474     if(tempbx >= 1280)      temp = 0x40;
7475     else if(tempbx >= 1024) temp = 0x20;
7476  } else {
7477     temp = 0x80;
7478     if(tempbx >= 1024)      temp = 0xA0;
7479  }
7480
7481  temp |= SiS_Pr->Init_P4_0E;
7482
7483  if(SiS_Pr->SiS_VBType & VB_SIS301) {
7484     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
7485        temp &= 0xf0;
7486        temp |= 0x0A;
7487     }
7488  }
7489
7490  SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7491
7492  tempeax = SiS_Pr->SiS_VGAVDE;
7493  tempebx = SiS_Pr->SiS_VDE;
7494  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7495     if(!(temp & 0xE0)) tempebx >>=1;
7496  }
7497
7498  tempcx = SiS_Pr->SiS_RVBHRS;
7499  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7500  tempcx >>= 8;
7501  tempcx |= 0x40;
7502
7503  if(tempeax <= tempebx) {
7504     tempcx ^= 0x40;
7505  } else {
7506     tempeax -= tempebx;
7507  }
7508
7509  tempeax *= (256 * 1024);
7510  templong = tempeax % tempebx;
7511  tempeax /= tempebx;
7512  if(templong) tempeax++;
7513
7514  temp = (unsigned short)(tempeax & 0x000000FF);
7515  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
7516  temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
7517  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
7518  temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
7519  temp |= (tempcx & 0x4F);
7520  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7521
7522  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7523
7524     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7525
7526     /* Calc Linebuffer max address and set/clear decimode */
7527     tempbx = 0;
7528     if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7529     tempax = SiS_Pr->SiS_VGAHDE;
7530     if(modeflag & HalfDCLK)    tempax >>= 1;
7531     if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
7532     if(tempax > 800) {
7533        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7534           tempax -= 800;
7535        } else {
7536           tempbx = 0x08;
7537           if(tempax == 960)       tempax *= 25; /* Correct */
7538           else if(tempax == 1024) tempax *= 25;
7539           else                    tempax *= 20;
7540           temp = tempax % 32;
7541           tempax /= 32;
7542           if(temp) tempax++;
7543           tempax++;
7544           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7545              if(resinfo == SIS_RI_1024x768 ||
7546                 resinfo == SIS_RI_1024x576 ||
7547                 resinfo == SIS_RI_1280x1024 ||
7548                 resinfo == SIS_RI_1280x720) {
7549                 /* Otherwise white line or garbage at right edge */
7550                 tempax = (tempax & 0xff00) | 0x20;
7551              }
7552           }
7553        }
7554     }
7555     tempax--;
7556     temp = ((tempax >> 4) & 0x30) | tempbx;
7557     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7558     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7559
7560     temp = 0x0036; tempbx = 0xD0;
7561     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
7562        temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7563     }
7564     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7565        if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7566           temp |= 0x01;
7567           if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7568              if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7569                 temp &= ~0x01;
7570              }
7571           }
7572        }
7573     }
7574     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7575
7576     tempbx = SiS_Pr->SiS_HT >> 1;
7577     if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7578     tempbx -= 2;
7579     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7580     temp = (tempbx >> 5) & 0x38;
7581     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7582
7583     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7584        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7585           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7586           /* LCD-too-dark-error-source, see FinalizeLCD() */
7587        }
7588     }
7589
7590     SiS_SetDualLinkEtc(SiS_Pr);
7591
7592  }  /* 301B */
7593
7594  SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
7595}
7596
7597/*********************************************/
7598/*         SET PART 5 REGISTER GROUP         */
7599/*********************************************/
7600
7601static void
7602SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
7603{
7604
7605  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)  return;
7606
7607  if(SiS_Pr->SiS_ModeType == ModeVGA) {
7608     if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7609        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
7610        SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
7611     }
7612  }
7613}
7614
7615/*********************************************/
7616/*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
7617/*********************************************/
7618
7619static bool
7620SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7621                   unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
7622                   unsigned short *DisplayType)
7623 {
7624  unsigned short modeflag = 0;
7625  bool checkhd = true;
7626
7627  /* Pass 1:1 not supported here */
7628
7629  if(ModeNo <= 0x13) {
7630     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7631     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7632  } else {
7633     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7634     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7635  }
7636
7637  (*ResIndex) &= 0x3F;
7638
7639  if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7640
7641     (*DisplayType) = 80;
7642     if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
7643        (*DisplayType) = 82;
7644        if(SiS_Pr->SiS_ModeType > ModeVGA) {
7645           if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
7646        }
7647     }
7648     if((*DisplayType) != 84) {
7649        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
7650     }
7651
7652  } else {
7653
7654     (*DisplayType = 0);
7655     switch(SiS_Pr->SiS_LCDResInfo) {
7656     case Panel_320x240_1: (*DisplayType) = 50;
7657                           checkhd = false;
7658                           break;
7659     case Panel_320x240_2: (*DisplayType) = 14;
7660                           break;
7661     case Panel_320x240_3: (*DisplayType) = 18;
7662                           break;
7663     case Panel_640x480:   (*DisplayType) = 10;
7664                           break;
7665     case Panel_1024x600:  (*DisplayType) = 26;
7666                           break;
7667     default: return true;
7668     }
7669
7670     if(checkhd) {
7671        if(modeflag & HalfDCLK) (*DisplayType)++;
7672     }
7673
7674     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
7675        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
7676     }
7677
7678  }
7679
7680  return true;
7681}
7682
7683static void
7684SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7685                unsigned short RefreshRateTableIndex)
7686{
7687  unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
7688  const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
7689  static const unsigned short CRIdx[] = {
7690        0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
7691        0x07, 0x10, 0x11, 0x15, 0x16
7692  };
7693
7694  if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
7695     (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
7696     (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
7697     (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
7698     return;
7699
7700  if(SiS_Pr->SiS_IF_DEF_LVDS) {
7701     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7702        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7703     }
7704  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
7705     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7706  } else return;
7707
7708  if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
7709
7710  if(SiS_Pr->ChipType < SIS_315H) {
7711     if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
7712  }
7713
7714  if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7715                          &ResIndex, &DisplayType))) {
7716     return;
7717  }
7718
7719  switch(DisplayType) {
7720    case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1;           break; /* xSTN */
7721    case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2;           break; /* xSTN */
7722    case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H;         break; /* xSTN */
7723    case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3;           break; /* xSTN */
7724    case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H;         break; /* xSTN */
7725    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1;           break;
7726    case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H;         break;
7727#if 0 /* Works better with calculated numbers */
7728    case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1;          break;
7729    case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H;        break;
7730    case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2;          break;
7731    case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H;        break;
7732#endif
7733    case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC;               break;
7734    case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC;               break;
7735    case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL;                break;
7736    case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL;                break;
7737    case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL;               break;
7738  }
7739
7740  if(LVDSCRT1Ptr) {
7741
7742     SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
7743
7744     for(i = 0; i <= 10; i++) {
7745        tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
7746        SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
7747     }
7748
7749     for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
7750        tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
7751        SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
7752     }
7753
7754     tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
7755     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
7756
7757     if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7758     else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7759
7760     tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
7761     if(modeflag & DoubleScanMode) tempah |= 0x80;
7762     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
7763
7764  } else {
7765
7766     SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
7767
7768  }
7769}
7770
7771/*********************************************/
7772/*              SET CRT2 ECLK                */
7773/*********************************************/
7774
7775static void
7776SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7777           unsigned short RefreshRateTableIndex)
7778{
7779  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
7780  unsigned short clkbase, vclkindex = 0;
7781  unsigned char  sr2b, sr2c;
7782
7783  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7784     SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
7785     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
7786        RefreshRateTableIndex--;
7787     }
7788     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7789                                    RefreshRateTableIndex);
7790     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
7791  } else {
7792     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7793                                    RefreshRateTableIndex);
7794  }
7795
7796  sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
7797  sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
7798
7799  if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
7800     if(SiS_Pr->SiS_UseROM) {
7801        if(ROMAddr[0x220] & 0x01) {
7802           sr2b = ROMAddr[0x227];
7803           sr2c = ROMAddr[0x228];
7804        }
7805     }
7806  }
7807
7808  clkbase = 0x02B;
7809  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7810     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
7811        clkbase += 3;
7812     }
7813  }
7814
7815  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
7816  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7817  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7818  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
7819  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7820  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7821  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
7822  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7823  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7824}
7825
7826/*********************************************/
7827/*           SET UP CHRONTEL CHIPS           */
7828/*********************************************/
7829
7830static void
7831SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7832               unsigned short RefreshRateTableIndex)
7833{
7834   unsigned short TVType, resindex;
7835   const struct SiS_CHTVRegData *CHTVRegData = NULL;
7836
7837   if(ModeNo <= 0x13)
7838      resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7839   else
7840      resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7841
7842   resindex &= 0x3F;
7843
7844   TVType = 0;
7845   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7846   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7847      TVType += 2;
7848      if(SiS_Pr->SiS_ModeType > ModeVGA) {
7849         if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
7850      }
7851      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7852         TVType = 4;
7853         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7854      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
7855         TVType = 6;
7856         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7857      }
7858   }
7859
7860   switch(TVType) {
7861      case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
7862      case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
7863      case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
7864      case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
7865      case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
7866      case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
7867      case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
7868      case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
7869      case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
7870      default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
7871   }
7872
7873
7874   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
7875
7876#ifdef CONFIG_FB_SIS_300
7877
7878      /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
7879
7880      /* We don't support modes >800x600 */
7881      if (resindex > 5) return;
7882
7883      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7884         SiS_SetCH700x(SiS_Pr,0x04,0x43);  /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
7885         SiS_SetCH700x(SiS_Pr,0x09,0x69);  /* Black level for PAL (105)*/
7886      } else {
7887         SiS_SetCH700x(SiS_Pr,0x04,0x03);   /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
7888         SiS_SetCH700x(SiS_Pr,0x09,0x71);   /* Black level for NTSC (113)*/
7889      }
7890
7891      SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]);  /* Mode register */
7892      SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]);  /* Start active video register */
7893      SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]);  /* Position overflow register */
7894      SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]);  /* Horiz Position register */
7895      SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]);  /* Vertical Position register */
7896
7897      /* Set minimum flicker filter for Luma channel (SR1-0=00),
7898                minimum text enhancement (S3-2=10),
7899                maximum flicker filter for Chroma channel (S5-4=10)
7900                =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
7901       */
7902      SiS_SetCH700x(SiS_Pr,0x01,0x28);
7903
7904      /* Set video bandwidth
7905            High bandwidth Luma composite video filter(S0=1)
7906            low bandwidth Luma S-video filter (S2-1=00)
7907            disable peak filter in S-video channel (S3=0)
7908            high bandwidth Chroma Filter (S5-4=11)
7909            =00110001=0x31
7910      */
7911      SiS_SetCH700x(SiS_Pr,0x03,0xb1);       /* old: 3103 */
7912
7913      /* Register 0x3D does not exist in non-macrovision register map
7914            (Maybe this is a macrovision register?)
7915       */
7916#ifndef SIS_CP
7917      SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
7918#endif
7919
7920      /* Register 0x10 only contains 1 writable bit (S0) for sensing,
7921             all other bits a read-only. Macrovision?
7922       */
7923      SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
7924
7925      /* Register 0x11 only contains 3 writable bits (S0-S2) for
7926             contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
7927       */
7928      SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
7929
7930      /* Clear DSEN
7931       */
7932      SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
7933
7934      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {            /* ---- NTSC ---- */
7935         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
7936            if(resindex == 0x04) {                      /* 640x480 overscan: Mode 16 */
7937               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off */
7938               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);       /* ACIV on, no need to set FSCI */
7939            } else if(resindex == 0x05) {               /* 800x600 overscan: Mode 23 */
7940               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);       /* 0x18-0x1f: FSCI 469,762,048 */
7941               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
7942               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
7943               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
7944               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
7945               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
7946               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
7947               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
7948               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF);       /* Loop filter on for mode 23 */
7949               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);       /* ACIV off, need to set FSCI */
7950            }
7951         } else {
7952            if(resindex == 0x04) {                      /* ----- 640x480 underscan; Mode 17 */
7953               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off */
7954               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7955            } else if(resindex == 0x05) {               /* ----- 800x600 underscan: Mode 24 */
7956#if 0
7957               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);       /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
7958               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0);       /* FSCI for mode 24 is 428,554,851 */
7959               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0);       /* 198b3a63 */
7960               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
7961               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
7962               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
7963               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
7964               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
7965               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off for mode 24 */
7966               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);       * ACIV off, need to set FSCI */
7967#endif         /* All alternatives wrong (datasheet wrong?), don't use FSCI */
7968               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);        /* loop filter off */
7969               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7970            }
7971         }
7972      } else {                                          /* ---- PAL ---- */
7973         /* We don't play around with FSCI in PAL mode */
7974         if(resindex == 0x04) {
7975            SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);  /* loop filter off */
7976            SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);  /* ACIV on */
7977         } else {
7978            SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);  /* loop filter off */
7979            SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);  /* ACIV on */
7980         }
7981      }
7982
7983#endif  /* 300 */
7984
7985   } else {
7986
7987      /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
7988
7989#ifdef CONFIG_FB_SIS_315
7990
7991      unsigned short temp;
7992
7993      /* We don't support modes >1024x768 */
7994      if (resindex > 6) return;
7995
7996      temp = CHTVRegData[resindex].Reg[0];
7997      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
7998      SiS_SetCH701x(SiS_Pr,0x00,temp);
7999
8000      SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
8001      SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
8002      SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
8003      SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
8004      SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
8005      SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
8006
8007      temp = CHTVRegData[resindex].Reg[7];
8008      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
8009      SiS_SetCH701x(SiS_Pr,0x07,temp);
8010
8011      SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
8012      SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
8013      SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
8014      SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
8015      SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
8016      SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
8017      SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
8018      SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
8019
8020      temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8021      /* D1 should be set for PAL, PAL-N and NTSC-J,
8022         but I won't do that for PAL unless somebody
8023         tells me to do so. Since the BIOS uses
8024         non-default CIV values and blacklevels,
8025         this might be compensated anyway.
8026       */
8027      if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8028      SiS_SetCH701x(SiS_Pr,0x21,temp);
8029
8030#endif  /* 315 */
8031
8032   }
8033
8034#ifdef SIS_CP
8035   SIS_CP_INIT301_CP3
8036#endif
8037
8038}
8039
8040#ifdef CONFIG_FB_SIS_315  /* ----------- 315 series only ---------- */
8041
8042void
8043SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
8044{
8045   unsigned short temp;
8046
8047   /* Enable Chrontel 7019 LCD panel backlight */
8048   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8049      if(SiS_Pr->ChipType == SIS_740) {
8050         SiS_SetCH701x(SiS_Pr,0x66,0x65);
8051      } else {
8052         temp = SiS_GetCH701x(SiS_Pr,0x66);
8053         temp |= 0x20;
8054         SiS_SetCH701x(SiS_Pr,0x66,temp);
8055      }
8056   }
8057}
8058
8059void
8060SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
8061{
8062   unsigned short temp;
8063
8064   /* Disable Chrontel 7019 LCD panel backlight */
8065   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8066      temp = SiS_GetCH701x(SiS_Pr,0x66);
8067      temp &= 0xDF;
8068      SiS_SetCH701x(SiS_Pr,0x66,temp);
8069   }
8070}
8071
8072static void
8073SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
8074{
8075  static const unsigned char regtable[]      = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8076  static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8077  static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8078  static const unsigned char asus1024_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8079  static const unsigned char asus1400_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8080  static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8081  static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8082  const unsigned char *tableptr = NULL;
8083  int i;
8084
8085  /* Set up Power up/down timing */
8086
8087  if(SiS_Pr->ChipType == SIS_740) {
8088     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8089        if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8090        else                                      tableptr = table1024_740;
8091     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8092               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8093               (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8094        if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8095        else                                      tableptr = table1400_740;
8096     } else return;
8097  } else {
8098     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8099        tableptr = table1024_650;
8100     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8101               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8102               (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8103        tableptr = table1400_650;
8104     } else return;
8105  }
8106
8107  for(i=0; i<5; i++) {
8108     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
8109  }
8110}
8111
8112static void
8113SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
8114{
8115  const unsigned char *tableptr = NULL;
8116  unsigned short tempbh;
8117  int i;
8118  static const unsigned char regtable[] = {
8119                0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8120                0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
8121  };
8122  static const unsigned char table1024_740[] = {
8123                0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8124                0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
8125  };
8126  static const unsigned char table1280_740[] = {
8127                0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8128                0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8129  };
8130  static const unsigned char table1400_740[] = {
8131                0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8132                0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8133  };
8134  static const unsigned char table1600_740[] = {
8135                0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8136                0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
8137  };
8138  static const unsigned char table1024_650[] = {
8139                0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8140                0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
8141  };
8142  static const unsigned char table1280_650[] = {
8143                0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8144                0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
8145  };
8146  static const unsigned char table1400_650[] = {
8147                0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8148                0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
8149  };
8150  static const unsigned char table1600_650[] = {
8151                0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8152                0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
8153  };
8154
8155  if(SiS_Pr->ChipType == SIS_740) {
8156     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
8157     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8158     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8159     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8160     else return;
8161  } else {
8162     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
8163     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8164     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8165     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8166     else return;
8167  }
8168
8169  tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8170  if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8171     tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8172     if(tempbh == 0xc8) {
8173        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8174     } else if(tempbh == 0xdb) {
8175        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8176        if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8177     } else if(tempbh == 0xde) {
8178        if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8179     }
8180  }
8181
8182  if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
8183  else                            tempbh = 0x0c;
8184
8185  for(i = 0; i < tempbh; i++) {
8186     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
8187  }
8188  SiS_ChrontelPowerSequencing(SiS_Pr);
8189  tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8190  tempbh |= 0xc0;
8191  SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
8192
8193  if(SiS_Pr->ChipType == SIS_740) {
8194     tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8195     tempbh &= 0xfb;
8196     SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
8197     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8198     tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8199     tempbh |= 0x40;
8200     SiS_SetCH701x(SiS_Pr,0x64,tempbh);
8201     tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8202     tempbh &= 0x3f;
8203     SiS_SetCH701x(SiS_Pr,0x03,tempbh);
8204  }
8205}
8206
8207static void
8208SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
8209{
8210  unsigned char temp, temp1;
8211
8212  temp1 = SiS_GetCH701x(SiS_Pr,0x49);
8213  SiS_SetCH701x(SiS_Pr,0x49,0x3e);
8214  temp = SiS_GetCH701x(SiS_Pr,0x47);
8215  temp &= 0x7f; /* Use external VSYNC */
8216  SiS_SetCH701x(SiS_Pr,0x47,temp);
8217  SiS_LongDelay(SiS_Pr, 3);
8218  temp = SiS_GetCH701x(SiS_Pr,0x47);
8219  temp |= 0x80; /* Use internal VSYNC */
8220  SiS_SetCH701x(SiS_Pr,0x47,temp);
8221  SiS_SetCH701x(SiS_Pr,0x49,temp1);
8222}
8223
8224static void
8225SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
8226{
8227  unsigned short temp;
8228
8229  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8230     if(SiS_Pr->ChipType == SIS_740) {
8231        temp = SiS_GetCH701x(SiS_Pr,0x1c);
8232        temp |= 0x04;   /* Invert XCLK phase */
8233        SiS_SetCH701x(SiS_Pr,0x1c,temp);
8234     }
8235     if(SiS_IsYPbPr(SiS_Pr)) {
8236        temp = SiS_GetCH701x(SiS_Pr,0x01);
8237        temp &= 0x3f;
8238        temp |= 0x80;   /* Enable YPrPb (HDTV) */
8239        SiS_SetCH701x(SiS_Pr,0x01,temp);
8240     }
8241     if(SiS_IsChScart(SiS_Pr)) {
8242        temp = SiS_GetCH701x(SiS_Pr,0x01);
8243        temp &= 0x3f;
8244        temp |= 0xc0;   /* Enable SCART + CVBS */
8245        SiS_SetCH701x(SiS_Pr,0x01,temp);
8246     }
8247     if(SiS_Pr->ChipType == SIS_740) {
8248        SiS_ChrontelResetVSync(SiS_Pr);
8249        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
8250     } else {
8251        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
8252        temp = SiS_GetCH701x(SiS_Pr,0x49);
8253        if(SiS_IsYPbPr(SiS_Pr)) {
8254           temp = SiS_GetCH701x(SiS_Pr,0x73);
8255           temp |= 0x60;
8256           SiS_SetCH701x(SiS_Pr,0x73,temp);
8257        }
8258        temp = SiS_GetCH701x(SiS_Pr,0x47);
8259        temp &= 0x7f;
8260        SiS_SetCH701x(SiS_Pr,0x47,temp);
8261        SiS_LongDelay(SiS_Pr, 2);
8262        temp = SiS_GetCH701x(SiS_Pr,0x47);
8263        temp |= 0x80;
8264        SiS_SetCH701x(SiS_Pr,0x47,temp);
8265     }
8266  }
8267}
8268
8269static void
8270SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
8271{
8272  unsigned short temp;
8273
8274  /* Complete power down of LVDS */
8275  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8276     if(SiS_Pr->ChipType == SIS_740) {
8277        SiS_LongDelay(SiS_Pr, 1);
8278        SiS_GenericDelay(SiS_Pr, 5887);
8279        SiS_SetCH701x(SiS_Pr,0x76,0xac);
8280        SiS_SetCH701x(SiS_Pr,0x66,0x00);
8281     } else {
8282        SiS_LongDelay(SiS_Pr, 2);
8283        temp = SiS_GetCH701x(SiS_Pr,0x76);
8284        temp &= 0xfc;
8285        SiS_SetCH701x(SiS_Pr,0x76,temp);
8286        SiS_SetCH701x(SiS_Pr,0x66,0x00);
8287     }
8288  }
8289}
8290
8291static void
8292SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
8293{
8294     unsigned short temp;
8295
8296     if(SiS_Pr->ChipType == SIS_740) {
8297
8298        temp = SiS_GetCH701x(SiS_Pr,0x4a);  /* Version ID */
8299        temp &= 0x01;
8300        if(!temp) {
8301
8302           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8303              temp = SiS_GetCH701x(SiS_Pr,0x49);
8304              SiS_SetCH701x(SiS_Pr,0x49,0x3e);
8305           }
8306
8307           /* Reset Chrontel 7019 datapath */
8308           SiS_SetCH701x(SiS_Pr,0x48,0x10);
8309           SiS_LongDelay(SiS_Pr, 1);
8310           SiS_SetCH701x(SiS_Pr,0x48,0x18);
8311
8312           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8313              SiS_ChrontelResetVSync(SiS_Pr);
8314              SiS_SetCH701x(SiS_Pr,0x49,temp);
8315           }
8316
8317        } else {
8318
8319           /* Clear/set/clear GPIO */
8320           temp = SiS_GetCH701x(SiS_Pr,0x5c);
8321           temp &= 0xef;
8322           SiS_SetCH701x(SiS_Pr,0x5c,temp);
8323           temp = SiS_GetCH701x(SiS_Pr,0x5c);
8324           temp |= 0x10;
8325           SiS_SetCH701x(SiS_Pr,0x5c,temp);
8326           temp = SiS_GetCH701x(SiS_Pr,0x5c);
8327           temp &= 0xef;
8328           SiS_SetCH701x(SiS_Pr,0x5c,temp);
8329           temp = SiS_GetCH701x(SiS_Pr,0x61);
8330           if(!temp) {
8331              SiS_SetCH701xForLCD(SiS_Pr);
8332           }
8333        }
8334
8335     } else { /* 650 */
8336        /* Reset Chrontel 7019 datapath */
8337        SiS_SetCH701x(SiS_Pr,0x48,0x10);
8338        SiS_LongDelay(SiS_Pr, 1);
8339        SiS_SetCH701x(SiS_Pr,0x48,0x18);
8340     }
8341}
8342
8343static void
8344SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
8345{
8346     unsigned short temp;
8347
8348     if(SiS_Pr->ChipType == SIS_740) {
8349
8350        if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8351           SiS_ChrontelResetVSync(SiS_Pr);
8352        }
8353
8354     } else {
8355
8356        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* Power up LVDS block */
8357        temp = SiS_GetCH701x(SiS_Pr,0x49);
8358        temp &= 1;
8359        if(temp != 1) {  /* TV block powered? (0 = yes, 1 = no) */
8360           temp = SiS_GetCH701x(SiS_Pr,0x47);
8361           temp &= 0x70;
8362           SiS_SetCH701x(SiS_Pr,0x47,temp);  /* enable VSYNC */
8363           SiS_LongDelay(SiS_Pr, 3);
8364           temp = SiS_GetCH701x(SiS_Pr,0x47);
8365           temp |= 0x80;
8366           SiS_SetCH701x(SiS_Pr,0x47,temp);  /* disable VSYNC */
8367        }
8368
8369     }
8370}
8371
8372static void
8373SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8374{
8375     unsigned short temp,temp1;
8376
8377     if(SiS_Pr->ChipType == SIS_740) {
8378
8379        temp = SiS_GetCH701x(SiS_Pr,0x61);
8380        if(temp < 1) {
8381           temp++;
8382           SiS_SetCH701x(SiS_Pr,0x61,temp);
8383        }
8384        SiS_SetCH701x(SiS_Pr,0x66,0x45);  /* Panel power on */
8385        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on */
8386        SiS_LongDelay(SiS_Pr, 1);
8387        SiS_GenericDelay(SiS_Pr, 5887);
8388
8389     } else {  /* 650 */
8390
8391        temp1 = 0;
8392        temp = SiS_GetCH701x(SiS_Pr,0x61);
8393        if(temp < 2) {
8394           temp++;
8395           SiS_SetCH701x(SiS_Pr,0x61,temp);
8396           temp1 = 1;
8397        }
8398        SiS_SetCH701x(SiS_Pr,0x76,0xac);
8399        temp = SiS_GetCH701x(SiS_Pr,0x66);
8400        temp |= 0x5f;
8401        SiS_SetCH701x(SiS_Pr,0x66,temp);
8402        if(ModeNo > 0x13) {
8403           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8404              SiS_GenericDelay(SiS_Pr, 1023);
8405           } else {
8406              SiS_GenericDelay(SiS_Pr, 767);
8407           }
8408        } else {
8409           if(!temp1)
8410              SiS_GenericDelay(SiS_Pr, 767);
8411        }
8412        temp = SiS_GetCH701x(SiS_Pr,0x76);
8413        temp |= 0x03;
8414        SiS_SetCH701x(SiS_Pr,0x76,temp);
8415        temp = SiS_GetCH701x(SiS_Pr,0x66);
8416        temp &= 0x7f;
8417        SiS_SetCH701x(SiS_Pr,0x66,temp);
8418        SiS_LongDelay(SiS_Pr, 1);
8419
8420     }
8421}
8422
8423static void
8424SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
8425{
8426     unsigned short temp;
8427
8428     SiS_LongDelay(SiS_Pr, 1);
8429
8430     do {
8431       temp = SiS_GetCH701x(SiS_Pr,0x66);
8432       temp &= 0x04;  /* PLL stable? -> bail out */
8433       if(temp == 0x04) break;
8434
8435       if(SiS_Pr->ChipType == SIS_740) {
8436          /* Power down LVDS output, PLL normal operation */
8437          SiS_SetCH701x(SiS_Pr,0x76,0xac);
8438       }
8439
8440       SiS_SetCH701xForLCD(SiS_Pr);
8441
8442       temp = SiS_GetCH701x(SiS_Pr,0x76);
8443       temp &= 0xfb;  /* Reset PLL */
8444       SiS_SetCH701x(SiS_Pr,0x76,temp);
8445       SiS_LongDelay(SiS_Pr, 2);
8446       temp = SiS_GetCH701x(SiS_Pr,0x76);
8447       temp |= 0x04;  /* PLL normal operation */
8448       SiS_SetCH701x(SiS_Pr,0x76,temp);
8449       if(SiS_Pr->ChipType == SIS_740) {
8450          SiS_SetCH701x(SiS_Pr,0x78,0xe0);      /* PLL loop filter */
8451       } else {
8452          SiS_SetCH701x(SiS_Pr,0x78,0x60);
8453       }
8454       SiS_LongDelay(SiS_Pr, 2);
8455    } while(0);
8456
8457    SiS_SetCH701x(SiS_Pr,0x77,0x00);  /* MV? */
8458}
8459
8460static void
8461SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
8462{
8463     unsigned short temp;
8464
8465     temp = SiS_GetCH701x(SiS_Pr,0x03);
8466     temp |= 0x80;      /* Set datapath 1 to TV   */
8467     temp &= 0xbf;      /* Set datapath 2 to LVDS */
8468     SiS_SetCH701x(SiS_Pr,0x03,temp);
8469
8470     if(SiS_Pr->ChipType == SIS_740) {
8471
8472        temp = SiS_GetCH701x(SiS_Pr,0x1c);
8473        temp &= 0xfb;   /* Normal XCLK phase */
8474        SiS_SetCH701x(SiS_Pr,0x1c,temp);
8475
8476        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8477
8478        temp = SiS_GetCH701x(SiS_Pr,0x64);
8479        temp |= 0x40;   /* ? Bit not defined */
8480        SiS_SetCH701x(SiS_Pr,0x64,temp);
8481
8482        temp = SiS_GetCH701x(SiS_Pr,0x03);
8483        temp &= 0x3f;   /* D1 input to both LVDS and TV */
8484        SiS_SetCH701x(SiS_Pr,0x03,temp);
8485
8486        if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
8487           SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
8488           SiS_LongDelay(SiS_Pr, 1);
8489           SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
8490           SiS_ChrontelResetDB(SiS_Pr);
8491           SiS_ChrontelDoSomething2(SiS_Pr);
8492           SiS_ChrontelDoSomething3(SiS_Pr, 0);
8493        } else {
8494           temp = SiS_GetCH701x(SiS_Pr,0x66);
8495           if(temp != 0x45) {
8496              SiS_ChrontelResetDB(SiS_Pr);
8497              SiS_ChrontelDoSomething2(SiS_Pr);
8498              SiS_ChrontelDoSomething3(SiS_Pr, 0);
8499           }
8500        }
8501
8502     } else { /* 650 */
8503
8504        SiS_ChrontelResetDB(SiS_Pr);
8505        SiS_ChrontelDoSomething2(SiS_Pr);
8506        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
8507        SiS_ChrontelDoSomething3(SiS_Pr,temp);
8508        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on, LVDS normal operation */
8509
8510     }
8511
8512}
8513#endif  /* 315 series  */
8514
8515/*********************************************/
8516/*      MAIN: SET CRT2 REGISTER GROUP        */
8517/*********************************************/
8518
8519bool
8520SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8521{
8522#ifdef CONFIG_FB_SIS_300
8523   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
8524#endif
8525   unsigned short ModeIdIndex, RefreshRateTableIndex;
8526
8527   SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8528
8529   if(!SiS_Pr->UseCustomMode) {
8530      SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8531   } else {
8532      ModeIdIndex = 0;
8533   }
8534
8535   /* Used for shifting CR33 */
8536   SiS_Pr->SiS_SelectCRT2Rate = 4;
8537
8538   SiS_UnLockCRT2(SiS_Pr);
8539
8540   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
8541
8542   SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8543
8544   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8545      SiS_DisableBridge(SiS_Pr);
8546      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
8547         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8548      }
8549      SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
8550   }
8551
8552   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
8553      SiS_LockCRT2(SiS_Pr);
8554      SiS_DisplayOn(SiS_Pr);
8555      return true;
8556   }
8557
8558   SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8559
8560   /* Set up Panel Link for LVDS and LCDA */
8561   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8562   if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8563       ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
8564       ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
8565      SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8566   }
8567
8568   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8569      SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8570   }
8571
8572   if(SiS_Pr->SiS_VBType & VB_SISVB) {
8573
8574      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8575
8576         SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8577#ifdef CONFIG_FB_SIS_315
8578         SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8579#endif
8580         SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
8581         SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8582#ifdef CONFIG_FB_SIS_315
8583         SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
8584#endif
8585         SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
8586
8587         SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
8588
8589         /* For 301BDH (Panel link initialization): */
8590         if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8591
8592            if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8593               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8594                  SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8595               }
8596            }
8597            SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8598         }
8599      }
8600
8601   } else {
8602
8603      SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
8604
8605      SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8606
8607      SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8608
8609      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8610         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8611            if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8612               if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8613#ifdef CONFIG_FB_SIS_315
8614                  SiS_SetCH701xForLCD(SiS_Pr);
8615#endif
8616               }
8617            }
8618            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8619               SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8620            }
8621         }
8622      }
8623
8624   }
8625
8626#ifdef CONFIG_FB_SIS_300
8627   if(SiS_Pr->ChipType < SIS_315H) {
8628      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8629         if(SiS_Pr->SiS_UseOEM) {
8630            if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8631               if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
8632                  SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8633               }
8634            } else {
8635               SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8636            }
8637         }
8638         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
8639            if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
8640               (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
8641               SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
8642            }
8643            SiS_DisplayOn(SiS_Pr);
8644         }
8645      }
8646   }
8647#endif
8648
8649#ifdef CONFIG_FB_SIS_315
8650   if(SiS_Pr->ChipType >= SIS_315H) {
8651      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8652         if(SiS_Pr->ChipType < SIS_661) {
8653            SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
8654            SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8655         } else {
8656            SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8657         }
8658         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
8659      }
8660   }
8661#endif
8662
8663   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8664      SiS_EnableBridge(SiS_Pr);
8665   }
8666
8667   SiS_DisplayOn(SiS_Pr);
8668
8669   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8670      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8671         /* Disable LCD panel when using TV */
8672         SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
8673      } else {
8674         /* Disable TV when using LCD */
8675         SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
8676      }
8677   }
8678
8679   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8680      SiS_LockCRT2(SiS_Pr);
8681   }
8682
8683   return true;
8684}
8685
8686
8687/*********************************************/
8688/*     ENABLE/DISABLE LCD BACKLIGHT (SIS)    */
8689/*********************************************/
8690
8691void
8692SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
8693{
8694  /* Switch on LCD backlight on SiS30xLV */
8695  SiS_DDC2Delay(SiS_Pr,0xff00);
8696  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
8697     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
8698     SiS_WaitVBRetrace(SiS_Pr);
8699  }
8700  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
8701     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
8702  }
8703}
8704
8705void
8706SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
8707{
8708  /* Switch off LCD backlight on SiS30xLV */
8709  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
8710  SiS_DDC2Delay(SiS_Pr,0xff00);
8711}
8712
8713/*********************************************/
8714/*          DDC RELATED FUNCTIONS            */
8715/*********************************************/
8716
8717static void
8718SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
8719{
8720  SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
8721  SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
8722  if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
8723     SiS_Pr->SiS_DDC_NData &= 0x0f;
8724     SiS_Pr->SiS_DDC_NClk  &= 0x0f;
8725  }
8726}
8727
8728#ifdef CONFIG_FB_SIS_300
8729static unsigned char *
8730SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
8731{
8732  int i, j, num;
8733  unsigned short tempah,temp;
8734  unsigned char *mydataptr;
8735
8736  for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
8737     mydataptr = dataptr;
8738     num = *mydataptr++;
8739     if(!num) return mydataptr;
8740     if(i) {
8741        SiS_SetStop(SiS_Pr);
8742        SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
8743     }
8744     if(SiS_SetStart(SiS_Pr)) continue;         /* Set start condition */
8745     tempah = SiS_Pr->SiS_DDC_DeviceAddr;
8746     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write DAB (S0=0=write) */
8747     if(temp) continue;                         /*    (ERROR: no ack) */
8748     tempah = *mydataptr++;
8749     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write register number */
8750     if(temp) continue;                         /*    (ERROR: no ack) */
8751     for(j=0; j<num; j++) {
8752        tempah = *mydataptr++;
8753        temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
8754        if(temp) break;
8755     }
8756     if(temp) continue;
8757     if(SiS_SetStop(SiS_Pr)) continue;
8758     return mydataptr;
8759  }
8760  return NULL;
8761}
8762
8763static bool
8764SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
8765{
8766  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;            /* DAB (Device Address Byte) */
8767  SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
8768  SiS_Pr->SiS_DDC_Data  = 0x02;                 /* Bitmask in IndexReg for Data */
8769  SiS_Pr->SiS_DDC_Clk   = 0x01;                 /* Bitmask in IndexReg for Clk */
8770  SiS_SetupDDCN(SiS_Pr);
8771
8772  SiS_SetSwitchDDC2(SiS_Pr);
8773
8774  while(*dataptr) {
8775     dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
8776     if(!dataptr) return false;
8777  }
8778  return true;
8779}
8780#endif
8781
8782/* The Chrontel 700x is connected to the 630/730 via
8783 * the 630/730's DDC/I2C port.
8784 *
8785 * On 630(S)T chipset, the index changed from 0x11 to
8786 * 0x0a, possibly for working around the DDC problems
8787 */
8788
8789static bool
8790SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
8791{
8792  unsigned short temp, i;
8793
8794  for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
8795     if(i) {
8796        SiS_SetStop(SiS_Pr);
8797        SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
8798     }
8799     if(SiS_SetStart(SiS_Pr)) continue;                                 /* Set start condition */
8800     temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr);      /* Write DAB (S0=0=write) */
8801     if(temp) continue;                                                 /*    (ERROR: no ack) */
8802     temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor));                    /* Write RAB (700x: set bit 7, see datasheet) */
8803     if(temp) continue;                                                 /*    (ERROR: no ack) */
8804     temp = SiS_WriteDDC2Data(SiS_Pr, val);                             /* Write data */
8805     if(temp) continue;                                                 /*    (ERROR: no ack) */
8806     if(SiS_SetStop(SiS_Pr)) continue;                                  /* Set stop condition */
8807     SiS_Pr->SiS_ChrontelInit = 1;
8808     return true;
8809  }
8810  return false;
8811}
8812
8813/* Write to Chrontel 700x */
8814void
8815SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
8816{
8817  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
8818
8819  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8820
8821  if(!(SiS_Pr->SiS_ChrontelInit)) {
8822     SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
8823     SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
8824     SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
8825     SiS_SetupDDCN(SiS_Pr);
8826  }
8827
8828  if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
8829      (!(SiS_Pr->SiS_ChrontelInit)) ) {
8830     SiS_Pr->SiS_DDC_Index = 0x0a;
8831     SiS_Pr->SiS_DDC_Data  = 0x80;
8832     SiS_Pr->SiS_DDC_Clk   = 0x40;
8833     SiS_SetupDDCN(SiS_Pr);
8834
8835     SiS_SetChReg(SiS_Pr, reg, val, 0x80);
8836  }
8837}
8838
8839/* Write to Chrontel 701x */
8840/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
8841void
8842SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
8843{
8844  SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
8845  SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
8846  SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
8847  SiS_SetupDDCN(SiS_Pr);
8848  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
8849  SiS_SetChReg(SiS_Pr, reg, val, 0);
8850}
8851
8852static
8853void
8854SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
8855{
8856  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
8857     SiS_SetCH700x(SiS_Pr, reg, val);
8858  else
8859     SiS_SetCH701x(SiS_Pr, reg, val);
8860}
8861
8862static unsigned short
8863SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
8864{
8865  unsigned short tempah, temp, i;
8866
8867  for(i=0; i<20; i++) {                         /* Do 20 attempts to read */
8868     if(i) {
8869        SiS_SetStop(SiS_Pr);
8870        SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
8871     }
8872     if(SiS_SetStart(SiS_Pr)) continue;                                 /* Set start condition */
8873     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr);       /* Write DAB (S0=0=write) */
8874     if(temp) continue;                                                 /*        (ERROR: no ack) */
8875     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor);  /* Write RAB (700x: | 0x80) */
8876     if(temp) continue;                                                 /*        (ERROR: no ack) */
8877     if (SiS_SetStart(SiS_Pr)) continue;                                /* Re-start */
8878     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
8879     if(temp) continue;                                                 /*        (ERROR: no ack) */
8880     tempah = SiS_ReadDDC2Data(SiS_Pr);                                 /* Read byte */
8881     if(SiS_SetStop(SiS_Pr)) continue;                                  /* Stop condition */
8882     SiS_Pr->SiS_ChrontelInit = 1;
8883     return tempah;
8884  }
8885  return 0xFFFF;
8886}
8887
8888/* Read from Chrontel 700x */
8889/* Parameter is [Register no (S7-S0)] */
8890unsigned short
8891SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
8892{
8893  unsigned short result;
8894
8895  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
8896
8897  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8898
8899  if(!(SiS_Pr->SiS_ChrontelInit)) {
8900     SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
8901     SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
8902     SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
8903     SiS_SetupDDCN(SiS_Pr);
8904  }
8905
8906  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8907
8908  if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
8909      (!SiS_Pr->SiS_ChrontelInit) ) {
8910
8911     SiS_Pr->SiS_DDC_Index = 0x0a;
8912     SiS_Pr->SiS_DDC_Data  = 0x80;
8913     SiS_Pr->SiS_DDC_Clk   = 0x40;
8914     SiS_SetupDDCN(SiS_Pr);
8915
8916     result = SiS_GetChReg(SiS_Pr,0x80);
8917  }
8918  return result;
8919}
8920
8921/* Read from Chrontel 701x */
8922/* Parameter is [Register no (S7-S0)] */
8923unsigned short
8924SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
8925{
8926  SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
8927  SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
8928  SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
8929  SiS_SetupDDCN(SiS_Pr);
8930  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
8931
8932  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8933
8934  return SiS_GetChReg(SiS_Pr,0);
8935}
8936
8937/* Read from Chrontel 70xx */
8938/* Parameter is [Register no (S7-S0)] */
8939static
8940unsigned short
8941SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
8942{
8943  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
8944     return SiS_GetCH700x(SiS_Pr, tempbx);
8945  else
8946     return SiS_GetCH701x(SiS_Pr, tempbx);
8947}
8948
8949void
8950SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
8951                unsigned char myor, unsigned short myand)
8952{
8953  unsigned short tempbl;
8954
8955  tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
8956  SiS_SetCH70xx(SiS_Pr, reg, tempbl);
8957}
8958
8959/* Our own DDC functions */
8960static
8961unsigned short
8962SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
8963                unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
8964                unsigned int VBFlags2)
8965{
8966     unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
8967     unsigned char flag, cr32;
8968     unsigned short        temp = 0, myadaptnum = adaptnum;
8969
8970     if(adaptnum != 0) {
8971        if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
8972        if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
8973     }
8974
8975     /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
8976
8977     SiS_Pr->SiS_ChrontelInit = 0;   /* force re-detection! */
8978
8979     SiS_Pr->SiS_DDC_SecAddr = 0;
8980     SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
8981     SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
8982     SiS_Pr->SiS_DDC_Index = 0x11;
8983     flag = 0xff;
8984
8985     cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
8986
8987#if 0
8988     if(VBFlags2 & VB2_SISBRIDGE) {
8989        if(myadaptnum == 0) {
8990           if(!(cr32 & 0x20)) {
8991              myadaptnum = 2;
8992              if(!(cr32 & 0x10)) {
8993                 myadaptnum = 1;
8994                 if(!(cr32 & 0x08)) {
8995                    myadaptnum = 0;
8996                 }
8997              }
8998           }
8999        }
9000     }
9001#endif
9002
9003     if(VGAEngine == SIS_300_VGA) {             /* 300 series */
9004
9005        if(myadaptnum != 0) {
9006           flag = 0;
9007           if(VBFlags2 & VB2_SISBRIDGE) {
9008              SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9009              SiS_Pr->SiS_DDC_Index = 0x0f;
9010           }
9011        }
9012
9013        if(!(VBFlags2 & VB2_301)) {
9014           if((cr32 & 0x80) && (checkcr32)) {
9015              if(myadaptnum >= 1) {
9016                 if(!(cr32 & 0x08)) {
9017                     myadaptnum = 1;
9018                     if(!(cr32 & 0x10)) return 0xFFFF;
9019                 }
9020              }
9021           }
9022        }
9023
9024        temp = 4 - (myadaptnum * 2);
9025        if(flag) temp = 0;
9026
9027     } else {                                           /* 315/330 series */
9028
9029        /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
9030
9031        if(VBFlags2 & VB2_SISBRIDGE) {
9032           if(myadaptnum == 2) {
9033              myadaptnum = 1;
9034           }
9035        }
9036
9037        if(myadaptnum == 1) {
9038           flag = 0;
9039           if(VBFlags2 & VB2_SISBRIDGE) {
9040              SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9041              SiS_Pr->SiS_DDC_Index = 0x0f;
9042           }
9043        }
9044
9045        if((cr32 & 0x80) && (checkcr32)) {
9046           if(myadaptnum >= 1) {
9047              if(!(cr32 & 0x08)) {
9048                 myadaptnum = 1;
9049                 if(!(cr32 & 0x10)) return 0xFFFF;
9050              }
9051           }
9052        }
9053
9054        temp = myadaptnum;
9055        if(myadaptnum == 1) {
9056           temp = 0;
9057           if(VBFlags2 & VB2_LVDS) flag = 0xff;
9058        }
9059
9060        if(flag) temp = 0;
9061    }
9062
9063    SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9064    SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
9065
9066    SiS_SetupDDCN(SiS_Pr);
9067
9068    return 0;
9069}
9070
9071static unsigned short
9072SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
9073{
9074   if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9075   if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
9076      return 0xFFFF;
9077   }
9078   if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
9079      return 0xFFFF;
9080   }
9081   return 0;
9082}
9083
9084static unsigned short
9085SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
9086{
9087   if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9088   if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
9089      return 0xFFFF;
9090   }
9091   return 0;
9092}
9093
9094static unsigned short
9095SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
9096{
9097   if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
9098   if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
9099   return 0;
9100}
9101
9102static void
9103SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
9104{
9105   SiS_SetSCLKLow(SiS_Pr);
9106   if(yesno) {
9107      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9108                      SiS_Pr->SiS_DDC_Index,
9109                      SiS_Pr->SiS_DDC_NData,
9110                      SiS_Pr->SiS_DDC_Data);
9111   } else {
9112      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9113                      SiS_Pr->SiS_DDC_Index,
9114                      SiS_Pr->SiS_DDC_NData,
9115                      0);
9116   }
9117   SiS_SetSCLKHigh(SiS_Pr);
9118}
9119
9120static unsigned short
9121SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
9122{
9123    unsigned char mask, value;
9124    unsigned short  temp, ret=0;
9125    bool failed = false;
9126
9127    SiS_SetSwitchDDC2(SiS_Pr);
9128    if(SiS_PrepareDDC(SiS_Pr)) {
9129         SiS_SetStop(SiS_Pr);
9130         return 0xFFFF;
9131    }
9132    mask = 0xf0;
9133    value = 0x20;
9134    if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9135       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9136       SiS_SendACK(SiS_Pr, 0);
9137       if(temp == 0) {
9138           mask = 0xff;
9139           value = 0xff;
9140       } else {
9141           failed = true;
9142           ret = 0xFFFF;
9143       }
9144    }
9145    if(!failed) {
9146       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9147       SiS_SendACK(SiS_Pr, 1);
9148       temp &= mask;
9149       if(temp == value) ret = 0;
9150       else {
9151          ret = 0xFFFF;
9152          if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9153             if(temp == 0x30) ret = 0;
9154          }
9155       }
9156    }
9157    SiS_SetStop(SiS_Pr);
9158    return ret;
9159}
9160
9161static
9162unsigned short
9163SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
9164{
9165   unsigned short flag;
9166
9167   flag = 0x180;
9168   SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9169   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9170   SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9171   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9172   SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9173   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9174   if(!(flag & 0x1a)) flag = 0;
9175   return flag;
9176}
9177
9178static
9179unsigned short
9180SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
9181{
9182   unsigned short flag, length, i;
9183   unsigned char chksum,gotcha;
9184
9185   if(DDCdatatype > 4) return 0xFFFF;
9186
9187   flag = 0;
9188   SiS_SetSwitchDDC2(SiS_Pr);
9189   if(!(SiS_PrepareDDC(SiS_Pr))) {
9190      length = 127;
9191      if(DDCdatatype != 1) length = 255;
9192      chksum = 0;
9193      gotcha = 0;
9194      for(i=0; i<length; i++) {
9195         buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9196         chksum += buffer[i];
9197         gotcha |= buffer[i];
9198         SiS_SendACK(SiS_Pr, 0);
9199      }
9200      buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9201      chksum += buffer[i];
9202      SiS_SendACK(SiS_Pr, 1);
9203      if(gotcha) flag = (unsigned short)chksum;
9204      else flag = 0xFFFF;
9205   } else {
9206      flag = 0xFFFF;
9207   }
9208   SiS_SetStop(SiS_Pr);
9209   return flag;
9210}
9211
9212/* Our private DDC functions
9213
9214   It complies somewhat with the corresponding VESA function
9215   in arguments and return values.
9216
9217   Since this is probably called before the mode is changed,
9218   we use our pre-detected pSiS-values instead of SiS_Pr as
9219   regards chipset and video bridge type.
9220
9221   Arguments:
9222       adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9223                 CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9224                 LCDA is CRT1, but DDC is read from CRT2 port.
9225       DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9226       buffer: ptr to 256 data bytes which will be filled with read data.
9227
9228   Returns 0xFFFF if error, otherwise
9229       if DDCdatatype > 0:  Returns 0 if reading OK (included a correct checksum)
9230       if DDCdatatype = 0:  Returns supported DDC modes
9231
9232 */
9233unsigned short
9234SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9235              unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
9236              unsigned int VBFlags2)
9237{
9238   unsigned char  sr1f, cr17=1;
9239   unsigned short result;
9240
9241   if(adaptnum > 2)
9242      return 0xFFFF;
9243
9244   if(DDCdatatype > 4)
9245      return 0xFFFF;
9246
9247   if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
9248      return 0xFFFF;
9249
9250   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
9251      return 0xFFFF;
9252
9253   sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9254   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9255   if(VGAEngine == SIS_300_VGA) {
9256      cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9257      if(!cr17) {
9258         SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9259         SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9260         SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9261      }
9262   }
9263   if((sr1f) || (!cr17)) {
9264      SiS_WaitRetrace1(SiS_Pr);
9265      SiS_WaitRetrace1(SiS_Pr);
9266      SiS_WaitRetrace1(SiS_Pr);
9267      SiS_WaitRetrace1(SiS_Pr);
9268   }
9269
9270   if(DDCdatatype == 0) {
9271      result = SiS_ProbeDDC(SiS_Pr);
9272   } else {
9273      result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9274      if((!result) && (DDCdatatype == 1)) {
9275         if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9276            (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9277            (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9278            (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9279            (buffer[0x12] == 1)) {
9280            if(!SiS_Pr->DDCPortMixup) {
9281               if(adaptnum == 1) {
9282                  if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9283               } else {
9284                  if(buffer[0x14] & 0x80)    result = 0xFFFE;
9285               }
9286            }
9287         }
9288      }
9289   }
9290   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9291   if(VGAEngine == SIS_300_VGA) {
9292      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9293   }
9294   return result;
9295}
9296
9297/* Generic I2C functions for Chrontel & DDC --------- */
9298
9299static void
9300SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
9301{
9302  SiS_SetSCLKHigh(SiS_Pr);
9303  SiS_WaitRetrace1(SiS_Pr);
9304
9305  SiS_SetSCLKLow(SiS_Pr);
9306  SiS_WaitRetrace1(SiS_Pr);
9307}
9308
9309unsigned short
9310SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
9311{
9312   SiS_WaitRetrace1(SiS_Pr);
9313   return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
9314}
9315
9316/* Set I2C start condition */
9317/* This is done by a SD high-to-low transition while SC is high */
9318static unsigned short
9319SiS_SetStart(struct SiS_Private *SiS_Pr)
9320{
9321  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                     /* (SC->low)  */
9322  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9323                  SiS_Pr->SiS_DDC_Index,
9324                  SiS_Pr->SiS_DDC_NData,
9325                  SiS_Pr->SiS_DDC_Data);                        /* SD->high */
9326  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* SC->high */
9327  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9328                  SiS_Pr->SiS_DDC_Index,
9329                  SiS_Pr->SiS_DDC_NData,
9330                  0x00);                                        /* SD->low = start condition */
9331  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* (SC->low) */
9332  return 0;
9333}
9334
9335/* Set I2C stop condition */
9336/* This is done by a SD low-to-high transition while SC is high */
9337static unsigned short
9338SiS_SetStop(struct SiS_Private *SiS_Pr)
9339{
9340  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                     /* (SC->low) */
9341  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9342                  SiS_Pr->SiS_DDC_Index,
9343                  SiS_Pr->SiS_DDC_NData,
9344                  0x00);                                        /* SD->low   */
9345  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* SC->high  */
9346  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9347                  SiS_Pr->SiS_DDC_Index,
9348                  SiS_Pr->SiS_DDC_NData,
9349                  SiS_Pr->SiS_DDC_Data);                        /* SD->high = stop condition */
9350  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* (SC->high) */
9351  return 0;
9352}
9353
9354/* Write 8 bits of data */
9355static unsigned short
9356SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
9357{
9358  unsigned short i,flag,temp;
9359
9360  flag = 0x80;
9361  for(i = 0; i < 8; i++) {
9362    SiS_SetSCLKLow(SiS_Pr);                                     /* SC->low */
9363    if(tempax & flag) {
9364      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9365                      SiS_Pr->SiS_DDC_Index,
9366                      SiS_Pr->SiS_DDC_NData,
9367                      SiS_Pr->SiS_DDC_Data);                    /* Write bit (1) to SD */
9368    } else {
9369      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9370                      SiS_Pr->SiS_DDC_Index,
9371                      SiS_Pr->SiS_DDC_NData,
9372                      0x00);                                    /* Write bit (0) to SD */
9373    }
9374    SiS_SetSCLKHigh(SiS_Pr);                                    /* SC->high */
9375    flag >>= 1;
9376  }
9377  temp = SiS_CheckACK(SiS_Pr);                                  /* Check acknowledge */
9378  return temp;
9379}
9380
9381static unsigned short
9382SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
9383{
9384  unsigned short i, temp, getdata;
9385
9386  getdata = 0;
9387  for(i = 0; i < 8; i++) {
9388    getdata <<= 1;
9389    SiS_SetSCLKLow(SiS_Pr);
9390    SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9391                    SiS_Pr->SiS_DDC_Index,
9392                    SiS_Pr->SiS_DDC_NData,
9393                    SiS_Pr->SiS_DDC_Data);
9394    SiS_SetSCLKHigh(SiS_Pr);
9395    temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9396    if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
9397  }
9398  return getdata;
9399}
9400
9401static unsigned short
9402SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
9403{
9404  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9405                  SiS_Pr->SiS_DDC_Index,
9406                  SiS_Pr->SiS_DDC_NClk,
9407                  0x00);                                        /* SetSCLKLow()  */
9408  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9409  return 0;
9410}
9411
9412static unsigned short
9413SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
9414{
9415  unsigned short temp, watchdog=1000;
9416
9417  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9418                  SiS_Pr->SiS_DDC_Index,
9419                  SiS_Pr->SiS_DDC_NClk,
9420                  SiS_Pr->SiS_DDC_Clk);                         /* SetSCLKHigh()  */
9421  do {
9422    temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9423  } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
9424  if (!watchdog) {
9425        return 0xFFFF;
9426  }
9427  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9428  return 0;
9429}
9430
9431/* Check I2C acknowledge */
9432/* Returns 0 if ack ok, non-0 if ack not ok */
9433static unsigned short
9434SiS_CheckACK(struct SiS_Private *SiS_Pr)
9435{
9436  unsigned short tempah;
9437
9438  SiS_SetSCLKLow(SiS_Pr);                                          /* (SC->low) */
9439  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9440                  SiS_Pr->SiS_DDC_Index,
9441                  SiS_Pr->SiS_DDC_NData,
9442                  SiS_Pr->SiS_DDC_Data);                           /* (SD->high) */
9443  SiS_SetSCLKHigh(SiS_Pr);                                         /* SC->high = clock impulse for ack */
9444  tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
9445  SiS_SetSCLKLow(SiS_Pr);                                          /* SC->low = end of clock impulse */
9446  if(tempah & SiS_Pr->SiS_DDC_Data) return 1;                      /* Ack OK if bit = 0 */
9447  return 0;
9448}
9449
9450/* End of I2C functions ----------------------- */
9451
9452
9453/* =============== SiS 315/330 O.E.M. ================= */
9454
9455#ifdef CONFIG_FB_SIS_315
9456
9457static unsigned short
9458GetRAMDACromptr(struct SiS_Private *SiS_Pr)
9459{
9460  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9461  unsigned short romptr;
9462
9463  if(SiS_Pr->ChipType < SIS_330) {
9464     romptr = SISGETROMW(0x128);
9465     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
9466        romptr = SISGETROMW(0x12a);
9467  } else {
9468     romptr = SISGETROMW(0x1a8);
9469     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
9470        romptr = SISGETROMW(0x1aa);
9471  }
9472  return romptr;
9473}
9474
9475static unsigned short
9476GetLCDromptr(struct SiS_Private *SiS_Pr)
9477{
9478  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9479  unsigned short romptr;
9480
9481  if(SiS_Pr->ChipType < SIS_330) {
9482     romptr = SISGETROMW(0x120);
9483     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9484        romptr = SISGETROMW(0x122);
9485  } else {
9486     romptr = SISGETROMW(0x1a0);
9487     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9488        romptr = SISGETROMW(0x1a2);
9489  }
9490  return romptr;
9491}
9492
9493static unsigned short
9494GetTVromptr(struct SiS_Private *SiS_Pr)
9495{
9496  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9497  unsigned short romptr;
9498
9499  if(SiS_Pr->ChipType < SIS_330) {
9500     romptr = SISGETROMW(0x114);
9501     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9502        romptr = SISGETROMW(0x11a);
9503  } else {
9504     romptr = SISGETROMW(0x194);
9505     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9506        romptr = SISGETROMW(0x19a);
9507  }
9508  return romptr;
9509}
9510
9511static unsigned short
9512GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
9513{
9514  unsigned short index;
9515
9516  if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9517     if(!(SiS_IsNotM650orLater(SiS_Pr))) {
9518        if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
9519           index >>= 4;
9520           index *= 3;
9521           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9522           else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9523           return index;
9524        }
9525     }
9526  }
9527
9528  index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
9529  if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
9530  if(SiS_Pr->SiS_VBType & VB_SIS301C) {  /* 1.15.20 and later (not VB specific) */
9531     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
9532     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
9533  } else {
9534     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
9535  }
9536  index--;
9537  index *= 3;
9538  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9539  else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9540  return index;
9541}
9542
9543static unsigned short
9544GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
9545{
9546  unsigned short index;
9547
9548  index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
9549  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
9550  else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9551  return index;
9552}
9553
9554static unsigned short
9555GetTVPtrIndex(struct SiS_Private *SiS_Pr)
9556{
9557  unsigned short index;
9558
9559  index = 0;
9560  if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9561  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
9562
9563  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
9564
9565  index <<= 1;
9566
9567  if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
9568     (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9569     index++;
9570  }
9571
9572  return index;
9573}
9574
9575static unsigned int
9576GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
9577{
9578   unsigned short index = 0, temp = 0;
9579
9580   if(SiS_Pr->SiS_TVMode & TVSetPAL)   index = 1;
9581   if(SiS_Pr->SiS_TVMode & TVSetPALM)  index = 2;
9582   if(SiS_Pr->SiS_TVMode & TVSetPALN)  index = 3;
9583   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
9584   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
9585      index = 4;
9586      if(SiS_Pr->SiS_TVMode & TVSetPALM)  index++;
9587      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
9588   }
9589
9590   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
9591      if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
9592         (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9593         index += addme;
9594         temp++;
9595      }
9596      temp += 0x0100;
9597   }
9598   return (unsigned int)(index | (temp << 16));
9599}
9600
9601static unsigned int
9602GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
9603{
9604   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
9605}
9606
9607#if 0
9608static unsigned int
9609GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
9610{
9611   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
9612}
9613#endif
9614
9615static int
9616GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
9617{
9618   int index = 0;
9619
9620   if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
9621   if(SiS_Pr->SiS_ROMNew) {
9622      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
9623      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
9624      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
9625      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
9626   } else {
9627      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
9628      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
9629      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
9630      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
9631   }
9632
9633   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
9634
9635   return index;
9636}
9637
9638static void
9639SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
9640{
9641  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9642  unsigned short delay=0,index,myindex,temp,romptr=0;
9643  bool dochiptest = true;
9644
9645  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9646     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
9647  } else {
9648     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
9649  }
9650
9651  /* Find delay (from ROM, internal tables, PCI subsystem) */
9652
9653  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {                    /* ------------ VGA */
9654
9655     if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9656        romptr = GetRAMDACromptr(SiS_Pr);
9657     }
9658     if(romptr) delay = ROMAddr[romptr];
9659     else {
9660        delay = 0x04;
9661        if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
9662           if(IS_SIS650) {
9663              delay = 0x0a;
9664           } else if(IS_SIS740) {
9665              delay = 0x00;
9666           } else if(SiS_Pr->ChipType < SIS_330) {
9667              delay = 0x0c;
9668           } else {
9669              delay = 0x0c;
9670           }
9671        } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9672           delay = 0x00;
9673        }
9674     }
9675
9676  } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {  /* ---------- LCD/LCDA */
9677
9678     bool gotitfrompci = false;
9679
9680     /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
9681
9682     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
9683        if(SiS_Pr->PDC != -1) {
9684           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
9685           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
9686           return;
9687        }
9688     } else {
9689        if(SiS_Pr->PDCA != -1) {
9690           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
9691           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
9692           return;
9693        }
9694     }
9695
9696     /* Custom Panel? */
9697
9698     if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
9699        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9700           delay = 0x00;
9701           if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
9702              delay = 0x20;
9703           }
9704           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
9705        } else {
9706           delay = 0x0c;
9707           if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9708              delay = 0x03;
9709              if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
9710                 delay = 0x00;
9711              }
9712           } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
9713              if(IS_SIS740) delay = 0x01;
9714              else          delay = 0x03;
9715           }
9716           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
9717        }
9718        return;
9719     }
9720
9721     /* This is a piece of typical SiS crap: They code the OEM LCD
9722      * delay into the code, at no defined place in the BIOS.
9723      * We now have to start doing a PCI subsystem check here.
9724      */
9725
9726     switch(SiS_Pr->SiS_CustomT) {
9727     case CUT_COMPAQ1280:
9728     case CUT_COMPAQ12802:
9729        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
9730           gotitfrompci = true;
9731           dochiptest = false;
9732           delay = 0x03;
9733        }
9734        break;
9735     case CUT_CLEVO1400:
9736     case CUT_CLEVO14002:
9737        gotitfrompci = true;
9738        dochiptest = false;
9739        delay = 0x02;
9740        break;
9741     case CUT_CLEVO1024:
9742     case CUT_CLEVO10242:
9743        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
9744           gotitfrompci = true;
9745           dochiptest = false;
9746           delay = 0x33;
9747           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9748           delay &= 0x0f;
9749        }
9750        break;
9751     }
9752
9753     /* Could we find it through the PCI ID? If no, use ROM or table */
9754
9755     if(!gotitfrompci) {
9756
9757        index = GetLCDPtrIndexBIOS(SiS_Pr);
9758        myindex = GetLCDPtrIndex(SiS_Pr);
9759
9760        if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9761
9762           if(SiS_IsNotM650orLater(SiS_Pr)) {
9763
9764              if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9765                 /* Always use the second pointer on 650; some BIOSes */
9766                 /* still carry old 301 data at the first location    */
9767                 /* romptr = SISGETROMW(0x120);                       */
9768                 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
9769                 romptr = SISGETROMW(0x122);
9770                 if(!romptr) return;
9771                 delay = ROMAddr[(romptr + index)];
9772              } else {
9773                 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9774              }
9775
9776          } else {
9777
9778             delay = SiS310_LCDDelayCompensation_651301LV[myindex];
9779             if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
9780                delay = SiS310_LCDDelayCompensation_651302LV[myindex];
9781
9782          }
9783
9784        } else if(SiS_Pr->SiS_UseROM                          &&
9785                  (!(SiS_Pr->SiS_ROMNew))                     &&
9786                  (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
9787                  (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
9788                  (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)  &&
9789                  (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)  &&
9790                  ((romptr = GetLCDromptr(SiS_Pr)))) {
9791
9792           /* Data for 1280x1024 wrong in 301B BIOS */
9793           /* Data for 1600x1200 wrong in 301C BIOS */
9794           delay = ROMAddr[(romptr + index)];
9795
9796        } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9797
9798           if(IS_SIS740) delay = 0x03;
9799           else          delay = 0x00;
9800
9801        } else {
9802
9803           delay = SiS310_LCDDelayCompensation_301[myindex];
9804           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
9805              if(IS_SIS740) delay = 0x01;
9806              else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
9807              else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9808           } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9809              if(IS_SIS740) delay = 0x01;  /* ? */
9810              else          delay = 0x03;
9811              if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
9812           } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
9813              if(IS_SIS740) delay = 0x01;
9814              else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
9815           }
9816
9817        }
9818
9819     }  /* got it from PCI */
9820
9821     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9822        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
9823        dochiptest = false;
9824     }
9825
9826  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 /* ------------ TV */
9827
9828     index = GetTVPtrIndex(SiS_Pr);
9829
9830     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9831
9832        if(SiS_IsNotM650orLater(SiS_Pr)) {
9833
9834           if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9835              /* Always use the second pointer on 650; some BIOSes */
9836              /* still carry old 301 data at the first location    */
9837              /* romptr = SISGETROMW(0x114);                       */
9838              /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
9839              romptr = SISGETROMW(0x11a);
9840              if(!romptr) return;
9841              delay = ROMAddr[romptr + index];
9842
9843           } else {
9844
9845              delay = SiS310_TVDelayCompensation_301B[index];
9846
9847           }
9848
9849        } else {
9850
9851           switch(SiS_Pr->SiS_CustomT) {
9852           case CUT_COMPAQ1280:
9853           case CUT_COMPAQ12802:
9854           case CUT_CLEVO1400:
9855           case CUT_CLEVO14002:
9856              delay = 0x02;
9857              dochiptest = false;
9858              break;
9859           case CUT_CLEVO1024:
9860           case CUT_CLEVO10242:
9861              delay = 0x03;
9862              dochiptest = false;
9863              break;
9864           default:
9865              delay = SiS310_TVDelayCompensation_651301LV[index];
9866              if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
9867                 delay = SiS310_TVDelayCompensation_651302LV[index];
9868              }
9869           }
9870        }
9871
9872     } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9873
9874        romptr = GetTVromptr(SiS_Pr);
9875        if(!romptr) return;
9876        delay = ROMAddr[romptr + index];
9877
9878     } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9879
9880        delay = SiS310_TVDelayCompensation_LVDS[index];
9881
9882     } else {
9883
9884        delay = SiS310_TVDelayCompensation_301[index];
9885        if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
9886           if(IS_SIS740) {
9887              delay = SiS310_TVDelayCompensation_740301B[index];
9888              /* LV: use 301 data? BIOS bug? */
9889           } else {
9890              delay = SiS310_TVDelayCompensation_301B[index];
9891              if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
9892           }
9893        }
9894
9895     }
9896
9897     if(SiS_LCDAEnabled(SiS_Pr)) {
9898        delay &= 0x0f;
9899        dochiptest = false;
9900     }
9901
9902  } else return;
9903
9904  /* Write delay */
9905
9906  if(SiS_Pr->SiS_VBType & VB_SISVB) {
9907
9908     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
9909
9910        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
9911        if(temp == 8) {         /* 1400x1050 BIOS (COMPAL) */
9912           delay &= 0x0f;
9913           delay |= 0xb0;
9914        } else if(temp == 6) {
9915           delay &= 0x0f;
9916           delay |= 0xc0;
9917        } else if(temp > 7) {   /* 1280x1024 BIOS (which one?) */
9918           delay = 0x35;
9919        }
9920        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9921
9922     } else {
9923
9924        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9925
9926     }
9927
9928  } else {  /* LVDS */
9929
9930     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
9931        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9932     } else {
9933        if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
9934           delay <<= 4;
9935           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
9936        } else {
9937           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9938        }
9939     }
9940
9941  }
9942
9943}
9944
9945static void
9946SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
9947{
9948  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9949  unsigned short index,temp,temp1,romptr=0;
9950
9951  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
9952
9953  if(ModeNo<=0x13)
9954     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
9955  else
9956     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
9957
9958  temp = GetTVPtrIndex(SiS_Pr);
9959  temp >>= 1;     /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9960  temp1 = temp;
9961
9962  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
9963     if(SiS_Pr->ChipType >= SIS_661) {
9964        temp1 = GetOEMTVPtr661(SiS_Pr);
9965        temp1 >>= 1;
9966        romptr = SISGETROMW(0x260);
9967        if(SiS_Pr->ChipType >= SIS_760) {
9968           romptr = SISGETROMW(0x360);
9969        }
9970     } else if(SiS_Pr->ChipType >= SIS_330) {
9971        romptr = SISGETROMW(0x192);
9972     } else {
9973        romptr = SISGETROMW(0x112);
9974     }
9975  }
9976
9977  if(romptr) {
9978     temp1 <<= 1;
9979     temp = ROMAddr[romptr + temp1 + index];
9980  } else {
9981     temp = SiS310_TVAntiFlick1[temp][index];
9982  }
9983  temp <<= 4;
9984
9985  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp);  /* index 0A D[6:4] */
9986}
9987
9988static void
9989SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
9990{
9991  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9992  unsigned short index,temp,temp1,romptr=0;
9993
9994  temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1;    /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9995
9996  if(ModeNo <= 0x13)
9997     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
9998  else
9999     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
10000
10001  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
10002     if(SiS_Pr->ChipType >= SIS_661) {
10003        romptr = SISGETROMW(0x26c);
10004        if(SiS_Pr->ChipType >= SIS_760) {
10005           romptr = SISGETROMW(0x36c);
10006        }
10007        temp1 = GetOEMTVPtr661(SiS_Pr);
10008        temp1 >>= 1;
10009     } else if(SiS_Pr->ChipType >= SIS_330) {
10010        romptr = SISGETROMW(0x1a4);
10011     } else {
10012        romptr = SISGETROMW(0x124);
10013     }
10014  }
10015
10016  if(romptr) {
10017     temp1 <<= 1;
10018     temp = ROMAddr[romptr + temp1 + index];
10019  } else {
10020     temp = SiS310_TVEdge1[temp][index];
10021  }
10022  temp <<= 5;
10023  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp);  /* index 0A D[7:5] */
10024}
10025
10026static void
10027SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
10028{
10029  unsigned short index, temp, i, j;
10030
10031  if(ModeNo <= 0x13) {
10032     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
10033  } else {
10034     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
10035  }
10036
10037  temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10038
10039  if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)        temp = 1;  /* NTSC-J uses PAL */
10040  else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
10041  else if(SiS_Pr->SiS_TVMode & TVSetPALN)    temp = 4;  /* PAL-N */
10042  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1;  /* HiVision uses PAL */
10043
10044  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10045     for(i=0x35, j=0; i<=0x38; i++, j++) {
10046        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10047     }
10048     for(i=0x48; i<=0x4A; i++, j++) {
10049        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10050     }
10051  } else {
10052     for(i=0x35, j=0; i<=0x38; i++, j++) {
10053        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
10054     }
10055  }
10056}
10057
10058static void
10059SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10060{
10061  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10062  unsigned short index,temp,i,j,resinfo,romptr=0;
10063  unsigned int  lindex;
10064
10065  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
10066
10067  /* NTSC-J data not in BIOS, and already set in SetGroup2 */
10068  if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
10069
10070  if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
10071     lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
10072     lindex <<= 2;
10073     for(j=0, i=0x31; i<=0x34; i++, j++) {
10074        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
10075     }
10076     return;
10077  }
10078
10079  /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
10080  if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
10081
10082  if(ModeNo<=0x13) {
10083     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10084  } else {
10085     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10086  }
10087
10088  temp = GetTVPtrIndex(SiS_Pr);
10089  /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
10090   * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
10091   */
10092  if(SiS_Pr->SiS_UseROM) {
10093     romptr = SISGETROMW(0x116);
10094     if(SiS_Pr->ChipType >= SIS_330) {
10095        romptr = SISGETROMW(0x196);
10096     }
10097     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10098        romptr = SISGETROMW(0x11c);
10099        if(SiS_Pr->ChipType >= SIS_330) {
10100           romptr = SISGETROMW(0x19c);
10101        }
10102        if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
10103           romptr = SISGETROMW(0x116);
10104           if(SiS_Pr->ChipType >= SIS_330) {
10105              romptr = SISGETROMW(0x196);
10106           }
10107        }
10108     }
10109  }
10110  if(romptr) {
10111     romptr += (temp << 2);
10112     for(j=0, i=0x31; i<=0x34; i++, j++) {
10113        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10114     }
10115  } else {
10116     index = temp % 2;
10117     temp >>= 1;          /* 0:NTSC, 1:PAL, 2:HiTV */
10118     for(j=0, i=0x31; i<=0x34; i++, j++) {
10119        if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
10120           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10121        else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
10122           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
10123        else
10124           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10125     }
10126  }
10127
10128  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
10129     if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
10130        if((resinfo == SIS_RI_640x480) ||
10131           (resinfo == SIS_RI_800x600)) {
10132           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
10133           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
10134           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
10135           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
10136        } else if(resinfo == SIS_RI_1024x768) {
10137           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
10138           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
10139           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
10140           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
10141        }
10142     }
10143  }
10144}
10145
10146static void
10147SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10148                unsigned short ModeIdIndex, unsigned short RTI)
10149{
10150   unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
10151   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10152
10153   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
10154      return;
10155
10156   /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
10157   /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
10158
10159   if(SiS_Pr->SiS_ROMNew) {
10160      if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)                         ||
10161         ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
10162          (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
10163         index = 25;
10164         if(SiS_Pr->UseCustomMode) {
10165            index = SiS_Pr->CSRClock;
10166         } else if(ModeNo > 0x13) {
10167            index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
10168            index = SiS_Pr->SiS_VCLKData[index].CLOCK;
10169         }
10170         if(index < 25) index = 25;
10171         index = ((index / 25) - 1) << 1;
10172         if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
10173            index++;
10174         }
10175         romptr = SISGETROMW(0x104);
10176         delay = ROMAddr[romptr + index];
10177         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
10178            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10179            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10180         } else {
10181            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10182            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10183         }
10184         return;
10185      }
10186   }
10187
10188   /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
10189
10190   if(SiS_Pr->UseCustomMode) delay = 0x04;
10191   else if(ModeNo <= 0x13)   delay = 0x04;
10192   else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
10193   delay |= (delay << 8);
10194
10195   if(SiS_Pr->ChipType >= XGI_20) {
10196
10197      delay = 0x0606;
10198      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10199
10200         delay = 0x0404;
10201         if(SiS_Pr->SiS_XGIROM) {
10202             index = GetTVPtrIndex(SiS_Pr);
10203             if((romptr = SISGETROMW(0x35e))) {
10204                delay = (ROMAddr[romptr + index] & 0x0f) << 1;
10205                delay |= (delay << 8);
10206             }
10207         }
10208
10209         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
10210            if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
10211               delay -= 0x0404;
10212            }
10213         }
10214      }
10215
10216   } else if(SiS_Pr->ChipType >= SIS_340) {
10217
10218      delay = 0x0606;
10219      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10220         delay = 0x0404;
10221      }
10222      /* TODO (eventually) */
10223
10224   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10225
10226      /* 3. TV */
10227
10228      index = GetOEMTVPtr661(SiS_Pr);
10229      if(SiS_Pr->SiS_ROMNew) {
10230         romptr = SISGETROMW(0x106);
10231         if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
10232         delay = ROMAddr[romptr + index];
10233      } else {
10234         delay = 0x04;
10235         if(index > 3) delay = 0;
10236      }
10237
10238   } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10239
10240      /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
10241
10242      if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
10243          ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
10244
10245         lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
10246
10247         /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
10248         delay = ROMAddr[romptr + lcdpdcindex + 1];     /* LCD  */
10249         delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
10250
10251      } else {
10252
10253         /* TMDS: Set our own, since BIOS has no idea */
10254         /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
10255         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10256            switch(SiS_Pr->SiS_LCDResInfo) {
10257            case Panel_1024x768:  delay = 0x0008; break;
10258            case Panel_1280x720:  delay = 0x0004; break;
10259            case Panel_1280x768:
10260            case Panel_1280x768_2:delay = 0x0004; break;
10261            case Panel_1280x800:
10262            case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
10263            case Panel_1280x854:  delay = 0x0004; break; /* FIXME */
10264            case Panel_1280x1024: delay = 0x1e04; break;
10265            case Panel_1400x1050: delay = 0x0004; break;
10266            case Panel_1600x1200: delay = 0x0400; break;
10267            case Panel_1680x1050: delay = 0x0e04; break;
10268            default:
10269               if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
10270                  delay = 0x0008;
10271               } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
10272                  delay = 0x1e04;
10273               } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
10274                  delay = 0x0004;
10275               } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
10276                  delay = 0x0400;
10277               } else
10278                  delay = 0x0e04;
10279               break;
10280            }
10281         }
10282
10283         /* Override by detected or user-set values */
10284         /* (but only if, for some reason, we can't read value from BIOS) */
10285         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
10286            delay = SiS_Pr->PDC & 0x1f;
10287         }
10288         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
10289            delay = (SiS_Pr->PDCA & 0x1f) << 8;
10290         }
10291
10292      }
10293
10294   }
10295
10296   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10297      delay >>= 8;
10298      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10299      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10300   } else {
10301      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10302      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10303   }
10304}
10305
10306static void
10307SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
10308{
10309   unsigned short infoflag;
10310   unsigned char  temp;
10311
10312   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10313
10314      if(ModeNo <= 0x13) {
10315         infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
10316      } else if(SiS_Pr->UseCustomMode) {
10317         infoflag = SiS_Pr->CInfoFlag;
10318      } else {
10319         infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
10320      }
10321
10322      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10323         infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
10324      }
10325
10326      infoflag &= 0xc0;
10327
10328      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10329         temp = (infoflag >> 6) | 0x0c;
10330         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10331            temp ^= 0x04;
10332            if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
10333         }
10334         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
10335      } else {
10336         temp = 0x30;
10337         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
10338         temp |= infoflag;
10339         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
10340         temp = 0;
10341         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10342            if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
10343         }
10344         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
10345      }
10346
10347   }
10348}
10349
10350static void
10351SetPanelParms661(struct SiS_Private *SiS_Pr)
10352{
10353   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10354   unsigned short romptr, temp1, temp2;
10355
10356   if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
10357      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
10358   }
10359
10360   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
10361      if(SiS_Pr->LVDSHL != -1) {
10362         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10363      }
10364   }
10365
10366   if(SiS_Pr->SiS_ROMNew) {
10367
10368      if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
10369         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
10370            temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
10371            temp2 = 0xfc;
10372            if(SiS_Pr->LVDSHL != -1) {
10373              temp1 &= 0xfc;
10374              temp2 = 0xf3;
10375            }
10376            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
10377         }
10378         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10379            temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
10380            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
10381         }
10382      }
10383
10384   }
10385}
10386
10387static void
10388SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
10389{
10390   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
10391      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
10392      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10393         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10394         SetPanelParms661(SiS_Pr);
10395      }
10396   } else {
10397      SetDelayComp(SiS_Pr,ModeNo);
10398   }
10399
10400   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
10401      SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
10402      SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
10403      SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
10404      if(SiS_Pr->SiS_VBType & VB_SIS301) {
10405         SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
10406      }
10407   }
10408}
10409
10410static void
10411SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10412                        unsigned short ModeIdIndex, unsigned short RRTI)
10413{
10414   if(SiS_Pr->SiS_VBType & VB_SISVB) {
10415
10416      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
10417
10418      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10419         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10420         SetPanelParms661(SiS_Pr);
10421      }
10422
10423      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10424         SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
10425         SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
10426         SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
10427         if(SiS_Pr->SiS_VBType & VB_SIS301) {
10428            SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
10429         }
10430      }
10431   }
10432}
10433
10434/* FinalizeLCD
10435 * This finalizes some CRT2 registers for the very panel used.
10436 * If we have a backup if these registers, we use it; otherwise
10437 * we set the register according to most BIOSes. However, this
10438 * function looks quite different in every BIOS, so you better
10439 * pray that we have a backup...
10440 */
10441static void
10442SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10443{
10444  unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
10445  unsigned short resinfo,modeflag;
10446
10447  if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
10448  if(SiS_Pr->SiS_ROMNew) return;
10449
10450  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10451     if(SiS_Pr->LVDSHL != -1) {
10452        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10453     }
10454  }
10455
10456  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10457  if(SiS_Pr->UseCustomMode) return;
10458
10459  switch(SiS_Pr->SiS_CustomT) {
10460  case CUT_COMPAQ1280:
10461  case CUT_COMPAQ12802:
10462  case CUT_CLEVO1400:
10463  case CUT_CLEVO14002:
10464     return;
10465  }
10466
10467  if(ModeNo <= 0x13) {
10468     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10469     modeflag =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10470  } else {
10471     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10472     modeflag =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10473  }
10474
10475  if(IS_SIS650) {
10476     if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
10477        if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10478           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
10479        } else {
10480           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
10481        }
10482     }
10483  }
10484
10485  if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10486     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10487        /* Maybe all panels? */
10488        if(SiS_Pr->LVDSHL == -1) {
10489           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10490        }
10491        return;
10492     }
10493  }
10494
10495  if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
10496     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10497        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10498           if(SiS_Pr->LVDSHL == -1) {
10499              /* Maybe all panels? */
10500              SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10501           }
10502           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10503              tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10504              if(tempch == 3) {
10505                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10506                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10507                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10508                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10509              }
10510           }
10511           return;
10512        }
10513     }
10514  }
10515
10516  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10517     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10518        if(SiS_Pr->SiS_VBType & VB_SISEMI) {
10519           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
10520#ifdef SET_EMI
10521           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
10522#endif
10523           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
10524        }
10525     } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10526        if(SiS_Pr->LVDSHL == -1) {
10527           /* Maybe ACER only? */
10528           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10529        }
10530     }
10531     tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10532     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10533        if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
10534           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
10535        } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10536           if(tempch == 0x03) {
10537              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10538              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10539              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10540              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10541           }
10542           if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
10543              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
10544              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
10545              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
10546              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
10547              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
10548              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
10549              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
10550              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
10551              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
10552              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
10553           } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {  /* 1.10.8w */
10554              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
10555              if(ModeNo <= 0x13) {
10556                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
10557                 if((resinfo == 0) || (resinfo == 2)) return;
10558                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
10559                 if((resinfo == 1) || (resinfo == 3)) return;
10560              }
10561              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10562              if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
10563                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);  /* 1.10.7u */
10564#if 0
10565                 tempbx = 806;  /* 0x326 */                      /* other older BIOSes */
10566                 tempbx--;
10567                 temp = tempbx & 0xff;
10568                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
10569                 temp = (tempbx >> 8) & 0x03;
10570                 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
10571#endif
10572              }
10573           } else if(ModeNo <= 0x13) {
10574              if(ModeNo <= 1) {
10575                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
10576                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
10577                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10578                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10579              }
10580              if(!(modeflag & HalfDCLK)) {
10581                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
10582                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
10583                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
10584                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
10585                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
10586                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10587                 if(ModeNo == 0x12) {
10588                    switch(tempch) {
10589                       case 0:
10590                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10591                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10592                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
10593                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10594                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
10595                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10596                          break;
10597                       case 2:
10598                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10599                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10600                          break;
10601                       case 3:
10602                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10603                          break;
10604                    }
10605                 }
10606              }
10607           }
10608        }
10609     } else {
10610        tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
10611        tempcl &= 0x0f;
10612        tempbh &= 0x70;
10613        tempbh >>= 4;
10614        tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
10615        tempbx = (tempbh << 8) | tempbl;
10616        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10617           if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
10618              if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
10619                 tempbx = 770;
10620              } else {
10621                 if(tempbx > 770) tempbx = 770;
10622                 if(SiS_Pr->SiS_VGAVDE < 600) {
10623                    tempax = 768 - SiS_Pr->SiS_VGAVDE;
10624                    tempax >>= 4;                                /* 1.10.7w; 1.10.6s: 3;  */
10625                    if(SiS_Pr->SiS_VGAVDE <= 480)  tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
10626                    tempbx -= tempax;
10627                 }
10628              }
10629           } else return;
10630        }
10631        temp = tempbx & 0xff;
10632        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
10633        temp = ((tempbx & 0xff00) >> 4) | tempcl;
10634        SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
10635     }
10636  }
10637}
10638
10639#endif
10640
10641/*  =================  SiS 300 O.E.M. ================== */
10642
10643#ifdef CONFIG_FB_SIS_300
10644
10645static void
10646SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
10647                unsigned short RefTabIndex)
10648{
10649  unsigned short crt2crtc=0, modeflag, myindex=0;
10650  unsigned char  temp;
10651  int i;
10652
10653  if(ModeNo <= 0x13) {
10654     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10655     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
10656  } else {
10657     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10658     crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
10659  }
10660
10661  crt2crtc &= 0x3f;
10662
10663  if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
10664     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
10665  }
10666
10667  if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
10668     if(modeflag & HalfDCLK) myindex = 1;
10669
10670     if(SiS_Pr->SiS_SetFlag & LowModeTests) {
10671        for(i=0; i<7; i++) {
10672           if(barco_p1[myindex][crt2crtc][i][0]) {
10673              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
10674                              barco_p1[myindex][crt2crtc][i][0],
10675                              barco_p1[myindex][crt2crtc][i][2],
10676                              barco_p1[myindex][crt2crtc][i][1]);
10677           }
10678        }
10679     }
10680     temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
10681     if(temp & 0x80) {
10682        temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
10683        temp++;
10684        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
10685     }
10686  }
10687}
10688
10689static unsigned short
10690GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
10691{
10692  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10693  unsigned short tempbx=0,romptr=0;
10694  static const unsigned char customtable300[] = {
10695        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
10696        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10697  };
10698  static const unsigned char customtable630[] = {
10699        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
10700        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10701  };
10702
10703  if(SiS_Pr->ChipType == SIS_300) {
10704
10705    tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
10706    if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
10707    tempbx -= 2;
10708    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
10709    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10710       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
10711    }
10712    if(SiS_Pr->SiS_UseROM) {
10713       if(ROMAddr[0x235] & 0x80) {
10714          tempbx = SiS_Pr->SiS_LCDTypeInfo;
10715          if(Flag) {
10716             romptr = SISGETROMW(0x255);
10717             if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10718             else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
10719             if(tempbx == 0xFF) return 0xFFFF;
10720          }
10721          tempbx <<= 1;
10722          if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
10723       }
10724    }
10725
10726  } else {
10727
10728    if(Flag) {
10729       if(SiS_Pr->SiS_UseROM) {
10730          romptr = SISGETROMW(0x255);
10731          if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10732          else       tempbx = 0xff;
10733       } else {
10734          tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
10735       }
10736       if(tempbx == 0xFF) return 0xFFFF;
10737       tempbx <<= 2;
10738       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10739       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10740       return tempbx;
10741    }
10742    tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
10743    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10744    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10745
10746  }
10747
10748  return tempbx;
10749}
10750
10751static void
10752SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
10753{
10754  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10755  unsigned short index,temp,romptr=0;
10756
10757  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10758
10759  if(SiS_Pr->SiS_UseROM) {
10760     if(!(ROMAddr[0x237] & 0x01)) return;
10761     if(!(ROMAddr[0x237] & 0x02)) return;
10762     romptr = SISGETROMW(0x24b);
10763  }
10764
10765  /* The Panel Compensation Delay should be set according to tables
10766   * here. Unfortunately, various BIOS versions don't care about
10767   * a uniform way using eg. ROM byte 0x220, but use different
10768   * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
10769   * Thus we don't set this if the user selected a custom pdc or if
10770   * we otherwise detected a valid pdc.
10771   */
10772  if(SiS_Pr->PDC != -1) return;
10773
10774  temp = GetOEMLCDPtr(SiS_Pr, 0);
10775
10776  if(SiS_Pr->UseCustomMode)
10777     index = 0;
10778  else
10779     index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
10780
10781  if(SiS_Pr->ChipType != SIS_300) {
10782     if(romptr) {
10783        romptr += (temp * 2);
10784        romptr = SISGETROMW(romptr);
10785        romptr += index;
10786        temp = ROMAddr[romptr];
10787     } else {
10788        if(SiS_Pr->SiS_VBType & VB_SISVB) {
10789           temp = SiS300_OEMLCDDelay2[temp][index];
10790        } else {
10791           temp = SiS300_OEMLCDDelay3[temp][index];
10792        }
10793     }
10794  } else {
10795     if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
10796        if(romptr) {
10797           romptr += (temp * 2);
10798           romptr = SISGETROMW(romptr);
10799           romptr += index;
10800           temp = ROMAddr[romptr];
10801        } else {
10802           temp = SiS300_OEMLCDDelay5[temp][index];
10803        }
10804     } else {
10805        if(SiS_Pr->SiS_UseROM) {
10806           romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
10807           if(romptr) {
10808              romptr += (temp * 2);
10809              romptr = SISGETROMW(romptr);
10810              romptr += index;
10811              temp = ROMAddr[romptr];
10812           } else {
10813              temp = SiS300_OEMLCDDelay4[temp][index];
10814           }
10815        } else {
10816           temp = SiS300_OEMLCDDelay4[temp][index];
10817        }
10818     }
10819  }
10820  temp &= 0x3c;
10821  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
10822}
10823
10824static void
10825SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10826{
10827#if 0  /* Unfinished; Data table missing */
10828  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10829  unsigned short index,temp;
10830
10831  if((SiS_Pr->SiS_UseROM) {
10832     if(!(ROMAddr[0x237] & 0x01)) return;
10833     if(!(ROMAddr[0x237] & 0x04)) return;
10834     /* No rom pointer in BIOS header! */
10835  }
10836
10837  temp = GetOEMLCDPtr(SiS_Pr, 1);
10838  if(temp == 0xFFFF) return;
10839
10840  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
10841  for(i=0x14, j=0; i<=0x17; i++, j++) {
10842      SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
10843  }
10844  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
10845
10846  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
10847  SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
10848  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
10849  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
10850  for(i=0x1b, j=3; i<=0x1d; i++, j++) {
10851      SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
10852  }
10853#endif
10854}
10855
10856static unsigned short
10857GetOEMTVPtr(struct SiS_Private *SiS_Pr)
10858{
10859  unsigned short index;
10860
10861  index = 0;
10862  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  index += 4;
10863  if(SiS_Pr->SiS_VBType & VB_SISVB) {
10864     if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)  index += 2;
10865     else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
10866     else if(SiS_Pr->SiS_TVMode & TVSetPAL)   index += 1;
10867  } else {
10868     if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
10869     if(SiS_Pr->SiS_TVMode & TVSetPAL)        index += 1;
10870  }
10871  return index;
10872}
10873
10874static void
10875SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10876{
10877  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10878  unsigned short index,temp,romptr=0;
10879
10880  if(SiS_Pr->SiS_UseROM) {
10881     if(!(ROMAddr[0x238] & 0x01)) return;
10882     if(!(ROMAddr[0x238] & 0x02)) return;
10883     romptr = SISGETROMW(0x241);
10884  }
10885
10886  temp = GetOEMTVPtr(SiS_Pr);
10887
10888  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
10889
10890  if(romptr) {
10891     romptr += (temp * 2);
10892     romptr = SISGETROMW(romptr);
10893     romptr += index;
10894     temp = ROMAddr[romptr];
10895  } else {
10896     if(SiS_Pr->SiS_VBType & VB_SISVB) {
10897        temp = SiS300_OEMTVDelay301[temp][index];
10898     } else {
10899        temp = SiS300_OEMTVDelayLVDS[temp][index];
10900     }
10901  }
10902  temp &= 0x3c;
10903  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
10904}
10905
10906static void
10907SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10908{
10909  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10910  unsigned short index,temp,romptr=0;
10911
10912  if(SiS_Pr->SiS_UseROM) {
10913     if(!(ROMAddr[0x238] & 0x01)) return;
10914     if(!(ROMAddr[0x238] & 0x04)) return;
10915     romptr = SISGETROMW(0x243);
10916  }
10917
10918  temp = GetOEMTVPtr(SiS_Pr);
10919
10920  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
10921
10922  if(romptr) {
10923     romptr += (temp * 2);
10924     romptr = SISGETROMW(romptr);
10925     romptr += index;
10926     temp = ROMAddr[romptr];
10927  } else {
10928     temp = SiS300_OEMTVFlicker[temp][index];
10929  }
10930  temp &= 0x70;
10931  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
10932}
10933
10934static void
10935SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
10936{
10937  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10938  unsigned short index,i,j,temp,romptr=0;
10939
10940  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
10941
10942  if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
10943
10944  if(SiS_Pr->SiS_UseROM) {
10945     if(!(ROMAddr[0x238] & 0x01)) return;
10946     if(!(ROMAddr[0x238] & 0x08)) return;
10947     romptr = SISGETROMW(0x245);
10948  }
10949
10950  temp = GetOEMTVPtr(SiS_Pr);
10951
10952  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
10953
10954  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10955     for(i=0x31, j=0; i<=0x34; i++, j++) {
10956        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
10957     }
10958  } else {
10959     if(romptr) {
10960        romptr += (temp * 2);
10961        romptr = SISGETROMW(romptr);
10962        romptr += (index * 4);
10963        for(i=0x31, j=0; i<=0x34; i++, j++) {
10964           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10965        }
10966     } else {
10967        for(i=0x31, j=0; i<=0x34; i++, j++) {
10968           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
10969        }
10970     }
10971  }
10972}
10973
10974static void
10975SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10976{
10977  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10978  unsigned short index,temp,i,j,romptr=0;
10979
10980  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
10981
10982  if(SiS_Pr->SiS_UseROM) {
10983     if(!(ROMAddr[0x238] & 0x01)) return;
10984     if(!(ROMAddr[0x238] & 0x10)) return;
10985     romptr = SISGETROMW(0x247);
10986  }
10987
10988  temp = GetOEMTVPtr(SiS_Pr);
10989
10990  if(SiS_Pr->SiS_TVMode & TVSetPALM)      temp = 8;
10991  else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
10992  /* NTSCJ uses NTSC filters */
10993
10994  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
10995
10996  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10997      for(i=0x35, j=0; i<=0x38; i++, j++) {
10998        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
10999      }
11000      for(i=0x48; i<=0x4A; i++, j++) {
11001        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11002      }
11003  } else {
11004      if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
11005         romptr += (temp * 2);
11006         romptr = SISGETROMW(romptr);
11007         romptr += (index * 4);
11008         for(i=0x35, j=0; i<=0x38; i++, j++) {
11009            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11010         }
11011      } else {
11012         for(i=0x35, j=0; i<=0x38; i++, j++) {
11013            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
11014         }
11015      }
11016  }
11017}
11018
11019static unsigned short
11020SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
11021{
11022   unsigned short ModeIdIndex;
11023   unsigned char  VGAINFO = SiS_Pr->SiS_VGAINFO;
11024
11025   if(*ModeNo <= 5) *ModeNo |= 1;
11026
11027   for(ModeIdIndex=0; ; ModeIdIndex++) {
11028      if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
11029      if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF)    return 0;
11030   }
11031
11032   if(*ModeNo != 0x07) {
11033      if(*ModeNo > 0x03) return ModeIdIndex;
11034      if(VGAINFO & 0x80) return ModeIdIndex;
11035      ModeIdIndex++;
11036   }
11037
11038   if(VGAINFO & 0x10) ModeIdIndex++;   /* 400 lines */
11039                                       /* else 350 lines */
11040   return ModeIdIndex;
11041}
11042
11043static void
11044SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
11045                  unsigned short RefTableIndex)
11046{
11047  unsigned short OEMModeIdIndex = 0;
11048
11049  if(!SiS_Pr->UseCustomMode) {
11050     OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
11051     if(!(OEMModeIdIndex)) return;
11052  }
11053
11054  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
11055     SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
11056     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
11057        SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
11058     }
11059  }
11060  if(SiS_Pr->UseCustomMode) return;
11061  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
11062     SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
11063     if(SiS_Pr->SiS_VBType & VB_SISVB) {
11064        SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
11065        SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
11066        SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
11067     }
11068  }
11069}
11070#endif
11071
11072