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