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 const unsigned char SiS_YPbPrTable[3][64] = {
  86  {
  87    0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
  88    0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
  89    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
  90    0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
  91    0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
  92    0x03,0x0a,0x65,0x9d /*0x8d*/,0x08,0x92,0x8f,0x40,
  93    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53 /*0x50*/,
  94    0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
  95  },
  96  {
  97    0x33,0x06,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
  98    0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
  99    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
 100    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
 101    0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
 102    0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
 103    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4e,
 104    0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
 105  },
 106  {
 107#if 0 /* OK, but sticks to left edge */
 108    0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
 109    0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
 110    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
 111    0xed,0x50,0x70,0x9f,0x16,0x59,0x21 /*0x2b*/,0x13,
 112    0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
 113    0x4b,0x4b,0x65 /*0x6f*/,0x2f,0x63,0x92,0x0f,0x40,
 114    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
 115    0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
 116#endif
 117#if 1 /* Perfect */
 118    0x23,0x2d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
 119    0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
 120    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
 121    0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
 122    0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
 123    0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
 124    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x73,
 125    0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
 126#endif
 127  }
 128};
 129
 130static const unsigned char SiS_TVPhase[] =
 131{
 132        0x21,0xED,0xBA,0x08,    /* 0x00 SiS_NTSCPhase */
 133        0x2A,0x05,0xE3,0x00,    /* 0x01 SiS_PALPhase */
 134        0x21,0xE4,0x2E,0x9B,    /* 0x02 SiS_PALMPhase */
 135        0x21,0xF4,0x3E,0xBA,    /* 0x03 SiS_PALNPhase */
 136        0x1E,0x8B,0xA2,0xA7,
 137        0x1E,0x83,0x0A,0xE0,    /* 0x05 SiS_SpecialPhaseM */
 138        0x00,0x00,0x00,0x00,
 139        0x00,0x00,0x00,0x00,
 140        0x21,0xF0,0x7B,0xD6,    /* 0x08 SiS_NTSCPhase2 */
 141        0x2A,0x09,0x86,0xE9,    /* 0x09 SiS_PALPhase2 */
 142        0x21,0xE6,0xEF,0xA4,    /* 0x0a SiS_PALMPhase2 */
 143        0x21,0xF6,0x94,0x46,    /* 0x0b SiS_PALNPhase2 */
 144        0x1E,0x8B,0xA2,0xA7,
 145        0x1E,0x83,0x0A,0xE0,    /* 0x0d SiS_SpecialPhaseM */
 146        0x00,0x00,0x00,0x00,
 147        0x00,0x00,0x00,0x00,
 148        0x1e,0x8c,0x5c,0x7a,    /* 0x10 SiS_SpecialPhase */
 149        0x25,0xd4,0xfd,0x5e     /* 0x11 SiS_SpecialPhaseJ */
 150};
 151
 152static const unsigned char SiS_HiTVGroup3_1[] = {
 153    0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
 154    0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
 155    0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
 156    0xac, 0xda, 0x60, 0xfe, 0x6a, 0x9a, 0x06, 0x10,
 157    0xd1, 0x04, 0x18, 0x0a, 0xff, 0x80, 0x00, 0x80,
 158    0x3b, 0x77, 0x00, 0xef, 0xe0, 0x10, 0xb0, 0xe0,
 159    0x10, 0x4f, 0x0f, 0x0f, 0x05, 0x0f, 0x08, 0x6e,
 160    0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
 161};
 162
 163static const unsigned char SiS_HiTVGroup3_2[] = {
 164    0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
 165    0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
 166    0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
 167    0xac, 0x6a, 0x60, 0x2b, 0x52, 0xcd, 0x61, 0x10,
 168    0x51, 0x04, 0x18, 0x0a, 0x1f, 0x80, 0x00, 0x80,
 169    0xff, 0xa4, 0x04, 0x2b, 0x94, 0x21, 0x72, 0x94,
 170    0x26, 0x05, 0x01, 0x0f, 0xed, 0x0f, 0x0a, 0x64,
 171    0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
 172};
 173
 174/* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */
 175
 176static const unsigned char SiS_Part2CLVX_1[] = {
 177    0x00,0x00,
 178    0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
 179    0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
 180    0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
 181    0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
 182};
 183
 184static const unsigned char SiS_Part2CLVX_2[] = {
 185    0x00,0x00,
 186    0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
 187    0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
 188    0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C,0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C,
 189    0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
 190};
 191
 192static const unsigned char SiS_Part2CLVX_3[] = {  /* NTSC, 525i, 525p */
 193    0xE0,0x01,
 194    0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D,0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D,
 195    0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C,0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C,
 196    0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E,
 197    0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00,0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02,
 198    0x58,0x02,
 199    0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D,0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E,
 200    0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F,0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F,
 201    0x00,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01,0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03,
 202    0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04,0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06,
 203    0x00,0x03,
 204    0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00,0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01,
 205    0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02,0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03,
 206    0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05,0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06,
 207    0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07,0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08,
 208    0xFF,0xFF
 209};
 210
 211static const unsigned char SiS_Part2CLVX_4[] = {   /* PAL */
 212    0x58,0x02,
 213    0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
 214    0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
 215    0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
 216    0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
 217    0x00,0x03,
 218    0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E,0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F,
 219    0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00,0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01,
 220    0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02,0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04,
 221    0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05,0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07,
 222    0x40,0x02,
 223    0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
 224    0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
 225    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
 226    0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
 227    0xFF,0xFF
 228};
 229
 230static const unsigned char SiS_Part2CLVX_5[] = {   /* 750p */
 231    0x00,0x03,
 232    0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
 233    0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
 234    0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E,0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E,
 235    0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01,0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04,
 236    0xFF,0xFF
 237};
 238
 239static const unsigned char SiS_Part2CLVX_6[] = {   /* 1080i */
 240    0x00,0x04,
 241    0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
 242    0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
 243    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F,
 244    0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
 245    0xFF,0xFF,
 246};
 247
 248#ifdef CONFIG_FB_SIS_315
 249/* 661 et al LCD data structure (2.03.00) */
 250static const unsigned char SiS_LCDStruct661[] = {
 251    /* 1024x768 */
 252/*  type|CR37|   HDE   |   VDE   |    HT   |    VT   |   hss    | hse   */
 253    0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
 254    0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x00,0x00,0x00,0x00,0x04,
 255    /*  | vss     |    vse  |clck|  clock  |CRT2DataP|CRT2DataP|idx     */
 256    /*                                        VESA    non-VESA  noscale */
 257    /* 1280x1024 */
 258    0x03,0xC0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
 259    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x08,
 260    /* 1400x1050 */
 261    0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38,
 262    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x09,
 263    /* 1600x1200 */
 264    0x0B,0xE0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
 265    0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x00,0x00,0x00,0x00,0x0A,
 266    /* 1280x768 (_2) */
 267    0x0A,0xE0,0x00,0x05,0x00,0x03,0x7C,0x06,0x26,0x03,0x30,0x00,0x70,
 268    0x00,0x03,0x00,0x06,0x00,0x4D,0xC8,0x48,0x00,0x00,0x00,0x00,0x06,
 269    /* 1280x720 */
 270    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x80,0x05,0x26,0x03,0x10,0x00,0x20,
 271    0x00,0x01,0x00,0x06,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x05,
 272    /* 1280x800 (_2) */
 273    0x0C,0xE0,0x00,0x05,0x20,0x03,0x10,0x06,0x2C,0x03,0x30,0x00,0x70,
 274    0x00,0x04,0x00,0x03,0x00,0x49,0xCE,0x1E,0x00,0x00,0x00,0x00,0x09,
 275    /* 1680x1050 */
 276    0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
 277    0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06,
 278    /* 1280x800_3 */
 279    0x0C,0xE0,0x00,0x05,0x20,0x03,0xAA,0x05,0x2E,0x03,0x30,0x00,0x50,
 280    0x00,0x04,0x00,0x03,0x00,0x47,0xA9,0x10,0x00,0x00,0x00,0x00,0x07,
 281    /* 800x600 */
 282    0x01,0xC0,0x20,0x03,0x58,0x02,0x20,0x04,0x74,0x02,0x2A,0x00,0x80,
 283    0x00,0x06,0x00,0x04,0x00,0x28,0x63,0x4B,0x00,0x00,0x00,0x00,0x00,
 284    /* 1280x854 */
 285    0x08,0xE0,0x00,0x05,0x56,0x03,0x80,0x06,0x5d,0x03,0x10,0x00,0x70,
 286    0x00,0x01,0x00,0x03,0x00,0x54,0x75,0x13,0x00,0x00,0x00,0x00,0x08
 287};
 288#endif
 289
 290#ifdef CONFIG_FB_SIS_300
 291static unsigned char SiS300_TrumpionData[14][80] = {
 292  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
 293    0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
 294    0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
 295    0x03,0x11,0x60,0xBC,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x09,0x04,0x04,0x05,
 296    0x04,0x0C,0x09,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5A,0x01,0xBE,0x01,0x00 },
 297  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x27,0x00,0x80,0x02,
 298    0x20,0x03,0x07,0x00,0x5E,0x01,0x0D,0x02,0x60,0x0C,0x30,0x11,0x00,0x00,0x04,0x23,
 299    0x00,0x00,0x03,0x80,0x03,0x28,0x06,0x08,0x40,0x11,0x00,0x11,0x04,0x23,0x00,0x23,
 300    0x03,0x11,0x60,0x90,0x01,0xFF,0x0F,0xF4,0x19,0x01,0x00,0x05,0x01,0x00,0x04,0x05,
 301    0x04,0x0C,0x02,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEC,0x57,0x01,0xBE,0x01,0x00 },
 302  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
 303    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
 304    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
 305    0x03,0x11,0x60,0xD9,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
 306    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x59,0x01,0xBE,0x01,0x00 },
 307  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
 308    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
 309    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
 310    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
 311    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
 312  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
 313    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
 314    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
 315    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
 316    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
 317  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
 318    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
 319    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
 320    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
 321    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
 322  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
 323    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
 324    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
 325    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
 326    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
 327  /* variant 2 */
 328  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
 329    0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
 330    0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
 331    0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
 332    0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
 333  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
 334    0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
 335    0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
 336    0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
 337    0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
 338  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
 339    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
 340    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
 341    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
 342    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
 343  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
 344    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
 345    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
 346    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
 347    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
 348  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
 349    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
 350    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
 351    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
 352    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
 353  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
 354    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
 355    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
 356    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
 357    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
 358  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
 359    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
 360    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
 361    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
 362    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 }
 363};
 364#endif
 365
 366#ifdef CONFIG_FB_SIS_315
 367static void     SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
 368static void     SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
 369static void     SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
 370static void     SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr);
 371#endif /* 315 */
 372
 373#ifdef CONFIG_FB_SIS_300
 374static  bool    SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
 375#endif
 376
 377static unsigned short   SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
 378                                int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
 379                                bool checkcr32, unsigned int VBFlags2);
 380static unsigned short   SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
 381static unsigned short   SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
 382                                unsigned char *buffer);
 383static void             SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
 384static unsigned short   SiS_SetStart(struct SiS_Private *SiS_Pr);
 385static unsigned short   SiS_SetStop(struct SiS_Private *SiS_Pr);
 386static unsigned short   SiS_SetSCLKLow(struct SiS_Private *SiS_Pr);
 387static unsigned short   SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr);
 388static unsigned short   SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr);
 389static unsigned short   SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax);
 390static unsigned short   SiS_CheckACK(struct SiS_Private *SiS_Pr);
 391static unsigned short   SiS_WriteDABDDC(struct SiS_Private *SiS_Pr);
 392static unsigned short   SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr);
 393static unsigned short   SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
 394static void             SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
 395static unsigned short   SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
 396
 397#ifdef CONFIG_FB_SIS_300
 398static void             SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
 399                                unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
 400static void             SetOEMLCDData2(struct SiS_Private *SiS_Pr,
 401                                unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
 402#endif
 403#ifdef CONFIG_FB_SIS_315
 404static void             SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
 405                                unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
 406static void             SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
 407                                unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
 408static void             SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
 409#endif
 410
 411static unsigned short   SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
 412static void             SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
 413
 414/*********************************************/
 415/*         HELPER: Lock/Unlock CRT2          */
 416/*********************************************/
 417
 418void
 419SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
 420{
 421   if(SiS_Pr->ChipType == XGI_20)
 422      return;
 423   else if(SiS_Pr->ChipType >= SIS_315H)
 424      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
 425   else
 426      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
 427}
 428
 429static
 430void
 431SiS_LockCRT2(struct SiS_Private *SiS_Pr)
 432{
 433   if(SiS_Pr->ChipType == XGI_20)
 434      return;
 435   else if(SiS_Pr->ChipType >= SIS_315H)
 436      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
 437   else
 438      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
 439}
 440
 441/*********************************************/
 442/*            HELPER: Write SR11             */
 443/*********************************************/
 444
 445static void
 446SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
 447{
 448   if(SiS_Pr->ChipType >= SIS_661) {
 449      DataAND &= 0x0f;
 450      DataOR  &= 0x0f;
 451   }
 452   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
 453}
 454
 455/*********************************************/
 456/*    HELPER: Get Pointer to LCD structure   */
 457/*********************************************/
 458
 459#ifdef CONFIG_FB_SIS_315
 460static unsigned char *
 461GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
 462{
 463   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 464   unsigned char  *myptr = NULL;
 465   unsigned short romindex = 0, reg = 0, idx = 0;
 466
 467   /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
 468    * due to the variaty of panels the BIOS doesn't know about.
 469    * Exception: If the BIOS has better knowledge (such as in case
 470    * of machines with a 301C and a panel that does not support DDC)
 471    * use the BIOS data as well.
 472    */
 473
 474   if((SiS_Pr->SiS_ROMNew) &&
 475      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
 476
 477      if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
 478      else                           reg = 0x7d;
 479
 480      idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
 481
 482      if(idx < (8*26)) {
 483         myptr = (unsigned char *)&SiS_LCDStruct661[idx];
 484      }
 485      romindex = SISGETROMW(0x100);
 486      if(romindex) {
 487         romindex += idx;
 488         myptr = &ROMAddr[romindex];
 489      }
 490   }
 491   return myptr;
 492}
 493
 494static unsigned short
 495GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
 496{
 497   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 498   unsigned short romptr = 0;
 499
 500   /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
 501    * due to the variaty of panels the BIOS doesn't know about.
 502    * Exception: If the BIOS has better knowledge (such as in case
 503    * of machines with a 301C and a panel that does not support DDC)
 504    * use the BIOS data as well.
 505    */
 506
 507   if((SiS_Pr->SiS_ROMNew) &&
 508      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
 509      romptr = SISGETROMW(0x102);
 510      romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
 511   }
 512
 513   return romptr;
 514}
 515#endif
 516
 517/*********************************************/
 518/*           Adjust Rate for CRT2            */
 519/*********************************************/
 520
 521static bool
 522SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
 523                unsigned short RRTI, unsigned short *i)
 524{
 525   unsigned short checkmask=0, modeid, infoflag;
 526
 527   modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
 528
 529   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 530
 531      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
 532
 533         checkmask |= SupportRAMDAC2;
 534         if(SiS_Pr->ChipType >= SIS_315H) {
 535            checkmask |= SupportRAMDAC2_135;
 536            if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 537               checkmask |= SupportRAMDAC2_162;
 538               if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
 539                  checkmask |= SupportRAMDAC2_202;
 540               }
 541            }
 542         }
 543
 544      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 545
 546         checkmask |= SupportLCD;
 547         if(SiS_Pr->ChipType >= SIS_315H) {
 548            if(SiS_Pr->SiS_VBType & VB_SISVB) {
 549               if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 550                  if(modeid == 0x2e) checkmask |= Support64048060Hz;
 551               }
 552            }
 553         }
 554
 555      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 556
 557         checkmask |= SupportHiVision;
 558
 559      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
 560
 561         checkmask |= SupportTV;
 562         if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 563            checkmask |= SupportTV1024;
 564            if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
 565               if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
 566                  checkmask |= SupportYPbPr750p;
 567               }
 568            }
 569         }
 570
 571      }
 572
 573   } else {     /* LVDS */
 574
 575      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 576         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 577            checkmask |= SupportCHTV;
 578         }
 579      }
 580
 581      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 582         checkmask |= SupportLCD;
 583      }
 584
 585   }
 586
 587   /* Look backwards in table for matching CRT2 mode */
 588   for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
 589      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
 590      if(infoflag & checkmask) return true;
 591      if((*i) == 0) break;
 592   }
 593
 594   /* Look through the whole mode-section of the table from the beginning
 595    * for a matching CRT2 mode if no mode was found yet.
 596    */
 597   for((*i) = 0; ; (*i)++) {
 598      if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
 599      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
 600      if(infoflag & checkmask) return true;
 601   }
 602   return false;
 603}
 604
 605/*********************************************/
 606/*              Get rate index               */
 607/*********************************************/
 608
 609unsigned short
 610SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 611{
 612   unsigned short RRTI,i,backup_i;
 613   unsigned short modeflag,index,temp,backupindex;
 614   static const unsigned short LCDRefreshIndex[] = {
 615                0x00, 0x00, 0x01, 0x01,
 616                0x01, 0x01, 0x01, 0x01,
 617                0x01, 0x01, 0x01, 0x01,
 618                0x01, 0x01, 0x01, 0x01,
 619                0x00, 0x00, 0x00, 0x00
 620   };
 621
 622   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
 623   if(ModeNo == 0xfe) return 0;
 624
 625   if(ModeNo <= 0x13) {
 626      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
 627   } else {
 628      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 629   }
 630
 631   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 632      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 633         if(modeflag & HalfDCLK) return 0;
 634      }
 635   }
 636
 637   if(ModeNo < 0x14) return 0xFFFF;
 638
 639   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
 640   backupindex = index;
 641
 642   if(index > 0) index--;
 643
 644   if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 645      if(SiS_Pr->SiS_VBType & VB_SISVB) {
 646         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 647            if(SiS_Pr->SiS_VBType & VB_NoLCD)            index = 0;
 648            else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
 649         }
 650         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 651            if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
 652               temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
 653               if(index > temp) index = temp;
 654            }
 655         }
 656      } else {
 657         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
 658         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 659            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
 660         }
 661      }
 662   }
 663
 664   RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
 665   ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
 666
 667   if(SiS_Pr->ChipType >= SIS_315H) {
 668      if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
 669         if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
 670             (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
 671            if(backupindex <= 1) RRTI++;
 672         }
 673      }
 674   }
 675
 676   i = 0;
 677   do {
 678      if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
 679      temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
 680      temp &= ModeTypeMask;
 681      if(temp < SiS_Pr->SiS_ModeType) break;
 682      i++;
 683      index--;
 684   } while(index != 0xFFFF);
 685
 686   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
 687      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
 688         temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
 689         if(temp & InterlaceMode) i++;
 690      }
 691   }
 692
 693   i--;
 694
 695   if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
 696      backup_i = i;
 697      if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
 698         i = backup_i;
 699      }
 700   }
 701
 702   return (RRTI + i);
 703}
 704
 705/*********************************************/
 706/*            STORE CRT2 INFO in CR34        */
 707/*********************************************/
 708
 709static void
 710SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 711{
 712   unsigned short temp1, temp2;
 713
 714   /* Store CRT1 ModeNo in CR34 */
 715   SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
 716   temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
 717   temp2 = ~(SetInSlaveMode >> 8);
 718   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
 719}
 720
 721/*********************************************/
 722/*    HELPER: GET SOME DATA FROM BIOS ROM    */
 723/*********************************************/
 724
 725#ifdef CONFIG_FB_SIS_300
 726static bool
 727SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
 728{
 729   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 730   unsigned short temp,temp1;
 731
 732   if(SiS_Pr->SiS_UseROM) {
 733      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 734         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
 735         temp1 = SISGETROMW(0x23b);
 736         if(temp1 & temp) return true;
 737      }
 738   }
 739   return false;
 740}
 741
 742static bool
 743SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
 744{
 745   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 746   unsigned short temp,temp1;
 747
 748   if(SiS_Pr->SiS_UseROM) {
 749      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 750         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
 751         temp1 = SISGETROMW(0x23d);
 752         if(temp1 & temp) return true;
 753      }
 754   }
 755   return false;
 756}
 757#endif
 758
 759/*********************************************/
 760/*          HELPER: DELAY FUNCTIONS          */
 761/*********************************************/
 762
 763void
 764SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
 765{
 766   while (delaytime-- > 0)
 767      SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
 768}
 769
 770#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 771static void
 772SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 773{
 774   SiS_DDC2Delay(SiS_Pr, delay * 36);
 775}
 776#endif
 777
 778#ifdef CONFIG_FB_SIS_315
 779static void
 780SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 781{
 782   while(delay--) {
 783      SiS_GenericDelay(SiS_Pr, 6623);
 784   }
 785}
 786#endif
 787
 788#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 789static void
 790SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 791{
 792   while(delay--) {
 793      SiS_GenericDelay(SiS_Pr, 66);
 794   }
 795}
 796#endif
 797
 798static void
 799SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
 800{
 801#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 802   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 803   unsigned short PanelID, DelayIndex, Delay=0;
 804#endif
 805
 806   if(SiS_Pr->ChipType < SIS_315H) {
 807
 808#ifdef CONFIG_FB_SIS_300
 809
 810      PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
 811      if(SiS_Pr->SiS_VBType & VB_SISVB) {
 812         if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
 813         if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
 814      }
 815      DelayIndex = PanelID >> 4;
 816      if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
 817         Delay = 3;
 818      } else {
 819         if(DelayTime >= 2) DelayTime -= 2;
 820         if(!(DelayTime & 0x01)) {
 821            Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
 822         } else {
 823            Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
 824         }
 825         if(SiS_Pr->SiS_UseROM) {
 826            if(ROMAddr[0x220] & 0x40) {
 827               if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
 828               else                    Delay = (unsigned short)ROMAddr[0x226];
 829            }
 830         }
 831      }
 832      SiS_ShortDelay(SiS_Pr, Delay);
 833
 834#endif  /* CONFIG_FB_SIS_300 */
 835
 836   } else {
 837
 838#ifdef CONFIG_FB_SIS_315
 839
 840      if((SiS_Pr->ChipType >= SIS_661)    ||
 841         (SiS_Pr->ChipType <= SIS_315PRO) ||
 842         (SiS_Pr->ChipType == SIS_330)    ||
 843         (SiS_Pr->SiS_ROMNew)) {
 844
 845         if(!(DelayTime & 0x01)) {
 846            SiS_DDC2Delay(SiS_Pr, 0x1000);
 847         } else {
 848            SiS_DDC2Delay(SiS_Pr, 0x4000);
 849         }
 850
 851      } else if (SiS_Pr->SiS_IF_DEF_LVDS == 1) {                        /* 315 series, LVDS; Special */
 852
 853         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
 854            PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
 855            if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
 856               if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
 857            }
 858            if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
 859               DelayIndex = PanelID & 0x0f;
 860            } else {
 861               DelayIndex = PanelID >> 4;
 862            }
 863            if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
 864               Delay = 3;
 865            } else {
 866               if(DelayTime >= 2) DelayTime -= 2;
 867               if(!(DelayTime & 0x01)) {
 868                  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
 869                } else {
 870                  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
 871               }
 872               if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
 873                  if(ROMAddr[0x13c] & 0x40) {
 874                     if(!(DelayTime & 0x01)) {
 875                        Delay = (unsigned short)ROMAddr[0x17e];
 876                     } else {
 877                        Delay = (unsigned short)ROMAddr[0x17f];
 878                     }
 879                  }
 880               }
 881            }
 882            SiS_ShortDelay(SiS_Pr, Delay);
 883         }
 884
 885      } else if(SiS_Pr->SiS_VBType & VB_SISVB) {                        /* 315 series, all bridges */
 886
 887         DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
 888         if(!(DelayTime & 0x01)) {
 889            Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
 890         } else {
 891            Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
 892         }
 893         Delay <<= 8;
 894         SiS_DDC2Delay(SiS_Pr, Delay);
 895
 896      }
 897
 898#endif /* CONFIG_FB_SIS_315 */
 899
 900   }
 901}
 902
 903#ifdef CONFIG_FB_SIS_315
 904static void
 905SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
 906{
 907   int i;
 908   for(i = 0; i < DelayLoop; i++) {
 909      SiS_PanelDelay(SiS_Pr, DelayTime);
 910   }
 911}
 912#endif
 913
 914/*********************************************/
 915/*    HELPER: WAIT-FOR-RETRACE FUNCTIONS     */
 916/*********************************************/
 917
 918void
 919SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
 920{
 921   unsigned short watchdog;
 922
 923   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
 924   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
 925
 926   watchdog = 65535;
 927   while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
 928   watchdog = 65535;
 929   while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
 930}
 931
 932#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 933static void
 934SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
 935{
 936   unsigned short watchdog;
 937
 938   watchdog = 65535;
 939   while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
 940   watchdog = 65535;
 941   while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
 942}
 943#endif
 944
 945static void
 946SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
 947{
 948   if(SiS_Pr->ChipType < SIS_315H) {
 949#ifdef CONFIG_FB_SIS_300
 950      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 951         if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
 952      }
 953      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
 954         SiS_WaitRetrace1(SiS_Pr);
 955      } else {
 956         SiS_WaitRetrace2(SiS_Pr, 0x25);
 957      }
 958#endif
 959   } else {
 960#ifdef CONFIG_FB_SIS_315
 961      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
 962         SiS_WaitRetrace1(SiS_Pr);
 963      } else {
 964         SiS_WaitRetrace2(SiS_Pr, 0x30);
 965      }
 966#endif
 967   }
 968}
 969
 970static void
 971SiS_VBWait(struct SiS_Private *SiS_Pr)
 972{
 973   unsigned short tempal,temp,i,j;
 974
 975   temp = 0;
 976   for(i = 0; i < 3; i++) {
 977     for(j = 0; j < 100; j++) {
 978        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
 979        if(temp & 0x01) {
 980           if((tempal & 0x08))  continue;
 981           else break;
 982        } else {
 983           if(!(tempal & 0x08)) continue;
 984           else break;
 985        }
 986     }
 987     temp ^= 0x01;
 988   }
 989}
 990
 991static void
 992SiS_VBLongWait(struct SiS_Private *SiS_Pr)
 993{
 994   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 995      SiS_VBWait(SiS_Pr);
 996   } else {
 997      SiS_WaitRetrace1(SiS_Pr);
 998   }
 999}
1000
1001/*********************************************/
1002/*               HELPER: MISC                */
1003/*********************************************/
1004
1005#ifdef CONFIG_FB_SIS_300
1006static bool
1007SiS_Is301B(struct SiS_Private *SiS_Pr)
1008{
1009   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
1010   return false;
1011}
1012#endif
1013
1014static bool
1015SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
1016{
1017   if(SiS_Pr->ChipType == SIS_730) {
1018      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
1019   }
1020   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
1021   return false;
1022}
1023
1024bool
1025SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
1026{
1027#ifdef CONFIG_FB_SIS_315
1028   if(SiS_Pr->ChipType >= SIS_315H) {
1029      if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
1030         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
1031      }
1032   }
1033#endif
1034   return false;
1035}
1036
1037bool
1038SiS_IsVAMode(struct SiS_Private *SiS_Pr)
1039{
1040#ifdef CONFIG_FB_SIS_315
1041   unsigned short flag;
1042
1043   if(SiS_Pr->ChipType >= SIS_315H) {
1044      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1045      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
1046   }
1047#endif
1048   return false;
1049}
1050
1051#ifdef CONFIG_FB_SIS_315
1052static bool
1053SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
1054{
1055   if(SiS_IsVAMode(SiS_Pr))  return true;
1056   if(SiS_CRT2IsLCD(SiS_Pr)) return true;
1057   return false;
1058}
1059#endif
1060
1061static bool
1062SiS_IsDualLink(struct SiS_Private *SiS_Pr)
1063{
1064#ifdef CONFIG_FB_SIS_315
1065   if(SiS_Pr->ChipType >= SIS_315H) {
1066      if((SiS_CRT2IsLCD(SiS_Pr)) ||
1067         (SiS_IsVAMode(SiS_Pr))) {
1068         if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
1069      }
1070   }
1071#endif
1072   return false;
1073}
1074
1075#ifdef CONFIG_FB_SIS_315
1076static bool
1077SiS_TVEnabled(struct SiS_Private *SiS_Pr)
1078{
1079   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
1080   if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1081      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
1082   }
1083   return false;
1084}
1085#endif
1086
1087#ifdef CONFIG_FB_SIS_315
1088static bool
1089SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
1090{
1091   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
1092   return false;
1093}
1094#endif
1095
1096#ifdef CONFIG_FB_SIS_315
1097static bool
1098SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
1099{
1100   if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
1101      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
1102   }
1103   return false;
1104}
1105#endif
1106
1107#ifdef CONFIG_FB_SIS_315
1108static bool
1109SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
1110{
1111   unsigned short flag;
1112
1113   if(SiS_Pr->ChipType == SIS_650) {
1114      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
1115      /* Check for revision != A0 only */
1116      if((flag == 0xe0) || (flag == 0xc0) ||
1117         (flag == 0xb0) || (flag == 0x90)) return false;
1118   } else if(SiS_Pr->ChipType >= SIS_661) return false;
1119   return true;
1120}
1121#endif
1122
1123#ifdef CONFIG_FB_SIS_315
1124static bool
1125SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
1126{
1127   if(SiS_Pr->ChipType >= SIS_315H) {
1128      /* YPrPb = 0x08 */
1129      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
1130   }
1131   return false;
1132}
1133#endif
1134
1135#ifdef CONFIG_FB_SIS_315
1136static bool
1137SiS_IsChScart(struct SiS_Private *SiS_Pr)
1138{
1139   if(SiS_Pr->ChipType >= SIS_315H) {
1140      /* Scart = 0x04 */
1141      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
1142   }
1143   return false;
1144}
1145#endif
1146
1147#ifdef CONFIG_FB_SIS_315
1148static bool
1149SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
1150{
1151   unsigned short flag;
1152
1153   if(SiS_Pr->ChipType >= SIS_315H) {
1154      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
1155      if(flag & SetCRT2ToTV)        return true;
1156      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1157      if(flag & EnableCHYPbPr)      return true;  /* = YPrPb = 0x08 */
1158      if(flag & EnableCHScart)      return true;  /* = Scart = 0x04 - TW */
1159   } else {
1160      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
1161      if(flag & SetCRT2ToTV)        return true;
1162   }
1163   return false;
1164}
1165#endif
1166
1167#ifdef CONFIG_FB_SIS_315
1168static bool
1169SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
1170{
1171   unsigned short flag;
1172
1173   if(SiS_Pr->ChipType >= SIS_315H) {
1174      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
1175      if(flag & SetCRT2ToLCD) return true;
1176      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1177      if(flag & SetToLCDA)    return true;
1178   } else {
1179      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
1180      if(flag & SetCRT2ToLCD) return true;
1181   }
1182   return false;
1183}
1184#endif
1185
1186static bool
1187SiS_HaveBridge(struct SiS_Private *SiS_Pr)
1188{
1189   unsigned short flag;
1190
1191   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1192      return true;
1193   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1194      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
1195      if((flag == 1) || (flag == 2)) return true;
1196   }
1197   return false;
1198}
1199
1200static bool
1201SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
1202{
1203   unsigned short flag;
1204
1205   if(SiS_HaveBridge(SiS_Pr)) {
1206      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
1207      if(SiS_Pr->ChipType < SIS_315H) {
1208        flag &= 0xa0;
1209        if((flag == 0x80) || (flag == 0x20)) return true;
1210      } else {
1211        flag &= 0x50;
1212        if((flag == 0x40) || (flag == 0x10)) return true;
1213      }
1214   }
1215   return false;
1216}
1217
1218static bool
1219SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
1220{
1221   unsigned short flag1;
1222
1223   flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
1224   if(flag1 & (SetInSlaveMode >> 8)) return true;
1225   return false;
1226}
1227
1228/*********************************************/
1229/*       GET VIDEO BRIDGE CONFIG INFO        */
1230/*********************************************/
1231
1232/* Setup general purpose IO for Chrontel communication */
1233#ifdef CONFIG_FB_SIS_300
1234void
1235SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
1236{
1237   unsigned int   acpibase;
1238   unsigned short temp;
1239
1240   if(!(SiS_Pr->SiS_ChSW)) return;
1241
1242   acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
1243   acpibase &= 0xFFFF;
1244   if(!acpibase) return;
1245   temp = SiS_GetRegShort((acpibase + 0x3c));   /* ACPI register 0x3c: GP Event 1 I/O mode select */
1246   temp &= 0xFEFF;
1247   SiS_SetRegShort((acpibase + 0x3c), temp);
1248   temp = SiS_GetRegShort((acpibase + 0x3c));
1249   temp = SiS_GetRegShort((acpibase + 0x3a));   /* ACPI register 0x3a: GP Pin Level (low/high) */
1250   temp &= 0xFEFF;
1251   if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
1252   SiS_SetRegShort((acpibase + 0x3a), temp);
1253   temp = SiS_GetRegShort((acpibase + 0x3a));
1254}
1255#endif
1256
1257void
1258SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1259                unsigned short ModeIdIndex, int checkcrt2mode)
1260{
1261   unsigned short tempax, tempbx, temp;
1262   unsigned short modeflag, resinfo = 0;
1263
1264   SiS_Pr->SiS_SetFlag = 0;
1265
1266   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1267
1268   SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
1269
1270   if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
1271      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1272   }
1273
1274   tempbx = 0;
1275
1276   if(SiS_HaveBridge(SiS_Pr)) {
1277
1278        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
1279        tempbx |= temp;
1280        tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
1281        tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
1282        tempbx |= tempax;
1283
1284#ifdef CONFIG_FB_SIS_315
1285        if(SiS_Pr->ChipType >= SIS_315H) {
1286           if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
1287              if(ModeNo == 0x03) {
1288                 /* Mode 0x03 is never in driver mode */
1289                 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
1290              }
1291              if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
1292                 /* Reset LCDA setting if not driver mode */
1293                 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
1294              }
1295              if(IS_SIS650) {
1296                 if(SiS_Pr->SiS_UseLCDA) {
1297                    if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
1298                       if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
1299                          SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
1300                       }
1301                    }
1302                 }
1303              }
1304              temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1305              if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
1306                 tempbx |= SetCRT2ToLCDA;
1307              }
1308           }
1309
1310           if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
1311              tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
1312              if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
1313                 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
1314                 if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
1315                 else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1316                    tempbx |= SetCRT2ToYPbPr525750;
1317                 }
1318              }
1319           }
1320
1321           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1322              temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1323              if(temp & SetToLCDA) {
1324                 tempbx |= SetCRT2ToLCDA;
1325              }
1326              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1327                 if(temp & EnableCHYPbPr) {
1328                    tempbx |= SetCRT2ToCHYPbPr;
1329                 }
1330              }
1331           }
1332        }
1333
1334#endif  /* CONFIG_FB_SIS_315 */
1335
1336        if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
1337           tempbx &= ~(SetCRT2ToRAMDAC);
1338        }
1339
1340        if(SiS_Pr->SiS_VBType & VB_SISVB) {
1341           temp = SetCRT2ToSVIDEO   |
1342                  SetCRT2ToAVIDEO   |
1343                  SetCRT2ToSCART    |
1344                  SetCRT2ToLCDA     |
1345                  SetCRT2ToLCD      |
1346                  SetCRT2ToRAMDAC   |
1347                  SetCRT2ToHiVision |
1348                  SetCRT2ToYPbPr525750;
1349        } else {
1350           if(SiS_Pr->ChipType >= SIS_315H) {
1351              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1352                 temp = SetCRT2ToAVIDEO |
1353                        SetCRT2ToSVIDEO |
1354                        SetCRT2ToSCART  |
1355                        SetCRT2ToLCDA   |
1356                        SetCRT2ToLCD    |
1357                        SetCRT2ToCHYPbPr;
1358              } else {
1359                 temp = SetCRT2ToLCDA   |
1360                        SetCRT2ToLCD;
1361              }
1362           } else {
1363              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1364                 temp = SetCRT2ToTV | SetCRT2ToLCD;
1365              } else {
1366                 temp = SetCRT2ToLCD;
1367              }
1368           }
1369        }
1370
1371        if(!(tempbx & temp)) {
1372           tempax = DisableCRT2Display;
1373           tempbx = 0;
1374        }
1375
1376        if(SiS_Pr->SiS_VBType & VB_SISVB) {
1377
1378           unsigned short clearmask = ( DriverMode |
1379                                DisableCRT2Display |
1380                                LoadDACFlag        |
1381                                SetNotSimuMode     |
1382                                SetInSlaveMode     |
1383                                SetPALTV           |
1384                                SwitchCRT2         |
1385                                SetSimuScanMode );
1386
1387           if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
1388           if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
1389           if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
1390           if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
1391           if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
1392           if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
1393
1394        } else {
1395
1396           if(SiS_Pr->ChipType >= SIS_315H) {
1397              if(tempbx & SetCRT2ToLCDA) {
1398                 tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
1399              }
1400           }
1401           if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1402              if(tempbx & SetCRT2ToTV) {
1403                 tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
1404              }
1405           }
1406           if(tempbx & SetCRT2ToLCD) {
1407              tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
1408           }
1409           if(SiS_Pr->ChipType >= SIS_315H) {
1410              if(tempbx & SetCRT2ToLCDA) {
1411                 tempbx |= SetCRT2ToLCD;
1412              }
1413           }
1414
1415        }
1416
1417        if(tempax & DisableCRT2Display) {
1418           if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1419              tempbx = SetSimuScanMode | DisableCRT2Display;
1420           }
1421        }
1422
1423        if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
1424
1425        /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
1426        if(SiS_Pr->SiS_ModeType <= ModeVGA) {
1427           if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
1428               ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
1429              modeflag &= (~CRT2Mode);
1430           }
1431        }
1432
1433        if(!(tempbx & SetSimuScanMode)) {
1434           if(tempbx & SwitchCRT2) {
1435              if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1436                 if(resinfo != SIS_RI_1600x1200) {
1437                    tempbx |= SetSimuScanMode;
1438                 }
1439              }
1440           } else {
1441              if(SiS_BridgeIsEnabled(SiS_Pr)) {
1442                 if(!(tempbx & DriverMode)) {
1443                    if(SiS_BridgeInSlavemode(SiS_Pr)) {
1444                       tempbx |= SetSimuScanMode;
1445                    }
1446                 }
1447              }
1448           }
1449        }
1450
1451        if(!(tempbx & DisableCRT2Display)) {
1452           if(tempbx & DriverMode) {
1453              if(tempbx & SetSimuScanMode) {
1454                 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1455                    if(resinfo != SIS_RI_1600x1200) {
1456                       tempbx |= SetInSlaveMode;
1457                    }
1458                 }
1459              }
1460           } else {
1461              tempbx |= SetInSlaveMode;
1462           }
1463        }
1464
1465   }
1466
1467   SiS_Pr->SiS_VBInfo = tempbx;
1468
1469#ifdef CONFIG_FB_SIS_300
1470   if(SiS_Pr->ChipType == SIS_630) {
1471      SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1472   }
1473#endif
1474
1475#if 0
1476   printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
1477      SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1478#endif
1479}
1480
1481/*********************************************/
1482/*           DETERMINE YPbPr MODE            */
1483/*********************************************/
1484
1485void
1486SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
1487{
1488
1489   unsigned char temp;
1490
1491   /* Note: This variable is only used on 30xLV systems.
1492    * CR38 has a different meaning on LVDS/CH7019 systems.
1493    * On 661 and later, these bits moved to CR35.
1494    *
1495    * On 301, 301B, only HiVision 1080i is supported.
1496    * On 30xLV, 301C, only YPbPr 1080i is supported.
1497    */
1498
1499   SiS_Pr->SiS_YPbPr = 0;
1500   if(SiS_Pr->ChipType >= SIS_661) return;
1501
1502   if(SiS_Pr->SiS_VBType) {
1503      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1504         SiS_Pr->SiS_YPbPr = YPbPrHiVision;
1505      }
1506   }
1507
1508   if(SiS_Pr->ChipType >= SIS_315H) {
1509      if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1510         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1511         if(temp & 0x08) {
1512            switch((temp >> 4)) {
1513            case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
1514            case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
1515            case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
1516            case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
1517            }
1518         }
1519      }
1520   }
1521
1522}
1523
1524/*********************************************/
1525/*           DETERMINE TVMode flag           */
1526/*********************************************/
1527
1528void
1529SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1530{
1531   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
1532   unsigned short temp, temp1, resinfo = 0, romindex = 0;
1533   unsigned char  OutputSelect = *SiS_Pr->pSiS_OutputSelect;
1534
1535   SiS_Pr->SiS_TVMode = 0;
1536
1537   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
1538   if(SiS_Pr->UseCustomMode) return;
1539
1540   if(ModeNo > 0x13) {
1541      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1542   }
1543
1544   if(SiS_Pr->ChipType < SIS_661) {
1545
1546      if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
1547
1548      if(SiS_Pr->SiS_VBType & VB_SISVB) {
1549         temp = 0;
1550         if((SiS_Pr->ChipType == SIS_630) ||
1551            (SiS_Pr->ChipType == SIS_730)) {
1552            temp = 0x35;
1553            romindex = 0xfe;
1554         } else if(SiS_Pr->ChipType >= SIS_315H) {
1555            temp = 0x38;
1556            if(SiS_Pr->ChipType < XGI_20) {
1557               romindex = 0xf3;
1558               if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
1559            }
1560         }
1561         if(temp) {
1562            if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
1563               OutputSelect = ROMAddr[romindex];
1564               if(!(OutputSelect & EnablePALMN)) {
1565                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
1566               }
1567            }
1568            temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
1569            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1570               if(temp1 & EnablePALM) {         /* 0x40 */
1571                  SiS_Pr->SiS_TVMode |= TVSetPALM;
1572                  SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1573               } else if(temp1 & EnablePALN) {  /* 0x80 */
1574                  SiS_Pr->SiS_TVMode |= TVSetPALN;
1575               }
1576            } else {
1577               if(temp1 & EnableNTSCJ) {        /* 0x40 */
1578                  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1579               }
1580            }
1581         }
1582         /* Translate HiVision/YPbPr to our new flags */
1583         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1584            if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1585            else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1586            else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
1587            else                                        SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1588            if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
1589               SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
1590               SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
1591            } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
1592               SiS_Pr->SiS_TVMode |= TVSetPAL;
1593            }
1594         }
1595      } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1596         if(SiS_Pr->SiS_CHOverScan) {
1597            if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
1598               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1599               if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
1600                  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1601               }
1602            } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1603               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
1604               if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
1605                  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1606               }
1607            }
1608            if(SiS_Pr->SiS_CHSOverScan) {
1609               SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1610            }
1611         }
1612         if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1613            temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1614            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1615               if(temp & EnablePALM)      SiS_Pr->SiS_TVMode |= TVSetPALM;
1616               else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
1617            } else {
1618               if(temp & EnableNTSCJ) {
1619                  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1620               }
1621            }
1622         }
1623      }
1624
1625   } else {  /* 661 and later */
1626
1627      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1628      if(temp1 & 0x01) {
1629         SiS_Pr->SiS_TVMode |= TVSetPAL;
1630         if(temp1 & 0x08) {
1631            SiS_Pr->SiS_TVMode |= TVSetPALN;
1632         } else if(temp1 & 0x04) {
1633            if(SiS_Pr->SiS_VBType & VB_SISVB) {
1634               SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1635            }
1636            SiS_Pr->SiS_TVMode |= TVSetPALM;
1637         }
1638      } else {
1639         if(temp1 & 0x02) {
1640            SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1641         }
1642      }
1643      if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1644         if(SiS_Pr->SiS_CHOverScan) {
1645            if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
1646               SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1647            }
1648         }
1649      }
1650      if(SiS_Pr->SiS_VBType & VB_SISVB) {
1651         if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1652            temp1 &= 0xe0;
1653            if(temp1 == 0x00)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1654            else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1655            else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1656         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1657            SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
1658         }
1659         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
1660            if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
1661               SiS_Pr->SiS_TVMode |= TVAspect169;
1662            } else {
1663               temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
1664               if(temp1 & 0x02) {
1665                  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
1666                     SiS_Pr->SiS_TVMode |= TVAspect169;
1667                  } else {
1668                     SiS_Pr->SiS_TVMode |= TVAspect43LB;
1669                  }
1670               } else {
1671                  SiS_Pr->SiS_TVMode |= TVAspect43;
1672               }
1673            }
1674         }
1675      }
1676   }
1677
1678   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
1679
1680   if(SiS_Pr->SiS_VBType & VB_SISVB) {
1681
1682      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1683         SiS_Pr->SiS_TVMode |= TVSetPAL;
1684         SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
1685      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1686         if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
1687            SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
1688         }
1689      }
1690
1691      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1692         if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
1693            SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1694         }
1695      }
1696
1697      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
1698         if(resinfo == SIS_RI_1024x768) {
1699            if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
1700               SiS_Pr->SiS_TVMode |= TVSet525p1024;
1701            } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
1702               SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
1703            }
1704         }
1705      }
1706
1707      SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
1708      if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
1709         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
1710         SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1711      } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
1712         SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1713      } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
1714         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
1715            SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1716         }
1717      }
1718
1719   }
1720
1721   SiS_Pr->SiS_VBInfo &= ~SetPALTV;
1722}
1723
1724/*********************************************/
1725/*               GET LCD INFO                */
1726/*********************************************/
1727
1728static unsigned short
1729SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
1730{
1731   unsigned short temp = SiS_Pr->SiS_LCDResInfo;
1732   /* Translate my LCDResInfo to BIOS value */
1733   switch(temp) {
1734   case Panel_1280x768_2: temp = Panel_1280x768;    break;
1735   case Panel_1280x800_2: temp = Panel_1280x800;    break;
1736   case Panel_1280x854:   temp = Panel661_1280x854; break;
1737   }
1738   return temp;
1739}
1740
1741static void
1742SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
1743{
1744#ifdef CONFIG_FB_SIS_315
1745   unsigned char  *ROMAddr;
1746   unsigned short temp;
1747
1748   if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
1749      if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
1750         SiS_Pr->SiS_NeedRomModeData = true;
1751         SiS_Pr->PanelHT  = temp;
1752      }
1753      if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
1754         SiS_Pr->SiS_NeedRomModeData = true;
1755         SiS_Pr->PanelVT  = temp;
1756      }
1757      SiS_Pr->PanelHRS = SISGETROMW(10);
1758      SiS_Pr->PanelHRE = SISGETROMW(12);
1759      SiS_Pr->PanelVRS = SISGETROMW(14);
1760      SiS_Pr->PanelVRE = SISGETROMW(16);
1761      SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1762      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
1763         SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
1764      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
1765         SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
1766      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
1767         SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
1768
1769   }
1770#endif
1771}
1772
1773static void
1774SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
1775                        const unsigned char *nonscalingmodes)
1776{
1777   int i = 0;
1778   while(nonscalingmodes[i] != 0xff) {
1779      if(nonscalingmodes[i++] == resinfo) {
1780         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
1781            (SiS_Pr->UsePanelScaler == -1)) {
1782            SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1783         }
1784         break;
1785      }
1786   }
1787}
1788
1789void
1790SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1791{
1792  unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
1793  bool panelcanscale = false;
1794#ifdef CONFIG_FB_SIS_300
1795  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1796  static const unsigned char SiS300SeriesLCDRes[] =
1797          { 0,  1,  2,  3,  7,  4,  5,  8,
1798            0,  0, 10,  0,  0,  0,  0, 15 };
1799#endif
1800#ifdef CONFIG_FB_SIS_315
1801  unsigned char   *myptr = NULL;
1802#endif
1803
1804  SiS_Pr->SiS_LCDResInfo  = 0;
1805  SiS_Pr->SiS_LCDTypeInfo = 0;
1806  SiS_Pr->SiS_LCDInfo     = 0;
1807  SiS_Pr->PanelHRS        = 999; /* HSync start */
1808  SiS_Pr->PanelHRE        = 999; /* HSync end */
1809  SiS_Pr->PanelVRS        = 999; /* VSync start */
1810  SiS_Pr->PanelVRE        = 999; /* VSync end */
1811  SiS_Pr->SiS_NeedRomModeData = false;
1812
1813  /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
1814  SiS_Pr->Alternate1600x1200 = false;
1815
1816  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
1817
1818  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1819
1820  if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
1821     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1822     modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
1823     modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
1824  }
1825
1826  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
1827
1828  /* For broken BIOSes: Assume 1024x768 */
1829  if(temp == 0) temp = 0x02;
1830
1831  if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
1832     SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
1833  } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
1834     SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
1835  } else {
1836     SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1837  }
1838  temp &= 0x0f;
1839#ifdef CONFIG_FB_SIS_300
1840  if(SiS_Pr->ChipType < SIS_315H) {
1841     /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
1842     if(SiS_Pr->SiS_VBType & VB_SIS301) {
1843        if(temp < 0x0f) temp &= 0x07;
1844     }
1845     /* Translate 300 series LCDRes to 315 series for unified usage */
1846     temp = SiS300SeriesLCDRes[temp];
1847  }
1848#endif
1849
1850  /* Translate to our internal types */
1851#ifdef CONFIG_FB_SIS_315
1852  if(SiS_Pr->ChipType == SIS_550) {
1853     if     (temp == Panel310_1152x768)  temp = Panel_320x240_2; /* Verified working */
1854     else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
1855     else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
1856  } else if(SiS_Pr->ChipType >= SIS_661) {
1857     if(temp == Panel661_1280x854)       temp = Panel_1280x854;
1858  }
1859#endif
1860
1861  if(SiS_Pr->SiS_VBType & VB_SISLVDS) {         /* SiS LVDS */
1862     if(temp == Panel310_1280x768) {
1863        temp = Panel_1280x768_2;
1864     }
1865     if(SiS_Pr->SiS_ROMNew) {
1866        if(temp == Panel661_1280x800) {
1867           temp = Panel_1280x800_2;
1868        }
1869     }
1870  }
1871
1872  SiS_Pr->SiS_LCDResInfo = temp;
1873
1874#ifdef CONFIG_FB_SIS_300
1875  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1876     if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
1877        SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
1878     } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
1879        SiS_Pr->SiS_LCDResInfo = Panel_848x480;
1880     } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
1881        SiS_Pr->SiS_LCDResInfo = Panel_856x480;
1882     }
1883  }
1884#endif
1885
1886  if(SiS_Pr->SiS_VBType & VB_SISVB) {
1887     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
1888        SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
1889  } else {
1890     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
1891        SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
1892  }
1893
1894  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
1895  SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
1896  /* Need temp below! */
1897
1898  /* These must/can't scale no matter what */
1899  switch(SiS_Pr->SiS_LCDResInfo) {
1900  case Panel_320x240_1:
1901  case Panel_320x240_2:
1902  case Panel_320x240_3:
1903  case Panel_1280x960:
1904      SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1905      break;
1906  case Panel_640x480:
1907      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1908  }
1909
1910  panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
1911
1912  if(!SiS_Pr->UsePanelScaler)          SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1913  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1914
1915  /* Dual link, Pass 1:1 BIOS default, etc. */
1916#ifdef CONFIG_FB_SIS_315
1917  if(SiS_Pr->ChipType >= SIS_661) {
1918     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1919        if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1920     }
1921     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1922        if(SiS_Pr->SiS_ROMNew) {
1923           if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1924        } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
1925           if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1926        }
1927     }
1928  } else if(SiS_Pr->ChipType >= SIS_315H) {
1929     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1930        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1931     }
1932     if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
1933        SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
1934        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1935        if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
1936        if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1937           if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1938        }
1939     } else if(!(SiS_Pr->SiS_ROMNew)) {
1940        if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1941           if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
1942              (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
1943              SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1944           }
1945           if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
1946              (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
1947              (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
1948              (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
1949              SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1950           }
1951        }
1952     }
1953  }
1954#endif
1955
1956  /* Pass 1:1 */
1957  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
1958     /* Always center screen on LVDS (if scaling is disabled) */
1959     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1960  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1961     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1962        /* Always center screen on SiS LVDS (if scaling is disabled) */
1963        SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1964     } else {
1965        /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
1966        if(panelcanscale)             SiS_Pr->SiS_LCDInfo |= LCDPass11;
1967        if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1968     }
1969  }
1970
1971  SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1972  SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1973
1974  switch(SiS_Pr->SiS_LCDResInfo) {
1975     case Panel_320x240_1:
1976     case Panel_320x240_2:
1977     case Panel_320x240_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
1978                            SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
1979                            SiS_Pr->PanelVCLKIdx300 = VCLK28;
1980                            SiS_Pr->PanelVCLKIdx315 = VCLK28;
1981                            break;
1982     case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
1983                                                      SiS_Pr->PanelVRE  =    3;
1984                            SiS_Pr->PanelVCLKIdx300 = VCLK28;
1985                            SiS_Pr->PanelVCLKIdx315 = VCLK28;
1986                            break;
1987     case Panel_800x600:    SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600;
1988                            SiS_Pr->PanelHT   = 1056; SiS_Pr->PanelVT   =  628;
1989                            SiS_Pr->PanelHRS  =   40; SiS_Pr->PanelHRE  =  128;
1990                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    4;
1991                            SiS_Pr->PanelVCLKIdx300 = VCLK40;
1992                            SiS_Pr->PanelVCLKIdx315 = VCLK40;
1993                            break;
1994     case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
1995                            SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
1996                            SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
1997                            SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
1998                            SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1999                            SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
2000                            break;
2001     case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
2002                            SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
2003                            SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
2004                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
2005                            if(SiS_Pr->ChipType < SIS_315H) {
2006                               SiS_Pr->PanelHRS = 23;
2007                                                      SiS_Pr->PanelVRE  =    5;
2008                            }
2009                            SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
2010                            SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
2011                            SiS_GetLCDInfoBIOS(SiS_Pr);
2012                            break;
2013     case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
2014                            SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
2015                            SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
2016                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
2017                            if(SiS_Pr->ChipType < SIS_315H) {
2018                               SiS_Pr->PanelHRS = 23;
2019                                                      SiS_Pr->PanelVRE  =    5;
2020                            }
2021                            SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
2022                            SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
2023                            break;
2024     case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
2025                            break;
2026     case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
2027                            SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
2028                            SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
2029                            SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
2030                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
2031                            /* Data above for TMDS (projector); get from BIOS for LVDS */
2032                            SiS_GetLCDInfoBIOS(SiS_Pr);
2033                            break;
2034     case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
2035                            if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2036                               SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
2037                               SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
2038                               SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
2039                            } else {
2040                               SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
2041                               SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
2042                               SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
2043                               SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
2044                               SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
2045                            }
2046                            break;
2047     case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
2048                            SiS_Pr->PanelHT   = 1660; SiS_Pr->PanelVT   =  806;
2049                            SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
2050                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
2051                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
2052                            SiS_GetLCDInfoBIOS(SiS_Pr);
2053                            break;
2054     case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
2055                            SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
2056                            SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
2057                            SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
2058                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
2059                            SiS_GetLCDInfoBIOS(SiS_Pr);
2060                            break;
2061     case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
2062                            SiS_Pr->PanelHT   = 1552; SiS_Pr->PanelVT   =  812;
2063                            SiS_Pr->PanelHRS   =  48; SiS_Pr->PanelHRE  =  112;
2064                            SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
2065                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
2066                            SiS_GetLCDInfoBIOS(SiS_Pr);
2067                            break;
2068     case Panel_1280x854:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  854;
2069                            SiS_Pr->PanelHT   = 1664; SiS_Pr->PanelVT   =  861;
2070                            SiS_Pr->PanelHRS   =  16; SiS_Pr->PanelHRE  =  112;
2071                            SiS_Pr->PanelVRS   =   1; SiS_Pr->PanelVRE  =    3;
2072                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
2073                            SiS_GetLCDInfoBIOS(SiS_Pr);
2074                            break;
2075     case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
2076                            SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
2077                            SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
2078                            SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
2079                            if(resinfo == SIS_RI_1280x1024) {
2080                               SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
2081                               SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
2082                            }
2083                            break;
2084     case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
2085                            SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
2086                            SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
2087                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
2088                            SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
2089                            SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
2090                            SiS_GetLCDInfoBIOS(SiS_Pr);
2091                            break;
2092     case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
2093                            SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
2094                            SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
2095                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
2096                            SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
2097                            SiS_GetLCDInfoBIOS(SiS_Pr);
2098                            break;
2099     case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
2100                            SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
2101                            SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
2102                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
2103                            SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
2104                            if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
2105                               if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2106                                  SiS_Pr->PanelHT  = 1760; SiS_Pr->PanelVT  = 1235;
2107                                  SiS_Pr->PanelHRS =   48; SiS_Pr->PanelHRE =   32;
2108                                  SiS_Pr->PanelVRS =    2; SiS_Pr->PanelVRE =    4;
2109                                  SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
2110                                  SiS_Pr->Alternate1600x1200 = true;
2111                               }
2112                            } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
2113                               SiS_Pr->PanelHT  = 2048; SiS_Pr->PanelVT  = 1320;
2114                               SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
2115                               SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
2116                            }
2117                            SiS_GetLCDInfoBIOS(SiS_Pr);
2118                            break;
2119     case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
2120                            SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
2121                            SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
2122                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
2123                            SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
2124                            SiS_GetLCDInfoBIOS(SiS_Pr);
2125                            break;
2126     case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
2127                            SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
2128                            break;
2129     case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
2130                            SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
2131                            break;
2132     case Panel_856x480:    SiS_Pr->PanelXRes =  856; SiS_Pr->PanelYRes =  480;
2133                            SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
2134                            break;
2135     case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
2136                            SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
2137                            SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
2138                            SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
2139                            if(SiS_Pr->CP_PreferredIndex != -1) {
2140                               SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
2141                               SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
2142                               SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
2143                               SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
2144                               SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
2145                               SiS_Pr->PanelHRE  = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
2146                               SiS_Pr->PanelVRS  = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
2147                               SiS_Pr->PanelVRE  = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
2148                               SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
2149                               SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
2150                               SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
2151                               SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
2152                               if(SiS_Pr->CP_PrefClock) {
2153                                  int idx;
2154                                  SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
2155                                  SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
2156                                  if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
2157                                  else                             idx = VCLK_CUSTOM_315;
2158                                  SiS_Pr->SiS_VCLKData[idx].CLOCK =
2159                                     SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
2160                                  SiS_Pr->SiS_VCLKData[idx].SR2B =
2161                                     SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
2162                                  SiS_Pr->SiS_VCLKData[idx].SR2C =
2163                                     SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
2164                               }
2165                            }
2166                            break;
2167     default:               SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
2168                            SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
2169                            break;
2170  }
2171
2172  /* Special cases */
2173  if( (SiS_Pr->SiS_IF_DEF_FSTN)              ||
2174      (SiS_Pr->SiS_IF_DEF_DSTN)              ||
2175      (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
2176      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
2177      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
2178      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
2179     SiS_Pr->PanelHRS = 999;
2180     SiS_Pr->PanelHRE = 999;
2181  }
2182
2183  if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
2184      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
2185      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
2186      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
2187     SiS_Pr->PanelVRS = 999;
2188     SiS_Pr->PanelVRE = 999;
2189  }
2190
2191  /* DontExpand overrule */
2192  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
2193
2194     if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
2195        /* No scaling for this mode on any panel (LCD=CRT2)*/
2196        SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2197     }
2198
2199     switch(SiS_Pr->SiS_LCDResInfo) {
2200
2201     case Panel_Custom:
2202     case Panel_1152x864:
2203     case Panel_1280x768:       /* TMDS only */
2204        SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2205        break;
2206
2207     case Panel_800x600: {
2208        static const unsigned char nonscalingmodes[] = {
2209           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
2210        };
2211        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2212        break;
2213     }
2214     case Panel_1024x768: {
2215        static const unsigned char nonscalingmodes[] = {
2216           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2217           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2218           0xff
2219        };
2220        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2221        break;
2222     }
2223     case Panel_1280x720: {
2224        static const unsigned char nonscalingmodes[] = {
2225           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2226           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2227           0xff
2228        };
2229        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2230        if(SiS_Pr->PanelHT == 1650) {
2231           SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2232        }
2233        break;
2234     }
2235     case Panel_1280x768_2: {  /* LVDS only */
2236        static const unsigned char nonscalingmodes[] = {
2237           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2238           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2239           SIS_RI_1152x768,0xff
2240        };
2241        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2242        switch(resinfo) {
2243        case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
2244                                  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2245                               }
2246                               break;
2247        }
2248        break;
2249     }
2250     case Panel_1280x800: {     /* SiS TMDS special (Averatec 6200 series) */
2251        static const unsigned char nonscalingmodes[] = {
2252           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2253           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2254           SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
2255        };
2256        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2257        break;
2258     }
2259     case Panel_1280x800_2:  {  /* SiS LVDS */
2260        static const unsigned char nonscalingmodes[] = {
2261           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2262           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2263           SIS_RI_1152x768,0xff
2264        };
2265        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2266        switch(resinfo) {
2267        case SIS_RI_1280x720:
2268        case SIS_RI_1280x768:  if(SiS_Pr->UsePanelScaler == -1) {
2269                                  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2270                               }
2271                               break;
2272        }
2273        break;
2274     }
2275     case Panel_1280x854: {     /* SiS LVDS */
2276        static const unsigned char nonscalingmodes[] = {
2277           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2278           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2279           SIS_RI_1152x768,0xff
2280        };
2281        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2282        switch(resinfo) {
2283        case SIS_RI_1280x720:
2284        case SIS_RI_1280x768:
2285        case SIS_RI_1280x800:  if(SiS_Pr->UsePanelScaler == -1) {
2286                                  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2287                               }
2288                               break;
2289        }
2290        break;
2291     }
2292     case Panel_1280x960: {
2293        static const unsigned char nonscalingmodes[] = {
2294           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2295           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2296           SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2297           SIS_RI_1280x854,0xff
2298        };
2299        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2300        break;
2301     }
2302     case Panel_1280x1024: {
2303        static const unsigned char nonscalingmodes[] = {
2304           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2305           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2306           SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2307           SIS_RI_1280x854,SIS_RI_1280x960,0xff
2308        };
2309        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2310        break;
2311     }
2312     case Panel_1400x1050: {
2313        static const unsigned char nonscalingmodes[] = {
2314             SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2315             SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2316             SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
2317             SIS_RI_1280x960,0xff
2318        };
2319        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2320        switch(resinfo) {
2321        case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
2322                                  SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2323                               }
2324                               break;
2325        case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2326                               break;
2327        }
2328        break;
2329     }
2330     case Panel_1600x1200: {
2331        static const unsigned char nonscalingmodes[] = {
2332             SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2333             SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2334             SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2335             SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
2336        };
2337        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2338        break;
2339     }
2340     case Panel_1680x1050: {
2341        static const unsigned char nonscalingmodes[] = {
2342             SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2343             SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2344             SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
2345             SIS_RI_1360x1024,0xff
2346        };
2347        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2348        break;
2349     }
2350     }
2351  }
2352
2353#ifdef CONFIG_FB_SIS_300
2354  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2355     if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2356        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
2357     }
2358  }
2359
2360  if(SiS_Pr->ChipType < SIS_315H) {
2361     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2362        if(SiS_Pr->SiS_UseROM) {
2363           if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
2364              if(!(ROMAddr[0x235] & 0x02)) {
2365                 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2366              }
2367           }
2368        }
2369     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2370        if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
2371           SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2372        }
2373     }
2374  }
2375#endif
2376
2377  /* Special cases */
2378
2379  if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
2380     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2381  }
2382
2383  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
2384     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2385  }
2386
2387  switch(SiS_Pr->SiS_LCDResInfo) {
2388  case Panel_640x480:
2389     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2390     break;
2391  case Panel_1280x800:
2392     /* Don't pass 1:1 by default (TMDS special) */
2393     if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2394     break;
2395  case Panel_1280x960:
2396     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2397     break;
2398  case Panel_Custom:
2399     if((!SiS_Pr->CP_PrefClock) ||
2400        (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
2401        SiS_Pr->SiS_LCDInfo |= LCDPass11;
2402     }
2403     break;
2404  }
2405
2406  if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
2407     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2408  }
2409
2410  /* (In)validate LCDPass11 flag */
2411  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2412     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2413  }
2414
2415  /* LVDS DDA */
2416  if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
2417
2418     if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
2419        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
2420           if(ModeNo == 0x12) {
2421              if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
2422                 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2423              }
2424           } else if(ModeNo > 0x13) {
2425              if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
2426                 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2427                    if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
2428                       SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2429                    }
2430                 }
2431              }
2432           }
2433        }
2434     }
2435
2436     if(modeflag & HalfDCLK) {
2437        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
2438           SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2439        } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
2440           SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2441        } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
2442           SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2443        } else if(ModeNo > 0x13) {
2444           if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
2445              if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2446           } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
2447              if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2448           }
2449        }
2450     }
2451
2452  }
2453
2454  /* VESA timing */
2455  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2456     if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
2457        SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2458     }
2459  } else {
2460     SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2461  }
2462
2463#if 0
2464  printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
2465        SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
2466#endif
2467}
2468
2469/*********************************************/
2470/*                 GET VCLK                  */
2471/*********************************************/
2472
2473unsigned short
2474SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2475                unsigned short RefreshRateTableIndex)
2476{
2477  unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
2478  unsigned short resinfo, tempbx;
2479  const unsigned char *CHTVVCLKPtr = NULL;
2480
2481  if(ModeNo <= 0x13) {
2482     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
2483     CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2484     VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
2485     VCLKIndexGENCRT = VCLKIndexGEN;
2486  } else {
2487     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2488     CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2489     VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
2490     VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
2491                (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
2492  }
2493
2494  if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
2495
2496     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2497
2498        CRT2Index >>= 6;
2499        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {       /*  LCD */
2500
2501           if(SiS_Pr->ChipType < SIS_315H) {
2502              VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2503              if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2504                 VCLKIndex = VCLKIndexGEN;
2505              }
2506           } else {
2507              VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2508              if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2509                 switch(resinfo) {
2510                 /* Correct those whose IndexGEN doesn't match VBVCLK array */
2511                 case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
2512                 case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
2513                 case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
2514                 case SIS_RI_848x480:  VCLKIndex = VCLK_848x480;  break;
2515                 case SIS_RI_856x480:  VCLKIndex = VCLK_856x480;  break;
2516                 case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
2517                 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
2518                 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
2519                 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
2520                 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
2521                 default:              VCLKIndex = VCLKIndexGEN;
2522                 }
2523
2524                 if(ModeNo <= 0x13) {
2525                    if(SiS_Pr->ChipType <= SIS_315PRO) {
2526                       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
2527                    } else {
2528                       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
2529                    }
2530                 }
2531                 if(SiS_Pr->ChipType <= SIS_315PRO) {
2532                    if(VCLKIndex == 0) VCLKIndex = 0x41;
2533                    if(VCLKIndex == 1) VCLKIndex = 0x43;
2534                    if(VCLKIndex == 4) VCLKIndex = 0x44;
2535                 }
2536              }
2537           }
2538
2539        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                   /*  TV */
2540
2541           if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2542              if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)        VCLKIndex = HiTVVCLKDIV2;
2543              else                                         VCLKIndex = HiTVVCLK;
2544              if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     VCLKIndex = HiTVSimuVCLK;
2545           } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  VCLKIndex = YPbPr750pVCLK;
2546           else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)    VCLKIndex = TVVCLKDIV2;
2547           else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)      VCLKIndex = TVVCLKDIV2;
2548           else                                            VCLKIndex = TVVCLK;
2549
2550           if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
2551           else                            VCLKIndex += TVCLKBASE_315;
2552
2553        } else {                                                        /* VGA2 */
2554
2555           VCLKIndex = VCLKIndexGENCRT;
2556           if(SiS_Pr->ChipType < SIS_315H) {
2557              if(ModeNo > 0x13) {
2558                 if( (SiS_Pr->ChipType == SIS_630) &&
2559                     (SiS_Pr->ChipRevision >= 0x30)) {
2560                    if(VCLKIndex == 0x14) VCLKIndex = 0x34;
2561                 }
2562                 /* Better VGA2 clock for 1280x1024@75 */
2563                 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
2564              }
2565           }
2566        }
2567
2568     } else {   /* If not programming CRT2 */
2569
2570        VCLKIndex = VCLKIndexGENCRT;
2571        if(SiS_Pr->ChipType < SIS_315H) {
2572           if(ModeNo > 0x13) {
2573              if( (SiS_Pr->ChipType != SIS_630) &&
2574                  (SiS_Pr->ChipType != SIS_300) ) {
2575                 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2576              }
2577           }
2578        }
2579     }
2580
2581  } else {       /*   LVDS  */
2582
2583     VCLKIndex = CRT2Index;
2584
2585     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2586
2587        if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
2588
2589           VCLKIndex &= 0x1f;
2590           tempbx = 0;
2591           if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2592           if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2593              tempbx += 2;
2594              if(SiS_Pr->SiS_ModeType > ModeVGA) {
2595                 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
2596              }
2597              if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2598                 tempbx = 4;
2599                 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2600              } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2601                 tempbx = 6;
2602                 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2603              }
2604           }
2605           switch(tempbx) {
2606             case  0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC;  break;
2607             case  1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC;  break;
2608             case  2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL;   break;
2609             case  3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
2610             case  4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM;  break;
2611             case  5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM;  break;
2612             case  6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN;  break;
2613             case  7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN;  break;
2614             case  8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL;  break;
2615             default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
2616           }
2617           VCLKIndex = CHTVVCLKPtr[VCLKIndex];
2618
2619        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2620
2621           if(SiS_Pr->ChipType < SIS_315H) {
2622              VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2623           } else {
2624              VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2625           }
2626
2627#ifdef CONFIG_FB_SIS_300
2628           /* Special Timing: Barco iQ Pro R series */
2629           if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2630
2631           /* Special Timing: 848x480 and 856x480 parallel lvds panels */
2632           if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2633              if(SiS_Pr->ChipType < SIS_315H) {
2634                 VCLKIndex = VCLK34_300;
2635                 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2636              } else {
2637                 VCLKIndex = VCLK34_315;
2638                 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2639              }
2640           }
2641#endif
2642
2643        } else {
2644
2645           VCLKIndex = VCLKIndexGENCRT;
2646           if(SiS_Pr->ChipType < SIS_315H) {
2647              if(ModeNo > 0x13) {
2648                 if( (SiS_Pr->ChipType == SIS_630) &&
2649                     (SiS_Pr->ChipRevision >= 0x30) ) {
2650                    if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
2651                 }
2652              }
2653           }
2654        }
2655
2656     } else {  /* if not programming CRT2 */
2657
2658        VCLKIndex = VCLKIndexGENCRT;
2659        if(SiS_Pr->ChipType < SIS_315H) {
2660           if(ModeNo > 0x13) {
2661              if( (SiS_Pr->ChipType != SIS_630) &&
2662                  (SiS_Pr->ChipType != SIS_300) ) {
2663                 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2664              }
2665#if 0
2666              if(SiS_Pr->ChipType == SIS_730) {
2667                 if(VCLKIndex == 0x0b) VCLKIndex = 0x40;   /* 1024x768-70 */
2668                 if(VCLKIndex == 0x0d) VCLKIndex = 0x41;   /* 1024x768-75 */
2669              }
2670#endif
2671           }
2672        }
2673
2674     }
2675
2676  }
2677
2678  return VCLKIndex;
2679}
2680
2681/*********************************************/
2682/*        SET CRT2 MODE TYPE REGISTERS       */
2683/*********************************************/
2684
2685static void
2686SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2687{
2688  unsigned short i, j, modeflag, tempah=0;
2689  short tempcl;
2690#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2691  unsigned short tempbl;
2692#endif
2693#ifdef CONFIG_FB_SIS_315
2694  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
2695  unsigned short tempah2, tempbl2;
2696#endif
2697
2698  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2699
2700  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2701
2702     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
2703     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
2704
2705  } else {
2706
2707     for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
2708     if(SiS_Pr->ChipType >= SIS_315H) {
2709        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
2710     }
2711
2712     tempcl = SiS_Pr->SiS_ModeType;
2713
2714     if(SiS_Pr->ChipType < SIS_315H) {
2715
2716#ifdef CONFIG_FB_SIS_300    /* ---- 300 series ---- */
2717
2718        /* For 301BDH: (with LCD via LVDS) */
2719        if(SiS_Pr->SiS_VBType & VB_NoLCD) {
2720           tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
2721           tempbl &= 0xef;
2722           tempbl |= 0x02;
2723           if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2724              tempbl |= 0x10;
2725              tempbl &= 0xfd;
2726           }
2727           SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
2728        }
2729
2730        if(ModeNo > 0x13) {
2731           tempcl -= ModeVGA;
2732           if(tempcl >= 0) {
2733              tempah = ((0x10 >> tempcl) | 0x80);
2734           }
2735        } else tempah = 0x80;
2736
2737        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  tempah ^= 0xA0;
2738
2739#endif  /* CONFIG_FB_SIS_300 */
2740
2741     } else {
2742
2743#ifdef CONFIG_FB_SIS_315    /* ------- 315/330 series ------ */
2744
2745        if(ModeNo > 0x13) {
2746           tempcl -= ModeVGA;
2747           if(tempcl >= 0) {
2748              tempah = (0x08 >> tempcl);
2749              if (tempah == 0) tempah = 1;
2750              tempah |= 0x40;
2751           }
2752        } else tempah = 0x40;
2753
2754        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
2755
2756#endif  /* CONFIG_FB_SIS_315 */
2757
2758     }
2759
2760     if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2761
2762     if(SiS_Pr->ChipType < SIS_315H) {
2763        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2764     } else {
2765#ifdef CONFIG_FB_SIS_315
2766        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2767           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2768        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2769           if(IS_SIS740) {
2770              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2771           } else {
2772              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2773           }
2774        }
2775#endif
2776     }
2777
2778     if(SiS_Pr->SiS_VBType & VB_SISVB) {
2779
2780        tempah = 0x01;
2781        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2782           tempah |= 0x02;
2783        }
2784        if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2785           tempah ^= 0x05;
2786           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
2787              tempah ^= 0x01;
2788           }
2789        }
2790
2791        if(SiS_Pr->ChipType < SIS_315H) {
2792
2793           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
2794
2795           tempah = (tempah << 5) & 0xFF;
2796           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2797           tempah = (tempah >> 5) & 0xFF;
2798
2799        } else {
2800
2801           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0x08;
2802           else if(!(SiS_IsDualEdge(SiS_Pr)))           tempah |= 0x08;
2803           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
2804           tempah &= ~0x08;
2805
2806        }
2807
2808        if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
2809           tempah |= 0x10;
2810        }
2811
2812        tempah |= 0x80;
2813        if(SiS_Pr->SiS_VBType & VB_SIS301) {
2814           if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
2815        }
2816
2817        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2818           if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
2819              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2820                 tempah |= 0x20;
2821              }
2822           }
2823        }
2824
2825        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
2826
2827        tempah = 0x80;
2828        if(SiS_Pr->SiS_VBType & VB_SIS301) {
2829           if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
2830        }
2831
2832        if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
2833
2834        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2835           if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
2836              tempah |= 0x40;
2837           }
2838        }
2839
2840        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
2841
2842     } else {  /* LVDS */
2843
2844        if(SiS_Pr->ChipType >= SIS_315H) {
2845
2846#ifdef CONFIG_FB_SIS_315
2847           /* LVDS can only be slave in 8bpp modes */
2848           tempah = 0x80;
2849           if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
2850              if(SiS_Pr->SiS_VBInfo & DriverMode) {
2851                 tempah |= 0x02;
2852              }
2853           }
2854
2855           if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  tempah |= 0x02;
2856
2857           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)        tempah ^= 0x01;
2858
2859           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
2860
2861           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
2862#endif
2863
2864        } else {
2865
2866#ifdef CONFIG_FB_SIS_300
2867           tempah = 0;
2868           if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
2869              tempah |= 0x02;
2870           }
2871           tempah <<= 5;
2872
2873           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2874
2875           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2876#endif
2877
2878        }
2879
2880     }
2881
2882  }  /* LCDA */
2883
2884  if(SiS_Pr->SiS_VBType & VB_SISVB) {
2885
2886     if(SiS_Pr->ChipType >= SIS_315H) {
2887
2888#ifdef CONFIG_FB_SIS_315
2889        /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
2890
2891        /* The following is nearly unpreditable and varies from machine
2892         * to machine. Especially the 301DH seems to be a real trouble
2893         * maker. Some BIOSes simply set the registers (like in the
2894         * NoLCD-if-statements here), some set them according to the
2895         * LCDA stuff. It is very likely that some machines are not
2896         * treated correctly in the following, very case-orientated
2897         * code. What do I do then...?
2898         */
2899
2900        /* 740 variants match for 30xB, 301B-DH, 30xLV */
2901
2902        if(!(IS_SIS740)) {
2903           tempah = 0x04;                                                  /* For all bridges */
2904           tempbl = 0xfb;
2905           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2906              tempah = 0x00;
2907              if(SiS_IsDualEdge(SiS_Pr)) {
2908                 tempbl = 0xff;
2909              }
2910           }
2911           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2912        }
2913
2914        /* The following two are responsible for eventually wrong colors
2915         * in TV output. The DH (VB_NoLCD) conditions are unknown; the
2916         * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
2917         * in a 650 box (Jake). What is the criteria?
2918         * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
2919         * treatment like the 651+301B-DH(b0) case. Seems more to be the
2920         * chipset than the bridge revision.
2921         */
2922
2923        if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
2924           tempah = 0x30;
2925           tempbl = 0xc0;
2926           if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2927              ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
2928              tempah = 0x00;
2929              tempbl = 0x00;
2930           }
2931           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
2932           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
2933        } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
2934           /* Fixes "TV-blue-bug" on 315+301 */
2935           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf);      /* For 301   */
2936           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
2937        } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
2938           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);       /* For 30xLV */
2939           SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
2940        } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {              /* For 301B-DH */
2941           tempah = 0x30; tempah2 = 0xc0;
2942           tempbl = 0xcf; tempbl2 = 0x3f;
2943           if(SiS_Pr->SiS_TVBlue == 0) {
2944                 tempah = tempah2 = 0x00;
2945           } else if(SiS_Pr->SiS_TVBlue == -1) {
2946              /* Set on 651/M650, clear on 315/650 */
2947              if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
2948                 tempah = tempah2 = 0x00;
2949              }
2950           }
2951           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2952           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2953        } else {
2954           tempah = 0x30; tempah2 = 0xc0;                      /* For 30xB, 301C */
2955           tempbl = 0xcf; tempbl2 = 0x3f;
2956           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2957              tempah = tempah2 = 0x00;
2958              if(SiS_IsDualEdge(SiS_Pr)) {
2959                 tempbl = tempbl2 = 0xff;
2960              }
2961           }
2962           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2963           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2964        }
2965
2966        if(IS_SIS740) {
2967           tempah = 0x80;
2968           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
2969           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
2970        } else {
2971           tempah = 0x00;
2972           tempbl = 0x7f;
2973           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2974              tempbl = 0xff;
2975              if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
2976           }
2977           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
2978        }
2979
2980#endif /* CONFIG_FB_SIS_315 */
2981
2982     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2983
2984#ifdef CONFIG_FB_SIS_300
2985        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
2986
2987        if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2988           ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
2989            (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
2990           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
2991        } else {
2992           SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
2993        }
2994#endif
2995
2996     }
2997
2998     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2999        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
3000        if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
3001           SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
3002        }
3003     }
3004
3005  } else {  /* LVDS */
3006
3007#ifdef CONFIG_FB_SIS_315
3008     if(SiS_Pr->ChipType >= SIS_315H) {
3009
3010        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
3011
3012           tempah = 0x04;
3013           tempbl = 0xfb;
3014           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3015              tempah = 0x00;
3016              if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
3017           }
3018           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
3019
3020           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
3021              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
3022           }
3023
3024           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
3025
3026        } else if(SiS_Pr->ChipType == SIS_550) {
3027
3028           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
3029           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
3030
3031        }
3032
3033     }
3034#endif
3035
3036  }
3037
3038}
3039
3040/*********************************************/
3041/*            GET RESOLUTION DATA            */
3042/*********************************************/
3043
3044unsigned short
3045SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
3046{
3047   if(ModeNo <= 0x13)
3048      return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
3049   else
3050      return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
3051}
3052
3053static void
3054SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
3055{
3056   unsigned short xres, yres, modeflag=0, resindex;
3057
3058   if(SiS_Pr->UseCustomMode) {
3059      xres = SiS_Pr->CHDisplay;
3060      if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
3061      SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
3062      /* DoubleScanMode-check done in CheckCalcCustomMode()! */
3063      SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
3064      return;
3065   }
3066
3067   resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
3068
3069   if(ModeNo <= 0x13) {
3070      xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
3071      yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
3072   } else {
3073      xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
3074      yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
3075      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3076   }
3077
3078   if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
3079
3080      if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
3081         if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3082            if(yres == 350) yres = 400;
3083         }
3084         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
3085            if(ModeNo == 0x12) yres = 400;
3086         }
3087      }
3088
3089      if(modeflag & HalfDCLK)       xres <<= 1;
3090      if(modeflag & DoubleScanMode) yres <<= 1;
3091
3092   }
3093
3094   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
3095
3096      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3097         switch(SiS_Pr->SiS_LCDResInfo) {
3098           case Panel_1024x768:
3099              if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
3100                 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
3101                    if(yres == 350) yres = 357;
3102                    if(yres == 400) yres = 420;
3103                    if(yres == 480) yres = 525;
3104                 }
3105              }
3106              break;
3107           case Panel_1280x1024:
3108              if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
3109                 /* BIOS bug - does this regardless of scaling */
3110                 if(yres == 400) yres = 405;
3111              }
3112              if(yres == 350) yres = 360;
3113              if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3114                 if(yres == 360) yres = 375;
3115              }
3116              break;
3117           case Panel_1600x1200:
3118              if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
3119                 if(yres == 1024) yres = 1056;
3120              }
3121              break;
3122         }
3123      }
3124
3125   } else {
3126
3127      if(SiS_Pr->SiS_VBType & VB_SISVB) {
3128         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
3129            if(xres == 720) xres = 640;
3130         }
3131      } else if(xres == 720) xres = 640;
3132
3133      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
3134         yres = 400;
3135         if(SiS_Pr->ChipType >= SIS_315H) {
3136            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
3137         } else {
3138            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
3139         }
3140         if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
3141      }
3142
3143   }
3144   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
3145   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
3146}
3147
3148/*********************************************/
3149/*           GET CRT2 TIMING DATA            */
3150/*********************************************/
3151
3152static void
3153SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3154               unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
3155               unsigned short *ResIndex)
3156{
3157  unsigned short tempbx=0, tempal=0, resinfo=0;
3158
3159  if(ModeNo <= 0x13) {
3160     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3161  } else {
3162     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3163     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
3164  }
3165
3166  if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
3167
3168     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
3169
3170        tempbx = SiS_Pr->SiS_LCDResInfo;
3171        if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
3172
3173        /* patch index */
3174        if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
3175           if     (resinfo == SIS_RI_1280x800)  tempal =  9;
3176           else if(resinfo == SIS_RI_1400x1050) tempal = 11;
3177        } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
3178                  (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
3179                  (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
3180           if     (resinfo == SIS_RI_1280x768)  tempal =  9;
3181        }
3182
3183        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3184           /* Pass 1:1 only (center-screen handled outside) */
3185           /* This is never called for the panel's native resolution */
3186           /* since Pass1:1 will not be set in this case */
3187           tempbx = 100;
3188           if(ModeNo >= 0x13) {
3189              tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3190           }
3191        }
3192
3193#ifdef CONFIG_FB_SIS_315
3194        if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
3195           if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
3196              if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
3197                 tempbx = 200;
3198                 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
3199              }
3200           }
3201        }
3202#endif
3203
3204     } else {                                                   /* TV */
3205
3206        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3207           /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
3208           tempbx = 2;
3209           if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3210              tempbx = 13;
3211              if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
3212           }
3213        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3214           if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      tempbx = 7;
3215           else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
3216           else                                         tempbx = 5;
3217           if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
3218        } else {
3219           if(SiS_Pr->SiS_TVMode & TVSetPAL)            tempbx = 3;
3220           else                                         tempbx = 4;
3221           if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
3222        }
3223
3224     }
3225
3226     tempal &= 0x3F;
3227
3228     if(ModeNo > 0x13) {
3229        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
3230           switch(resinfo) {
3231           case SIS_RI_720x480:
3232              tempal = 6;
3233              if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN))   tempal = 9;
3234              break;
3235           case SIS_RI_720x576:
3236           case SIS_RI_768x576:
3237           case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
3238              tempal = 6;
3239              if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3240                 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)        tempal = 8;
3241              }
3242              break;
3243           case SIS_RI_800x480:
3244              tempal = 4;
3245              break;
3246           case SIS_RI_512x384:
3247           case SIS_RI_1024x768:
3248              tempal = 7;
3249              if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3250                 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)        tempal = 8;
3251              }
3252              break;
3253           case SIS_RI_1280x720:
3254              if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3255                 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)        tempal = 9;
3256              }
3257              break;
3258           }
3259        }
3260     }
3261
3262     *CRT2Index = tempbx;
3263     *ResIndex = tempal;
3264
3265  } else {   /* LVDS, 301B-DH (if running on LCD) */
3266
3267     tempbx = 0;
3268     if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
3269
3270        tempbx = 90;
3271        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
3272           tempbx = 92;
3273           if(SiS_Pr->SiS_ModeType > ModeVGA) {
3274              if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
3275           }
3276           if(SiS_Pr->SiS_TVMode & TVSetPALM)      tempbx = 94;
3277           else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
3278        }
3279        if(tempbx != 99) {
3280           if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
3281        }
3282
3283     } else {
3284
3285        switch(SiS_Pr->SiS_LCDResInfo) {
3286        case Panel_640x480:   tempbx = 12; break;
3287        case Panel_320x240_1: tempbx = 10; break;
3288        case Panel_320x240_2:
3289        case Panel_320x240_3: tempbx = 14; break;
3290        case Panel_800x600:   tempbx = 16; break;
3291        case Panel_1024x600:  tempbx = 18; break;
3292        case Panel_1152x768:
3293        case Panel_1024x768:  tempbx = 20; break;
3294        case Panel_1280x768:  tempbx = 22; break;
3295        case Panel_1280x1024: tempbx = 24; break;
3296        case Panel_1400x1050: tempbx = 26; break;
3297        case Panel_1600x1200: tempbx = 28; break;
3298#ifdef CONFIG_FB_SIS_300
3299        case Panel_Barco1366: tempbx = 80; break;
3300#endif
3301        }
3302
3303        switch(SiS_Pr->SiS_LCDResInfo) {
3304        case Panel_320x240_1:
3305        case Panel_320x240_2:
3306        case Panel_320x240_3:
3307        case Panel_640x480:
3308           break;
3309        default:
3310           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3311        }
3312
3313        if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
3314
3315#ifdef CONFIG_FB_SIS_300
3316        if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3317           tempbx = 82;
3318           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3319        } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
3320           tempbx = 84;
3321           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3322        }
3323#endif
3324
3325     }
3326
3327     (*CRT2Index) = tempbx;
3328     (*ResIndex) = tempal & 0x1F;
3329  }
3330}
3331
3332static void
3333SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3334                unsigned short RefreshRateTableIndex)
3335{
3336  unsigned short tempax=0, tempbx=0, index, dotclock;
3337  unsigned short temp1=0, modeflag=0, tempcx=0;
3338
3339  SiS_Pr->SiS_RVBHCMAX  = 1;
3340  SiS_Pr->SiS_RVBHCFACT = 1;
3341
3342  if(ModeNo <= 0x13) {
3343
3344     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3345     index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
3346
3347     tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
3348     tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
3349     temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
3350
3351     dotclock = (modeflag & Charx8Dot) ? 8 : 9;
3352
3353  } else {
3354
3355     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3356     index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
3357
3358     tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
3359     tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
3360     tempax &= 0x03FF;
3361     tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
3362     tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
3363     tempcx &= 0x0100;
3364     tempcx <<= 2;
3365     tempbx |= tempcx;
3366     temp1  = SiS_Pr->SiS_CRT1Table[index].CR[7];
3367
3368     dotclock = 8;
3369
3370  }
3371
3372  if(temp1 & 0x01) tempbx |= 0x0100;
3373  if(temp1 & 0x20) tempbx |= 0x0200;
3374
3375  tempax += 5;
3376  tempax *= dotclock;
3377  if(modeflag & HalfDCLK) tempax <<= 1;
3378
3379  tempbx++;
3380
3381  SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3382  SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
3383}
3384
3385static void
3386SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3387                unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
3388{
3389   unsigned short ResIndex;
3390
3391   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3392      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3393         if(SiS_Pr->UseCustomMode) {
3394            ResIndex = SiS_Pr->CHTotal;
3395            if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
3396            SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
3397            SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3398         } else {
3399            if(ModeNo < 0x13) {
3400               ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3401            } else {
3402               ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3403            }
3404            if(ResIndex == 0x09) {
3405               if(SiS_Pr->Alternate1600x1200)        ResIndex = 0x20; /* 1600x1200 LCDA */
3406               else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
3407            }
3408            SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
3409            SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
3410            SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
3411            SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
3412         }
3413      } else {
3414         SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3415         SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3416      }
3417   } else {
3418      /* This handles custom modes and custom panels */
3419      SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3420      SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3421      SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
3422      SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
3423      SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
3424      SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
3425   }
3426}
3427
3428static void
3429SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3430                    unsigned short RefreshRateTableIndex)
3431{
3432   unsigned short CRT2Index, ResIndex, backup;
3433   const struct SiS_LVDSData *LVDSData = NULL;
3434
3435   SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3436
3437   if(SiS_Pr->SiS_VBType & VB_SISVB) {
3438      SiS_Pr->SiS_RVBHCMAX  = 1;
3439      SiS_Pr->SiS_RVBHCFACT = 1;
3440      SiS_Pr->SiS_NewFlickerMode = 0;
3441      SiS_Pr->SiS_RVBHRS = 50;
3442      SiS_Pr->SiS_RY1COE = 0;
3443      SiS_Pr->SiS_RY2COE = 0;
3444      SiS_Pr->SiS_RY3COE = 0;
3445      SiS_Pr->SiS_RY4COE = 0;
3446      SiS_Pr->SiS_RVBHRS2 = 0;
3447   }
3448
3449   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3450
3451#ifdef CONFIG_FB_SIS_315
3452      SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3453      SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
3454#endif
3455
3456   } else {
3457
3458      /* 301BDH needs LVDS Data */
3459      backup = SiS_Pr->SiS_IF_DEF_LVDS;
3460      if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3461         SiS_Pr->SiS_IF_DEF_LVDS = 1;
3462      }
3463
3464      SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
3465                                            &CRT2Index, &ResIndex);
3466
3467      SiS_Pr->SiS_IF_DEF_LVDS = backup;
3468
3469      switch(CRT2Index) {
3470         case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1;    break;
3471         case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2;    break;
3472         case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
3473         case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
3474         case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
3475         case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
3476#ifdef CONFIG_FB_SIS_300
3477         case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
3478         case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
3479         case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
3480         case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
3481         case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
3482#endif
3483         case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
3484         case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
3485         case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
3486         case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
3487         case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
3488         case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
3489         case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
3490         case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
3491         case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;        break;
3492      }
3493
3494      if(LVDSData) {
3495         SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
3496         SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
3497         SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
3498         SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
3499      } else {
3500         SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3501      }
3502
3503      if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
3504          (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
3505          (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
3506         if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
3507             (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
3508            SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3509            SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3510#ifdef CONFIG_FB_SIS_300
3511            if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3512               if(ResIndex < 0x08) {
3513                  SiS_Pr->SiS_HDE = 1280;
3514                  SiS_Pr->SiS_VDE = 1024;
3515               }
3516            }
3517#endif
3518         }
3519      }
3520   }
3521}
3522
3523static void
3524SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3525                unsigned short RefreshRateTableIndex)
3526{
3527  unsigned char  *ROMAddr = NULL;
3528  unsigned short tempax, tempbx, modeflag, romptr=0;
3529  unsigned short resinfo, CRT2Index, ResIndex;
3530  const struct SiS_LCDData *LCDPtr = NULL;
3531  const struct SiS_TVData  *TVPtr  = NULL;
3532#ifdef CONFIG_FB_SIS_315
3533  short resinfo661;
3534#endif
3535
3536  if(ModeNo <= 0x13) {
3537     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3538     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
3539  } else if(SiS_Pr->UseCustomMode) {
3540     modeflag = SiS_Pr->CModeFlag;
3541     resinfo = 0;
3542  } else {
3543     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3544     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
3545#ifdef CONFIG_FB_SIS_315
3546     resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3547     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
3548         (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
3549         (resinfo661 >= 0)                     &&
3550         (SiS_Pr->SiS_NeedRomModeData) ) {
3551        if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
3552           if((romptr = (SISGETROMW(21)))) {
3553              romptr += (resinfo661 * 10);
3554              ROMAddr = SiS_Pr->VirtualRomBase;
3555           }
3556        }
3557     }
3558#endif
3559  }
3560
3561  SiS_Pr->SiS_NewFlickerMode = 0;
3562  SiS_Pr->SiS_RVBHRS = 50;
3563  SiS_Pr->SiS_RY1COE = 0;
3564  SiS_Pr->SiS_RY2COE = 0;
3565  SiS_Pr->SiS_RY3COE = 0;
3566  SiS_Pr->SiS_RY4COE = 0;
3567  SiS_Pr->SiS_RVBHRS2 = 0;
3568
3569  SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
3570
3571  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
3572
3573     if(SiS_Pr->UseCustomMode) {
3574
3575        SiS_Pr->SiS_RVBHCMAX  = 1;
3576        SiS_Pr->SiS_RVBHCFACT = 1;
3577        SiS_Pr->SiS_HDE       = SiS_Pr->SiS_VGAHDE;
3578        SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
3579
3580        tempax = SiS_Pr->CHTotal;
3581        if(modeflag & HalfDCLK) tempax <<= 1;
3582        SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3583        SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3584
3585     } else {
3586
3587        SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3588
3589     }
3590
3591  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3592
3593     SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3594                    &CRT2Index,&ResIndex);
3595
3596     switch(CRT2Index) {
3597        case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
3598        case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
3599        case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
3600        case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
3601        case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
3602        case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
3603        case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
3604        case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
3605        case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
3606        case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
3607        case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
3608        case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
3609        case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
3610        default: TVPtr = SiS_Pr->SiS_StPALData;     break;
3611     }
3612
3613     SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
3614     SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
3615     SiS_Pr->SiS_VGAHT     = (TVPtr+ResIndex)->VGAHT;
3616     SiS_Pr->SiS_VGAVT     = (TVPtr+ResIndex)->VGAVT;
3617     SiS_Pr->SiS_HDE       = (TVPtr+ResIndex)->TVHDE;
3618     SiS_Pr->SiS_VDE       = (TVPtr+ResIndex)->TVVDE;
3619     SiS_Pr->SiS_RVBHRS2   = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
3620     if(modeflag & HalfDCLK) {
3621        SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
3622        if(SiS_Pr->SiS_RVBHRS2) {
3623           SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3624           tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
3625           if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
3626           else                                   SiS_Pr->SiS_RVBHRS2 += tempax;
3627        }
3628     } else {
3629        SiS_Pr->SiS_RVBHRS    = (TVPtr+ResIndex)->RVBHRS;
3630     }
3631     SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
3632
3633     if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3634
3635        if((resinfo == SIS_RI_960x600)   ||
3636           (resinfo == SIS_RI_1024x768)  ||
3637           (resinfo == SIS_RI_1280x1024) ||
3638           (resinfo == SIS_RI_1280x720)) {
3639           SiS_Pr->SiS_NewFlickerMode = 0x40;
3640        }
3641
3642        if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
3643
3644        SiS_Pr->SiS_HT = ExtHiTVHT;
3645        SiS_Pr->SiS_VT = ExtHiTVVT;
3646        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3647           if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
3648              SiS_Pr->SiS_HT = StHiTVHT;
3649              SiS_Pr->SiS_VT = StHiTVVT;
3650           }
3651        }
3652
3653     } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3654
3655        if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3656           SiS_Pr->SiS_HT = 1650;
3657           SiS_Pr->SiS_VT = 750;
3658        } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3659           SiS_Pr->SiS_HT = NTSCHT;
3660           if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
3661           SiS_Pr->SiS_VT = NTSCVT;
3662        } else {
3663           SiS_Pr->SiS_HT = NTSCHT;
3664           if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
3665           SiS_Pr->SiS_VT = NTSCVT;
3666        }
3667
3668     } else {
3669
3670        SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
3671        SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
3672        SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
3673        SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
3674
3675        if(modeflag & HalfDCLK) {
3676           SiS_Pr->SiS_RY1COE = 0x00;
3677           SiS_Pr->SiS_RY2COE = 0xf4;
3678           SiS_Pr->SiS_RY3COE = 0x10;
3679           SiS_Pr->SiS_RY4COE = 0x38;
3680        }
3681
3682        if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
3683           SiS_Pr->SiS_HT = NTSCHT;
3684           if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
3685           SiS_Pr->SiS_VT = NTSCVT;
3686        } else {
3687           SiS_Pr->SiS_HT = PALHT;
3688           SiS_Pr->SiS_VT = PALVT;
3689        }
3690
3691     }
3692
3693  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3694
3695     SiS_Pr->SiS_RVBHCMAX  = 1;
3696     SiS_Pr->SiS_RVBHCFACT = 1;
3697
3698     if(SiS_Pr->UseCustomMode) {
3699
3700        SiS_Pr->SiS_HDE   = SiS_Pr->SiS_VGAHDE;
3701        SiS_Pr->SiS_VDE   = SiS_Pr->SiS_VGAVDE;
3702
3703        tempax = SiS_Pr->CHTotal;
3704        if(modeflag & HalfDCLK) tempax <<= 1;
3705        SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3706        SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3707
3708     } else {
3709
3710        bool gotit = false;
3711
3712        if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
3713
3714           SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
3715           SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3716           SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
3717           SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
3718           gotit = true;
3719
3720        } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3721
3722#ifdef CONFIG_FB_SIS_315
3723           SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
3724           SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3725           SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
3726           SiS_Pr->SiS_VGAVT     = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
3727           SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
3728           SiS_Pr->SiS_VT        = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
3729           SiS_Pr->SiS_RVBHRS2   = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
3730           if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
3731              SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3732              tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
3733              if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
3734              else                         SiS_Pr->SiS_RVBHRS2 += tempax;
3735           }
3736           if(SiS_Pr->SiS_VGAHT) gotit = true;
3737           else {
3738              SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
3739              SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
3740              SiS_Pr->SiS_RVBHCMAX  = 1;
3741              SiS_Pr->SiS_RVBHCFACT = 1;
3742              SiS_Pr->SiS_VGAHT   = SiS_Pr->PanelHT;
3743              SiS_Pr->SiS_VGAVT   = SiS_Pr->PanelVT;
3744              SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
3745              SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
3746              SiS_Pr->SiS_RVBHRS2 = 0;
3747              gotit = true;
3748           }
3749#endif
3750
3751        }
3752
3753        if(!gotit) {
3754
3755           SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3756                          &CRT2Index,&ResIndex);
3757
3758           switch(CRT2Index) {
3759              case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
3760              case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
3761              case Panel_1280x720      :
3762              case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
3763              case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
3764              case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
3765              case Panel_1280x800      :
3766              case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
3767              case Panel_1280x800_2    :
3768              case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data;    break;
3769              case Panel_1280x854      :
3770              case Panel_1280x854  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data;      break;
3771              case Panel_1280x960      :
3772              case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
3773              case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
3774              case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
3775              case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
3776              case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
3777              case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
3778              case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
3779              case Panel_1680x1050     :
3780              case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
3781              case 100                 : LCDPtr = SiS_Pr->SiS_NoScaleData;          break;
3782#ifdef CONFIG_FB_SIS_315
3783              case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
3784              case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
3785#endif
3786              default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
3787           }
3788
3789           SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
3790           SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3791           SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
3792           SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
3793           SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
3794           SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
3795
3796        }
3797
3798        tempax = SiS_Pr->PanelXRes;
3799        tempbx = SiS_Pr->PanelYRes;
3800
3801        switch(SiS_Pr->SiS_LCDResInfo) {
3802        case Panel_1024x768:
3803           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3804              if(SiS_Pr->ChipType < SIS_315H) {
3805                 if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3806                 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3807              }
3808           } else {
3809              if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
3810              else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
3811              else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
3812              else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
3813              else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3814              else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3815           }
3816           break;
3817        case Panel_1280x960:
3818           if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
3819           else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
3820           else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
3821           break;
3822        case Panel_1280x1024:
3823           if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
3824           else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
3825           else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
3826           break;
3827        case Panel_1600x1200:
3828           if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
3829              if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
3830              else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
3831           }
3832           break;
3833        }
3834
3835        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3836           tempax = SiS_Pr->SiS_VGAHDE;
3837           tempbx = SiS_Pr->SiS_VGAVDE;
3838        }
3839
3840        SiS_Pr->SiS_HDE = tempax;
3841        SiS_Pr->SiS_VDE = tempbx;
3842     }
3843  }
3844}
3845
3846static void
3847SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3848                unsigned short RefreshRateTableIndex)
3849{
3850
3851   if(SiS_Pr->SiS_VBType & VB_SISVB) {
3852
3853      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3854         SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3855      } else {
3856         if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3857            /* Need LVDS Data for LCD on 301B-DH */
3858            SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3859         } else {
3860            SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3861         }
3862      }
3863
3864   } else {
3865
3866      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3867
3868   }
3869}
3870
3871/*********************************************/
3872/*         GET LVDS DES (SKEW) DATA          */
3873/*********************************************/
3874
3875static const struct SiS_LVDSDes *
3876SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
3877{
3878   const struct SiS_LVDSDes *PanelDesPtr = NULL;
3879
3880#ifdef CONFIG_FB_SIS_300
3881   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3882
3883      if(SiS_Pr->ChipType < SIS_315H) {
3884         if(SiS_Pr->SiS_LCDTypeInfo == 4) {
3885            if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3886               PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
3887               if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3888                  PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
3889               }
3890            } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3891               PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
3892               if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3893                  PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
3894               }
3895            }
3896         }
3897      }
3898   }
3899#endif
3900   return PanelDesPtr;
3901}
3902
3903static void
3904SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3905                   unsigned short RefreshRateTableIndex)
3906{
3907  unsigned short modeflag, ResIndex;
3908  const struct SiS_LVDSDes *PanelDesPtr = NULL;
3909
3910  SiS_Pr->SiS_LCDHDES = 0;
3911  SiS_Pr->SiS_LCDVDES = 0;
3912
3913  /* Some special cases */
3914  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3915
3916     /* Trumpion */
3917     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
3918        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3919           if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3920              SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3921           }
3922        }
3923        return;
3924     }
3925
3926     /* 640x480 on LVDS */
3927     if(SiS_Pr->ChipType < SIS_315H) {
3928        if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
3929           SiS_Pr->SiS_LCDHDES = 8;
3930           if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3931           else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3932           else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3933           return;
3934        }
3935     }
3936
3937  } /* LCD */
3938
3939  if( (SiS_Pr->UseCustomMode)                    ||
3940      (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
3941      (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
3942      (SiS_Pr->SiS_CustomT == CUT_PANEL856)      ||
3943      (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
3944     return;
3945  }
3946
3947  if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3948  else               ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3949
3950  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3951
3952#ifdef CONFIG_FB_SIS_315
3953     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3954        /* non-pass 1:1 only, see above */
3955        if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3956           SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3957        }
3958        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3959           SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3960        }
3961     }
3962     if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3963        switch(SiS_Pr->SiS_CustomT) {
3964        case CUT_UNIWILL1024:
3965        case CUT_UNIWILL10242:
3966        case CUT_CLEVO1400:
3967           if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3968              SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3969           }
3970           break;
3971        }
3972        switch(SiS_Pr->SiS_LCDResInfo) {
3973        case Panel_1280x1024:
3974           if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
3975              SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3976           }
3977           break;
3978        case Panel_1280x800:    /* Verified for Averatec 6240 */
3979        case Panel_1280x800_2:  /* Verified for Asus A4L */
3980        case Panel_1280x854:    /* Not verified yet FIXME */
3981           SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3982           break;
3983        }
3984     }
3985#endif
3986
3987  } else {
3988
3989     if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
3990
3991        if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
3992           if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
3993        }
3994
3995     } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
3996
3997        SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
3998        SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
3999
4000     } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
4001
4002        if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
4003           SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
4004        }
4005        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
4006           SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
4007        } else {
4008           if(SiS_Pr->ChipType < SIS_315H) {
4009              SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
4010           } else {
4011              switch(SiS_Pr->SiS_LCDResInfo) {
4012              case Panel_800x600:
4013              case Panel_1024x768:
4014              case Panel_1280x1024:
4015                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
4016                 break;
4017              case Panel_1400x1050:
4018                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
4019                 break;
4020              }
4021           }
4022        }
4023
4024     } else {
4025
4026        if(SiS_Pr->ChipType < SIS_315H) {
4027#ifdef CONFIG_FB_SIS_300
4028           switch(SiS_Pr->SiS_LCDResInfo) {
4029           case Panel_800x600:
4030              if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
4031                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
4032              } else {
4033                 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
4034                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
4035                 if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
4036                 else                          SiS_Pr->SiS_LCDVDES -= 4;
4037              }
4038              break;
4039           case Panel_1024x768:
4040              if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
4041                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
4042              } else {
4043                 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
4044                 if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
4045                 if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
4046              }
4047              break;
4048           case Panel_1024x600:
4049           default:
4050              if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
4051                  (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
4052                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
4053              } else {
4054                 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
4055              }
4056              break;
4057           }
4058
4059           switch(SiS_Pr->SiS_LCDTypeInfo) {
4060           case 1:
4061              SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
4062              break;
4063           case 3: /* 640x480 only? */
4064              SiS_Pr->SiS_LCDHDES = 8;
4065              if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
4066              else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
4067              else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
4068              break;
4069           }
4070#endif
4071        } else {
4072#ifdef CONFIG_FB_SIS_315
4073           switch(SiS_Pr->SiS_LCDResInfo) {
4074           case Panel_1024x768:
4075           case Panel_1280x1024:
4076              if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
4077                 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
4078              }
4079              break;
4080           case Panel_320x240_1:
4081           case Panel_320x240_2:
4082           case Panel_320x240_3:
4083              SiS_Pr->SiS_LCDVDES = 524;
4084              break;
4085           }
4086#endif
4087        }
4088     }
4089
4090     if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
4091        modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
4092        if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
4093           if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
4094        } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
4095           if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
4096              if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
4097                 if(SiS_Pr->ChipType < SIS_315H) {
4098                    if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
4099                 } else {
4100#ifdef CONFIG_FB_SIS_315
4101                    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
4102                    if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
4103                    if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
4104                    if(!(modeflag & HalfDCLK)) {
4105                       SiS_Pr->SiS_LCDHDES = 320;
4106                       if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
4107                       if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
4108                    }
4109#endif
4110                 }
4111              }
4112           }
4113        }
4114     }
4115  }
4116}
4117
4118/*********************************************/
4119/*           DISABLE VIDEO BRIDGE            */
4120/*********************************************/
4121
4122#ifdef CONFIG_FB_SIS_315
4123static int
4124SiS_HandlePWD(struct SiS_Private *SiS_Pr)
4125{
4126   int ret = 0;
4127#ifdef SET_PWD
4128   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
4129   unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
4130   unsigned char  drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
4131   unsigned short temp;
4132
4133   if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
4134       (romptr)                         &&
4135       (SiS_Pr->SiS_PWDOffset) ) {
4136      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
4137      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
4138      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
4139      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
4140      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
4141      temp = 0x00;
4142      if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
4143         temp = 0x80;
4144         ret = 1;
4145      }
4146      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
4147   }
4148#endif
4149   return ret;
4150}
4151#endif
4152
4153/* NEVER use any variables (VBInfo), this will be called
4154 * from outside the context of modeswitch!
4155 * MUST call getVBType before calling this
4156 */
4157void
4158SiS_DisableBridge(struct SiS_Private *SiS_Pr)
4159{
4160#ifdef CONFIG_FB_SIS_315
4161  unsigned short tempah, pushax=0, modenum;
4162#endif
4163  unsigned short temp=0;
4164
4165  if(SiS_Pr->SiS_VBType & VB_SISVB) {
4166
4167     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {            /* ===== For 30xB/C/LV ===== */
4168
4169        if(SiS_Pr->ChipType < SIS_315H) {
4170
4171#ifdef CONFIG_FB_SIS_300           /* 300 series */
4172
4173           if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4174              if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4175                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
4176              } else {
4177                 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4178              }
4179              SiS_PanelDelay(SiS_Pr, 3);
4180           }
4181           if(SiS_Is301B(SiS_Pr)) {
4182              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
4183              SiS_ShortDelay(SiS_Pr,1);
4184           }
4185           SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
4186           SiS_DisplayOff(SiS_Pr);
4187           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4188           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4189           SiS_UnLockCRT2(SiS_Pr);
4190           if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
4191              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4192              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4193           }
4194           if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4195               (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4196              SiS_PanelDelay(SiS_Pr, 2);
4197              if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4198                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
4199              } else {
4200                 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
4201              }
4202           }
4203
4204#endif  /* CONFIG_FB_SIS_300 */
4205
4206        } else {
4207
4208#ifdef CONFIG_FB_SIS_315           /* 315 series */
4209
4210           int didpwd = 0;
4211           bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
4212                          (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
4213
4214           modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
4215
4216           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4217
4218#ifdef SET_EMI
4219              if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4220                 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4221                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4222                 }
4223              }
4224#endif
4225
4226              didpwd = SiS_HandlePWD(SiS_Pr);
4227
4228              if( (modenum <= 0x13)           ||
4229                  (SiS_IsVAMode(SiS_Pr))      ||
4230                  (!(SiS_IsDualEdge(SiS_Pr))) ) {
4231                 if(!didpwd) {
4232                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
4233                    if(custom1) SiS_PanelDelay(SiS_Pr, 3);
4234                 } else {
4235                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
4236                 }
4237              }
4238
4239              if(!custom1) {
4240                 SiS_DDC2Delay(SiS_Pr,0xff00);
4241                 SiS_DDC2Delay(SiS_Pr,0xe000);
4242                 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4243                 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4244                 if(IS_SIS740) {
4245                    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4246                 }
4247                 SiS_PanelDelay(SiS_Pr, 3);
4248              }
4249
4250           }
4251
4252           if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4253              /* if(SiS_Pr->ChipType < SIS_340) {*/
4254                 tempah = 0xef;
4255                 if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
4256                 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
4257              /*}*/
4258           }
4259
4260           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4261              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
4262           }
4263
4264           tempah = 0x3f;
4265           if(SiS_IsDualEdge(SiS_Pr)) {
4266              tempah = 0x7f;
4267              if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
4268           }
4269           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
4270
4271           if((SiS_IsVAMode(SiS_Pr)) ||
4272              ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
4273
4274              SiS_DisplayOff(SiS_Pr);
4275              if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4276                 SiS_PanelDelay(SiS_Pr, 2);
4277              }
4278              SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4279              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
4280
4281           }
4282
4283           if((!(SiS_IsVAMode(SiS_Pr))) ||
4284              ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
4285
4286              if(!(SiS_IsDualEdge(SiS_Pr))) {
4287                 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
4288                 SiS_DisplayOff(SiS_Pr);
4289              }
4290              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4291
4292              if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4293                 SiS_PanelDelay(SiS_Pr, 2);
4294              }
4295
4296              SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4297              temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4298              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
4299              SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4300              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4301
4302           }
4303
4304           if(SiS_IsNotM650orLater(SiS_Pr)) {
4305              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4306           }
4307
4308           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4309
4310              if( (!(SiS_IsVAMode(SiS_Pr)))  &&
4311                  (!(SiS_CRT2IsLCD(SiS_Pr))) &&
4312                  (!(SiS_IsDualEdge(SiS_Pr))) ) {
4313
4314                 if(custom1) SiS_PanelDelay(SiS_Pr, 2);
4315                 if(!didpwd) {
4316                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
4317                 }
4318                 if(custom1) SiS_PanelDelay(SiS_Pr, 4);
4319              }
4320
4321              if(!custom1) {
4322                 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4323                 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4324                    if(SiS_IsVAorLCD(SiS_Pr)) {
4325                       SiS_PanelDelayLoop(SiS_Pr, 3, 20);
4326                    }
4327                 }
4328              }
4329
4330           }
4331
4332#endif /* CONFIG_FB_SIS_315 */
4333
4334        }
4335
4336     } else {     /* ============ For 301 ================ */
4337
4338        if(SiS_Pr->ChipType < SIS_315H) {
4339#ifdef CONFIG_FB_SIS_300
4340           if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4341              SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4342              SiS_PanelDelay(SiS_Pr, 3);
4343           }
4344#endif
4345        }
4346
4347        SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
4348        SiS_DisplayOff(SiS_Pr);
4349
4350        if(SiS_Pr->ChipType >= SIS_315H) {
4351           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4352        }
4353
4354        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);                /* disable lock mode */
4355
4356        if(SiS_Pr->ChipType >= SIS_315H) {
4357            temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4358            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
4359            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4360            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4361        } else {
4362#ifdef CONFIG_FB_SIS_300
4363            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
4364            if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4365                (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4366                SiS_PanelDelay(SiS_Pr, 2);
4367                SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
4368            }
4369#endif
4370        }
4371
4372      }
4373
4374  } else {     /* ============ For LVDS =============*/
4375
4376    if(SiS_Pr->ChipType < SIS_315H) {
4377
4378#ifdef CONFIG_FB_SIS_300        /* 300 series */
4379
4380        if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
4381           SiS_SetCH700x(SiS_Pr,0x0E,0x09);
4382        }
4383
4384        if(SiS_Pr->ChipType == SIS_730) {
4385           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4386              SiS_WaitVBRetrace(SiS_Pr);
4387           }
4388           if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4389              SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4390              SiS_PanelDelay(SiS_Pr, 3);
4391           }
4392        } else {
4393           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4394              if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4395                 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4396                    SiS_WaitVBRetrace(SiS_Pr);
4397                    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
4398                       SiS_DisplayOff(SiS_Pr);
4399                    }
4400                    SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4401                    SiS_PanelDelay(SiS_Pr, 3);
4402                 }
4403              }
4404           }
4405        }
4406
4407        SiS_DisplayOff(SiS_Pr);
4408
4409        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4410
4411        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4412        SiS_UnLockCRT2(SiS_Pr);
4413        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4414        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4415
4416        if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4417            (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4418           SiS_PanelDelay(SiS_Pr, 2);
4419           SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
4420        }
4421
4422#endif  /* CONFIG_FB_SIS_300 */
4423
4424    } else {
4425
4426#ifdef CONFIG_FB_SIS_315        /* 315 series */
4427
4428        if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4429           /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
4430              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
4431           /* } */
4432        }
4433
4434        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4435
4436           if(SiS_Pr->ChipType == SIS_740) {
4437              temp = SiS_GetCH701x(SiS_Pr,0x61);
4438              if(temp < 1) {
4439                 SiS_SetCH701x(SiS_Pr,0x76,0xac);
4440                 SiS_SetCH701x(SiS_Pr,0x66,0x00);
4441              }
4442
4443              if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4444                  (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4445                 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
4446              }
4447           }
4448
4449           if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4450               (SiS_IsVAMode(SiS_Pr)) ) {
4451              SiS_Chrontel701xBLOff(SiS_Pr);
4452              SiS_Chrontel701xOff(SiS_Pr);
4453           }
4454
4455           if(SiS_Pr->ChipType != SIS_740) {
4456              if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4457                  (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4458                 SiS_SetCH701x(SiS_Pr,0x49,0x01);
4459              }
4460           }
4461
4462        }
4463
4464        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4465           SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4466           SiS_PanelDelay(SiS_Pr, 3);
4467        }
4468
4469        if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4470            (!(SiS_IsDualEdge(SiS_Pr))) ||
4471            (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
4472           SiS_DisplayOff(SiS_Pr);
4473        }
4474
4475        if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4476            (!(SiS_IsDualEdge(SiS_Pr))) ||
4477            (!(SiS_IsVAMode(SiS_Pr))) ) {
4478           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4479        }
4480
4481        if(SiS_Pr->ChipType == SIS_740) {
4482           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4483        }
4484
4485        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4486
4487        if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4488            (!(SiS_IsDualEdge(SiS_Pr))) ||
4489            (!(SiS_IsVAMode(SiS_Pr))) ) {
4490           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4491        }
4492
4493        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4494           if(SiS_CRT2IsLCD(SiS_Pr)) {
4495              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4496              if(SiS_Pr->ChipType == SIS_550) {
4497                 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
4498                 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
4499              }
4500           }
4501        } else {
4502           if(SiS_Pr->ChipType == SIS_740) {
4503              if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4504                 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4505              }
4506           } else if(SiS_IsVAMode(SiS_Pr)) {
4507              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4508           }
4509        }
4510
4511        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4512           if(SiS_IsDualEdge(SiS_Pr)) {
4513              /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
4514           } else {
4515              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
4516           }
4517        }
4518
4519        SiS_UnLockCRT2(SiS_Pr);
4520
4521        if(SiS_Pr->ChipType == SIS_550) {
4522           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
4523           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
4524        } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4525                   (!(SiS_IsDualEdge(SiS_Pr))) ||
4526                   (!(SiS_IsVAMode(SiS_Pr))) ) {
4527           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4528        }
4529
4530        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4531           if(SiS_CRT2IsLCD(SiS_Pr)) {
4532              if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4533                 SiS_PanelDelay(SiS_Pr, 2);
4534                 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
4535              }
4536           }
4537        }
4538
4539#endif  /* CONFIG_FB_SIS_315 */
4540
4541    }  /* 315 series */
4542
4543  }  /* LVDS */
4544
4545}
4546
4547/*********************************************/
4548/*            ENABLE VIDEO BRIDGE            */
4549/*********************************************/
4550
4551/* NEVER use any variables (VBInfo), this will be called
4552 * from outside the context of a mode switch!
4553 * MUST call getVBType before calling this
4554 */
4555static
4556void
4557SiS_EnableBridge(struct SiS_Private *SiS_Pr)
4558{
4559  unsigned short temp=0, tempah;
4560#ifdef CONFIG_FB_SIS_315
4561  unsigned short temp1, pushax=0;
4562  bool delaylong = false;
4563#endif
4564
4565  if(SiS_Pr->SiS_VBType & VB_SISVB) {
4566
4567    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {             /* ====== For 301B et al  ====== */
4568
4569      if(SiS_Pr->ChipType < SIS_315H) {
4570
4571#ifdef CONFIG_FB_SIS_300     /* 300 series */
4572
4573         if(SiS_CRT2IsLCD(SiS_Pr)) {
4574            if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4575               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4576            } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4577               SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4578            }
4579            if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
4580               if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4581                  SiS_PanelDelay(SiS_Pr, 0);
4582               }
4583            }
4584         }
4585
4586         if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
4587            (SiS_CRT2IsLCD(SiS_Pr))) {
4588
4589            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* Enable CRT2 */
4590            SiS_DisplayOn(SiS_Pr);
4591            SiS_UnLockCRT2(SiS_Pr);
4592            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4593            if(SiS_BridgeInSlavemode(SiS_Pr)) {
4594               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4595            } else {
4596               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4597            }
4598            if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4599               if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4600                  if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4601                     SiS_PanelDelay(SiS_Pr, 1);
4602                  }
4603                  SiS_WaitVBRetrace(SiS_Pr);
4604                  SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4605               }
4606            }
4607
4608         } else {
4609
4610            temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
4611            if(SiS_BridgeInSlavemode(SiS_Pr)) {
4612               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4613               if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4614            }
4615            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4616            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4617            SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
4618            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
4619            SiS_DisplayOn(SiS_Pr);
4620            if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4621               if(SiS_CRT2IsLCD(SiS_Pr)) {
4622                  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4623                     if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4624                        SiS_PanelDelay(SiS_Pr, 1);
4625                     }
4626                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4627                  }
4628               }
4629            }
4630
4631         }
4632
4633
4634#endif /* CONFIG_FB_SIS_300 */
4635
4636      } else {
4637
4638#ifdef CONFIG_FB_SIS_315    /* 315 series */
4639
4640#ifdef SET_EMI
4641         unsigned char   r30=0, r31=0, r32=0, r33=0, cr36=0;
4642         int didpwd = 0;
4643         /* unsigned short  emidelay=0; */
4644#endif
4645
4646         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4647            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
4648#ifdef SET_EMI
4649            if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4650               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4651            }
4652#endif
4653         }
4654
4655         if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4656            /*if(SiS_Pr->ChipType < SIS_340) { */
4657               tempah = 0x10;
4658               if(SiS_LCDAEnabled(SiS_Pr)) {
4659                  if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
4660                  else                      tempah = 0x08;
4661               }
4662               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
4663            /*}*/
4664         }
4665
4666         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4667
4668            SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4669            SiS_DisplayOff(SiS_Pr);
4670            pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4671            if(IS_SIS740) {
4672               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4673            }
4674
4675            didpwd = SiS_HandlePWD(SiS_Pr);
4676
4677            if(SiS_IsVAorLCD(SiS_Pr)) {
4678               if(!didpwd) {
4679                  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
4680                     SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4681                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4682                     SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4683                     if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4684                        SiS_GenericDelay(SiS_Pr, 17664);
4685                     }
4686                  }
4687               } else {
4688                  SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4689                  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4690                     SiS_GenericDelay(SiS_Pr, 17664);
4691                  }
4692               }
4693            }
4694
4695            if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
4696               SiS_PanelDelayLoop(SiS_Pr, 3, 10);
4697               delaylong = true;
4698            }
4699
4700         }
4701
4702         if(!(SiS_IsVAMode(SiS_Pr))) {
4703
4704            temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
4705            if(SiS_BridgeInSlavemode(SiS_Pr)) {
4706               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4707               if(!(tempah & SetCRT2ToRAMDAC)) {
4708                  if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
4709               }
4710            }
4711            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4712
4713            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
4714
4715            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4716            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4717
4718            if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4719               SiS_PanelDelay(SiS_Pr, 2);
4720            }
4721
4722         } else {
4723
4724            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
4725
4726         }
4727
4728         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
4729         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4730
4731         if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
4732            if( (SiS_LCDAEnabled(SiS_Pr)) ||
4733                (SiS_CRT2IsLCD(SiS_Pr)) ) {
4734               /* Enable "LVDS PLL power on" (even on 301C) */
4735               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
4736               /* Enable "LVDS Driver Power on" (even on 301C) */
4737               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
4738            }
4739         }
4740
4741         tempah = 0xc0;
4742         if(SiS_IsDualEdge(SiS_Pr)) {
4743            tempah = 0x80;
4744            if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
4745         }
4746         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
4747
4748         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4749
4750            SiS_PanelDelay(SiS_Pr, 2);
4751
4752            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
4753            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4754
4755            if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4756#ifdef SET_EMI
4757               if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4758                  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4759                  SiS_GenericDelay(SiS_Pr, 2048);
4760               }
4761#endif
4762               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
4763
4764               if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4765#ifdef SET_EMI
4766                  cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
4767
4768                  if(SiS_Pr->SiS_ROMNew) {
4769                     unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
4770                     unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
4771                     if(romptr) {
4772                        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
4773                        SiS_Pr->EMI_30 = 0;
4774                        SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
4775                        SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
4776                        SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
4777                        if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
4778                        /* emidelay = SISGETROMW((romptr + 0x22)); */
4779                        SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
4780                     }
4781                  }
4782
4783                  /*                                              (P4_30|0x40)  */
4784                  /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
4785                  /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
4786                  /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
4787                  /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
4788                  /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
4789                  /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
4790                  /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
4791                  /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
4792                  /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
4793
4794                  if(SiS_Pr->HaveEMI) {
4795                     r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
4796                     r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
4797                  } else {
4798                     r30 = 0;
4799                  }
4800
4801                  /* EMI_30 is read at driver start; however, the BIOS sets this
4802                   * (if it is used) only if the LCD is in use. In case we caught
4803                   * the machine while on TV output, this bit is not set and we
4804                   * don't know if it should be set - hence our detection is wrong.
4805                   * Work-around this here:
4806                   */
4807
4808                  if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
4809                     switch((cr36 & 0x0f)) {
4810                     case 2:
4811                        r30 |= 0x40;
4812                        if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
4813                        if(!SiS_Pr->HaveEMI) {
4814                           r31 = 0x05; r32 = 0x60; r33 = 0x33;
4815                           if((cr36 & 0xf0) == 0x30) {
4816                              r31 = 0x0d; r32 = 0x70; r33 = 0x40;
4817                           }
4818                        }
4819                        break;
4820                     case 3:  /* 1280x1024 */
4821                        if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
4822                        if(!SiS_Pr->HaveEMI) {
4823                           r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4824                           if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4825                              r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
4826                           }
4827                        }
4828                        break;
4829                     case 9:  /* 1400x1050 */
4830                        r30 |= 0x40;
4831                        if(!SiS_Pr->HaveEMI) {
4832                           r31 = 0x05; r32 = 0x60; r33 = 0x00;
4833                           if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4834                              r31 = 0x0d; r32 = 0x70; r33 = 0x40;  /* BIOS values */
4835                           }
4836                        }
4837                        break;
4838                     case 11: /* 1600x1200 - unknown */
4839                        r30 |= 0x40;
4840                        if(!SiS_Pr->HaveEMI) {
4841                           r31 = 0x05; r32 = 0x60; r33 = 0x00;
4842                        }
4843                     }
4844                  }
4845
4846                  /* BIOS values don't work so well sometimes */
4847                  if(!SiS_Pr->OverruleEMI) {
4848#ifdef COMPAL_HACK
4849                     if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4850                        if((cr36 & 0x0f) == 0x09) {
4851                           r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
4852                        }
4853                     }
4854#endif
4855#ifdef COMPAQ_HACK
4856                     if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4857                        if((cr36 & 0x0f) == 0x03) {
4858                           r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4859                        }
4860                     }
4861#endif
4862#ifdef ASUS_HACK
4863                     if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
4864                        if((cr36 & 0x0f) == 0x02) {
4865                           /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
4866                           /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
4867                           /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
4868                           /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
4869                        }
4870                     }
4871#endif
4872                  }
4873
4874                  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
4875                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
4876                     SiS_GenericDelay(SiS_Pr, 2048);
4877                  }
4878                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
4879                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
4880                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
4881#endif  /* SET_EMI */
4882
4883                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
4884
4885#ifdef SET_EMI
4886                  if( (SiS_LCDAEnabled(SiS_Pr)) ||
4887                      (SiS_CRT2IsLCD(SiS_Pr)) ) {
4888                     if(r30 & 0x40) {
4889                        /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
4890                        SiS_PanelDelayLoop(SiS_Pr, 3, 5);
4891                        if(delaylong) {
4892                           SiS_PanelDelayLoop(SiS_Pr, 3, 5);
4893                           delaylong = false;
4894                        }
4895                        SiS_WaitVBRetrace(SiS_Pr);
4896                        SiS_WaitVBRetrace(SiS_Pr);
4897                        if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
4898                           SiS_GenericDelay(SiS_Pr, 1280);
4899                        }
4900                        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   /* Enable */
4901                        /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
4902                     }
4903                  }
4904#endif
4905               }
4906            }
4907
4908            if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4909               if(SiS_IsVAorLCD(SiS_Pr)) {
4910                  SiS_PanelDelayLoop(SiS_Pr, 3, 10);
4911                  if(delaylong) {
4912                     SiS_PanelDelayLoop(SiS_Pr, 3, 10);
4913                  }
4914                  SiS_WaitVBRetrace(SiS_Pr);
4915                  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4916                     SiS_GenericDelay(SiS_Pr, 2048);
4917                     SiS_WaitVBRetrace(SiS_Pr);
4918                  }
4919                  if(!didpwd) {
4920                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4921                  } else {
4922                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
4923                  }
4924               }
4925            }
4926
4927            SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4928            SiS_DisplayOn(SiS_Pr);
4929            SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
4930
4931         }
4932
4933         if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4934            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4935         }
4936
4937#endif /* CONFIG_FB_SIS_315 */
4938
4939      }
4940
4941    } else {    /* ============  For 301 ================ */
4942
4943       if(SiS_Pr->ChipType < SIS_315H) {
4944          if(SiS_CRT2IsLCD(SiS_Pr)) {
4945             SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4946             SiS_PanelDelay(SiS_Pr, 0);
4947          }
4948       }
4949
4950       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
4951       if(SiS_BridgeInSlavemode(SiS_Pr)) {
4952          tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4953          if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4954       }
4955       SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4956
4957       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                  /* enable CRT2 */
4958
4959       if(SiS_Pr->ChipType >= SIS_315H) {
4960          temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4961          if(!(temp & 0x80)) {
4962             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);         /* BVBDOENABLE=1 */
4963          }
4964       }
4965
4966       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);     /* enable VB processor */
4967
4968       SiS_VBLongWait(SiS_Pr);
4969       SiS_DisplayOn(SiS_Pr);
4970       if(SiS_Pr->ChipType >= SIS_315H) {
4971          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4972       }
4973       SiS_VBLongWait(SiS_Pr);
4974
4975       if(SiS_Pr->ChipType < SIS_315H) {
4976          if(SiS_CRT2IsLCD(SiS_Pr)) {
4977             SiS_PanelDelay(SiS_Pr, 1);
4978             SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4979          }
4980       }
4981
4982    }
4983
4984  } else {   /* =================== For LVDS ================== */
4985
4986    if(SiS_Pr->ChipType < SIS_315H) {
4987
4988#ifdef CONFIG_FB_SIS_300    /* 300 series */
4989
4990       if(SiS_CRT2IsLCD(SiS_Pr)) {
4991          if(SiS_Pr->ChipType == SIS_730) {
4992             SiS_PanelDelay(SiS_Pr, 1);
4993             SiS_PanelDelay(SiS_Pr, 1);
4994             SiS_PanelDelay(SiS_Pr, 1);
4995          }
4996          SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4997          if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4998             SiS_PanelDelay(SiS_Pr, 0);
4999          }
5000       }
5001
5002       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
5003       SiS_DisplayOn(SiS_Pr);
5004       SiS_UnLockCRT2(SiS_Pr);
5005       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
5006       if(SiS_BridgeInSlavemode(SiS_Pr)) {
5007          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
5008       } else {
5009          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
5010       }
5011
5012       if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
5013          if(!(SiS_CRT2IsLCD(SiS_Pr))) {
5014             SiS_WaitVBRetrace(SiS_Pr);
5015             SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
5016          }
5017       }
5018
5019       if(SiS_CRT2IsLCD(SiS_Pr)) {
5020          if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
5021             if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
5022                if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
5023                   SiS_PanelDelay(SiS_Pr, 1);
5024                   SiS_PanelDelay(SiS_Pr, 1);
5025                }
5026                SiS_WaitVBRetrace(SiS_Pr);
5027                SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
5028             }
5029          }
5030       }
5031
5032#endif  /* CONFIG_FB_SIS_300 */
5033
5034    } else {
5035
5036#ifdef CONFIG_FB_SIS_315    /* 315 series */
5037
5038       if(!(SiS_IsNotM650orLater(SiS_Pr))) {
5039          /*if(SiS_Pr->ChipType < SIS_340) {*/  /* XGI needs this */
5040             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
5041          /*}*/
5042       }
5043
5044       if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
5045          if(SiS_CRT2IsLCD(SiS_Pr)) {
5046             SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
5047             SiS_PanelDelay(SiS_Pr, 0);
5048          }
5049       }
5050
5051       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
5052       SiS_UnLockCRT2(SiS_Pr);
5053
5054       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
5055
5056       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
5057          temp = SiS_GetCH701x(SiS_Pr,0x66);
5058          temp &= 0x20;
5059          SiS_Chrontel701xBLOff(SiS_Pr);
5060       }
5061
5062       if(SiS_Pr->ChipType != SIS_550) {
5063          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
5064       }
5065
5066       if(SiS_Pr->ChipType == SIS_740) {
5067          if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
5068             if(SiS_IsLCDOrLCDA(SiS_Pr)) {
5069                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
5070             }
5071          }
5072       }
5073
5074       temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
5075       if(!(temp1 & 0x80)) {
5076          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
5077       }
5078
5079       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
5080          if(temp) {
5081             SiS_Chrontel701xBLOn(SiS_Pr);
5082          }
5083       }
5084
5085       if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
5086          if(SiS_CRT2IsLCD(SiS_Pr)) {
5087             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
5088             if(SiS_Pr->ChipType == SIS_550) {
5089                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
5090                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
5091             }
5092          }
5093       } else if(SiS_IsVAMode(SiS_Pr)) {
5094          if(SiS_Pr->ChipType != SIS_740) {
5095             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
5096          }
5097       }
5098
5099       if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
5100          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
5101       }
5102
5103       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
5104          if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
5105             SiS_Chrontel701xOn(SiS_Pr);
5106          }
5107          if( (SiS_IsVAMode(SiS_Pr)) ||
5108              (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
5109             SiS_ChrontelDoSomething1(SiS_Pr);
5110          }
5111       }
5112
5113       if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
5114          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
5115             if( (SiS_IsVAMode(SiS_Pr)) ||
5116                 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
5117                SiS_Chrontel701xBLOn(SiS_Pr);
5118                SiS_ChrontelInitTVVSync(SiS_Pr);
5119             }
5120          }
5121       } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
5122          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
5123             if(SiS_CRT2IsLCD(SiS_Pr)) {
5124                SiS_PanelDelay(SiS_Pr, 1);
5125                SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
5126             }
5127          }
5128       }
5129
5130#endif  /* CONFIG_FB_SIS_315 */
5131
5132    } /* 310 series */
5133
5134  }  /* LVDS */
5135
5136}
5137
5138/*********************************************/
5139/*         SET PART 1 REGISTER GROUP         */
5140/*********************************************/
5141
5142/* Set CRT2 OFFSET / PITCH */
5143static void
5144SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5145                unsigned short RRTI)
5146{
5147   unsigned short offset;
5148   unsigned char  temp;
5149
5150   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
5151
5152   offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
5153
5154   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
5155   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
5156
5157   temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
5158   if(offset & 0x07) temp++;
5159   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
5160}
5161
5162/* Set CRT2 sync and PanelLink mode */
5163static void
5164SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
5165{
5166   unsigned short tempah=0, tempbl, infoflag;
5167
5168   tempbl = 0xC0;
5169
5170   if(SiS_Pr->UseCustomMode) {
5171      infoflag = SiS_Pr->CInfoFlag;
5172   } else {
5173      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
5174   }
5175
5176   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {                                   /* LVDS */
5177
5178      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5179         tempah = 0;
5180      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
5181         tempah = SiS_Pr->SiS_LCDInfo;
5182      } else tempah = infoflag >> 8;
5183      tempah &= 0xC0;
5184      tempah |= 0x20;
5185      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5186      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5187         if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
5188            (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5189            tempah |= 0xf0;
5190         }
5191         if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
5192             (SiS_Pr->SiS_IF_DEF_DSTN) ||
5193             (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
5194             (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
5195             (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
5196            tempah |= 0x30;
5197         }
5198         if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
5199             (SiS_Pr->SiS_IF_DEF_DSTN) ) {
5200            tempah &= ~0xc0;
5201         }
5202      }
5203      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5204         if(SiS_Pr->ChipType >= SIS_315H) {
5205            tempah >>= 3;
5206            tempah &= 0x18;
5207            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
5208            /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
5209         } else {
5210            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
5211         }
5212      } else {
5213         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
5214      }
5215
5216   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5217
5218      if(SiS_Pr->ChipType < SIS_315H) {
5219
5220#ifdef CONFIG_FB_SIS_300  /* ---- 300 series --- */
5221
5222         if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {                        /* 630 - 301B(-DH) */
5223
5224            tempah = infoflag >> 8;
5225            tempbl = 0;
5226            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5227               if(SiS_Pr->SiS_LCDInfo & LCDSync) {
5228                  tempah = SiS_Pr->SiS_LCDInfo;
5229                  tempbl = (tempah >> 6) & 0x03;
5230               }
5231            }
5232            tempah &= 0xC0;
5233            tempah |= 0x20;
5234            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5235            tempah |= 0xc0;
5236            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
5237            if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
5238               SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
5239            }
5240
5241         } else {                                                       /* 630 - 301 */
5242
5243            tempah = ((infoflag >> 8) & 0xc0) | 0x20;
5244            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5245            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
5246
5247         }
5248
5249#endif /* CONFIG_FB_SIS_300 */
5250
5251      } else {
5252
5253#ifdef CONFIG_FB_SIS_315  /* ------- 315 series ------ */
5254
5255         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {                  /* 315 - LVDS */
5256
5257            tempbl = 0;
5258            if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
5259               (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5260               tempah = infoflag >> 8;
5261               if(SiS_Pr->SiS_LCDInfo & LCDSync) {
5262                 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
5263               }
5264            } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
5265                      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
5266               tempah = infoflag >> 8;
5267               tempbl = 0x03;
5268            } else {
5269               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
5270               tempbl = (tempah >> 6) & 0x03;
5271               tempbl |= 0x08;
5272               if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
5273            }
5274            tempah &= 0xC0;
5275            tempah |= 0x20;
5276            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5277            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
5278            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
5279            if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
5280               if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5281                  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
5282               }
5283            }
5284
5285         } else {                                                       /* 315 - TMDS */
5286
5287            tempah = tempbl = infoflag >> 8;
5288            if(!SiS_Pr->UseCustomMode) {
5289               tempbl = 0;
5290               if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
5291                  if(ModeNo <= 0x13) {
5292                     tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
5293                  }
5294               }
5295               if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5296                  if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5297                    if(SiS_Pr->SiS_LCDInfo & LCDSync) {
5298                       tempah = SiS_Pr->SiS_LCDInfo;
5299                       tempbl = (tempah >> 6) & 0x03;
5300                    }
5301                  }
5302               }
5303            }
5304            tempah &= 0xC0;
5305            tempah |= 0x20;
5306            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5307            if(SiS_Pr->SiS_VBType & VB_NoLCD) {
5308               /* Imitate BIOS bug */
5309               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
5310            }
5311            if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
5312               tempah >>= 3;
5313               tempah &= 0x18;
5314               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
5315            } else {
5316               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
5317               if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
5318                  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5319                     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
5320                  }
5321               }
5322            }
5323
5324         }
5325#endif  /* CONFIG_FB_SIS_315 */
5326      }
5327   }
5328}
5329
5330/* Set CRT2 FIFO on 300/540/630/730 */
5331#ifdef CONFIG_FB_SIS_300
5332static void
5333SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
5334{
5335  unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
5336  unsigned short temp, index, modeidindex, refreshratetableindex;
5337  unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
5338  unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
5339  unsigned int   data, pci50, pciA0;
5340  static const unsigned char colortharray[] = {
5341        1, 1, 2, 2, 3, 4
5342  };
5343
5344  SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
5345
5346  if(!SiS_Pr->CRT1UsesCustomMode) {
5347
5348     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 /* get CRT1 ModeNo */
5349     SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
5350     SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
5351     SiS_Pr->SiS_SelectCRT2Rate = 0;
5352     refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
5353
5354     if(CRT1ModeNo >= 0x13) {
5355        /* Get VCLK */
5356        index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
5357        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
5358
5359        /* Get colordepth */
5360        colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
5361        if(!colorth) colorth++;
5362     }
5363
5364  } else {
5365
5366     CRT1ModeNo = 0xfe;
5367
5368     /* Get VCLK */
5369     VCLK = SiS_Pr->CSRClock_CRT1;
5370
5371     /* Get color depth */
5372     colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
5373
5374  }
5375
5376  if(CRT1ModeNo >= 0x13) {
5377     /* Get MCLK */
5378     if(SiS_Pr->ChipType == SIS_300) {
5379        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
5380     } else {
5381        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
5382     }
5383     index &= 0x07;
5384     MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
5385
5386     temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
5387     if(!temp) temp++;
5388     temp <<= 2;
5389
5390     data2 = temp - ((colorth * VCLK) / MCLK);
5391
5392     temp = (28 * 16) % data2;
5393     data2 = (28 * 16) / data2;
5394     if(temp) data2++;
5395
5396     if(SiS_Pr->ChipType == SIS_300) {
5397
5398        SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
5399        data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
5400
5401     } else {
5402
5403        pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
5404        pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
5405
5406        if(SiS_Pr->ChipType == SIS_730) {
5407
5408           index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
5409           index += (unsigned short)(((pci50 >> 9)) & 0x03);
5410
5411           /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
5412           index = 0;  /* -- do it like the BIOS anyway... */
5413
5414        } else {
5415
5416           pci50 >>= 24;
5417           pciA0 >>= 24;
5418
5419           index = (pci50 >> 1) & 0x07;
5420
5421           if(pci50 & 0x01)    index += 6;
5422           if(!(pciA0 & 0x01)) index += 24;
5423
5424           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
5425
5426        }
5427
5428        data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
5429        if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
5430
5431     }
5432
5433     data += data2;                                             /* CRT1 Request Period */
5434
5435     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5436     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
5437
5438     if(!SiS_Pr->UseCustomMode) {
5439
5440        CRT2ModeNo = ModeNo;
5441        SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
5442
5443        refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
5444
5445        /* Get VCLK  */
5446        index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
5447        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
5448
5449        if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5450           if(SiS_Pr->SiS_UseROM) {
5451              if(ROMAddr[0x220] & 0x01) {
5452                 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
5453              }
5454           }
5455        }
5456
5457     } else {
5458
5459        /* Get VCLK */
5460        CRT2ModeNo = 0xfe;
5461        VCLK = SiS_Pr->CSRClock;
5462
5463     }
5464
5465     /* Get colordepth */
5466     colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
5467     if(!colorth) colorth++;
5468
5469     data = data * VCLK * colorth;
5470     temp = data % (MCLK << 4);
5471     data = data / (MCLK << 4);
5472     if(temp) data++;
5473
5474     if(data < 6) data = 6;
5475     else if(data > 0x14) data = 0x14;
5476
5477     if(SiS_Pr->ChipType == SIS_300) {
5478        temp = 0x16;
5479        if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
5480           temp = 0x13;
5481     } else {
5482        temp = 0x16;
5483        if(( (SiS_Pr->ChipType == SIS_630) ||
5484             (SiS_Pr->ChipType == SIS_730) )  &&
5485           (SiS_Pr->ChipRevision >= 0x30))
5486           temp = 0x1b;
5487     }
5488     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
5489
5490     if((SiS_Pr->ChipType == SIS_630) &&
5491        (SiS_Pr->ChipRevision >= 0x30)) {
5492        if(data > 0x13) data = 0x13;
5493     }
5494     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
5495
5496  } else {  /* If mode <= 0x13, we just restore everything */
5497
5498     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5499     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
5500
5501  }
5502}
5503#endif
5504
5505/* Set CRT2 FIFO on 315/330 series */
5506#ifdef CONFIG_FB_SIS_315
5507static void
5508SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
5509{
5510  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
5511  if( (SiS_Pr->ChipType == SIS_760)      &&
5512      (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
5513      (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
5514      (SiS_Pr->SiS_VGAHDE >= 1280)        &&
5515      (SiS_Pr->SiS_VGAVDE >= 1024) ) {
5516     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
5517     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
5518     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5519     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
5520     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5521     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
5522  } else {
5523     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
5524  }
5525
5526}
5527#endif
5528
5529static unsigned short
5530SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
5531{
5532  unsigned int tempax,tempbx;
5533
5534  tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
5535  tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
5536  tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
5537  return (unsigned short)tempax;
5538}
5539
5540/* Set Part 1 / SiS bridge slave mode */
5541static void
5542SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
5543                  unsigned short RefreshRateTableIndex)
5544{
5545  unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
5546  static const unsigned short CRTranslation[] = {
5547       /* CR0   CR1   CR2   CR3   CR4   CR5   CR6   CR7   */
5548          0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
5549       /* CR8   CR9   SR0A  SR0B  SR0C  SR0D  SR0E  CR0F  */
5550          0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
5551       /* CR10  CR11  CR12  CR13  CR14  CR15  CR16  CR17  */
5552          0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
5553  };
5554
5555  if(ModeNo <= 0x13) {
5556     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5557  } else if(SiS_Pr->UseCustomMode) {
5558     modeflag = SiS_Pr->CModeFlag;
5559     xres = SiS_Pr->CHDisplay;
5560  } else {
5561     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5562     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
5563  }
5564
5565  /* The following is only done if bridge is in slave mode: */
5566
5567  if(SiS_Pr->ChipType >= SIS_315H) {
5568     if(xres >= 1600) {  /* BIOS: == 1600 */
5569        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
5570     }
5571  }
5572
5573  SiS_Pr->CHTotal = 8224;  /* Max HT, 0x2020, results in 0x3ff in registers */
5574
5575  SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
5576  if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
5577
5578  SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
5579  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5580     SiS_Pr->CHBlankStart += 16;
5581  }
5582
5583  SiS_Pr->CHBlankEnd = 32;
5584  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5585     if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
5586  }
5587
5588  temp = SiS_Pr->SiS_VGAHT - 96;
5589  if(!(modeflag & HalfDCLK)) temp -= 32;
5590  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
5591     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
5592     temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
5593     temp -= 3;
5594     temp <<= 3;
5595  } else {
5596     if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
5597  }
5598  SiS_Pr->CHSyncStart = temp;
5599
5600  SiS_Pr->CHSyncEnd = 0xffe8;   /* results in 0x2000 in registers */
5601
5602  SiS_Pr->CVTotal = 2049;       /* Max VT, 0x0801, results in 0x7ff in registers */
5603
5604  VGAVDE = SiS_Pr->SiS_VGAVDE;
5605  if     (VGAVDE ==  357) VGAVDE =  350;
5606  else if(VGAVDE ==  360) VGAVDE =  350;
5607  else if(VGAVDE ==  375) VGAVDE =  350;
5608  else if(VGAVDE ==  405) VGAVDE =  400;
5609  else if(VGAVDE ==  420) VGAVDE =  400;
5610  else if(VGAVDE ==  525) VGAVDE =  480;
5611  else if(VGAVDE == 1056) VGAVDE = 1024;
5612  SiS_Pr->CVDisplay = VGAVDE;
5613
5614  SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
5615
5616  SiS_Pr->CVBlankEnd = 1;
5617  if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
5618
5619  temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
5620  SiS_Pr->CVSyncStart = VGAVDE + temp;
5621
5622  temp >>= 3;
5623  SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
5624
5625  SiS_CalcCRRegisters(SiS_Pr, 0);
5626  SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
5627
5628  for(i = 0; i <= 7; i++) {
5629     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
5630  }
5631  for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
5632     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5633  }
5634  for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
5635     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5636  }
5637  for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
5638     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5639  }
5640
5641  temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
5642  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
5643
5644  temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
5645  if(modeflag & DoubleScanMode) temp |= 0x80;
5646  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
5647
5648  temp = 0;
5649  temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
5650  if(modeflag & HalfDCLK) temp |= 0x08;
5651  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                  /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
5652
5653  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00);                  /* CR14: (text mode: underline location) */
5654  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00);                  /* CR17: n/a */
5655
5656  temp = 0;
5657  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5658     temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
5659  }
5660  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                  /* SR0E, dither[7] */
5661
5662  temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
5663  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);                  /* ? */
5664}
5665
5666/* Setup panel link
5667 * This is used for LVDS, LCDA and Chrontel TV output
5668 * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
5669 */
5670static void
5671SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5672                unsigned short RefreshRateTableIndex)
5673{
5674  unsigned short modeflag, resinfo = 0;
5675  unsigned short push2, tempax, tempbx, tempcx, temp;
5676  unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 0;
5677  bool islvds = false, issis  = false, chkdclkfirst = false;
5678#ifdef CONFIG_FB_SIS_300
5679  unsigned short crt2crtc = 0;
5680#endif
5681#ifdef CONFIG_FB_SIS_315
5682  unsigned short pushcx;
5683#endif
5684
5685  if(ModeNo <= 0x13) {
5686     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5687     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
5688#ifdef CONFIG_FB_SIS_300
5689     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5690#endif
5691  } else if(SiS_Pr->UseCustomMode) {
5692     modeflag = SiS_Pr->CModeFlag;
5693  } else {
5694     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5695     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5696#ifdef CONFIG_FB_SIS_300
5697     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
5698#endif
5699  }
5700
5701  /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
5702  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
5703     islvds = true;
5704  }
5705
5706  /* is really sis if sis bridge, but not 301B-DH */
5707  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
5708     issis = true;
5709  }
5710
5711  if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
5712     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
5713        chkdclkfirst = true;
5714     }
5715  }
5716
5717#ifdef CONFIG_FB_SIS_315
5718  if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
5719     if(IS_SIS330) {
5720        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5721     } else if(IS_SIS740) {
5722        if(islvds) {
5723           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5724           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
5725        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5726           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5727        }
5728     } else {
5729        if(islvds) {
5730           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5731           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
5732        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5733           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
5734           if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
5735              if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
5736                 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5737                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
5738              }
5739           }
5740        }
5741     }
5742  }
5743#endif
5744
5745  /* Horizontal */
5746
5747  tempax = SiS_Pr->SiS_LCDHDES;
5748  if(islvds) {
5749     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5750        if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
5751           if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
5752              (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
5753              tempax -= 8;
5754           }
5755        }
5756     }
5757  }
5758
5759  temp = (tempax & 0x0007);
5760  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                  /* BPLHDESKEW[2:0]   */
5761  temp = (tempax >> 3) & 0x00FF;
5762  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                  /* BPLHDESKEW[10:3]  */
5763
5764  tempbx = SiS_Pr->SiS_HDE;
5765  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5766     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5767        tempbx = SiS_Pr->PanelXRes;
5768     }
5769     if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
5770        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
5771        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
5772        tempbx >>= 1;
5773     }
5774  }
5775
5776  tempax += tempbx;
5777  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
5778
5779  temp = tempax;
5780  if(temp & 0x07) temp += 8;
5781  temp >>= 3;
5782  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                  /* BPLHDEE  */
5783
5784  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
5785
5786  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5787     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5788        if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
5789     }
5790  }
5791
5792  tempcx += tempax;
5793  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
5794
5795  temp = (tempcx >> 3) & 0x00FF;
5796  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5797     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5798        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5799           switch(ModeNo) {
5800           case 0x04:
5801           case 0x05:
5802           case 0x0d: temp = 0x56; break;
5803           case 0x10: temp = 0x60; break;
5804           case 0x13: temp = 0x5f; break;
5805           case 0x40:
5806           case 0x41:
5807           case 0x4f:
5808           case 0x43:
5809           case 0x44:
5810           case 0x62:
5811           case 0x56:
5812           case 0x53:
5813           case 0x5d:
5814           case 0x5e: temp = 0x54; break;
5815           }
5816        }
5817     }
5818  }
5819  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);                  /* BPLHRS */
5820
5821  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5822     temp += 2;
5823     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5824        temp += 8;
5825        if(SiS_Pr->PanelHRE != 999) {
5826           temp = tempcx + SiS_Pr->PanelHRE;
5827           if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
5828           temp >>= 3;
5829        }
5830     }
5831  } else {
5832     temp += 10;
5833  }
5834
5835  temp &= 0x1F;
5836  temp |= ((tempcx & 0x07) << 5);
5837  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);                  /* BPLHRE */
5838
5839  /* Vertical */
5840
5841  tempax = SiS_Pr->SiS_VGAVDE;
5842  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5843     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5844        tempax = SiS_Pr->PanelYRes;
5845     }
5846  }
5847
5848  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
5849  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5850
5851  push2 = tempbx;
5852
5853  tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
5854  if(SiS_Pr->ChipType < SIS_315H) {
5855     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5856        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5857           tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
5858        }
5859     }
5860  }
5861  if(islvds) tempcx >>= 1;
5862  else       tempcx >>= 2;
5863
5864  if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
5865      (!(SiS_Pr->SiS_LCDInfo & LCDPass11))                  &&
5866      (SiS_Pr->PanelVRS != 999) ) {
5867     tempcx = SiS_Pr->PanelVRS;
5868     tempbx += tempcx;
5869     if(issis) tempbx++;
5870  } else {
5871     tempbx += tempcx;
5872     if(SiS_Pr->ChipType < SIS_315H) tempbx++;
5873     else if(issis)                   tempbx++;
5874  }
5875
5876  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5877
5878  temp = tempbx & 0x00FF;
5879  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5880     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5881        if(ModeNo == 0x10) temp = 0xa9;
5882     }
5883  }
5884  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);                  /* BPLVRS */
5885
5886  tempcx >>= 3;
5887  tempcx++;
5888
5889  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5890     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5891        if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
5892     }
5893  }
5894
5895  tempcx += tempbx;
5896  temp = tempcx & 0x000F;
5897  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);        /* BPLVRE  */
5898
5899  temp = ((tempbx >> 8) & 0x07) << 3;
5900  if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5901     if(SiS_Pr->SiS_HDE != 640) {
5902        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
5903     }
5904  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5905  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
5906  tempbx = 0x87;
5907  if((SiS_Pr->ChipType >= SIS_315H) ||
5908     (SiS_Pr->ChipRevision >= 0x30)) {
5909     tempbx = 0x07;
5910     if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
5911        if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
5912     }
5913     /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
5914     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5915        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5916           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
5917        } else {
5918           if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
5919        }
5920     }
5921  }
5922  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
5923
5924  tempbx = push2;                                               /* BPLVDEE */
5925
5926  tempcx = SiS_Pr->SiS_LCDVDES;                                 /* BPLVDES */
5927
5928  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5929     switch(SiS_Pr->SiS_LCDResInfo) {
5930     case Panel_640x480:
5931        tempbx = SiS_Pr->SiS_VGAVDE - 1;
5932        tempcx = SiS_Pr->SiS_VGAVDE;
5933        break;
5934     case Panel_800x600:
5935        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5936           if(resinfo == SIS_RI_800x600) tempcx++;
5937        }
5938        break;
5939     case Panel_1024x600:
5940        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5941           if(resinfo == SIS_RI_1024x600) tempcx++;
5942           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
5943              if(resinfo == SIS_RI_800x600) tempcx++;
5944           }
5945        }
5946        break;
5947     case Panel_1024x768:
5948        if(SiS_Pr->ChipType < SIS_315H) {
5949           if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5950              if(resinfo == SIS_RI_1024x768) tempcx++;
5951           }
5952        }
5953        break;
5954     }
5955  }
5956
5957  temp = ((tempbx >> 8) & 0x07) << 3;
5958  temp |= ((tempcx >> 8) & 0x07);
5959  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
5960  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
5961  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
5962
5963  /* Vertical scaling */
5964
5965  if(SiS_Pr->ChipType < SIS_315H) {
5966
5967#ifdef CONFIG_FB_SIS_300      /* 300 series */
5968     tempeax = SiS_Pr->SiS_VGAVDE << 6;
5969     temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
5970     tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
5971     if(temp) tempeax++;
5972
5973     if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
5974
5975     temp = (unsigned short)(tempeax & 0x00FF);
5976     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);       /* BPLVCFACT */
5977     tempvcfact = temp;
5978#endif /* CONFIG_FB_SIS_300 */
5979
5980  } else {
5981
5982#ifdef CONFIG_FB_SIS_315  /* 315 series */
5983     tempeax = SiS_Pr->SiS_VGAVDE << 18;
5984     tempebx = SiS_Pr->SiS_VDE;
5985     temp = (tempeax % tempebx);
5986     tempeax = tempeax / tempebx;
5987     if(temp) tempeax++;
5988     tempvcfact = tempeax;
5989
5990     temp = (unsigned short)(tempeax & 0x00FF);
5991     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
5992     temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
5993     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
5994     temp = (unsigned short)((tempeax & 0x00030000) >> 16);
5995     if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
5996     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
5997
5998     if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
5999        temp = (unsigned short)(tempeax & 0x00FF);
6000        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
6001        temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
6002        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
6003        temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
6004        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
6005        temp = 0;
6006        if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
6007        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
6008     }
6009#endif
6010
6011  }
6012
6013  /* Horizontal scaling */
6014
6015  tempeax = SiS_Pr->SiS_VGAHDE;         /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
6016  if(chkdclkfirst) {
6017     if(modeflag & HalfDCLK) tempeax >>= 1;
6018  }
6019  tempebx = tempeax << 16;
6020  if(SiS_Pr->SiS_HDE == tempeax) {
6021     tempecx = 0xFFFF;
6022  } else {
6023     tempecx = tempebx / SiS_Pr->SiS_HDE;
6024     if(SiS_Pr->ChipType >= SIS_315H) {
6025        if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
6026     }
6027  }
6028
6029  if(SiS_Pr->ChipType >= SIS_315H) {
6030     tempeax = (tempebx / tempecx) - 1;
6031  } else {
6032     tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
6033  }
6034  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
6035  temp = (unsigned short)(tempecx & 0x00FF);
6036  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
6037
6038  if(SiS_Pr->ChipType >= SIS_315H) {
6039     tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
6040     tempbx = (unsigned short)(tempeax & 0xFFFF);
6041  } else {
6042     tempeax = SiS_Pr->SiS_VGAVDE << 6;
6043     tempbx = tempvcfact & 0x3f;
6044     if(tempbx == 0) tempbx = 64;
6045     tempeax /= tempbx;
6046     tempbx = (unsigned short)(tempeax & 0xFFFF);
6047  }
6048  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
6049  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
6050     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
6051     else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480)             tempbx = 1;
6052  }
6053
6054  temp = ((tempbx >> 8) & 0x07) << 3;
6055  temp = temp | ((tempecx >> 8) & 0x07);
6056  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
6057  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
6058
6059  tempecx >>= 16;                                               /* BPLHCFACT  */
6060  if(!chkdclkfirst) {
6061     if(modeflag & HalfDCLK) tempecx >>= 1;
6062  }
6063  temp = (unsigned short)((tempecx & 0xFF00) >> 8);
6064  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
6065  temp = (unsigned short)(tempecx & 0x00FF);
6066  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
6067
6068#ifdef CONFIG_FB_SIS_315
6069  if(SiS_Pr->ChipType >= SIS_315H) {
6070     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
6071        if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
6072           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
6073        }
6074     } else {
6075        if(islvds) {
6076           if(SiS_Pr->ChipType == SIS_740) {
6077              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
6078           } else {
6079              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
6080           }
6081        }
6082     }
6083  }
6084#endif
6085
6086#ifdef CONFIG_FB_SIS_300
6087  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
6088     unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
6089     unsigned char *trumpdata;
6090     int   i, j = crt2crtc;
6091     unsigned char TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
6092     unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
6093     unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
6094
6095     if(SiS_Pr->SiS_UseROM) {
6096        trumpdata = &ROMAddr[0x8001 + (j * 80)];
6097     } else {
6098        if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
6099        trumpdata = &SiS300_TrumpionData[j][0];
6100     }
6101
6102     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
6103     for(i=0; i<5; i++) {
6104        SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
6105     }
6106     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6107        if(ModeNo == 0x13) {
6108           for(i=0; i<4; i++) {
6109              SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
6110           }
6111        } else if(ModeNo == 0x10) {
6112           for(i=0; i<4; i++) {
6113              SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
6114              SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
6115           }
6116        }
6117     }
6118     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
6119  }
6120#endif
6121
6122#ifdef CONFIG_FB_SIS_315
6123  if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
6124     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
6125     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
6126     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
6127     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
6128     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
6129     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
6130     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
6131     tempax = SiS_Pr->SiS_HDE;                                  /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
6132     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
6133        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
6134        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
6135     tempax += 64;
6136     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
6137     temp = (tempax >> 8) << 3;
6138     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
6139     tempax += 32;                                              /* Blpe = lBlps+32 */
6140     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
6141     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00);               /* Bflml = 0 */
6142     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
6143
6144     tempax = SiS_Pr->SiS_VDE;
6145     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
6146        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
6147        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
6148     tempax >>= 1;
6149     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
6150     temp = (tempax >> 8) << 3;
6151     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
6152
6153     tempeax = SiS_Pr->SiS_HDE;
6154     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
6155        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
6156        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
6157     tempeax <<= 2;                                             /* BDxFIFOSTOP = (HDE*4)/128 */
6158     temp = tempeax & 0x7f;
6159     tempeax >>= 7;
6160     if(temp) tempeax++;
6161     temp = tempeax & 0x3f;
6162     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
6163     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00);               /* BDxWadrst0 */
6164     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
6165     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
6166     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
6167
6168     tempax = SiS_Pr->SiS_HDE;
6169     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
6170        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
6171        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
6172     tempax >>= 4;                                              /* BDxWadroff = HDE*4/8/8 */
6173     pushcx = tempax;
6174     temp = tempax & 0x00FF;
6175     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
6176     temp = ((tempax & 0xFF00) >> 8) << 3;
6177     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x44, 0x07, temp);
6178
6179     tempax = SiS_Pr->SiS_VDE;                                  /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
6180     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
6181        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
6182        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
6183     tempeax = tempax * pushcx;
6184     temp = tempeax & 0xFF;
6185     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
6186     temp = (tempeax & 0xFF00) >> 8;
6187     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
6188     temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
6189     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
6190     temp = ((tempeax & 0x01000000) >> 24) << 7;
6191     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x3C, 0x7F, temp);
6192
6193     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
6194     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
6195     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
6196     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
6197     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
6198
6199     if(SiS_Pr->SiS_IF_DEF_FSTN) {
6200        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
6201        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
6202        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
6203        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
6204        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
6205        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
6206        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
6207        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
6208        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
6209        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
6210        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
6211        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
6212        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
6213        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
6214        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
6215        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
6216        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
6217        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
6218        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
6219        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
6220     }
6221  }
6222#endif  /* CONFIG_FB_SIS_315 */
6223}
6224
6225/* Set Part 1 */
6226static void
6227SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6228                unsigned short RefreshRateTableIndex)
6229{
6230#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
6231  unsigned char   *ROMAddr = SiS_Pr->VirtualRomBase;
6232#endif
6233  unsigned short  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
6234  unsigned short  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
6235#ifdef CONFIG_FB_SIS_315
6236  unsigned short  tempbl=0;
6237#endif
6238
6239  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
6240     SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
6241     return;
6242  }
6243
6244  if(ModeNo <= 0x13) {
6245     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6246  } else if(SiS_Pr->UseCustomMode) {
6247     modeflag = SiS_Pr->CModeFlag;
6248  } else {
6249     CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
6250     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
6251     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6252  }
6253
6254  SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
6255
6256  if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
6257         (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
6258         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
6259
6260     if(SiS_Pr->ChipType < SIS_315H ) {
6261#ifdef CONFIG_FB_SIS_300
6262        SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
6263#endif
6264     } else {
6265#ifdef CONFIG_FB_SIS_315
6266        SiS_SetCRT2FIFO_310(SiS_Pr);
6267#endif
6268     }
6269
6270     /* 1. Horizontal setup */
6271
6272     if(SiS_Pr->ChipType < SIS_315H ) {
6273
6274#ifdef CONFIG_FB_SIS_300   /* ------------- 300 series --------------*/
6275
6276        temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;                   /* BTVGA2HT 0x08,0x09 */
6277        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
6278
6279        temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
6280        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
6281
6282        temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
6283        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
6284
6285        pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
6286        tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
6287        tempbx = pushbx + tempcx;
6288        tempcx <<= 1;
6289        tempcx += tempbx;
6290
6291        bridgeadd = 12;
6292
6293#endif /* CONFIG_FB_SIS_300 */
6294
6295     } else {
6296
6297#ifdef CONFIG_FB_SIS_315  /* ------------------- 315/330 series --------------- */
6298
6299        tempcx = SiS_Pr->SiS_VGAHT;                               /* BTVGA2HT 0x08,0x09 */
6300        if(modeflag & HalfDCLK) {
6301           if(SiS_Pr->SiS_VBType & VB_SISVB) {
6302              tempcx >>= 1;
6303           } else {
6304              tempax = SiS_Pr->SiS_VGAHDE >> 1;
6305              tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
6306              if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
6307                 tempcx = SiS_Pr->SiS_HT - tempax;
6308              }
6309           }
6310        }
6311        tempcx--;
6312        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx);            /* CRT2 Horizontal Total */
6313        temp = (tempcx >> 4) & 0xF0;
6314        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
6315
6316        tempcx = SiS_Pr->SiS_VGAHT;                               /* BTVGA2HDEE 0x0A,0x0C */
6317        tempbx = SiS_Pr->SiS_VGAHDE;
6318        tempcx -= tempbx;
6319        tempcx >>= 2;
6320        if(modeflag & HalfDCLK) {
6321           tempbx >>= 1;
6322           tempcx >>= 1;
6323        }
6324        tempbx += 16;
6325
6326        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx);            /* CRT2 Horizontal Display Enable End */
6327
6328        pushbx = tempbx;
6329        tempcx >>= 1;
6330        tempbx += tempcx;
6331        tempcx += tempbx;
6332
6333        bridgeadd = 16;
6334
6335        if(SiS_Pr->SiS_VBType & VB_SISVB) {
6336           if(SiS_Pr->ChipType >= SIS_661) {
6337              if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
6338                 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
6339                 if(resinfo == SIS_RI_1280x1024) {
6340                    tempcx = (tempcx & 0xff00) | 0x30;
6341                 } else if(resinfo == SIS_RI_1600x1200) {
6342                    tempcx = (tempcx & 0xff00) | 0xff;
6343                 }
6344              }
6345           }
6346        }
6347
6348#endif  /* CONFIG_FB_SIS_315 */
6349
6350     }  /* 315/330 series */
6351
6352     if(SiS_Pr->SiS_VBType & VB_SISVB) {
6353
6354        if(SiS_Pr->UseCustomMode) {
6355           tempbx = SiS_Pr->CHSyncStart + bridgeadd;
6356           tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
6357           tempax = SiS_Pr->SiS_VGAHT;
6358           if(modeflag & HalfDCLK) tempax >>= 1;
6359           tempax--;
6360           if(tempcx > tempax) tempcx = tempax;
6361        }
6362
6363        if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6364           unsigned char cr4, cr14, cr5, cr15;
6365           if(SiS_Pr->UseCustomMode) {
6366              cr4  = SiS_Pr->CCRT1CRTC[4];
6367              cr14 = SiS_Pr->CCRT1CRTC[14];
6368              cr5  = SiS_Pr->CCRT1CRTC[5];
6369              cr15 = SiS_Pr->CCRT1CRTC[15];
6370           } else {
6371              cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
6372              cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
6373              cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
6374              cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
6375           }
6376           tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3;                /* (VGAHRS-3)*8 */
6377           tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
6378           tempcx &= 0x00FF;
6379           tempcx |= (tempbx & 0xFF00);
6380           tempbx += bridgeadd;
6381           tempcx += bridgeadd;
6382           tempax = SiS_Pr->SiS_VGAHT;
6383           if(modeflag & HalfDCLK) tempax >>= 1;
6384           tempax--;
6385           if(tempcx > tempax) tempcx = tempax;
6386        }
6387
6388        if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
6389           tempbx = 1040;
6390           tempcx = 1044;   /* HWCursor bug! */
6391        }
6392
6393     }
6394
6395     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx);               /* CRT2 Horizontal Retrace Start */
6396
6397     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx);               /* CRT2 Horizontal Retrace End */
6398
6399     temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
6400     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                 /* Overflow */
6401
6402     /* 2. Vertical setup */
6403
6404     tempcx = SiS_Pr->SiS_VGAVT - 1;
6405     temp = tempcx & 0x00FF;
6406
6407     if(SiS_Pr->ChipType < SIS_661) {
6408        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6409           if(SiS_Pr->ChipType < SIS_315H) {
6410              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6411                 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6412                    temp--;
6413                 }
6414              }
6415           } else {
6416              temp--;
6417           }
6418        } else if(SiS_Pr->ChipType >= SIS_315H) {
6419           temp--;
6420        }
6421     }
6422     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
6423
6424     tempbx = SiS_Pr->SiS_VGAVDE - 1;
6425     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx);               /* CRT2 Vertical Display Enable End */
6426
6427     temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
6428     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
6429
6430     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
6431        tempbx++;
6432        tempax = tempbx;
6433        tempcx++;
6434        tempcx -= tempax;
6435        tempcx >>= 2;
6436        tempbx += tempcx;
6437        if(tempcx < 4) tempcx = 4;
6438        tempcx >>= 2;
6439        tempcx += tempbx;
6440        tempcx++;
6441     } else {
6442        tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
6443        tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
6444     }
6445
6446     if(SiS_Pr->SiS_VBType & VB_SISVB) {
6447        if(SiS_Pr->UseCustomMode) {
6448           tempbx = SiS_Pr->CVSyncStart;
6449           tempcx = SiS_Pr->CVSyncEnd;
6450        }
6451        if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6452           unsigned char cr8, cr7, cr13;
6453           if(SiS_Pr->UseCustomMode) {
6454              cr8    = SiS_Pr->CCRT1CRTC[8];
6455              cr7    = SiS_Pr->CCRT1CRTC[7];
6456              cr13   = SiS_Pr->CCRT1CRTC[13];
6457              tempcx = SiS_Pr->CCRT1CRTC[9];
6458           } else {
6459              cr8    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
6460              cr7    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
6461              cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
6462              tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
6463           }
6464           tempbx = cr8;
6465           if(cr7  & 0x04) tempbx |= 0x0100;
6466           if(cr7  & 0x80) tempbx |= 0x0200;
6467           if(cr13 & 0x08) tempbx |= 0x0400;
6468        }
6469     }
6470     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
6471
6472     temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
6473     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow */
6474
6475     /* 3. Panel delay compensation */
6476
6477     if(SiS_Pr->ChipType < SIS_315H) {
6478
6479#ifdef CONFIG_FB_SIS_300  /* ---------- 300 series -------------- */
6480
6481        if(SiS_Pr->SiS_VBType & VB_SISVB) {
6482           temp = 0x20;
6483           if(SiS_Pr->ChipType == SIS_300) {
6484              temp = 0x10;
6485              if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
6486              if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6487           }
6488           if(SiS_Pr->SiS_VBType & VB_SIS301) {
6489              if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6490           }
6491           if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
6492           if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
6493           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)             temp = 0x08;
6494           if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6495              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)       temp = 0x2c;
6496              else                                          temp = 0x20;
6497           }
6498           if(SiS_Pr->SiS_UseROM) {
6499              if(ROMAddr[0x220] & 0x80) {
6500                 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
6501                    temp = ROMAddr[0x221];
6502                 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
6503                    temp = ROMAddr[0x222];
6504                 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
6505                    temp = ROMAddr[0x223];
6506                 else
6507                    temp = ROMAddr[0x224];
6508              }
6509           }
6510           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6511              if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC;
6512           }
6513
6514        } else {
6515           temp = 0x20;
6516           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6517              if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
6518           }
6519           if(SiS_Pr->SiS_UseROM) {
6520              if(ROMAddr[0x220] & 0x80) {
6521                 temp = ROMAddr[0x220];
6522              }
6523           }
6524           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6525              if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
6526           }
6527        }
6528
6529        temp &= 0x3c;
6530
6531        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
6532
6533#endif  /* CONFIG_FB_SIS_300 */
6534
6535     } else {
6536
6537#ifdef CONFIG_FB_SIS_315   /* --------------- 315/330 series ---------------*/
6538
6539        if(SiS_Pr->ChipType < SIS_661) {
6540
6541           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6542
6543              if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
6544              else                            temp = 0x00;
6545
6546              if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
6547              tempbl = 0xF0;
6548              if(SiS_Pr->ChipType == SIS_650) {
6549                 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6550                    if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
6551                 }
6552              }
6553
6554              if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
6555                 temp = 0x08;
6556                 tempbl = 0;
6557                 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
6558                    if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
6559                 }
6560              }
6561
6562              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp);      /* Panel Link Delay Compensation */
6563           }
6564
6565        } /* < 661 */
6566
6567        tempax = 0;
6568        if(modeflag & DoubleScanMode) tempax |= 0x80;
6569        if(modeflag & HalfDCLK)       tempax |= 0x40;
6570        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
6571
6572#endif  /* CONFIG_FB_SIS_315 */
6573
6574     }
6575
6576  }  /* Slavemode */
6577
6578  if(SiS_Pr->SiS_VBType & VB_SISVB) {
6579     if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
6580        /* For 301BDH with LCD, we set up the Panel Link */
6581        SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
6582     } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6583        SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
6584     }
6585  } else {
6586     if(SiS_Pr->ChipType < SIS_315H) {
6587        SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
6588     } else {
6589        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6590           if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6591              SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
6592           }
6593        } else {
6594           SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
6595        }
6596     }
6597  }
6598}
6599
6600/*********************************************/
6601/*         SET PART 2 REGISTER GROUP         */
6602/*********************************************/
6603
6604#ifdef CONFIG_FB_SIS_315
6605static unsigned char *
6606SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
6607{
6608   const unsigned char *tableptr = NULL;
6609   unsigned short      a, b, p = 0;
6610
6611   a = SiS_Pr->SiS_VGAHDE;
6612   b = SiS_Pr->SiS_HDE;
6613   if(tabletype) {
6614      a = SiS_Pr->SiS_VGAVDE;
6615      b = SiS_Pr->SiS_VDE;
6616   }
6617
6618   if(a < b) {
6619      tableptr = SiS_Part2CLVX_1;
6620   } else if(a == b) {
6621      tableptr = SiS_Part2CLVX_2;
6622   } else {
6623      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6624         tableptr = SiS_Part2CLVX_4;
6625      } else {
6626         tableptr = SiS_Part2CLVX_3;
6627      }
6628      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6629         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)        tableptr = SiS_Part2CLVX_3;
6630         else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   tableptr = SiS_Part2CLVX_3;
6631         else                                           tableptr = SiS_Part2CLVX_5;
6632      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6633         tableptr = SiS_Part2CLVX_6;
6634      }
6635      do {
6636         if((tableptr[p] | tableptr[p+1] << 8) == a) break;
6637         p += 0x42;
6638      } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
6639      if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
6640   }
6641   p += 2;
6642   return ((unsigned char *)&tableptr[p]);
6643}
6644
6645static void
6646SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6647                    unsigned short RefreshRateTableIndex)
6648{
6649   unsigned char *tableptr;
6650   unsigned char temp;
6651   int i, j;
6652
6653   if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
6654
6655   tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
6656   for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
6657      SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6658   }
6659   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6660      tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
6661      for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
6662         SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6663      }
6664   }
6665   temp = 0x10;
6666   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
6667   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
6668}
6669
6670static bool
6671SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
6672                    unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
6673                    unsigned short *ResIndex)
6674{
6675
6676  if(SiS_Pr->ChipType < SIS_315H) return false;
6677
6678  if(ModeNo <= 0x13)
6679     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6680  else
6681     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6682
6683  (*ResIndex) &= 0x3f;
6684  (*CRT2Index) = 0;
6685
6686  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6687     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6688        (*CRT2Index) = 200;
6689     }
6690  }
6691
6692  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
6693     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6694        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
6695     }
6696  }
6697  return (((*CRT2Index) != 0));
6698}
6699#endif
6700
6701#ifdef CONFIG_FB_SIS_300
6702static void
6703SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
6704{
6705   unsigned short tempcx;
6706   static const unsigned char atable[] = {
6707       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
6708       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
6709   };
6710
6711   if(!SiS_Pr->UseCustomMode) {
6712      if( ( ( (SiS_Pr->ChipType == SIS_630) ||
6713              (SiS_Pr->ChipType == SIS_730) ) &&
6714            (SiS_Pr->ChipRevision > 2) )  &&
6715          (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
6716          (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
6717          (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
6718         if(ModeNo == 0x13) {
6719            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
6720            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
6721            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
6722         } else if((crt2crtc & 0x3F) == 4) {
6723            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
6724            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
6725            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
6726            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
6727            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
6728         }
6729      }
6730
6731      if(SiS_Pr->ChipType < SIS_315H) {
6732         if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
6733            crt2crtc &= 0x1f;
6734            tempcx = 0;
6735            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6736               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6737                  tempcx += 7;
6738               }
6739            }
6740            tempcx += crt2crtc;
6741            if(crt2crtc >= 4) {
6742               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
6743            }
6744
6745            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6746               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6747                  if(crt2crtc == 4) {
6748                     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
6749                  }
6750               }
6751            }
6752            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
6753            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
6754         }
6755      }
6756   }
6757}
6758
6759/* For ECS A907. Highly preliminary. */
6760static void
6761SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
6762                    unsigned short ModeNo)
6763{
6764  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6765  unsigned short crt2crtc, resindex;
6766  int i, j;
6767
6768  if(SiS_Pr->ChipType != SIS_300) return;
6769  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
6770  if(SiS_Pr->UseCustomMode) return;
6771
6772  if(ModeNo <= 0x13) {
6773     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6774  } else {
6775     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6776  }
6777
6778  resindex = crt2crtc & 0x3F;
6779  if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6780  else                                    CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
6781
6782  /* The BIOS code (1.16.51,56) is obviously a fragment! */
6783  if(ModeNo > 0x13) {
6784     CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6785     resindex = 4;
6786  }
6787
6788  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6789  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6790  for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
6791     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6792  }
6793  for(j = 0x1c; j <= 0x1d; i++, j++ ) {
6794     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6795  }
6796  for(j = 0x1f; j <= 0x21; i++, j++ ) {
6797     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6798  }
6799  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6800  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6801}
6802#endif
6803
6804static void
6805SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
6806{
6807  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
6808  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
6809  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
6810
6811  if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6812     if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6813        static const unsigned char specialtv[] = {
6814                0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
6815                0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
6816                0x58,0xe4,0x73,0xda,0x13
6817        };
6818        int i, j;
6819        for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
6820           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
6821        }
6822        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
6823        if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
6824           if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6825              SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
6826              SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
6827           } else {
6828              SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);  /* 15 */
6829              SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a);  /* 1b */
6830           }
6831        }
6832     }
6833  } else {
6834     if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
6835        (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
6836        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 21 */
6837        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 5a */
6838     } else {
6839        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a);  /* 21 */
6840        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53);  /* 5a */
6841     }
6842  }
6843}
6844
6845static void
6846SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
6847{
6848  unsigned short temp;
6849
6850  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6851     if(SiS_Pr->SiS_VGAVDE == 525) {
6852        temp = 0xc3;
6853        if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6854           temp++;
6855           if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
6856        }
6857        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6858        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
6859     } else if(SiS_Pr->SiS_VGAVDE == 420) {
6860        temp = 0x4d;
6861        if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6862           temp++;
6863           if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
6864        }
6865        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6866     }
6867  }
6868
6869  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6870     if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
6871        if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
6872           SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
6873           /* Not always for LV, see SetGrp2 */
6874        }
6875        temp = 1;
6876        if(ModeNo <= 0x13) temp = 3;
6877        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
6878     }
6879#if 0
6880     /* 651+301C, for 1280x768 - do I really need that? */
6881     if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
6882        if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
6883           if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
6884              ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
6885              SiS_SetReg(SiS_Part2Port,0x01,0x2b);
6886              SiS_SetReg(SiS_Part2Port,0x02,0x13);
6887              SiS_SetReg(SiS_Part2Port,0x04,0xe5);
6888              SiS_SetReg(SiS_Part2Port,0x05,0x08);
6889              SiS_SetReg(SiS_Part2Port,0x06,0xe2);
6890              SiS_SetReg(SiS_Part2Port,0x1c,0x21);
6891              SiS_SetReg(SiS_Part2Port,0x1d,0x45);
6892              SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
6893              SiS_SetReg(SiS_Part2Port,0x20,0x00);
6894              SiS_SetReg(SiS_Part2Port,0x21,0xa9);
6895              SiS_SetReg(SiS_Part2Port,0x23,0x0b);
6896              SiS_SetReg(SiS_Part2Port,0x25,0x04);
6897           }
6898        }
6899     }
6900#endif
6901  }
6902}
6903
6904static void
6905SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6906                unsigned short RefreshRateTableIndex)
6907{
6908  unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
6909  unsigned short push2, modeflag, crt2crtc, bridgeoffset;
6910  unsigned int   longtemp, PhaseIndex;
6911  bool           newtvphase;
6912  const unsigned char *TimingPoint;
6913#ifdef CONFIG_FB_SIS_315
6914  unsigned short resindex, CRT2Index;
6915  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6916
6917  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
6918#endif
6919
6920  if(ModeNo <= 0x13) {
6921     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6922     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6923  } else if(SiS_Pr->UseCustomMode) {
6924     modeflag = SiS_Pr->CModeFlag;
6925     crt2crtc = 0;
6926  } else {
6927     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6928     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6929  }
6930
6931  temp = 0;
6932  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
6933  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
6934  if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)     temp |= 0x02;
6935  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)  temp |= 0x01;
6936
6937  if(!(SiS_Pr->SiS_TVMode & TVSetPAL))        temp |= 0x10;
6938
6939  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
6940
6941  PhaseIndex  = 0x01; /* SiS_PALPhase */
6942  TimingPoint = SiS_Pr->SiS_PALTiming;
6943
6944  newtvphase = false;
6945  if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
6946      ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6947        (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6948     newtvphase = true;
6949  }
6950
6951  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6952
6953     TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
6954     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6955        TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
6956        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6957           TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
6958        }
6959     }
6960
6961  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6962
6963     i = 0;
6964     if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      i = 2;
6965     else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
6966
6967     TimingPoint = &SiS_YPbPrTable[i][0];
6968
6969     PhaseIndex = 0x00; /* SiS_NTSCPhase */
6970
6971  } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6972
6973     if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
6974
6975  } else {
6976
6977     TimingPoint = SiS_Pr->SiS_NTSCTiming;
6978     PhaseIndex  = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00;     /* SiS_PALPhase : SiS_NTSCPhase */
6979     if(newtvphase) PhaseIndex += 8;                                    /* SiS_PALPhase2 : SiS_NTSCPhase2 */
6980
6981  }
6982
6983  if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
6984     PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03;       /* SiS_PALMPhase : SiS_PALNPhase */
6985     if(newtvphase) PhaseIndex += 8;                                    /* SiS_PALMPhase2 : SiS_PALNPhase2 */
6986  }
6987
6988  if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6989     if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6990        PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
6991     } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
6992        PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
6993     } else {
6994        PhaseIndex = 0x10; /* SiS_SpecialPhase */
6995     }
6996  }
6997
6998  for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
6999     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
7000  }
7001
7002  for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
7003     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
7004  }
7005  for(i = 0x39; i <= 0x45; i++, j++) {
7006     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
7007  }
7008
7009  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7010     if(SiS_Pr->SiS_ModeType != ModeText) {
7011        SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
7012     }
7013  }
7014
7015  SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
7016
7017  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
7018  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
7019  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
7020  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
7021
7022  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)    tempax = 950;
7023  else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  tempax = 680;
7024  else if(SiS_Pr->SiS_TVMode & TVSetPAL)        tempax = 520;
7025  else                                          tempax = 440; /* NTSC, YPbPr 525 */
7026
7027  if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
7028      ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
7029        ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
7030
7031     tempax -= SiS_Pr->SiS_VDE;
7032     tempax >>= 1;
7033     if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
7034        tempax >>= 1;
7035     }
7036     tempax &= 0x00ff;
7037
7038     temp = tempax + (unsigned short)TimingPoint[0];
7039     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7040
7041     temp = tempax + (unsigned short)TimingPoint[1];
7042     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7043
7044     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
7045        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7046           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
7047           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
7048        } else {
7049           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
7050           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
7051        }
7052     }
7053
7054  }
7055
7056  tempcx = SiS_Pr->SiS_HT;
7057  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
7058  tempcx--;
7059  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
7060  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
7061  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
7062
7063  tempcx = SiS_Pr->SiS_HT >> 1;
7064  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
7065  tempcx += 7;
7066  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
7067  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
7068
7069  tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
7070  tempbx += tempcx;
7071  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
7072  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
7073
7074  tempbx += 8;
7075  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7076     tempbx -= 4;
7077     tempcx = tempbx;
7078  }
7079  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
7080
7081  j += 2;
7082  tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
7083  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
7084  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
7085
7086  tempcx += 8;
7087  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
7088  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
7089
7090  tempcx = SiS_Pr->SiS_HT >> 1;
7091  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
7092  j += 2;
7093  tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
7094  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
7095
7096  tempcx -= 11;
7097  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7098     tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
7099  }
7100  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
7101
7102  tempbx = SiS_Pr->SiS_VDE;
7103  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7104     if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
7105     if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
7106     if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
7107  } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
7108             (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
7109     tempbx >>= 1;
7110     if(SiS_Pr->ChipType >= SIS_315H) {
7111        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7112           if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
7113        } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7114           if(SiS_Pr->SiS_ModeType <= ModeVGA) {
7115              if(crt2crtc == 4) tempbx++;
7116           }
7117        }
7118     }
7119     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7120        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7121           if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
7122        }
7123        if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
7124           if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
7125        }
7126     }
7127  }
7128  tempbx -= 2;
7129  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
7130
7131  temp = (tempcx >> 8) & 0x0F;
7132  temp |= ((tempbx >> 2) & 0xC0);
7133  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
7134     temp |= 0x10;
7135     if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
7136  }
7137  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
7138
7139  if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
7140     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
7141  }
7142
7143  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7144     tempbx = SiS_Pr->SiS_VDE;
7145     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
7146         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
7147        tempbx >>= 1;
7148     }
7149     tempbx -= 3;
7150     temp = ((tempbx >> 3) & 0x60) | 0x18;
7151     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
7152     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
7153
7154     if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
7155        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
7156     }
7157  }
7158
7159  tempbx = 0;
7160  if(!(modeflag & HalfDCLK)) {
7161     if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
7162        tempax = 0;
7163        tempbx |= 0x20;
7164     }
7165  }
7166
7167  tempch = tempcl = 0x01;
7168  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7169     if(SiS_Pr->SiS_VGAHDE >= 960) {
7170        if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
7171           tempcl = 0x20;
7172           if(SiS_Pr->SiS_VGAHDE >= 1280) {
7173              tempch = 20;
7174              tempbx &= ~0x20;
7175           } else {
7176              tempch = 25; /* OK */
7177           }
7178        }
7179     }
7180  }
7181
7182  if(!(tempbx & 0x20)) {
7183     if(modeflag & HalfDCLK) tempcl <<= 1;
7184     longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
7185     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
7186     tempax = longtemp / SiS_Pr->SiS_HDE;
7187     if(longtemp % SiS_Pr->SiS_HDE) tempax++;
7188     tempbx |= ((tempax >> 8) & 0x1F);
7189     tempcx = tempax >> 13;
7190  }
7191
7192  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
7193  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
7194
7195  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7196
7197     tempcx &= 0x07;
7198     if(tempbx & 0x20) tempcx = 0;
7199     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
7200
7201     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7202        tempbx = 0x0382;
7203        tempcx = 0x007e;
7204     } else {
7205        tempbx = 0x0369;
7206        tempcx = 0x0061;
7207     }
7208     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
7209     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
7210     temp = (tempcx & 0x0300) >> 6;
7211     temp |= ((tempbx >> 8) & 0x03);
7212     if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7213        temp |= 0x10;
7214        if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)      temp |= 0x20;
7215        else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
7216     }
7217     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
7218
7219     temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7220     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
7221
7222     SiS_SetTVSpecial(SiS_Pr, ModeNo);
7223
7224     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
7225        temp = 0;
7226        if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
7227        SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
7228     }
7229
7230  }
7231
7232  if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7233     if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
7234        temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
7235        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
7236     }
7237     SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
7238  }
7239
7240  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7241     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
7242        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
7243     }
7244  }
7245
7246  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
7247
7248  /* From here: Part2 LCD setup */
7249
7250  tempbx = SiS_Pr->SiS_HDE;
7251  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7252  tempbx--;                                     /* RHACTE = HDE - 1 */
7253  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
7254  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
7255
7256  temp = 0x01;
7257  if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7258     if(SiS_Pr->SiS_ModeType == ModeEGA) {
7259        if(SiS_Pr->SiS_VGAHDE >= 1024) {
7260           temp = 0x02;
7261           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7262              temp = 0x01;
7263           }
7264        }
7265     }
7266  }
7267  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
7268
7269  tempbx = SiS_Pr->SiS_VDE - 1;
7270  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
7271  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
7272
7273  tempcx = SiS_Pr->SiS_VT - 1;
7274  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
7275  temp = (tempcx >> 3) & 0xE0;
7276  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
7277     /* Enable dithering; only do this for 32bpp mode */
7278     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
7279        temp |= 0x10;
7280     }
7281  }
7282  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
7283
7284  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
7285  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
7286
7287  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
7288  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
7289
7290#ifdef CONFIG_FB_SIS_315
7291  if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7292                                                &CRT2Index, &resindex)) {
7293      switch(CRT2Index) {
7294        case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
7295        default:
7296        case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
7297      }
7298
7299      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
7300      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
7301      for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
7302        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7303      }
7304      for(j = 0x1c; j <= 0x1d; i++, j++ ) {
7305        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7306      }
7307      for(j = 0x1f; j <= 0x21; i++, j++ ) {
7308        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7309      }
7310      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
7311      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
7312
7313      SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7314
7315  } else {
7316#endif
7317
7318    /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
7319    /*             Clevo dual-link 1024x768 */
7320    /*             Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
7321    /*             Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
7322
7323    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7324       if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7325          tempbx = SiS_Pr->SiS_VDE - 1;
7326          tempcx = SiS_Pr->SiS_VT - 1;
7327       } else {
7328          tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7329          tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7330       }
7331    } else {
7332       tempbx = SiS_Pr->PanelYRes;
7333       tempcx = SiS_Pr->SiS_VT;
7334       tempax = 1;
7335       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7336          tempax = SiS_Pr->PanelYRes;
7337          /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
7338          if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7339             tempax = tempcx = 0;
7340          } else {
7341             tempax -= SiS_Pr->SiS_VDE;
7342          }
7343          tempax >>= 1;
7344       }
7345       tempcx -= tempax; /* lcdvdes */
7346       tempbx -= tempax; /* lcdvdee */
7347    }
7348
7349    /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7350
7351    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);      /* lcdvdes  */
7352    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);      /* lcdvdee  */
7353
7354    temp = (tempbx >> 5) & 0x38;
7355    temp |= ((tempcx >> 8) & 0x07);
7356    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7357
7358    tempax = SiS_Pr->SiS_VDE;
7359    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7360       tempax = SiS_Pr->PanelYRes;
7361    }
7362    tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7363    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7364       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7365          tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7366       }
7367    }
7368
7369    tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7370    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7371       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7372          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7373             tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7374             if(tempax % 4) { tempax >>= 2; tempax++; }
7375             else           { tempax >>= 2;           }
7376             tempbx -= (tempax - 1);
7377          } else {
7378             tempbx -= 10;
7379             if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7380          }
7381       }
7382    }
7383    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7384       tempbx++;
7385       if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7386          if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7387             tempbx = 770;
7388             tempcx = 3;
7389          }
7390       }
7391    }
7392
7393    /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7394
7395    if(SiS_Pr->UseCustomMode) {
7396       tempbx = SiS_Pr->CVSyncStart;
7397    }
7398
7399    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);          /* lcdvrs */
7400
7401    temp = (tempbx >> 4) & 0xF0;
7402    tempbx += (tempcx + 1);
7403    temp |= (tempbx & 0x0F);
7404
7405    if(SiS_Pr->UseCustomMode) {
7406       temp &= 0xf0;
7407       temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7408    }
7409
7410    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7411
7412#ifdef CONFIG_FB_SIS_300
7413    SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
7414#endif
7415
7416    bridgeoffset = 7;
7417    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)       bridgeoffset += 2;
7418    if(SiS_Pr->SiS_VBType & VB_SIS30xCLV)       bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
7419    if(SiS_IsDualLink(SiS_Pr))                  bridgeoffset++;
7420    else if(SiS_Pr->SiS_VBType & VB_SIS302LV)   bridgeoffset++;    /* OK for Asus A4L 1280x800 */
7421    /* Higher bridgeoffset shifts to the LEFT */
7422
7423    temp = 0;
7424    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7425       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7426          temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7427          if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
7428       }
7429    }
7430    temp += bridgeoffset;
7431    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);             /* lcdhdes */
7432    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7433
7434    tempcx = SiS_Pr->SiS_HT;
7435    tempax = tempbx = SiS_Pr->SiS_HDE;
7436    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7437       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7438          tempax = SiS_Pr->PanelXRes;
7439          tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7440       }
7441    }
7442    if(SiS_IsDualLink(SiS_Pr)) {
7443       tempcx >>= 1;
7444       tempbx >>= 1;
7445       tempax >>= 1;
7446    }
7447
7448    tempbx += bridgeoffset;
7449
7450    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);          /* lcdhdee */
7451    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7452
7453    tempcx = (tempcx - tempax) >> 2;
7454
7455    tempbx += tempcx;
7456    push2 = tempbx;
7457
7458    if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7459       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7460          if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7461             if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7462          }
7463       }
7464    }
7465
7466    if(SiS_Pr->UseCustomMode) {
7467       tempbx = SiS_Pr->CHSyncStart;
7468       if(modeflag & HalfDCLK) tempbx <<= 1;
7469       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7470       tempbx += bridgeoffset;
7471    }
7472
7473    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);          /* lcdhrs */
7474    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7475
7476    tempbx = push2;
7477
7478    tempcx <<= 1;
7479    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7480       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7481    }
7482    tempbx += tempcx;
7483
7484    if(SiS_Pr->UseCustomMode) {
7485       tempbx = SiS_Pr->CHSyncEnd;
7486       if(modeflag & HalfDCLK) tempbx <<= 1;
7487       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7488       tempbx += bridgeoffset;
7489    }
7490
7491    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);          /* lcdhre */
7492
7493    SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7494
7495#ifdef CONFIG_FB_SIS_300
7496    SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
7497#endif
7498#ifdef CONFIG_FB_SIS_315
7499  } /* CRT2-LCD from table */
7500#endif
7501}
7502
7503/*********************************************/
7504/*         SET PART 3 REGISTER GROUP         */
7505/*********************************************/
7506
7507static void
7508SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
7509{
7510  unsigned short i;
7511  const unsigned char *tempdi;
7512
7513  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7514
7515#ifndef SIS_CP
7516  SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7517#else
7518  SIS_CP_INIT301_CP
7519#endif
7520
7521  if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7522     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7523     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7524  } else {
7525     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7526     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7527  }
7528
7529  if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7530     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7531     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7532     SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7533  }
7534
7535  tempdi = NULL;
7536  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7537     tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7538     if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7539        tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7540     }
7541  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7542     if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7543        tempdi = SiS_HiTVGroup3_1;
7544        if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7545     }
7546  }
7547  if(tempdi) {
7548     for(i=0; i<=0x3E; i++) {
7549        SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7550     }
7551     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
7552        if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7553           SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7554        }
7555     }
7556  }
7557
7558#ifdef SIS_CP
7559  SIS_CP_INIT301_CP2
7560#endif
7561}
7562
7563/*********************************************/
7564/*         SET PART 4 REGISTER GROUP         */
7565/*********************************************/
7566
7567#ifdef CONFIG_FB_SIS_315
7568#if 0
7569static void
7570SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
7571{
7572   unsigned short temp, temp1, temp2;
7573
7574   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7575   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
7576   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7577   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7578   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7579   temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
7580   temp = (unsigned short)((int)(temp) + shift);
7581   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7582   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7583   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
7584   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7585   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7586   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7587}
7588#endif
7589
7590static void
7591SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
7592{
7593   unsigned short temp, temp1;
7594   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
7595
7596   if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
7597   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7598
7599   if(SiS_Pr->ChipType >= XGI_20) return;
7600
7601   if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
7602      if(!(ROMAddr[0x61] & 0x04)) return;
7603   }
7604
7605   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7606   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7607   if(!(temp & 0x01)) {
7608      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7609      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
7610      if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
7611         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7612      }
7613      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7614      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
7615      else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7616      else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
7617      else                                         temp = 0x0402;
7618      if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
7619         temp1 = 0;
7620         if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7621         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7622         if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7623         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
7624         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7625         if(ModeNo > 0x13) {
7626            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
7627         }
7628      } else {
7629         temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7630         if(temp1 == 0x01) temp |= 0x01;
7631         if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
7632         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
7633         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7634         if(ModeNo > 0x13) {
7635            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7636         }
7637      }
7638
7639#if 0
7640      if(SiS_Pr->ChipType >= SIS_661) {                 /* ? */
7641         if(SiS_Pr->SiS_TVMode & TVAspect43) {
7642            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7643               if(resinfo == SIS_RI_1024x768) {
7644                  SiS_ShiftXPos(SiS_Pr, 97);
7645               } else {
7646                  SiS_ShiftXPos(SiS_Pr, 111);
7647               }
7648            } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7649               SiS_ShiftXPos(SiS_Pr, 136);
7650            }
7651         }
7652      }
7653#endif
7654
7655   }
7656
7657}
7658#endif
7659
7660static void
7661SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7662                 unsigned short RefreshRateTableIndex)
7663{
7664  unsigned short vclkindex, temp, reg1, reg2;
7665
7666  if(SiS_Pr->UseCustomMode) {
7667     reg1 = SiS_Pr->CSR2B;
7668     reg2 = SiS_Pr->CSR2C;
7669  } else {
7670     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
7671     reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7672     reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7673  }
7674
7675  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7676     if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
7677        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7678        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7679        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7680     } else {
7681        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7682        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7683     }
7684  } else {
7685     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7686     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7687     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7688  }
7689  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7690  temp = 0x08;
7691  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7692  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7693}
7694
7695static void
7696SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
7697{
7698  if(SiS_Pr->ChipType >= SIS_315H) {
7699     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
7700        if((SiS_CRT2IsLCD(SiS_Pr)) ||
7701           (SiS_IsVAMode(SiS_Pr))) {
7702           if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
7703              SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7704           } else {
7705              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7706           }
7707        }
7708     }
7709  }
7710  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
7711     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7712#ifdef SET_EMI
7713     SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7714#endif
7715     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7716  }
7717}
7718
7719static void
7720SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7721                unsigned short RefreshRateTableIndex)
7722{
7723  unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
7724  unsigned int   tempebx, tempeax, templong;
7725
7726  if(ModeNo <= 0x13) {
7727     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7728     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7729  } else if(SiS_Pr->UseCustomMode) {
7730     modeflag = SiS_Pr->CModeFlag;
7731     resinfo = 0;
7732  } else {
7733     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7734     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7735  }
7736
7737  if(SiS_Pr->ChipType >= SIS_315H) {
7738     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7739        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7740           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7741        }
7742     }
7743  }
7744
7745  if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
7746     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7747        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
7748     }
7749  }
7750
7751  if(SiS_Pr->ChipType >= SIS_315H) {
7752     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7753        SiS_SetDualLinkEtc(SiS_Pr);
7754        return;
7755     }
7756  }
7757
7758  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7759
7760  tempbx = SiS_Pr->SiS_RVBHCMAX;
7761  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7762
7763  temp = (tempbx >> 1) & 0x80;
7764
7765  tempcx = SiS_Pr->SiS_VGAHT - 1;
7766  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7767
7768  temp |= ((tempcx >> 5) & 0x78);
7769
7770  tempcx = SiS_Pr->SiS_VGAVT - 1;
7771  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7772  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7773
7774  temp |= ((tempcx >> 8) & 0x07);
7775  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7776
7777  tempbx = SiS_Pr->SiS_VGAHDE;
7778  if(modeflag & HalfDCLK)    tempbx >>= 1;
7779  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7780
7781  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7782     temp = 0;
7783     if(tempbx > 800)        temp = 0x60;
7784  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7785     temp = 0;
7786     if(tempbx > 1024)       temp = 0xC0;
7787     else if(tempbx >= 960)  temp = 0xA0;
7788  } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7789     temp = 0;
7790     if(tempbx >= 1280)      temp = 0x40;
7791     else if(tempbx >= 1024) temp = 0x20;
7792  } else {
7793     temp = 0x80;
7794     if(tempbx >= 1024)      temp = 0xA0;
7795  }
7796
7797  temp |= SiS_Pr->Init_P4_0E;
7798
7799  if(SiS_Pr->SiS_VBType & VB_SIS301) {
7800     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
7801        temp &= 0xf0;
7802        temp |= 0x0A;
7803     }
7804  }
7805
7806  SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7807
7808  tempeax = SiS_Pr->SiS_VGAVDE;
7809  tempebx = SiS_Pr->SiS_VDE;
7810  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7811     if(!(temp & 0xE0)) tempebx >>=1;
7812  }
7813
7814  tempcx = SiS_Pr->SiS_RVBHRS;
7815  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7816  tempcx >>= 8;
7817  tempcx |= 0x40;
7818
7819  if(tempeax <= tempebx) {
7820     tempcx ^= 0x40;
7821  } else {
7822     tempeax -= tempebx;
7823  }
7824
7825  tempeax *= (256 * 1024);
7826  templong = tempeax % tempebx;
7827  tempeax /= tempebx;
7828  if(templong) tempeax++;
7829
7830  temp = (unsigned short)(tempeax & 0x000000FF);
7831  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
7832  temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
7833  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
7834  temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
7835  temp |= (tempcx & 0x4F);
7836  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7837
7838  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7839
7840     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7841
7842     /* Calc Linebuffer max address and set/clear decimode */
7843     tempbx = 0;
7844     if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7845     tempax = SiS_Pr->SiS_VGAHDE;
7846     if(modeflag & HalfDCLK)    tempax >>= 1;
7847     if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
7848     if(tempax > 800) {
7849        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7850           tempax -= 800;
7851        } else {
7852           tempbx = 0x08;
7853           if(tempax == 960)       tempax *= 25; /* Correct */
7854           else if(tempax == 1024) tempax *= 25;
7855           else                    tempax *= 20;
7856           temp = tempax % 32;
7857           tempax /= 32;
7858           if(temp) tempax++;
7859           tempax++;
7860           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7861              if(resinfo == SIS_RI_1024x768 ||
7862                 resinfo == SIS_RI_1024x576 ||
7863                 resinfo == SIS_RI_1280x1024 ||
7864                 resinfo == SIS_RI_1280x720) {
7865                 /* Otherwise white line or garbage at right edge */
7866                 tempax = (tempax & 0xff00) | 0x20;
7867              }
7868           }
7869        }
7870     }
7871     tempax--;
7872     temp = ((tempax >> 4) & 0x30) | tempbx;
7873     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7874     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7875
7876     temp = 0x0036; tempbx = 0xD0;
7877     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
7878        temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7879     }
7880     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7881        if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7882           temp |= 0x01;
7883           if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7884              if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7885                 temp &= ~0x01;
7886              }
7887           }
7888        }
7889     }
7890     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7891
7892     tempbx = SiS_Pr->SiS_HT >> 1;
7893     if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7894     tempbx -= 2;
7895     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7896     temp = (tempbx >> 5) & 0x38;
7897     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7898
7899     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7900        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7901           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7902           /* LCD-too-dark-error-source, see FinalizeLCD() */
7903        }
7904     }
7905
7906     SiS_SetDualLinkEtc(SiS_Pr);
7907
7908  }  /* 301B */
7909
7910  SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
7911}
7912
7913/*********************************************/
7914/*         SET PART 5 REGISTER GROUP         */
7915/*********************************************/
7916
7917static void
7918SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
7919{
7920
7921  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)  return;
7922
7923  if(SiS_Pr->SiS_ModeType == ModeVGA) {
7924     if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7925        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
7926        SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
7927     }
7928  }
7929}
7930
7931/*********************************************/
7932/*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
7933/*********************************************/
7934
7935static bool
7936SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7937                   unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
7938                   unsigned short *DisplayType)
7939 {
7940  unsigned short modeflag = 0;
7941  bool checkhd = true;
7942
7943  /* Pass 1:1 not supported here */
7944
7945  if(ModeNo <= 0x13) {
7946     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7947     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7948  } else {
7949     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7950     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7951  }
7952
7953  (*ResIndex) &= 0x3F;
7954
7955  if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7956
7957     (*DisplayType) = 80;
7958     if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
7959        (*DisplayType) = 82;
7960        if(SiS_Pr->SiS_ModeType > ModeVGA) {
7961           if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
7962        }
7963     }
7964     if((*DisplayType) != 84) {
7965        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
7966     }
7967
7968  } else {
7969
7970     (*DisplayType = 0);
7971     switch(SiS_Pr->SiS_LCDResInfo) {
7972     case Panel_320x240_1: (*DisplayType) = 50;
7973                           checkhd = false;
7974                           break;
7975     case Panel_320x240_2: (*DisplayType) = 14;
7976                           break;
7977     case Panel_320x240_3: (*DisplayType) = 18;
7978                           break;
7979     case Panel_640x480:   (*DisplayType) = 10;
7980                           break;
7981     case Panel_1024x600:  (*DisplayType) = 26;
7982                           break;
7983     default: return true;
7984     }
7985
7986     if(checkhd) {
7987        if(modeflag & HalfDCLK) (*DisplayType)++;
7988     }
7989
7990     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
7991        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
7992     }
7993
7994  }
7995
7996  return true;
7997}
7998
7999static void
8000SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
8001                unsigned short RefreshRateTableIndex)
8002{
8003  unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
8004  const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
8005  static const unsigned short CRIdx[] = {
8006        0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
8007        0x07, 0x10, 0x11, 0x15, 0x16
8008  };
8009
8010  if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
8011     (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
8012     (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
8013     (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
8014     return;
8015
8016  if(SiS_Pr->SiS_IF_DEF_LVDS) {
8017     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
8018        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
8019     }
8020  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
8021     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
8022  } else return;
8023
8024  if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
8025
8026  if(SiS_Pr->ChipType < SIS_315H) {
8027     if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
8028  }
8029
8030  if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
8031                          &ResIndex, &DisplayType))) {
8032     return;
8033  }
8034
8035  switch(DisplayType) {
8036    case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1;           break; /* xSTN */
8037    case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2;           break; /* xSTN */
8038    case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H;         break; /* xSTN */
8039    case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3;           break; /* xSTN */
8040    case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H;         break; /* xSTN */
8041    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1;           break;
8042    case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H;         break;
8043#if 0 /* Works better with calculated numbers */
8044    case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1;          break;
8045    case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H;        break;
8046    case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2;          break;
8047    case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H;        break;
8048#endif
8049    case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC;               break;
8050    case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC;               break;
8051    case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL;                break;
8052    case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL;                break;
8053    case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL;               break;
8054  }
8055
8056  if(LVDSCRT1Ptr) {
8057
8058     SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
8059
8060     for(i = 0; i <= 10; i++) {
8061        tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
8062        SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
8063     }
8064
8065     for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
8066        tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8067        SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
8068     }
8069
8070     tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
8071     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
8072
8073     if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
8074     else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
8075
8076     tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
8077     if(modeflag & DoubleScanMode) tempah |= 0x80;
8078     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
8079
8080  } else {
8081
8082     SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
8083
8084  }
8085}
8086
8087/*********************************************/
8088/*              SET CRT2 ECLK                */
8089/*********************************************/
8090
8091static void
8092SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
8093           unsigned short RefreshRateTableIndex)
8094{
8095  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
8096  unsigned short clkbase, vclkindex = 0;
8097  unsigned char  sr2b, sr2c;
8098
8099  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
8100     SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
8101     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
8102        RefreshRateTableIndex--;
8103     }
8104     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
8105                                    RefreshRateTableIndex);
8106     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8107  } else {
8108     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
8109                                    RefreshRateTableIndex);
8110  }
8111
8112  sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
8113  sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
8114
8115  if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
8116     if(SiS_Pr->SiS_UseROM) {
8117        if(ROMAddr[0x220] & 0x01) {
8118           sr2b = ROMAddr[0x227];
8119           sr2c = ROMAddr[0x228];
8120        }
8121     }
8122  }
8123
8124  clkbase = 0x02B;
8125  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
8126     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
8127        clkbase += 3;
8128     }
8129  }
8130
8131  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
8132  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
8133  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
8134  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
8135  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
8136  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
8137  SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
8138  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
8139  SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
8140}
8141
8142/*********************************************/
8143/*           SET UP CHRONTEL CHIPS           */
8144/*********************************************/
8145
8146static void
8147SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
8148               unsigned short RefreshRateTableIndex)
8149{
8150   unsigned short TVType, resindex;
8151   const struct SiS_CHTVRegData *CHTVRegData = NULL;
8152
8153   if(ModeNo <= 0x13)
8154      resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
8155   else
8156      resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
8157
8158   resindex &= 0x3F;
8159
8160   TVType = 0;
8161   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
8162   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
8163      TVType += 2;
8164      if(SiS_Pr->SiS_ModeType > ModeVGA) {
8165         if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
8166      }
8167      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
8168         TVType = 4;
8169         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
8170      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
8171         TVType = 6;
8172         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
8173      }
8174   }
8175
8176   switch(TVType) {
8177      case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
8178      case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
8179      case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
8180      case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
8181      case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
8182      case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
8183      case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
8184      case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
8185      case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
8186      default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
8187   }
8188
8189
8190   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8191
8192#ifdef CONFIG_FB_SIS_300
8193
8194      /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
8195
8196      /* We don't support modes >800x600 */
8197      if (resindex > 5) return;
8198
8199      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
8200         SiS_SetCH700x(SiS_Pr,0x04,0x43);  /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
8201         SiS_SetCH700x(SiS_Pr,0x09,0x69);  /* Black level for PAL (105)*/
8202      } else {
8203         SiS_SetCH700x(SiS_Pr,0x04,0x03);   /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
8204         SiS_SetCH700x(SiS_Pr,0x09,0x71);   /* Black level for NTSC (113)*/
8205      }
8206
8207      SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]);  /* Mode register */
8208      SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]);  /* Start active video register */
8209      SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]);  /* Position overflow register */
8210      SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]);  /* Horiz Position register */
8211      SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]);  /* Vertical Position register */
8212
8213      /* Set minimum flicker filter for Luma channel (SR1-0=00),
8214                minimum text enhancement (S3-2=10),
8215                maximum flicker filter for Chroma channel (S5-4=10)
8216                =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
8217       */
8218      SiS_SetCH700x(SiS_Pr,0x01,0x28);
8219
8220      /* Set video bandwidth
8221            High bandwidth Luma composite video filter(S0=1)
8222            low bandwidth Luma S-video filter (S2-1=00)
8223            disable peak filter in S-video channel (S3=0)
8224            high bandwidth Chroma Filter (S5-4=11)
8225            =00110001=0x31
8226      */
8227      SiS_SetCH700x(SiS_Pr,0x03,0xb1);       /* old: 3103 */
8228
8229      /* Register 0x3D does not exist in non-macrovision register map
8230            (Maybe this is a macrovision register?)
8231       */
8232#ifndef SIS_CP
8233      SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
8234#endif
8235
8236      /* Register 0x10 only contains 1 writable bit (S0) for sensing,
8237             all other bits a read-only. Macrovision?
8238       */
8239      SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
8240
8241      /* Register 0x11 only contains 3 writable bits (S0-S2) for
8242             contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
8243       */
8244      SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
8245
8246      /* Clear DSEN
8247       */
8248      SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
8249
8250      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {            /* ---- NTSC ---- */
8251         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
8252            if(resindex == 0x04) {                      /* 640x480 overscan: Mode 16 */
8253               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off */
8254               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);       /* ACIV on, no need to set FSCI */
8255            } else if(resindex == 0x05) {               /* 800x600 overscan: Mode 23 */
8256               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);       /* 0x18-0x1f: FSCI 469,762,048 */
8257               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
8258               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
8259               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
8260               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
8261               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
8262               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
8263               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
8264               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF);       /* Loop filter on for mode 23 */
8265               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);       /* ACIV off, need to set FSCI */
8266            }
8267         } else {
8268            if(resindex == 0x04) {                      /* ----- 640x480 underscan; Mode 17 */
8269               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off */
8270               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
8271            } else if(resindex == 0x05) {               /* ----- 800x600 underscan: Mode 24 */
8272#if 0
8273               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);       /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
8274               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0);       /* FSCI for mode 24 is 428,554,851 */
8275               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0);       /* 198b3a63 */
8276               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
8277               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
8278               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
8279               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
8280               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
8281               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off for mode 24 */
8282               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);       * ACIV off, need to set FSCI */
8283#endif         /* All alternatives wrong (datasheet wrong?), don't use FSCI */
8284               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);        /* loop filter off */
8285               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
8286            }
8287         }
8288      } else {                                          /* ---- PAL ---- */
8289        /* We don't play around with FSCI in PAL mode */
8290        SiS_SetCH70xxANDOR(SiS_Pr, 0x20, 0x00, 0xEF);   /* loop filter off */
8291        SiS_SetCH70xxANDOR(SiS_Pr, 0x21, 0x01, 0xFE);   /* ACIV on */
8292      }
8293
8294#endif  /* 300 */
8295
8296   } else {
8297
8298      /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
8299
8300#ifdef CONFIG_FB_SIS_315
8301
8302      unsigned short temp;
8303
8304      /* We don't support modes >1024x768 */
8305      if (resindex > 6) return;
8306
8307      temp = CHTVRegData[resindex].Reg[0];
8308      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
8309      SiS_SetCH701x(SiS_Pr,0x00,temp);
8310
8311      SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
8312      SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
8313      SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
8314      SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
8315      SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
8316      SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
8317
8318      temp = CHTVRegData[resindex].Reg[7];
8319      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
8320      SiS_SetCH701x(SiS_Pr,0x07,temp);
8321
8322      SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
8323      SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
8324      SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
8325      SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
8326      SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
8327      SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
8328      SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
8329      SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
8330
8331      temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8332      /* D1 should be set for PAL, PAL-N and NTSC-J,
8333         but I won't do that for PAL unless somebody
8334         tells me to do so. Since the BIOS uses
8335         non-default CIV values and blacklevels,
8336         this might be compensated anyway.
8337       */
8338      if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8339      SiS_SetCH701x(SiS_Pr,0x21,temp);
8340
8341#endif  /* 315 */
8342
8343   }
8344
8345#ifdef SIS_CP
8346   SIS_CP_INIT301_CP3
8347#endif
8348
8349}
8350
8351#ifdef CONFIG_FB_SIS_315  /* ----------- 315 series only ---------- */
8352
8353void
8354SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
8355{
8356   unsigned short temp;
8357
8358   /* Enable Chrontel 7019 LCD panel backlight */
8359   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8360      if(SiS_Pr->ChipType == SIS_740) {
8361         SiS_SetCH701x(SiS_Pr,0x66,0x65);
8362      } else {
8363         temp = SiS_GetCH701x(SiS_Pr,0x66);
8364         temp |= 0x20;
8365         SiS_SetCH701x(SiS_Pr,0x66,temp);
8366      }
8367   }
8368}
8369
8370void
8371SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
8372{
8373   unsigned short temp;
8374
8375   /* Disable Chrontel 7019 LCD panel backlight */
8376   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8377      temp = SiS_GetCH701x(SiS_Pr,0x66);
8378      temp &= 0xDF;
8379      SiS_SetCH701x(SiS_Pr,0x66,temp);
8380   }
8381}
8382
8383static void
8384SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
8385{
8386  static const unsigned char regtable[]      = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8387  static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8388  static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8389  static const unsigned char asus1024_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8390  static const unsigned char asus1400_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8391  static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8392  static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8393  const unsigned char *tableptr = NULL;
8394  int i;
8395
8396  /* Set up Power up/down timing */
8397
8398  if(SiS_Pr->ChipType == SIS_740) {
8399     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8400        if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8401        else                                      tableptr = table1024_740;
8402     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8403               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8404               (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8405        if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8406        else                                      tableptr = table1400_740;
8407     } else return;
8408  } else {
8409     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8410        tableptr = table1024_650;
8411     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8412               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8413               (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8414        tableptr = table1400_650;
8415     } else return;
8416  }
8417
8418  for(i=0; i<5; i++) {
8419     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
8420  }
8421}
8422
8423static void
8424SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
8425{
8426  const unsigned char *tableptr = NULL;
8427  unsigned short tempbh;
8428  int i;
8429  static const unsigned char regtable[] = {
8430                0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8431                0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
8432  };
8433  static const unsigned char table1024_740[] = {
8434                0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8435                0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
8436  };
8437  static const unsigned char table1280_740[] = {
8438                0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8439                0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8440  };
8441  static const unsigned char table1400_740[] = {
8442                0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8443                0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8444  };
8445  static const unsigned char table1600_740[] = {
8446                0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8447                0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
8448  };
8449  static const unsigned char table1024_650[] = {
8450                0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8451                0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
8452  };
8453  static const unsigned char table1280_650[] = {
8454                0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8455                0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
8456  };
8457  static const unsigned char table1400_650[] = {
8458                0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8459                0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
8460  };
8461  static const unsigned char table1600_650[] = {
8462                0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8463                0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
8464  };
8465
8466  if(SiS_Pr->ChipType == SIS_740) {
8467     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
8468     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8469     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8470     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8471     else return;
8472  } else {
8473     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
8474     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8475     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8476     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8477     else return;
8478  }
8479
8480  tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8481  if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8482     tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8483     if(tempbh == 0xc8) {
8484        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8485     } else if(tempbh == 0xdb) {
8486        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8487        if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8488     } else if(tempbh == 0xde) {
8489        if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8490     }
8491  }
8492
8493  if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
8494  else                            tempbh = 0x0c;
8495
8496  for(i = 0; i < tempbh; i++) {
8497     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
8498  }
8499  SiS_ChrontelPowerSequencing(SiS_Pr);
8500  tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8501  tempbh |= 0xc0;
8502  SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
8503
8504  if(SiS_Pr->ChipType == SIS_740) {
8505     tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8506     tempbh &= 0xfb;
8507     SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
8508     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8509     tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8510     tempbh |= 0x40;
8511     SiS_SetCH701x(SiS_Pr,0x64,tempbh);
8512     tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8513     tempbh &= 0x3f;
8514     SiS_SetCH701x(SiS_Pr,0x03,tempbh);
8515  }
8516}
8517
8518static void
8519SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
8520{
8521  unsigned char temp, temp1;
8522
8523  temp1 = SiS_GetCH701x(SiS_Pr,0x49);
8524  SiS_SetCH701x(SiS_Pr,0x49,0x3e);
8525  temp = SiS_GetCH701x(SiS_Pr,0x47);
8526  temp &= 0x7f; /* Use external VSYNC */
8527  SiS_SetCH701x(SiS_Pr,0x47,temp);
8528  SiS_LongDelay(SiS_Pr, 3);
8529  temp = SiS_GetCH701x(SiS_Pr,0x47);
8530  temp |= 0x80; /* Use internal VSYNC */
8531  SiS_SetCH701x(SiS_Pr,0x47,temp);
8532  SiS_SetCH701x(SiS_Pr,0x49,temp1);
8533}
8534
8535static void
8536SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
8537{
8538  unsigned short temp;
8539
8540  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8541     if(SiS_Pr->ChipType == SIS_740) {
8542        temp = SiS_GetCH701x(SiS_Pr,0x1c);
8543        temp |= 0x04;   /* Invert XCLK phase */
8544        SiS_SetCH701x(SiS_Pr,0x1c,temp);
8545     }
8546     if(SiS_IsYPbPr(SiS_Pr)) {
8547        temp = SiS_GetCH701x(SiS_Pr,0x01);
8548        temp &= 0x3f;
8549        temp |= 0x80;   /* Enable YPrPb (HDTV) */
8550        SiS_SetCH701x(SiS_Pr,0x01,temp);
8551     }
8552     if(SiS_IsChScart(SiS_Pr)) {
8553        temp = SiS_GetCH701x(SiS_Pr,0x01);
8554        temp &= 0x3f;
8555        temp |= 0xc0;   /* Enable SCART + CVBS */
8556        SiS_SetCH701x(SiS_Pr,0x01,temp);
8557     }
8558     if(SiS_Pr->ChipType == SIS_740) {
8559        SiS_ChrontelResetVSync(SiS_Pr);
8560        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
8561     } else {
8562        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
8563        temp = SiS_GetCH701x(SiS_Pr,0x49);
8564        if(SiS_IsYPbPr(SiS_Pr)) {
8565           temp = SiS_GetCH701x(SiS_Pr,0x73);
8566           temp |= 0x60;
8567           SiS_SetCH701x(SiS_Pr,0x73,temp);
8568        }
8569        temp = SiS_GetCH701x(SiS_Pr,0x47);
8570        temp &= 0x7f;
8571        SiS_SetCH701x(SiS_Pr,0x47,temp);
8572        SiS_LongDelay(SiS_Pr, 2);
8573        temp = SiS_GetCH701x(SiS_Pr,0x47);
8574        temp |= 0x80;
8575        SiS_SetCH701x(SiS_Pr,0x47,temp);
8576     }
8577  }
8578}
8579
8580static void
8581SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
8582{
8583  unsigned short temp;
8584
8585  /* Complete power down of LVDS */
8586  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8587     if(SiS_Pr->ChipType == SIS_740) {
8588        SiS_LongDelay(SiS_Pr, 1);
8589        SiS_GenericDelay(SiS_Pr, 5887);
8590        SiS_SetCH701x(SiS_Pr,0x76,0xac);
8591        SiS_SetCH701x(SiS_Pr,0x66,0x00);
8592     } else {
8593        SiS_LongDelay(SiS_Pr, 2);
8594        temp = SiS_GetCH701x(SiS_Pr,0x76);
8595        temp &= 0xfc;
8596        SiS_SetCH701x(SiS_Pr,0x76,temp);
8597        SiS_SetCH701x(SiS_Pr,0x66,0x00);
8598     }
8599  }
8600}
8601
8602static void
8603SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
8604{
8605     unsigned short temp;
8606
8607     if(SiS_Pr->ChipType == SIS_740) {
8608
8609        temp = SiS_GetCH701x(SiS_Pr,0x4a);  /* Version ID */
8610        temp &= 0x01;
8611        if(!temp) {
8612
8613           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8614              temp = SiS_GetCH701x(SiS_Pr,0x49);
8615              SiS_SetCH701x(SiS_Pr,0x49,0x3e);
8616           }
8617
8618           /* Reset Chrontel 7019 datapath */
8619           SiS_SetCH701x(SiS_Pr,0x48,0x10);
8620           SiS_LongDelay(SiS_Pr, 1);
8621           SiS_SetCH701x(SiS_Pr,0x48,0x18);
8622
8623           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8624              SiS_ChrontelResetVSync(SiS_Pr);
8625              SiS_SetCH701x(SiS_Pr,0x49,temp);
8626           }
8627
8628        } else {
8629
8630           /* Clear/set/clear GPIO */
8631           temp = SiS_GetCH701x(SiS_Pr,0x5c);
8632           temp &= 0xef;
8633           SiS_SetCH701x(SiS_Pr,0x5c,temp);
8634           temp = SiS_GetCH701x(SiS_Pr,0x5c);
8635           temp |= 0x10;
8636           SiS_SetCH701x(SiS_Pr,0x5c,temp);
8637           temp = SiS_GetCH701x(SiS_Pr,0x5c);
8638           temp &= 0xef;
8639           SiS_SetCH701x(SiS_Pr,0x5c,temp);
8640           temp = SiS_GetCH701x(SiS_Pr,0x61);
8641           if(!temp) {
8642              SiS_SetCH701xForLCD(SiS_Pr);
8643           }
8644        }
8645
8646     } else { /* 650 */
8647        /* Reset Chrontel 7019 datapath */
8648        SiS_SetCH701x(SiS_Pr,0x48,0x10);
8649        SiS_LongDelay(SiS_Pr, 1);
8650        SiS_SetCH701x(SiS_Pr,0x48,0x18);
8651     }
8652}
8653
8654static void
8655SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
8656{
8657     unsigned short temp;
8658
8659     if(SiS_Pr->ChipType == SIS_740) {
8660
8661        if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8662           SiS_ChrontelResetVSync(SiS_Pr);
8663        }
8664
8665     } else {
8666
8667        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* Power up LVDS block */
8668        temp = SiS_GetCH701x(SiS_Pr,0x49);
8669        temp &= 1;
8670        if(temp != 1) {  /* TV block powered? (0 = yes, 1 = no) */
8671           temp = SiS_GetCH701x(SiS_Pr,0x47);
8672           temp &= 0x70;
8673           SiS_SetCH701x(SiS_Pr,0x47,temp);  /* enable VSYNC */
8674           SiS_LongDelay(SiS_Pr, 3);
8675           temp = SiS_GetCH701x(SiS_Pr,0x47);
8676           temp |= 0x80;
8677           SiS_SetCH701x(SiS_Pr,0x47,temp);  /* disable VSYNC */
8678        }
8679
8680     }
8681}
8682
8683static void
8684SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8685{
8686     unsigned short temp,temp1;
8687
8688     if(SiS_Pr->ChipType == SIS_740) {
8689
8690        temp = SiS_GetCH701x(SiS_Pr,0x61);
8691        if(temp < 1) {
8692           temp++;
8693           SiS_SetCH701x(SiS_Pr,0x61,temp);
8694        }
8695        SiS_SetCH701x(SiS_Pr,0x66,0x45);  /* Panel power on */
8696        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on */
8697        SiS_LongDelay(SiS_Pr, 1);
8698        SiS_GenericDelay(SiS_Pr, 5887);
8699
8700     } else {  /* 650 */
8701
8702        temp1 = 0;
8703        temp = SiS_GetCH701x(SiS_Pr,0x61);
8704        if(temp < 2) {
8705           temp++;
8706           SiS_SetCH701x(SiS_Pr,0x61,temp);
8707           temp1 = 1;
8708        }
8709        SiS_SetCH701x(SiS_Pr,0x76,0xac);
8710        temp = SiS_GetCH701x(SiS_Pr,0x66);
8711        temp |= 0x5f;
8712        SiS_SetCH701x(SiS_Pr,0x66,temp);
8713        if(ModeNo > 0x13) {
8714           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8715              SiS_GenericDelay(SiS_Pr, 1023);
8716           } else {
8717              SiS_GenericDelay(SiS_Pr, 767);
8718           }
8719        } else {
8720           if(!temp1)
8721              SiS_GenericDelay(SiS_Pr, 767);
8722        }
8723        temp = SiS_GetCH701x(SiS_Pr,0x76);
8724        temp |= 0x03;
8725        SiS_SetCH701x(SiS_Pr,0x76,temp);
8726        temp = SiS_GetCH701x(SiS_Pr,0x66);
8727        temp &= 0x7f;
8728        SiS_SetCH701x(SiS_Pr,0x66,temp);
8729        SiS_LongDelay(SiS_Pr, 1);
8730
8731     }
8732}
8733
8734static void
8735SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
8736{
8737     unsigned short temp;
8738
8739     SiS_LongDelay(SiS_Pr, 1);
8740
8741     do {
8742       temp = SiS_GetCH701x(SiS_Pr,0x66);
8743       temp &= 0x04;  /* PLL stable? -> bail out */
8744       if(temp == 0x04) break;
8745
8746       if(SiS_Pr->ChipType == SIS_740) {
8747          /* Power down LVDS output, PLL normal operation */
8748          SiS_SetCH701x(SiS_Pr,0x76,0xac);
8749       }
8750
8751       SiS_SetCH701xForLCD(SiS_Pr);
8752
8753       temp = SiS_GetCH701x(SiS_Pr,0x76);
8754       temp &= 0xfb;  /* Reset PLL */
8755       SiS_SetCH701x(SiS_Pr,0x76,temp);
8756       SiS_LongDelay(SiS_Pr, 2);
8757       temp = SiS_GetCH701x(SiS_Pr,0x76);
8758       temp |= 0x04;  /* PLL normal operation */
8759       SiS_SetCH701x(SiS_Pr,0x76,temp);
8760       if(SiS_Pr->ChipType == SIS_740) {
8761          SiS_SetCH701x(SiS_Pr,0x78,0xe0);      /* PLL loop filter */
8762       } else {
8763          SiS_SetCH701x(SiS_Pr,0x78,0x60);
8764       }
8765       SiS_LongDelay(SiS_Pr, 2);
8766    } while(0);
8767
8768    SiS_SetCH701x(SiS_Pr,0x77,0x00);  /* MV? */
8769}
8770
8771static void
8772SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
8773{
8774     unsigned short temp;
8775
8776     temp = SiS_GetCH701x(SiS_Pr,0x03);
8777     temp |= 0x80;      /* Set datapath 1 to TV   */
8778     temp &= 0xbf;      /* Set datapath 2 to LVDS */
8779     SiS_SetCH701x(SiS_Pr,0x03,temp);
8780
8781     if(SiS_Pr->ChipType == SIS_740) {
8782
8783        temp = SiS_GetCH701x(SiS_Pr,0x1c);
8784        temp &= 0xfb;   /* Normal XCLK phase */
8785        SiS_SetCH701x(SiS_Pr,0x1c,temp);
8786
8787        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8788
8789        temp = SiS_GetCH701x(SiS_Pr,0x64);
8790        temp |= 0x40;   /* ? Bit not defined */
8791        SiS_SetCH701x(SiS_Pr,0x64,temp);
8792
8793        temp = SiS_GetCH701x(SiS_Pr,0x03);
8794        temp &= 0x3f;   /* D1 input to both LVDS and TV */
8795        SiS_SetCH701x(SiS_Pr,0x03,temp);
8796
8797        if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
8798           SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
8799           SiS_LongDelay(SiS_Pr, 1);
8800           SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
8801           SiS_ChrontelResetDB(SiS_Pr);
8802           SiS_ChrontelDoSomething2(SiS_Pr);
8803           SiS_ChrontelDoSomething3(SiS_Pr, 0);
8804        } else {
8805           temp = SiS_GetCH701x(SiS_Pr,0x66);
8806           if(temp != 0x45) {
8807              SiS_ChrontelResetDB(SiS_Pr);
8808              SiS_ChrontelDoSomething2(SiS_Pr);
8809              SiS_ChrontelDoSomething3(SiS_Pr, 0);
8810           }
8811        }
8812
8813     } else { /* 650 */
8814
8815        SiS_ChrontelResetDB(SiS_Pr);
8816        SiS_ChrontelDoSomething2(SiS_Pr);
8817        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
8818        SiS_ChrontelDoSomething3(SiS_Pr,temp);
8819        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on, LVDS normal operation */
8820
8821     }
8822
8823}
8824#endif  /* 315 series  */
8825
8826/*********************************************/
8827/*      MAIN: SET CRT2 REGISTER GROUP        */
8828/*********************************************/
8829
8830bool
8831SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8832{
8833#ifdef CONFIG_FB_SIS_300
8834   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
8835#endif
8836   unsigned short ModeIdIndex, RefreshRateTableIndex;
8837
8838   SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8839
8840   if(!SiS_Pr->UseCustomMode) {
8841      SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8842   } else {
8843      ModeIdIndex = 0;
8844   }
8845
8846   /* Used for shifting CR33 */
8847   SiS_Pr->SiS_SelectCRT2Rate = 4;
8848
8849   SiS_UnLockCRT2(SiS_Pr);
8850
8851   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
8852
8853   SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8854
8855   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8856      SiS_DisableBridge(SiS_Pr);
8857      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
8858         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8859      }
8860      SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
8861   }
8862
8863   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
8864      SiS_LockCRT2(SiS_Pr);
8865      SiS_DisplayOn(SiS_Pr);
8866      return true;
8867   }
8868
8869   SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8870
8871   /* Set up Panel Link for LVDS and LCDA */
8872   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8873   if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8874       ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
8875       ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
8876      SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8877   }
8878
8879   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8880      SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8881   }
8882
8883   if(SiS_Pr->SiS_VBType & VB_SISVB) {
8884
8885      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8886
8887         SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8888#ifdef CONFIG_FB_SIS_315
8889         SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8890#endif
8891         SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
8892         SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8893#ifdef CONFIG_FB_SIS_315
8894         SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
8895#endif
8896         SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
8897
8898         SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
8899
8900         /* For 301BDH (Panel link initialization): */
8901         if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8902
8903            if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8904               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8905                  SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8906               }
8907            }
8908            SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8909         }
8910      }
8911
8912   } else {
8913
8914      SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
8915
8916      SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8917
8918      SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8919
8920      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8921         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8922            if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8923               if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8924#ifdef CONFIG_FB_SIS_315
8925                  SiS_SetCH701xForLCD(SiS_Pr);
8926#endif
8927               }
8928            }
8929            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8930               SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8931            }
8932         }
8933      }
8934
8935   }
8936
8937#ifdef CONFIG_FB_SIS_300
8938   if(SiS_Pr->ChipType < SIS_315H) {
8939      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8940         if(SiS_Pr->SiS_UseOEM) {
8941            if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8942               if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
8943                  SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8944               }
8945            } else {
8946               SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8947            }
8948         }
8949         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
8950            if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
8951               (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
8952               SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
8953            }
8954            SiS_DisplayOn(SiS_Pr);
8955         }
8956      }
8957   }
8958#endif
8959
8960#ifdef CONFIG_FB_SIS_315
8961   if(SiS_Pr->ChipType >= SIS_315H) {
8962      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8963         if(SiS_Pr->ChipType < SIS_661) {
8964            SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
8965            SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8966         } else {
8967            SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8968         }
8969         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
8970      }
8971   }
8972#endif
8973
8974   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8975      SiS_EnableBridge(SiS_Pr);
8976   }
8977
8978   SiS_DisplayOn(SiS_Pr);
8979
8980   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8981      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8982         /* Disable LCD panel when using TV */
8983         SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
8984      } else {
8985         /* Disable TV when using LCD */
8986         SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
8987      }
8988   }
8989
8990   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8991      SiS_LockCRT2(SiS_Pr);
8992   }
8993
8994   return true;
8995}
8996
8997
8998/*********************************************/
8999/*     ENABLE/DISABLE LCD BACKLIGHT (SIS)    */
9000/*********************************************/
9001
9002void
9003SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
9004{
9005  /* Switch on LCD backlight on SiS30xLV */
9006  SiS_DDC2Delay(SiS_Pr,0xff00);
9007  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
9008     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
9009     SiS_WaitVBRetrace(SiS_Pr);
9010  }
9011  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
9012     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
9013  }
9014}
9015
9016void
9017SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
9018{
9019  /* Switch off LCD backlight on SiS30xLV */
9020  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
9021  SiS_DDC2Delay(SiS_Pr,0xff00);
9022}
9023
9024/*********************************************/
9025/*          DDC RELATED FUNCTIONS            */
9026/*********************************************/
9027
9028static void
9029SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
9030{
9031  SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
9032  SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
9033  if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
9034     SiS_Pr->SiS_DDC_NData &= 0x0f;
9035     SiS_Pr->SiS_DDC_NClk  &= 0x0f;
9036  }
9037}
9038
9039#ifdef CONFIG_FB_SIS_300
9040static unsigned char *
9041SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
9042{
9043  int i, j, num;
9044  unsigned short tempah,temp;
9045  unsigned char *mydataptr;
9046
9047  for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
9048     mydataptr = dataptr;
9049     num = *mydataptr++;
9050     if(!num) return mydataptr;
9051     if(i) {
9052        SiS_SetStop(SiS_Pr);
9053        SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
9054     }
9055     if(SiS_SetStart(SiS_Pr)) continue;         /* Set start condition */
9056     tempah = SiS_Pr->SiS_DDC_DeviceAddr;
9057     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write DAB (S0=0=write) */
9058     if(temp) continue;                         /*    (ERROR: no ack) */
9059     tempah = *mydataptr++;
9060     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write register number */
9061     if(temp) continue;                         /*    (ERROR: no ack) */
9062     for(j=0; j<num; j++) {
9063        tempah = *mydataptr++;
9064        temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
9065        if(temp) break;
9066     }
9067     if(temp) continue;
9068     if(SiS_SetStop(SiS_Pr)) continue;
9069     return mydataptr;
9070  }
9071  return NULL;
9072}
9073
9074static bool
9075SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
9076{
9077  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;            /* DAB (Device Address Byte) */
9078  SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9079  SiS_Pr->SiS_DDC_Data  = 0x02;                 /* Bitmask in IndexReg for Data */
9080  SiS_Pr->SiS_DDC_Clk   = 0x01;                 /* Bitmask in IndexReg for Clk */
9081  SiS_SetupDDCN(SiS_Pr);
9082
9083  SiS_SetSwitchDDC2(SiS_Pr);
9084
9085  while(*dataptr) {
9086     dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
9087     if(!dataptr) return false;
9088  }
9089  return true;
9090}
9091#endif
9092
9093/* The Chrontel 700x is connected to the 630/730 via
9094 * the 630/730's DDC/I2C port.
9095 *
9096 * On 630(S)T chipset, the index changed from 0x11 to
9097 * 0x0a, possibly for working around the DDC problems
9098 */
9099
9100static bool
9101SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
9102{
9103  unsigned short temp, i;
9104
9105  for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
9106     if(i) {
9107        SiS_SetStop(SiS_Pr);
9108        SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
9109     }
9110     if(SiS_SetStart(SiS_Pr)) continue;                                 /* Set start condition */
9111     temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr);      /* Write DAB (S0=0=write) */
9112     if(temp) continue;                                                 /*    (ERROR: no ack) */
9113     temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor));                    /* Write RAB (700x: set bit 7, see datasheet) */
9114     if(temp) continue;                                                 /*    (ERROR: no ack) */
9115     temp = SiS_WriteDDC2Data(SiS_Pr, val);                             /* Write data */
9116     if(temp) continue;                                                 /*    (ERROR: no ack) */
9117     if(SiS_SetStop(SiS_Pr)) continue;                                  /* Set stop condition */
9118     SiS_Pr->SiS_ChrontelInit = 1;
9119     return true;
9120  }
9121  return false;
9122}
9123
9124/* Write to Chrontel 700x */
9125void
9126SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
9127{
9128  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
9129
9130  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9131
9132  if(!(SiS_Pr->SiS_ChrontelInit)) {
9133     SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
9134     SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
9135     SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
9136     SiS_SetupDDCN(SiS_Pr);
9137  }
9138
9139  if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
9140      (!(SiS_Pr->SiS_ChrontelInit)) ) {
9141     SiS_Pr->SiS_DDC_Index = 0x0a;
9142     SiS_Pr->SiS_DDC_Data  = 0x80;
9143     SiS_Pr->SiS_DDC_Clk   = 0x40;
9144     SiS_SetupDDCN(SiS_Pr);
9145
9146     SiS_SetChReg(SiS_Pr, reg, val, 0x80);
9147  }
9148}
9149
9150/* Write to Chrontel 701x */
9151/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
9152void
9153SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
9154{
9155  SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9156  SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
9157  SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
9158  SiS_SetupDDCN(SiS_Pr);
9159  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
9160  SiS_SetChReg(SiS_Pr, reg, val, 0);
9161}
9162
9163static
9164void
9165SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
9166{
9167  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
9168     SiS_SetCH700x(SiS_Pr, reg, val);
9169  else
9170     SiS_SetCH701x(SiS_Pr, reg, val);
9171}
9172
9173static unsigned short
9174SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
9175{
9176  unsigned short tempah, temp, i;
9177
9178  for(i=0; i<20; i++) {                         /* Do 20 attempts to read */
9179     if(i) {
9180        SiS_SetStop(SiS_Pr);
9181        SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
9182     }
9183     if(SiS_SetStart(SiS_Pr)) continue;                                 /* Set start condition */
9184     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr);       /* Write DAB (S0=0=write) */
9185     if(temp) continue;                                                 /*        (ERROR: no ack) */
9186     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor);  /* Write RAB (700x: | 0x80) */
9187     if(temp) continue;                                                 /*        (ERROR: no ack) */
9188     if (SiS_SetStart(SiS_Pr)) continue;                                /* Re-start */
9189     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
9190     if(temp) continue;                                                 /*        (ERROR: no ack) */
9191     tempah = SiS_ReadDDC2Data(SiS_Pr);                                 /* Read byte */
9192     if(SiS_SetStop(SiS_Pr)) continue;                                  /* Stop condition */
9193     SiS_Pr->SiS_ChrontelInit = 1;
9194     return tempah;
9195  }
9196  return 0xFFFF;
9197}
9198
9199/* Read from Chrontel 700x */
9200/* Parameter is [Register no (S7-S0)] */
9201unsigned short
9202SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
9203{
9204  unsigned short result;
9205
9206  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
9207
9208  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9209
9210  if(!(SiS_Pr->SiS_ChrontelInit)) {
9211     SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
9212     SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
9213     SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
9214     SiS_SetupDDCN(SiS_Pr);
9215  }
9216
9217  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9218
9219  if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
9220      (!SiS_Pr->SiS_ChrontelInit) ) {
9221
9222     SiS_Pr->SiS_DDC_Index = 0x0a;
9223     SiS_Pr->SiS_DDC_Data  = 0x80;
9224     SiS_Pr->SiS_DDC_Clk   = 0x40;
9225     SiS_SetupDDCN(SiS_Pr);
9226
9227     result = SiS_GetChReg(SiS_Pr,0x80);
9228  }
9229  return result;
9230}
9231
9232/* Read from Chrontel 701x */
9233/* Parameter is [Register no (S7-S0)] */
9234unsigned short
9235SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
9236{
9237  SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9238  SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
9239  SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
9240  SiS_SetupDDCN(SiS_Pr);
9241  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
9242
9243  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9244
9245  return SiS_GetChReg(SiS_Pr,0);
9246}
9247
9248/* Read from Chrontel 70xx */
9249/* Parameter is [Register no (S7-S0)] */
9250static
9251unsigned short
9252SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
9253{
9254  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
9255     return SiS_GetCH700x(SiS_Pr, tempbx);
9256  else
9257     return SiS_GetCH701x(SiS_Pr, tempbx);
9258}
9259
9260void
9261SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
9262                unsigned char myor, unsigned short myand)
9263{
9264  unsigned short tempbl;
9265
9266  tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
9267  SiS_SetCH70xx(SiS_Pr, reg, tempbl);
9268}
9269
9270/* Our own DDC functions */
9271static
9272unsigned short
9273SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9274                unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
9275                unsigned int VBFlags2)
9276{
9277     unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
9278     unsigned char flag, cr32;
9279     unsigned short        temp = 0, myadaptnum = adaptnum;
9280
9281     if(adaptnum != 0) {
9282        if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
9283        if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
9284     }
9285
9286     /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
9287
9288     SiS_Pr->SiS_ChrontelInit = 0;   /* force re-detection! */
9289
9290     SiS_Pr->SiS_DDC_SecAddr = 0;
9291     SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
9292     SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
9293     SiS_Pr->SiS_DDC_Index = 0x11;
9294     flag = 0xff;
9295
9296     cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
9297
9298#if 0
9299     if(VBFlags2 & VB2_SISBRIDGE) {
9300        if(myadaptnum == 0) {
9301           if(!(cr32 & 0x20)) {
9302              myadaptnum = 2;
9303              if(!(cr32 & 0x10)) {
9304                 myadaptnum = 1;
9305                 if(!(cr32 & 0x08)) {
9306                    myadaptnum = 0;
9307                 }
9308              }
9309           }
9310        }
9311     }
9312#endif
9313
9314     if(VGAEngine == SIS_300_VGA) {             /* 300 series */
9315
9316        if(myadaptnum != 0) {
9317           flag = 0;
9318           if(VBFlags2 & VB2_SISBRIDGE) {
9319              SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9320              SiS_Pr->SiS_DDC_Index = 0x0f;
9321           }
9322        }
9323
9324        if(!(VBFlags2 & VB2_301)) {
9325           if((cr32 & 0x80) && (checkcr32)) {
9326              if(myadaptnum >= 1) {
9327                 if(!(cr32 & 0x08)) {
9328                     myadaptnum = 1;
9329                     if(!(cr32 & 0x10)) return 0xFFFF;
9330                 }
9331              }
9332           }
9333        }
9334
9335        temp = 4 - (myadaptnum * 2);
9336        if(flag) temp = 0;
9337
9338     } else {                                           /* 315/330 series */
9339
9340        /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
9341
9342        if(VBFlags2 & VB2_SISBRIDGE) {
9343           if(myadaptnum == 2) {
9344              myadaptnum = 1;
9345           }
9346        }
9347
9348        if(myadaptnum == 1) {
9349           flag = 0;
9350           if(VBFlags2 & VB2_SISBRIDGE) {
9351              SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9352              SiS_Pr->SiS_DDC_Index = 0x0f;
9353           }
9354        }
9355
9356        if((cr32 & 0x80) && (checkcr32)) {
9357           if(myadaptnum >= 1) {
9358              if(!(cr32 & 0x08)) {
9359                 myadaptnum = 1;
9360                 if(!(cr32 & 0x10)) return 0xFFFF;
9361              }
9362           }
9363        }
9364
9365        temp = myadaptnum;
9366        if(myadaptnum == 1) {
9367           temp = 0;
9368           if(VBFlags2 & VB2_LVDS) flag = 0xff;
9369        }
9370
9371        if(flag) temp = 0;
9372    }
9373
9374    SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9375    SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
9376
9377    SiS_SetupDDCN(SiS_Pr);
9378
9379    return 0;
9380}
9381
9382static unsigned short
9383SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
9384{
9385   if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9386   if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
9387      return 0xFFFF;
9388   }
9389   if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
9390      return 0xFFFF;
9391   }
9392   return 0;
9393}
9394
9395static unsigned short
9396SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
9397{
9398   if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9399   if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
9400      return 0xFFFF;
9401   }
9402   return 0;
9403}
9404
9405static unsigned short
9406SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
9407{
9408   if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
9409   if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
9410   return 0;
9411}
9412
9413static void
9414SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
9415{
9416   SiS_SetSCLKLow(SiS_Pr);
9417   if(yesno) {
9418      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9419                      SiS_Pr->SiS_DDC_Index,
9420                      SiS_Pr->SiS_DDC_NData,
9421                      SiS_Pr->SiS_DDC_Data);
9422   } else {
9423      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9424                      SiS_Pr->SiS_DDC_Index,
9425                      SiS_Pr->SiS_DDC_NData,
9426                      0);
9427   }
9428   SiS_SetSCLKHigh(SiS_Pr);
9429}
9430
9431static unsigned short
9432SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
9433{
9434    unsigned char mask, value;
9435    unsigned short  temp, ret=0;
9436    bool failed = false;
9437
9438    SiS_SetSwitchDDC2(SiS_Pr);
9439    if(SiS_PrepareDDC(SiS_Pr)) {
9440         SiS_SetStop(SiS_Pr);
9441         return 0xFFFF;
9442    }
9443    mask = 0xf0;
9444    value = 0x20;
9445    if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9446       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9447       SiS_SendACK(SiS_Pr, 0);
9448       if(temp == 0) {
9449           mask = 0xff;
9450           value = 0xff;
9451       } else {
9452           failed = true;
9453           ret = 0xFFFF;
9454       }
9455    }
9456    if(!failed) {
9457       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9458       SiS_SendACK(SiS_Pr, 1);
9459       temp &= mask;
9460       if(temp == value) ret = 0;
9461       else {
9462          ret = 0xFFFF;
9463          if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9464             if(temp == 0x30) ret = 0;
9465          }
9466       }
9467    }
9468    SiS_SetStop(SiS_Pr);
9469    return ret;
9470}
9471
9472static
9473unsigned short
9474SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
9475{
9476   unsigned short flag;
9477
9478   flag = 0x180;
9479   SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9480   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9481   SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9482   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9483   SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9484   if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9485   if(!(flag & 0x1a)) flag = 0;
9486   return flag;
9487}
9488
9489static
9490unsigned short
9491SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
9492{
9493   unsigned short flag, length, i;
9494   unsigned char chksum,gotcha;
9495
9496   if(DDCdatatype > 4) return 0xFFFF;
9497
9498   flag = 0;
9499   SiS_SetSwitchDDC2(SiS_Pr);
9500   if(!(SiS_PrepareDDC(SiS_Pr))) {
9501      length = 127;
9502      if(DDCdatatype != 1) length = 255;
9503      chksum = 0;
9504      gotcha = 0;
9505      for(i=0; i<length; i++) {
9506         buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9507         chksum += buffer[i];
9508         gotcha |= buffer[i];
9509         SiS_SendACK(SiS_Pr, 0);
9510      }
9511      buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9512      chksum += buffer[i];
9513      SiS_SendACK(SiS_Pr, 1);
9514      if(gotcha) flag = (unsigned short)chksum;
9515      else flag = 0xFFFF;
9516   } else {
9517      flag = 0xFFFF;
9518   }
9519   SiS_SetStop(SiS_Pr);
9520   return flag;
9521}
9522
9523/* Our private DDC functions
9524
9525   It complies somewhat with the corresponding VESA function
9526   in arguments and return values.
9527
9528   Since this is probably called before the mode is changed,
9529   we use our pre-detected pSiS-values instead of SiS_Pr as
9530   regards chipset and video bridge type.
9531
9532   Arguments:
9533       adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9534                 CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9535                 LCDA is CRT1, but DDC is read from CRT2 port.
9536       DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9537       buffer: ptr to 256 data bytes which will be filled with read data.
9538
9539   Returns 0xFFFF if error, otherwise
9540       if DDCdatatype > 0:  Returns 0 if reading OK (included a correct checksum)
9541       if DDCdatatype = 0:  Returns supported DDC modes
9542
9543 */
9544unsigned short
9545SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9546              unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
9547              unsigned int VBFlags2)
9548{
9549   unsigned char  sr1f, cr17=1;
9550   unsigned short result;
9551
9552   if(adaptnum > 2)
9553      return 0xFFFF;
9554
9555   if(DDCdatatype > 4)
9556      return 0xFFFF;
9557
9558   if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
9559      return 0xFFFF;
9560
9561   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
9562      return 0xFFFF;
9563
9564   sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9565   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9566   if(VGAEngine == SIS_300_VGA) {
9567      cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9568      if(!cr17) {
9569         SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9570         SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9571         SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9572      }
9573   }
9574   if((sr1f) || (!cr17)) {
9575      SiS_WaitRetrace1(SiS_Pr);
9576      SiS_WaitRetrace1(SiS_Pr);
9577      SiS_WaitRetrace1(SiS_Pr);
9578      SiS_WaitRetrace1(SiS_Pr);
9579   }
9580
9581   if(DDCdatatype == 0) {
9582      result = SiS_ProbeDDC(SiS_Pr);
9583   } else {
9584      result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9585      if((!result) && (DDCdatatype == 1)) {
9586         if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9587            (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9588            (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9589            (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9590            (buffer[0x12] == 1)) {
9591            if(!SiS_Pr->DDCPortMixup) {
9592               if(adaptnum == 1) {
9593                  if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9594               } else {
9595                  if(buffer[0x14] & 0x80)    result = 0xFFFE;
9596               }
9597            }
9598         }
9599      }
9600   }
9601   SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9602   if(VGAEngine == SIS_300_VGA) {
9603      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9604   }
9605   return result;
9606}
9607
9608/* Generic I2C functions for Chrontel & DDC --------- */
9609
9610static void
9611SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
9612{
9613  SiS_SetSCLKHigh(SiS_Pr);
9614  SiS_WaitRetrace1(SiS_Pr);
9615
9616  SiS_SetSCLKLow(SiS_Pr);
9617  SiS_WaitRetrace1(SiS_Pr);
9618}
9619
9620unsigned short
9621SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
9622{
9623   SiS_WaitRetrace1(SiS_Pr);
9624   return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
9625}
9626
9627/* Set I2C start condition */
9628/* This is done by a SD high-to-low transition while SC is high */
9629static unsigned short
9630SiS_SetStart(struct SiS_Private *SiS_Pr)
9631{
9632  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                     /* (SC->low)  */
9633  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9634                  SiS_Pr->SiS_DDC_Index,
9635                  SiS_Pr->SiS_DDC_NData,
9636                  SiS_Pr->SiS_DDC_Data);                        /* SD->high */
9637  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* SC->high */
9638  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9639                  SiS_Pr->SiS_DDC_Index,
9640                  SiS_Pr->SiS_DDC_NData,
9641                  0x00);                                        /* SD->low = start condition */
9642  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* (SC->low) */
9643  return 0;
9644}
9645
9646/* Set I2C stop condition */
9647/* This is done by a SD low-to-high transition while SC is high */
9648static unsigned short
9649SiS_SetStop(struct SiS_Private *SiS_Pr)
9650{
9651  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                     /* (SC->low) */
9652  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9653                  SiS_Pr->SiS_DDC_Index,
9654                  SiS_Pr->SiS_DDC_NData,
9655                  0x00);                                        /* SD->low   */
9656  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* SC->high  */
9657  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9658                  SiS_Pr->SiS_DDC_Index,
9659                  SiS_Pr->SiS_DDC_NData,
9660                  SiS_Pr->SiS_DDC_Data);                        /* SD->high = stop condition */
9661  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* (SC->high) */
9662  return 0;
9663}
9664
9665/* Write 8 bits of data */
9666static unsigned short
9667SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
9668{
9669  unsigned short i,flag,temp;
9670
9671  flag = 0x80;
9672  for(i = 0; i < 8; i++) {
9673    SiS_SetSCLKLow(SiS_Pr);                                     /* SC->low */
9674    if(tempax & flag) {
9675      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9676                      SiS_Pr->SiS_DDC_Index,
9677                      SiS_Pr->SiS_DDC_NData,
9678                      SiS_Pr->SiS_DDC_Data);                    /* Write bit (1) to SD */
9679    } else {
9680      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9681                      SiS_Pr->SiS_DDC_Index,
9682                      SiS_Pr->SiS_DDC_NData,
9683                      0x00);                                    /* Write bit (0) to SD */
9684    }
9685    SiS_SetSCLKHigh(SiS_Pr);                                    /* SC->high */
9686    flag >>= 1;
9687  }
9688  temp = SiS_CheckACK(SiS_Pr);                                  /* Check acknowledge */
9689  return temp;
9690}
9691
9692static unsigned short
9693SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
9694{
9695  unsigned short i, temp, getdata;
9696
9697  getdata = 0;
9698  for(i = 0; i < 8; i++) {
9699    getdata <<= 1;
9700    SiS_SetSCLKLow(SiS_Pr);
9701    SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9702                    SiS_Pr->SiS_DDC_Index,
9703                    SiS_Pr->SiS_DDC_NData,
9704                    SiS_Pr->SiS_DDC_Data);
9705    SiS_SetSCLKHigh(SiS_Pr);
9706    temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9707    if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
9708  }
9709  return getdata;
9710}
9711
9712static unsigned short
9713SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
9714{
9715  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9716                  SiS_Pr->SiS_DDC_Index,
9717                  SiS_Pr->SiS_DDC_NClk,
9718                  0x00);                                        /* SetSCLKLow()  */
9719  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9720  return 0;
9721}
9722
9723static unsigned short
9724SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
9725{
9726  unsigned short temp, watchdog=1000;
9727
9728  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9729                  SiS_Pr->SiS_DDC_Index,
9730                  SiS_Pr->SiS_DDC_NClk,
9731                  SiS_Pr->SiS_DDC_Clk);                         /* SetSCLKHigh()  */
9732  do {
9733    temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9734  } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
9735  if (!watchdog) {
9736        return 0xFFFF;
9737  }
9738  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9739  return 0;
9740}
9741
9742/* Check I2C acknowledge */
9743/* Returns 0 if ack ok, non-0 if ack not ok */
9744static unsigned short
9745SiS_CheckACK(struct SiS_Private *SiS_Pr)
9746{
9747  unsigned short tempah;
9748
9749  SiS_SetSCLKLow(SiS_Pr);                                          /* (SC->low) */
9750  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9751                  SiS_Pr->SiS_DDC_Index,
9752                  SiS_Pr->SiS_DDC_NData,
9753                  SiS_Pr->SiS_DDC_Data);                           /* (SD->high) */
9754  SiS_SetSCLKHigh(SiS_Pr);                                         /* SC->high = clock impulse for ack */
9755  tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
9756  SiS_SetSCLKLow(SiS_Pr);                                          /* SC->low = end of clock impulse */
9757  if(tempah & SiS_Pr->SiS_DDC_Data) return 1;                      /* Ack OK if bit = 0 */
9758  return 0;
9759}
9760
9761/* End of I2C functions ----------------------- */
9762
9763
9764/* =============== SiS 315/330 O.E.M. ================= */
9765
9766#ifdef CONFIG_FB_SIS_315
9767
9768static unsigned short
9769GetRAMDACromptr(struct SiS_Private *SiS_Pr)
9770{
9771  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9772  unsigned short romptr;
9773
9774  if(SiS_Pr->ChipType < SIS_330) {
9775     romptr = SISGETROMW(0x128);
9776     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
9777        romptr = SISGETROMW(0x12a);
9778  } else {
9779     romptr = SISGETROMW(0x1a8);
9780     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
9781        romptr = SISGETROMW(0x1aa);
9782  }
9783  return romptr;
9784}
9785
9786static unsigned short
9787GetLCDromptr(struct SiS_Private *SiS_Pr)
9788{
9789  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9790  unsigned short romptr;
9791
9792  if(SiS_Pr->ChipType < SIS_330) {
9793     romptr = SISGETROMW(0x120);
9794     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9795        romptr = SISGETROMW(0x122);
9796  } else {
9797     romptr = SISGETROMW(0x1a0);
9798     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9799        romptr = SISGETROMW(0x1a2);
9800  }
9801  return romptr;
9802}
9803
9804static unsigned short
9805GetTVromptr(struct SiS_Private *SiS_Pr)
9806{
9807  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9808  unsigned short romptr;
9809
9810  if(SiS_Pr->ChipType < SIS_330) {
9811     romptr = SISGETROMW(0x114);
9812     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9813        romptr = SISGETROMW(0x11a);
9814  } else {
9815     romptr = SISGETROMW(0x194);
9816     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9817        romptr = SISGETROMW(0x19a);
9818  }
9819  return romptr;
9820}
9821
9822static unsigned short
9823GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
9824{
9825  unsigned short index;
9826
9827  if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9828     if(!(SiS_IsNotM650orLater(SiS_Pr))) {
9829        if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
9830           index >>= 4;
9831           index *= 3;
9832           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9833           else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9834           return index;
9835        }
9836     }
9837  }
9838
9839  index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
9840  if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
9841  if(SiS_Pr->SiS_VBType & VB_SIS301C) {  /* 1.15.20 and later (not VB specific) */
9842     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
9843     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
9844  } else {
9845     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
9846  }
9847  index--;
9848  index *= 3;
9849  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9850  else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9851  return index;
9852}
9853
9854static unsigned short
9855GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
9856{
9857  unsigned short index;
9858
9859  index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
9860  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
9861  else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9862  return index;
9863}
9864
9865static unsigned short
9866GetTVPtrIndex(struct SiS_Private *SiS_Pr)
9867{
9868  unsigned short index;
9869
9870  index = 0;
9871  if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9872  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
9873
9874  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
9875
9876  index <<= 1;
9877
9878  if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
9879     (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9880     index++;
9881  }
9882
9883  return index;
9884}
9885
9886static unsigned int
9887GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
9888{
9889   unsigned short index = 0, temp = 0;
9890
9891   if(SiS_Pr->SiS_TVMode & TVSetPAL)   index = 1;
9892   if(SiS_Pr->SiS_TVMode & TVSetPALM)  index = 2;
9893   if(SiS_Pr->SiS_TVMode & TVSetPALN)  index = 3;
9894   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
9895   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
9896      index = 4;
9897      if(SiS_Pr->SiS_TVMode & TVSetPALM)  index++;
9898      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
9899   }
9900
9901   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
9902      if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
9903         (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9904         index += addme;
9905         temp++;
9906      }
9907      temp += 0x0100;
9908   }
9909   return (unsigned int)(index | (temp << 16));
9910}
9911
9912static unsigned int
9913GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
9914{
9915   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
9916}
9917
9918#if 0
9919static unsigned int
9920GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
9921{
9922   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
9923}
9924#endif
9925
9926static int
9927GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
9928{
9929   int index = 0;
9930
9931   if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
9932   if(SiS_Pr->SiS_ROMNew) {
9933      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
9934      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
9935      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
9936      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
9937   } else {
9938      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
9939      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
9940      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
9941      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
9942   }
9943
9944   if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
9945
9946   return index;
9947}
9948
9949static void
9950SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
9951{
9952  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9953  unsigned short delay=0,index,myindex,temp,romptr=0;
9954  bool dochiptest = true;
9955
9956  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9957     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
9958  } else {
9959     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
9960  }
9961
9962  /* Find delay (from ROM, internal tables, PCI subsystem) */
9963
9964  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {                    /* ------------ VGA */
9965
9966     if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9967        romptr = GetRAMDACromptr(SiS_Pr);
9968     }
9969     if(romptr) delay = ROMAddr[romptr];
9970     else {
9971        delay = 0x04;
9972        if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
9973           if(IS_SIS650) {
9974              delay = 0x0a;
9975           } else if(IS_SIS740) {
9976              delay = 0x00;
9977           } else {
9978              delay = 0x0c;
9979           }
9980        } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9981           delay = 0x00;
9982        }
9983     }
9984
9985  } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {  /* ---------- LCD/LCDA */
9986
9987     bool gotitfrompci = false;
9988
9989     /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
9990
9991     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
9992        if(SiS_Pr->PDC != -1) {
9993           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
9994           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
9995           return;
9996        }
9997     } else {
9998        if(SiS_Pr->PDCA != -1) {
9999           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
10000           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
10001           return;
10002        }
10003     }
10004
10005     /* Custom Panel? */
10006
10007     if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
10008        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10009           delay = 0x00;
10010           if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
10011              delay = 0x20;
10012           }
10013           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
10014        } else {
10015           delay = 0x0c;
10016           if(SiS_Pr->SiS_VBType & VB_SIS301C) {
10017              delay = 0x03;
10018              if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
10019                 delay = 0x00;
10020              }
10021           } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
10022              if(IS_SIS740) delay = 0x01;
10023              else          delay = 0x03;
10024           }
10025           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
10026        }
10027        return;
10028     }
10029
10030     /* This is a piece of typical SiS crap: They code the OEM LCD
10031      * delay into the code, at no defined place in the BIOS.
10032      * We now have to start doing a PCI subsystem check here.
10033      */
10034
10035     switch(SiS_Pr->SiS_CustomT) {
10036     case CUT_COMPAQ1280:
10037     case CUT_COMPAQ12802:
10038        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10039           gotitfrompci = true;
10040           dochiptest = false;
10041           delay = 0x03;
10042        }
10043        break;
10044     case CUT_CLEVO1400:
10045     case CUT_CLEVO14002:
10046        gotitfrompci = true;
10047        dochiptest = false;
10048        delay = 0x02;
10049        break;
10050     case CUT_CLEVO1024:
10051     case CUT_CLEVO10242:
10052        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10053           gotitfrompci = true;
10054           dochiptest = false;
10055           delay = 0x33;
10056           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
10057           delay &= 0x0f;
10058        }
10059        break;
10060     }
10061
10062     /* Could we find it through the PCI ID? If no, use ROM or table */
10063
10064     if(!gotitfrompci) {
10065
10066        index = GetLCDPtrIndexBIOS(SiS_Pr);
10067        myindex = GetLCDPtrIndex(SiS_Pr);
10068
10069        if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
10070
10071           if(SiS_IsNotM650orLater(SiS_Pr)) {
10072
10073              if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10074                 /* Always use the second pointer on 650; some BIOSes */
10075                 /* still carry old 301 data at the first location    */
10076                 /* romptr = SISGETROMW(0x120);                       */
10077                 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
10078                 romptr = SISGETROMW(0x122);
10079                 if(!romptr) return;
10080                 delay = ROMAddr[(romptr + index)];
10081              } else {
10082                 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
10083              }
10084
10085          } else {
10086
10087             delay = SiS310_LCDDelayCompensation_651301LV[myindex];
10088             if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
10089                delay = SiS310_LCDDelayCompensation_651302LV[myindex];
10090
10091          }
10092
10093        } else if(SiS_Pr->SiS_UseROM                          &&
10094                  (!(SiS_Pr->SiS_ROMNew))                     &&
10095                  (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
10096                  (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
10097                  (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)  &&
10098                  (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)  &&
10099                  ((romptr = GetLCDromptr(SiS_Pr)))) {
10100
10101           /* Data for 1280x1024 wrong in 301B BIOS */
10102           /* Data for 1600x1200 wrong in 301C BIOS */
10103           delay = ROMAddr[(romptr + index)];
10104
10105        } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
10106
10107           if(IS_SIS740) delay = 0x03;
10108           else          delay = 0x00;
10109
10110        } else {
10111
10112           delay = SiS310_LCDDelayCompensation_301[myindex];
10113           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
10114              if(IS_SIS740) delay = 0x01;
10115              else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
10116              else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
10117           } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
10118              if(IS_SIS740) delay = 0x01;  /* ? */
10119              else          delay = 0x03;
10120              if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
10121           } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
10122              if(IS_SIS740) delay = 0x01;
10123              else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
10124           }
10125
10126        }
10127
10128     }  /* got it from PCI */
10129
10130     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10131        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
10132        dochiptest = false;
10133     }
10134
10135  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 /* ------------ TV */
10136
10137     index = GetTVPtrIndex(SiS_Pr);
10138
10139     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
10140
10141        if(SiS_IsNotM650orLater(SiS_Pr)) {
10142
10143           if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10144              /* Always use the second pointer on 650; some BIOSes */
10145              /* still carry old 301 data at the first location    */
10146              /* romptr = SISGETROMW(0x114);                       */
10147              /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
10148              romptr = SISGETROMW(0x11a);
10149              if(!romptr) return;
10150              delay = ROMAddr[romptr + index];
10151
10152           } else {
10153
10154              delay = SiS310_TVDelayCompensation_301B[index];
10155
10156           }
10157
10158        } else {
10159
10160           switch(SiS_Pr->SiS_CustomT) {
10161           case CUT_COMPAQ1280:
10162           case CUT_COMPAQ12802:
10163           case CUT_CLEVO1400:
10164           case CUT_CLEVO14002:
10165              delay = 0x02;
10166              dochiptest = false;
10167              break;
10168           case CUT_CLEVO1024:
10169           case CUT_CLEVO10242:
10170              delay = 0x03;
10171              dochiptest = false;
10172              break;
10173           default:
10174              delay = SiS310_TVDelayCompensation_651301LV[index];
10175              if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
10176                 delay = SiS310_TVDelayCompensation_651302LV[index];
10177              }
10178           }
10179        }
10180
10181     } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10182
10183        romptr = GetTVromptr(SiS_Pr);
10184        if(!romptr) return;
10185        delay = ROMAddr[romptr + index];
10186
10187     } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
10188
10189        delay = SiS310_TVDelayCompensation_LVDS[index];
10190
10191     } else {
10192
10193        delay = SiS310_TVDelayCompensation_301[index];
10194        if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10195           if(IS_SIS740) {
10196              delay = SiS310_TVDelayCompensation_740301B[index];
10197              /* LV: use 301 data? BIOS bug? */
10198           } else {
10199              delay = SiS310_TVDelayCompensation_301B[index];
10200              if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
10201           }
10202        }
10203
10204     }
10205
10206     if(SiS_LCDAEnabled(SiS_Pr)) {
10207        delay &= 0x0f;
10208        dochiptest = false;
10209     }
10210
10211  } else return;
10212
10213  /* Write delay */
10214
10215  if(SiS_Pr->SiS_VBType & VB_SISVB) {
10216
10217     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
10218
10219        temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
10220        if(temp == 8) {         /* 1400x1050 BIOS (COMPAL) */
10221           delay &= 0x0f;
10222           delay |= 0xb0;
10223        } else if(temp == 6) {
10224           delay &= 0x0f;
10225           delay |= 0xc0;
10226        } else if(temp > 7) {   /* 1280x1024 BIOS (which one?) */
10227           delay = 0x35;
10228        }
10229        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
10230
10231     } else {
10232
10233        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
10234
10235     }
10236
10237  } else {  /* LVDS */
10238
10239     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10240        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
10241     } else {
10242        if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
10243           delay <<= 4;
10244           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
10245        } else {
10246           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
10247        }
10248     }
10249
10250  }
10251
10252}
10253
10254static void
10255SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10256{
10257  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10258  unsigned short index,temp,temp1,romptr=0;
10259
10260  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
10261
10262  if(ModeNo<=0x13)
10263     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
10264  else
10265     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
10266
10267  temp = GetTVPtrIndex(SiS_Pr);
10268  temp >>= 1;     /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10269  temp1 = temp;
10270
10271  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
10272     if(SiS_Pr->ChipType >= SIS_661) {
10273        temp1 = GetOEMTVPtr661(SiS_Pr);
10274        temp1 >>= 1;
10275        romptr = SISGETROMW(0x260);
10276        if(SiS_Pr->ChipType >= SIS_760) {
10277           romptr = SISGETROMW(0x360);
10278        }
10279     } else if(SiS_Pr->ChipType >= SIS_330) {
10280        romptr = SISGETROMW(0x192);
10281     } else {
10282        romptr = SISGETROMW(0x112);
10283     }
10284  }
10285
10286  if(romptr) {
10287     temp1 <<= 1;
10288     temp = ROMAddr[romptr + temp1 + index];
10289  } else {
10290     temp = SiS310_TVAntiFlick1[temp][index];
10291  }
10292  temp <<= 4;
10293
10294  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp);  /* index 0A D[6:4] */
10295}
10296
10297static void
10298SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
10299{
10300  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10301  unsigned short index,temp,temp1,romptr=0;
10302
10303  temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1;    /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10304
10305  if(ModeNo <= 0x13)
10306     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
10307  else
10308     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
10309
10310  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
10311     if(SiS_Pr->ChipType >= SIS_661) {
10312        romptr = SISGETROMW(0x26c);
10313        if(SiS_Pr->ChipType >= SIS_760) {
10314           romptr = SISGETROMW(0x36c);
10315        }
10316        temp1 = GetOEMTVPtr661(SiS_Pr);
10317        temp1 >>= 1;
10318     } else if(SiS_Pr->ChipType >= SIS_330) {
10319        romptr = SISGETROMW(0x1a4);
10320     } else {
10321        romptr = SISGETROMW(0x124);
10322     }
10323  }
10324
10325  if(romptr) {
10326     temp1 <<= 1;
10327     temp = ROMAddr[romptr + temp1 + index];
10328  } else {
10329     temp = SiS310_TVEdge1[temp][index];
10330  }
10331  temp <<= 5;
10332  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp);  /* index 0A D[7:5] */
10333}
10334
10335static void
10336SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
10337{
10338  unsigned short index, temp, i, j;
10339
10340  if(ModeNo <= 0x13) {
10341     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
10342  } else {
10343     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
10344  }
10345
10346  temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10347
10348  if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)        temp = 1;  /* NTSC-J uses PAL */
10349  else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
10350  else if(SiS_Pr->SiS_TVMode & TVSetPALN)    temp = 4;  /* PAL-N */
10351  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1;  /* HiVision uses PAL */
10352
10353  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10354     for(i=0x35, j=0; i<=0x38; i++, j++) {
10355        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10356     }
10357     for(i=0x48; i<=0x4A; i++, j++) {
10358        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10359     }
10360  } else {
10361     for(i=0x35, j=0; i<=0x38; i++, j++) {
10362        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
10363     }
10364  }
10365}
10366
10367static void
10368SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10369{
10370  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10371  unsigned short index,temp,i,j,resinfo,romptr=0;
10372  unsigned int  lindex;
10373
10374  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
10375
10376  /* NTSC-J data not in BIOS, and already set in SetGroup2 */
10377  if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
10378
10379  if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
10380     lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
10381     lindex <<= 2;
10382     for(j=0, i=0x31; i<=0x34; i++, j++) {
10383        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
10384     }
10385     return;
10386  }
10387
10388  /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
10389  if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
10390
10391  if(ModeNo<=0x13) {
10392     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10393  } else {
10394     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10395  }
10396
10397  temp = GetTVPtrIndex(SiS_Pr);
10398  /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
10399   * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
10400   */
10401  if(SiS_Pr->SiS_UseROM) {
10402     romptr = SISGETROMW(0x116);
10403     if(SiS_Pr->ChipType >= SIS_330) {
10404        romptr = SISGETROMW(0x196);
10405     }
10406     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10407        romptr = SISGETROMW(0x11c);
10408        if(SiS_Pr->ChipType >= SIS_330) {
10409           romptr = SISGETROMW(0x19c);
10410        }
10411        if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
10412           romptr = SISGETROMW(0x116);
10413           if(SiS_Pr->ChipType >= SIS_330) {
10414              romptr = SISGETROMW(0x196);
10415           }
10416        }
10417     }
10418  }
10419  if(romptr) {
10420     romptr += (temp << 2);
10421     for(j=0, i=0x31; i<=0x34; i++, j++) {
10422        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10423     }
10424  } else {
10425     index = temp % 2;
10426     temp >>= 1;          /* 0:NTSC, 1:PAL, 2:HiTV */
10427     for(j=0, i=0x31; i<=0x34; i++, j++) {
10428        if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
10429           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10430        else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
10431           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
10432        else
10433           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10434     }
10435  }
10436
10437  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
10438     if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
10439        if((resinfo == SIS_RI_640x480) ||
10440           (resinfo == SIS_RI_800x600)) {
10441           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
10442           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
10443           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
10444           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
10445        } else if(resinfo == SIS_RI_1024x768) {
10446           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
10447           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
10448           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
10449           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
10450        }
10451     }
10452  }
10453}
10454
10455static void
10456SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10457                unsigned short ModeIdIndex, unsigned short RTI)
10458{
10459   unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
10460   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10461
10462   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
10463      return;
10464
10465   /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
10466   /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
10467
10468   if(SiS_Pr->SiS_ROMNew) {
10469      if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)                         ||
10470         ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
10471          (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
10472         index = 25;
10473         if(SiS_Pr->UseCustomMode) {
10474            index = SiS_Pr->CSRClock;
10475         } else if(ModeNo > 0x13) {
10476            index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
10477            index = SiS_Pr->SiS_VCLKData[index].CLOCK;
10478         }
10479         if(index < 25) index = 25;
10480         index = ((index / 25) - 1) << 1;
10481         if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
10482            index++;
10483         }
10484         romptr = SISGETROMW(0x104);
10485         delay = ROMAddr[romptr + index];
10486         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
10487            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10488            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10489         } else {
10490            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10491            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10492         }
10493         return;
10494      }
10495   }
10496
10497   /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
10498
10499   if(SiS_Pr->UseCustomMode) delay = 0x04;
10500   else if(ModeNo <= 0x13)   delay = 0x04;
10501   else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
10502   delay |= (delay << 8);
10503
10504   if(SiS_Pr->ChipType >= XGI_20) {
10505
10506      delay = 0x0606;
10507      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10508
10509         delay = 0x0404;
10510         if(SiS_Pr->SiS_XGIROM) {
10511             index = GetTVPtrIndex(SiS_Pr);
10512             if((romptr = SISGETROMW(0x35e))) {
10513                delay = (ROMAddr[romptr + index] & 0x0f) << 1;
10514                delay |= (delay << 8);
10515             }
10516         }
10517
10518         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
10519            if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
10520               delay -= 0x0404;
10521            }
10522         }
10523      }
10524
10525   } else if(SiS_Pr->ChipType >= SIS_340) {
10526
10527      delay = 0x0606;
10528      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10529         delay = 0x0404;
10530      }
10531      /* TODO (eventually) */
10532
10533   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10534
10535      /* 3. TV */
10536
10537      index = GetOEMTVPtr661(SiS_Pr);
10538      if(SiS_Pr->SiS_ROMNew) {
10539         romptr = SISGETROMW(0x106);
10540         if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
10541         delay = ROMAddr[romptr + index];
10542      } else {
10543         delay = 0x04;
10544         if(index > 3) delay = 0;
10545      }
10546
10547   } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10548
10549      /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
10550
10551      if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
10552          ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
10553
10554         lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
10555
10556         /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
10557         delay = ROMAddr[romptr + lcdpdcindex + 1];     /* LCD  */
10558         delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
10559
10560      } else {
10561
10562         /* TMDS: Set our own, since BIOS has no idea */
10563         /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
10564         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10565            switch(SiS_Pr->SiS_LCDResInfo) {
10566            case Panel_1024x768:  delay = 0x0008; break;
10567            case Panel_1280x720:  delay = 0x0004; break;
10568            case Panel_1280x768:
10569            case Panel_1280x768_2:delay = 0x0004; break;
10570            case Panel_1280x800:
10571            case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
10572            case Panel_1280x854:  delay = 0x0004; break; /* FIXME */
10573            case Panel_1280x1024: delay = 0x1e04; break;
10574            case Panel_1400x1050: delay = 0x0004; break;
10575            case Panel_1600x1200: delay = 0x0400; break;
10576            case Panel_1680x1050: delay = 0x0e04; break;
10577            default:
10578               if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
10579                  delay = 0x0008;
10580               } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
10581                  delay = 0x1e04;
10582               } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
10583                  delay = 0x0004;
10584               } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
10585                  delay = 0x0400;
10586               } else
10587                  delay = 0x0e04;
10588               break;
10589            }
10590         }
10591
10592         /* Override by detected or user-set values */
10593         /* (but only if, for some reason, we can't read value from BIOS) */
10594         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
10595            delay = SiS_Pr->PDC & 0x1f;
10596         }
10597         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
10598            delay = (SiS_Pr->PDCA & 0x1f) << 8;
10599         }
10600
10601      }
10602
10603   }
10604
10605   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10606      delay >>= 8;
10607      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10608      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10609   } else {
10610      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10611      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10612   }
10613}
10614
10615static void
10616SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
10617{
10618   unsigned short infoflag;
10619   unsigned char  temp;
10620
10621   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10622
10623      if(ModeNo <= 0x13) {
10624         infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
10625      } else if(SiS_Pr->UseCustomMode) {
10626         infoflag = SiS_Pr->CInfoFlag;
10627      } else {
10628         infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
10629      }
10630
10631      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10632         infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
10633      }
10634
10635      infoflag &= 0xc0;
10636
10637      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10638         temp = (infoflag >> 6) | 0x0c;
10639         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10640            temp ^= 0x04;
10641            if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
10642         }
10643         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
10644      } else {
10645         temp = 0x30;
10646         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
10647         temp |= infoflag;
10648         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
10649         temp = 0;
10650         if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10651            if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
10652         }
10653         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
10654      }
10655
10656   }
10657}
10658
10659static void
10660SetPanelParms661(struct SiS_Private *SiS_Pr)
10661{
10662   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10663   unsigned short romptr, temp1, temp2;
10664
10665   if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
10666      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
10667   }
10668
10669   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
10670      if(SiS_Pr->LVDSHL != -1) {
10671         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10672      }
10673   }
10674
10675   if(SiS_Pr->SiS_ROMNew) {
10676
10677      if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
10678         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
10679            temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
10680            temp2 = 0xfc;
10681            if(SiS_Pr->LVDSHL != -1) {
10682              temp1 &= 0xfc;
10683              temp2 = 0xf3;
10684            }
10685            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
10686         }
10687         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10688            temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
10689            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
10690         }
10691      }
10692
10693   }
10694}
10695
10696static void
10697SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
10698{
10699   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
10700      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
10701      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10702         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10703         SetPanelParms661(SiS_Pr);
10704      }
10705   } else {
10706      SetDelayComp(SiS_Pr,ModeNo);
10707   }
10708
10709   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
10710      SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
10711      SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
10712      SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
10713      if(SiS_Pr->SiS_VBType & VB_SIS301) {
10714         SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
10715      }
10716   }
10717}
10718
10719static void
10720SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10721                        unsigned short ModeIdIndex, unsigned short RRTI)
10722{
10723   if(SiS_Pr->SiS_VBType & VB_SISVB) {
10724
10725      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
10726
10727      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10728         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10729         SetPanelParms661(SiS_Pr);
10730      }
10731
10732      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10733         SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
10734         SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
10735         SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
10736         if(SiS_Pr->SiS_VBType & VB_SIS301) {
10737            SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
10738         }
10739      }
10740   }
10741}
10742
10743/* FinalizeLCD
10744 * This finalizes some CRT2 registers for the very panel used.
10745 * If we have a backup if these registers, we use it; otherwise
10746 * we set the register according to most BIOSes. However, this
10747 * function looks quite different in every BIOS, so you better
10748 * pray that we have a backup...
10749 */
10750static void
10751SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10752{
10753  unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
10754  unsigned short resinfo,modeflag;
10755
10756  if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
10757  if(SiS_Pr->SiS_ROMNew) return;
10758
10759  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10760     if(SiS_Pr->LVDSHL != -1) {
10761        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10762     }
10763  }
10764
10765  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10766  if(SiS_Pr->UseCustomMode) return;
10767
10768  switch(SiS_Pr->SiS_CustomT) {
10769  case CUT_COMPAQ1280:
10770  case CUT_COMPAQ12802:
10771  case CUT_CLEVO1400:
10772  case CUT_CLEVO14002:
10773     return;
10774  }
10775
10776  if(ModeNo <= 0x13) {
10777     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10778     modeflag =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10779  } else {
10780     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10781     modeflag =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10782  }
10783
10784  if(IS_SIS650) {
10785     if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
10786        if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10787           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
10788        } else {
10789           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
10790        }
10791     }
10792  }
10793
10794  if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10795     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10796        /* Maybe all panels? */
10797        if(SiS_Pr->LVDSHL == -1) {
10798           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10799        }
10800        return;
10801     }
10802  }
10803
10804  if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
10805     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10806        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10807           if(SiS_Pr->LVDSHL == -1) {
10808              /* Maybe all panels? */
10809              SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10810           }
10811           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10812              tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10813              if(tempch == 3) {
10814                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10815                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10816                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10817                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10818              }
10819           }
10820           return;
10821        }
10822     }
10823  }
10824
10825  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10826     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10827        if(SiS_Pr->SiS_VBType & VB_SISEMI) {
10828           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
10829#ifdef SET_EMI
10830           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
10831#endif
10832           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
10833        }
10834     } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10835        if(SiS_Pr->LVDSHL == -1) {
10836           /* Maybe ACER only? */
10837           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10838        }
10839     }
10840     tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10841     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10842        if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
10843           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
10844        } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10845           if(tempch == 0x03) {
10846              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10847              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10848              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10849              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10850           }
10851           if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
10852              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
10853              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
10854              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
10855              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
10856              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
10857              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
10858              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
10859              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
10860              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
10861              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
10862           } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {  /* 1.10.8w */
10863              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
10864              if(ModeNo <= 0x13) {
10865                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
10866                 if((resinfo == 0) || (resinfo == 2)) return;
10867                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
10868                 if((resinfo == 1) || (resinfo == 3)) return;
10869              }
10870              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10871              if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
10872                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);  /* 1.10.7u */
10873#if 0
10874                 tempbx = 806;  /* 0x326 */                      /* other older BIOSes */
10875                 tempbx--;
10876                 temp = tempbx & 0xff;
10877                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
10878                 temp = (tempbx >> 8) & 0x03;
10879                 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
10880#endif
10881              }
10882           } else if(ModeNo <= 0x13) {
10883              if(ModeNo <= 1) {
10884                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
10885                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
10886                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10887                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10888              }
10889              if(!(modeflag & HalfDCLK)) {
10890                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
10891                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
10892                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
10893                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
10894                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
10895                 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10896                 if(ModeNo == 0x12) {
10897                    switch(tempch) {
10898                       case 0:
10899                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10900                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10901                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
10902                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10903                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
10904                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10905                          break;
10906                       case 2:
10907                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10908                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10909                          break;
10910                       case 3:
10911                          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10912                          break;
10913                    }
10914                 }
10915              }
10916           }
10917        }
10918     } else {
10919        tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
10920        tempcl &= 0x0f;
10921        tempbh &= 0x70;
10922        tempbh >>= 4;
10923        tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
10924        tempbx = (tempbh << 8) | tempbl;
10925        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10926           if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
10927              if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
10928                 tempbx = 770;
10929              } else {
10930                 if(tempbx > 770) tempbx = 770;
10931                 if(SiS_Pr->SiS_VGAVDE < 600) {
10932                    tempax = 768 - SiS_Pr->SiS_VGAVDE;
10933                    tempax >>= 4;                                /* 1.10.7w; 1.10.6s: 3;  */
10934                    if(SiS_Pr->SiS_VGAVDE <= 480)  tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
10935                    tempbx -= tempax;
10936                 }
10937              }
10938           } else return;
10939        }
10940        temp = tempbx & 0xff;
10941        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
10942        temp = ((tempbx & 0xff00) >> 4) | tempcl;
10943        SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
10944     }
10945  }
10946}
10947
10948#endif
10949
10950/*  =================  SiS 300 O.E.M. ================== */
10951
10952#ifdef CONFIG_FB_SIS_300
10953
10954static void
10955SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
10956                unsigned short RefTabIndex)
10957{
10958  unsigned short crt2crtc=0, modeflag, myindex=0;
10959  unsigned char  temp;
10960  int i;
10961
10962  if(ModeNo <= 0x13) {
10963     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10964     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
10965  } else {
10966     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10967     crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
10968  }
10969
10970  crt2crtc &= 0x3f;
10971
10972  if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
10973     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
10974  }
10975
10976  if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
10977     if(modeflag & HalfDCLK) myindex = 1;
10978
10979     if(SiS_Pr->SiS_SetFlag & LowModeTests) {
10980        for(i=0; i<7; i++) {
10981           if(barco_p1[myindex][crt2crtc][i][0]) {
10982              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
10983                              barco_p1[myindex][crt2crtc][i][0],
10984                              barco_p1[myindex][crt2crtc][i][2],
10985                              barco_p1[myindex][crt2crtc][i][1]);
10986           }
10987        }
10988     }
10989     temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
10990     if(temp & 0x80) {
10991        temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
10992        temp++;
10993        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
10994     }
10995  }
10996}
10997
10998static unsigned short
10999GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
11000{
11001  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
11002  unsigned short tempbx=0,romptr=0;
11003  static const unsigned char customtable300[] = {
11004        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
11005        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
11006  };
11007  static const unsigned char customtable630[] = {
11008        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
11009        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
11010  };
11011
11012  if(SiS_Pr->ChipType == SIS_300) {
11013
11014    tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
11015    if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
11016    tempbx -= 2;
11017    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
11018    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11019       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
11020    }
11021    if(SiS_Pr->SiS_UseROM) {
11022       if(ROMAddr[0x235] & 0x80) {
11023          tempbx = SiS_Pr->SiS_LCDTypeInfo;
11024          if(Flag) {
11025             romptr = SISGETROMW(0x255);
11026             if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
11027             else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
11028             if(tempbx == 0xFF) return 0xFFFF;
11029          }
11030          tempbx <<= 1;
11031          if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
11032       }
11033    }
11034
11035  } else {
11036
11037    if(Flag) {
11038       if(SiS_Pr->SiS_UseROM) {
11039          romptr = SISGETROMW(0x255);
11040          if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
11041          else       tempbx = 0xff;
11042       } else {
11043          tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
11044       }
11045       if(tempbx == 0xFF) return 0xFFFF;
11046       tempbx <<= 2;
11047       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
11048       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
11049       return tempbx;
11050    }
11051    tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
11052    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
11053    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
11054
11055  }
11056
11057  return tempbx;
11058}
11059
11060static void
11061SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
11062{
11063  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
11064  unsigned short index,temp,romptr=0;
11065
11066  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
11067
11068  if(SiS_Pr->SiS_UseROM) {
11069     if(!(ROMAddr[0x237] & 0x01)) return;
11070     if(!(ROMAddr[0x237] & 0x02)) return;
11071     romptr = SISGETROMW(0x24b);
11072  }
11073
11074  /* The Panel Compensation Delay should be set according to tables
11075   * here. Unfortunately, various BIOS versions don't care about
11076   * a uniform way using eg. ROM byte 0x220, but use different
11077   * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
11078   * Thus we don't set this if the user selected a custom pdc or if
11079   * we otherwise detected a valid pdc.
11080   */
11081  if(SiS_Pr->PDC != -1) return;
11082
11083  temp = GetOEMLCDPtr(SiS_Pr, 0);
11084
11085  if(SiS_Pr->UseCustomMode)
11086     index = 0;
11087  else
11088     index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
11089
11090  if(SiS_Pr->ChipType != SIS_300) {
11091     if(romptr) {
11092        romptr += (temp * 2);
11093        romptr = SISGETROMW(romptr);
11094        romptr += index;
11095        temp = ROMAddr[romptr];
11096     } else {
11097        if(SiS_Pr->SiS_VBType & VB_SISVB) {
11098           temp = SiS300_OEMLCDDelay2[temp][index];
11099        } else {
11100           temp = SiS300_OEMLCDDelay3[temp][index];
11101        }
11102     }
11103  } else {
11104     if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
11105        if(romptr) {
11106           romptr += (temp * 2);
11107           romptr = SISGETROMW(romptr);
11108           romptr += index;
11109           temp = ROMAddr[romptr];
11110        } else {
11111           temp = SiS300_OEMLCDDelay5[temp][index];
11112        }
11113     } else {
11114        if(SiS_Pr->SiS_UseROM) {
11115           romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
11116           if(romptr) {
11117              romptr += (temp * 2);
11118              romptr = SISGETROMW(romptr);
11119              romptr += index;
11120              temp = ROMAddr[romptr];
11121           } else {
11122              temp = SiS300_OEMLCDDelay4[temp][index];
11123           }
11124        } else {
11125           temp = SiS300_OEMLCDDelay4[temp][index];
11126        }
11127     }
11128  }
11129  temp &= 0x3c;
11130  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
11131}
11132
11133static void
11134SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
11135{
11136#if 0  /* Unfinished; Data table missing */
11137  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
11138  unsigned short index,temp;
11139
11140  if((SiS_Pr->SiS_UseROM) {
11141     if(!(ROMAddr[0x237] & 0x01)) return;
11142     if(!(ROMAddr[0x237] & 0x04)) return;
11143     /* No rom pointer in BIOS header! */
11144  }
11145
11146  temp = GetOEMLCDPtr(SiS_Pr, 1);
11147  if(temp == 0xFFFF) return;
11148
11149  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
11150  for(i=0x14, j=0; i<=0x17; i++, j++) {
11151      SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
11152  }
11153  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
11154
11155  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
11156  SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
11157  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
11158  SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
11159  for(i=0x1b, j=3; i<=0x1d; i++, j++) {
11160      SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
11161  }
11162#endif
11163}
11164
11165static unsigned short
11166GetOEMTVPtr(struct SiS_Private *SiS_Pr)
11167{
11168  unsigned short index;
11169
11170  index = 0;
11171  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  index += 4;
11172  if(SiS_Pr->SiS_VBType & VB_SISVB) {
11173     if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)  index += 2;
11174     else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
11175     else if(SiS_Pr->SiS_TVMode & TVSetPAL)   index += 1;
11176  } else {
11177     if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
11178     if(SiS_Pr->SiS_TVMode & TVSetPAL)        index += 1;
11179  }
11180  return index;
11181}
11182
11183static void
11184SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
11185{
11186  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
11187  unsigned short index,temp,romptr=0;
11188
11189  if(SiS_Pr->SiS_UseROM) {
11190     if(!(ROMAddr[0x238] & 0x01)) return;
11191     if(!(ROMAddr[0x238] & 0x02)) return;
11192     romptr = SISGETROMW(0x241);
11193  }
11194
11195  temp = GetOEMTVPtr(SiS_Pr);
11196
11197  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
11198
11199  if(romptr) {
11200     romptr += (temp * 2);
11201     romptr = SISGETROMW(romptr);
11202     romptr += index;
11203     temp = ROMAddr[romptr];
11204  } else {
11205     if(SiS_Pr->SiS_VBType & VB_SISVB) {
11206        temp = SiS300_OEMTVDelay301[temp][index];
11207     } else {
11208        temp = SiS300_OEMTVDelayLVDS[temp][index];
11209     }
11210  }
11211  temp &= 0x3c;
11212  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
11213}
11214
11215static void
11216SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
11217{
11218  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
11219  unsigned short index,temp,romptr=0;
11220
11221  if(SiS_Pr->SiS_UseROM) {
11222     if(!(ROMAddr[0x238] & 0x01)) return;
11223     if(!(ROMAddr[0x238] & 0x04)) return;
11224     romptr = SISGETROMW(0x243);
11225  }
11226
11227  temp = GetOEMTVPtr(SiS_Pr);
11228
11229  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
11230
11231  if(romptr) {
11232     romptr += (temp * 2);
11233     romptr = SISGETROMW(romptr);
11234     romptr += index;
11235     temp = ROMAddr[romptr];
11236  } else {
11237     temp = SiS300_OEMTVFlicker[temp][index];
11238  }
11239  temp &= 0x70;
11240  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
11241}
11242
11243static void
11244SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
11245{
11246  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
11247  unsigned short index,i,j,temp,romptr=0;
11248
11249  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
11250
11251  if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
11252
11253  if(SiS_Pr->SiS_UseROM) {
11254     if(!(ROMAddr[0x238] & 0x01)) return;
11255     if(!(ROMAddr[0x238] & 0x08)) return;
11256     romptr = SISGETROMW(0x245);
11257  }
11258
11259  temp = GetOEMTVPtr(SiS_Pr);
11260
11261  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
11262
11263  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
11264     for(i=0x31, j=0; i<=0x34; i++, j++) {
11265        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
11266     }
11267  } else {
11268     if(romptr) {
11269        romptr += (temp * 2);
11270        romptr = SISGETROMW(romptr);
11271        romptr += (index * 4);
11272        for(i=0x31, j=0; i<=0x34; i++, j++) {
11273           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11274        }
11275     } else {
11276        for(i=0x31, j=0; i<=0x34; i++, j++) {
11277           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
11278        }
11279     }
11280  }
11281}
11282
11283static void
11284SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
11285{
11286  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
11287  unsigned short index,temp,i,j,romptr=0;
11288
11289  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
11290
11291  if(SiS_Pr->SiS_UseROM) {
11292     if(!(ROMAddr[0x238] & 0x01)) return;
11293     if(!(ROMAddr[0x238] & 0x10)) return;
11294     romptr = SISGETROMW(0x247);
11295  }
11296
11297  temp = GetOEMTVPtr(SiS_Pr);
11298
11299  if(SiS_Pr->SiS_TVMode & TVSetPALM)      temp = 8;
11300  else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
11301  /* NTSCJ uses NTSC filters */
11302
11303  index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
11304
11305  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
11306      for(i=0x35, j=0; i<=0x38; i++, j++) {
11307        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11308      }
11309      for(i=0x48; i<=0x4A; i++, j++) {
11310        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11311      }
11312  } else {
11313      if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
11314         romptr += (temp * 2);
11315         romptr = SISGETROMW(romptr);
11316         romptr += (index * 4);
11317         for(i=0x35, j=0; i<=0x38; i++, j++) {
11318            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11319         }
11320      } else {
11321         for(i=0x35, j=0; i<=0x38; i++, j++) {
11322            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
11323         }
11324      }
11325  }
11326}
11327
11328static unsigned short
11329SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
11330{
11331   unsigned short ModeIdIndex;
11332   unsigned char  VGAINFO = SiS_Pr->SiS_VGAINFO;
11333
11334   if(*ModeNo <= 5) *ModeNo |= 1;
11335
11336   for(ModeIdIndex=0; ; ModeIdIndex++) {
11337      if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
11338      if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF)    return 0;
11339   }
11340
11341   if(*ModeNo != 0x07) {
11342      if(*ModeNo > 0x03) return ModeIdIndex;
11343      if(VGAINFO & 0x80) return ModeIdIndex;
11344      ModeIdIndex++;
11345   }
11346
11347   if(VGAINFO & 0x10) ModeIdIndex++;   /* 400 lines */
11348                                       /* else 350 lines */
11349   return ModeIdIndex;
11350}
11351
11352static void
11353SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
11354                  unsigned short RefTableIndex)
11355{
11356  unsigned short OEMModeIdIndex = 0;
11357
11358  if(!SiS_Pr->UseCustomMode) {
11359     OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
11360     if(!(OEMModeIdIndex)) return;
11361  }
11362
11363  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
11364     SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
11365     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
11366        SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
11367     }
11368  }
11369  if(SiS_Pr->UseCustomMode) return;
11370  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
11371     SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
11372     if(SiS_Pr->SiS_VBType & VB_SISVB) {
11373        SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
11374        SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
11375        SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
11376     }
11377  }
11378}
11379#endif
11380
11381