blob: c3e070a6effd9f61a25f5a98e2d8ba674da37954 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* $XFree86$ */
2/* $XdotOrg$ */
3/*
4 * Mode initializing code (CRT2 section)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005 * 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)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 *
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 *
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 * *
Thomas Winischhofer544393f2005-09-09 13:04:45 -070042 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 * * 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 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 */
59
Thomas Winischhofer544393f2005-09-09 13:04:45 -070060#ifdef HAVE_CONFIG_H
61#include "config.h"
62#endif
63
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#if 1
65#define SET_EMI /* 302LV/ELV: Set EMI values */
66#endif
67
Thomas Winischhofer544393f2005-09-09 13:04:45 -070068#if 1
69#define SET_PWD /* 301/302LV: Set PWD */
70#endif
71
Linus Torvalds1da177e2005-04-16 15:20:36 -070072#define COMPAL_HACK /* Needed for Compal 1400x1050 (EMI) */
73#define COMPAQ_HACK /* Needed for Inventec/Compaq 1280x1024 (EMI) */
74#define ASUS_HACK /* Needed for Asus A2H 1024x768 (EMI) */
75
76#include "init301.h"
77
78#ifdef SIS300
79#include "oem300.h"
80#endif
81
82#ifdef SIS315H
83#include "oem310.h"
84#endif
85
86#define SiS_I2CDELAY 1000
87#define SiS_I2CDELAYSHORT 150
88
Thomas Winischhofer544393f2005-09-09 13:04:45 -070089static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
90#ifdef SIS_LINUX_KERNEL
91static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
92#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94/*********************************************/
95/* HELPER: Lock/Unlock CRT2 */
96/*********************************************/
97
98void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070099SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700101 if(SiS_Pr->ChipType == XGI_20)
102 return;
103 else if(SiS_Pr->ChipType >= SIS_315H)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
105 else
106 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
107}
108
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700109#ifdef SIS_LINUX_KERNEL
110static
111#endif
112void
113SiS_LockCRT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700115 if(SiS_Pr->ChipType == XGI_20)
116 return;
117 else if(SiS_Pr->ChipType >= SIS_315H)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
119 else
120 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
121}
122
123/*********************************************/
124/* HELPER: Write SR11 */
125/*********************************************/
126
127static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700128SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700130 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 DataAND &= 0x0f;
132 DataOR &= 0x0f;
133 }
134 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
135}
136
137/*********************************************/
138/* HELPER: Get Pointer to LCD structure */
139/*********************************************/
140
141#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700142static unsigned char *
143GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700145 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
146 unsigned char *myptr = NULL;
147 unsigned short romindex = 0, reg = 0, idx = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
149 /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
150 * due to the variaty of panels the BIOS doesn't know about.
151 * Exception: If the BIOS has better knowledge (such as in case
152 * of machines with a 301C and a panel that does not support DDC)
153 * use the BIOS data as well.
154 */
155
156 if((SiS_Pr->SiS_ROMNew) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700157 ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700159 if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
160 else reg = 0x7d;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
162 idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
163
164 if(idx < (8*26)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700165 myptr = (unsigned char *)&SiS_LCDStruct661[idx];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 }
167 romindex = SISGETROMW(0x100);
168 if(romindex) {
169 romindex += idx;
170 myptr = &ROMAddr[romindex];
171 }
172 }
173 return myptr;
174}
175
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700176static unsigned short
177GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700179 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
180 unsigned short romptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181
182 /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
183 * due to the variaty of panels the BIOS doesn't know about.
184 * Exception: If the BIOS has better knowledge (such as in case
185 * of machines with a 301C and a panel that does not support DDC)
186 * use the BIOS data as well.
187 */
188
189 if((SiS_Pr->SiS_ROMNew) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700190 ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 romptr = SISGETROMW(0x102);
192 romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
193 }
194
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700195 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196}
197#endif
198
199/*********************************************/
200/* Adjust Rate for CRT2 */
201/*********************************************/
202
203static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700204SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
205 unsigned short RRTI, unsigned short *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700207 unsigned short checkmask=0, modeid, infoflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700209 modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700211 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700213 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700215 checkmask |= SupportRAMDAC2;
216 if(SiS_Pr->ChipType >= SIS_315H) {
217 checkmask |= SupportRAMDAC2_135;
218 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
219 checkmask |= SupportRAMDAC2_162;
220 if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
221 checkmask |= SupportRAMDAC2_202;
222 }
223 }
224 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700226 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700228 checkmask |= SupportLCD;
229 if(SiS_Pr->ChipType >= SIS_315H) {
230 if(SiS_Pr->SiS_VBType & VB_SISVB) {
231 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
232 if(modeid == 0x2e) checkmask |= Support64048060Hz;
233 }
234 }
235 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700237 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700239 checkmask |= SupportHiVision;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700241 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700243 checkmask |= SupportTV;
244 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
245 checkmask |= SupportTV1024;
246 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
247 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
248 checkmask |= SupportYPbPr750p;
249 }
250 }
251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700255 } else { /* LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700257 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
258 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
259 checkmask |= SupportCHTV;
260 }
261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700263 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
264 checkmask |= SupportLCD;
265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700269 /* Look backwards in table for matching CRT2 mode */
270 for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
271 infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
272 if(infoflag & checkmask) return TRUE;
273 if((*i) == 0) break;
274 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700276 /* Look through the whole mode-section of the table from the beginning
277 * for a matching CRT2 mode if no mode was found yet.
278 */
279 for((*i) = 0; ; (*i)++) {
280 if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
281 infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
282 if(infoflag & checkmask) return TRUE;
283 }
284 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285}
286
287/*********************************************/
288/* Get rate index */
289/*********************************************/
290
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700291unsigned short
292SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700294 unsigned short RRTI,i,backup_i;
295 unsigned short modeflag,index,temp,backupindex;
296 static const unsigned short LCDRefreshIndex[] = {
297 0x00, 0x00, 0x01, 0x01,
298 0x01, 0x01, 0x01, 0x01,
299 0x01, 0x01, 0x01, 0x01,
300 0x01, 0x01, 0x01, 0x01,
301 0x00, 0x00, 0x00, 0x00
302 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700304 /* Do NOT check for UseCustomMode here, will skrew up FIFO */
305 if(ModeNo == 0xfe) return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700307 if(ModeNo <= 0x13) {
308 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
309 } else {
310 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700313 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
314 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
315 if(modeflag & HalfDCLK) return 0;
316 }
317 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700319 if(ModeNo < 0x14) return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700321 index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
322 backupindex = index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700324 if(index > 0) index--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700326 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
327 if(SiS_Pr->SiS_VBType & VB_SISVB) {
328 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
329 if(SiS_Pr->SiS_VBType & VB_NoLCD) index = 0;
330 else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
331 }
332 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
333 if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
334 temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
335 if(index > temp) index = temp;
336 }
337 }
338 } else {
339 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
340 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
341 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
342 }
343 }
344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700346 RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
347 ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700349 if(SiS_Pr->ChipType >= SIS_315H) {
350 if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
351 if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
352 (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
353 if(backupindex <= 1) RRTI++;
354 }
355 }
356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700358 i = 0;
359 do {
360 if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
361 temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
362 temp &= ModeTypeMask;
363 if(temp < SiS_Pr->SiS_ModeType) break;
364 i++;
365 index--;
366 } while(index != 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700368 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
369 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
370 temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
371 if(temp & InterlaceMode) i++;
372 }
373 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700375 i--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700377 if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
378 backup_i = i;
379 if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
380 i = backup_i;
381 }
382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700384 return (RRTI + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385}
386
387/*********************************************/
388/* STORE CRT2 INFO in CR34 */
389/*********************************************/
390
391static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700392SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700394 unsigned short temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700396 /* Store CRT1 ModeNo in CR34 */
397 SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
398 temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
399 temp2 = ~(SetInSlaveMode >> 8);
400 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401}
402
403/*********************************************/
404/* HELPER: GET SOME DATA FROM BIOS ROM */
405/*********************************************/
406
407#ifdef SIS300
408static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700409SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700411 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
412 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700414 if(SiS_Pr->SiS_UseROM) {
415 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
416 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
417 temp1 = SISGETROMW(0x23b);
418 if(temp1 & temp) return TRUE;
419 }
420 }
421 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422}
423
424static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700425SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700427 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
428 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700430 if(SiS_Pr->SiS_UseROM) {
431 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
432 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
433 temp1 = SISGETROMW(0x23d);
434 if(temp1 & temp) return TRUE;
435 }
436 }
437 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438}
439#endif
440
441/*********************************************/
442/* HELPER: DELAY FUNCTIONS */
443/*********************************************/
444
445void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700446SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700448 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700450 for(i = 0; i < delaytime; i++) {
451 j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453}
454
455#if defined(SIS300) || defined(SIS315H)
456static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700457SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700459 SiS_DDC2Delay(SiS_Pr, delay * 36);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460}
461#endif
462
463#ifdef SIS315H
464static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700465SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700467 while(delay--) {
468 SiS_GenericDelay(SiS_Pr, 6623);
469 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470}
471#endif
472
473#if defined(SIS300) || defined(SIS315H)
474static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700475SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700477 while(delay--) {
478 SiS_GenericDelay(SiS_Pr, 66);
479 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480}
481#endif
482
483static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700484SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485{
486#if defined(SIS300) || defined(SIS315H)
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700487 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
488 unsigned short PanelID, DelayIndex, Delay=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489#endif
490
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700491 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
493#ifdef SIS300
494
495 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
496 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700497 if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
498 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
500 DelayIndex = PanelID >> 4;
501 if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700502 Delay = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700504 if(DelayTime >= 2) DelayTime -= 2;
505 if(!(DelayTime & 0x01)) {
506 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
507 } else {
508 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
509 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 if(SiS_Pr->SiS_UseROM) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700511 if(ROMAddr[0x220] & 0x40) {
512 if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
513 else Delay = (unsigned short)ROMAddr[0x226];
514 }
515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 }
517 SiS_ShortDelay(SiS_Pr, Delay);
518
519#endif /* SIS300 */
520
521 } else {
522
523#ifdef SIS315H
524
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700525 if((SiS_Pr->ChipType >= SIS_661) ||
526 (SiS_Pr->ChipType <= SIS_315PRO) ||
527 (SiS_Pr->ChipType == SIS_330) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 (SiS_Pr->SiS_ROMNew)) {
529
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700530 if(!(DelayTime & 0x01)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 SiS_DDC2Delay(SiS_Pr, 0x1000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700532 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 SiS_DDC2Delay(SiS_Pr, 0x4000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
536 } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700537 (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */
539
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700540 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
541 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
543 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
544 }
545 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
546 DelayIndex = PanelID & 0x0f;
547 } else {
548 DelayIndex = PanelID >> 4;
549 }
550 if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700551 Delay = 3;
552 } else {
553 if(DelayTime >= 2) DelayTime -= 2;
554 if(!(DelayTime & 0x01)) {
555 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
556 } else {
557 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
558 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700560 if(ROMAddr[0x13c] & 0x40) {
561 if(!(DelayTime & 0x01)) {
562 Delay = (unsigned short)ROMAddr[0x17e];
563 } else {
564 Delay = (unsigned short)ROMAddr[0x17f];
565 }
566 }
567 }
568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 SiS_ShortDelay(SiS_Pr, Delay);
570 }
571
572 } else if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 315 series, all bridges */
573
574 DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700575 if(!(DelayTime & 0x01)) {
576 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
577 } else {
578 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
579 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 Delay <<= 8;
581 SiS_DDC2Delay(SiS_Pr, Delay);
582
583 }
584
585#endif /* SIS315H */
586
587 }
588}
589
590#ifdef SIS315H
591static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700592SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 int i;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700595 for(i = 0; i < DelayLoop; i++) {
596 SiS_PanelDelay(SiS_Pr, DelayTime);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 }
598}
599#endif
600
601/*********************************************/
602/* HELPER: WAIT-FOR-RETRACE FUNCTIONS */
603/*********************************************/
604
605void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700606SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700608 unsigned short watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700610 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
611 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700613 watchdog = 65535;
614 while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
615 watchdog = 65535;
616 while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617}
618
619#if defined(SIS300) || defined(SIS315H)
620static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700621SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700623 unsigned short watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700625 watchdog = 65535;
626 while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
627 watchdog = 65535;
628 while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629}
630#endif
631
632static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700633SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700635 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700637 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
638 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
639 }
640 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
641 SiS_WaitRetrace1(SiS_Pr);
642 } else {
643 SiS_WaitRetrace2(SiS_Pr, 0x25);
644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700646 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700648 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
649 SiS_WaitRetrace1(SiS_Pr);
650 } else {
651 SiS_WaitRetrace2(SiS_Pr, 0x30);
652 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700654 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655}
656
657static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700658SiS_VBWait(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700660 unsigned short tempal,temp,i,j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700662 temp = 0;
663 for(i = 0; i < 3; i++) {
664 for(j = 0; j < 100; j++) {
665 tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
666 if(temp & 0x01) {
667 if((tempal & 0x08)) continue;
668 else break;
669 } else {
670 if(!(tempal & 0x08)) continue;
671 else break;
672 }
673 }
674 temp ^= 0x01;
675 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676}
677
678static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700679SiS_VBLongWait(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700681 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
682 SiS_VBWait(SiS_Pr);
683 } else {
684 SiS_WaitRetrace1(SiS_Pr);
685 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686}
687
688/*********************************************/
689/* HELPER: MISC */
690/*********************************************/
691
692#ifdef SIS300
693static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700694SiS_Is301B(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700696 if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
697 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699#endif
700
701static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700702SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700704 if(SiS_Pr->ChipType == SIS_730) {
705 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return TRUE;
706 }
707 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return TRUE;
708 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709}
710
711BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700712SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713{
714#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700715 if(SiS_Pr->ChipType >= SIS_315H) {
716 if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
717 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return TRUE;
718 }
719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700721 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722}
723
724BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700725SiS_IsVAMode(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726{
727#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700728 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700730 if(SiS_Pr->ChipType >= SIS_315H) {
731 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
732 if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
733 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700735 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736}
737
738#ifdef SIS315H
739static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700740SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700742 if(SiS_IsVAMode(SiS_Pr)) return TRUE;
743 if(SiS_CRT2IsLCD(SiS_Pr)) return TRUE;
744 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745}
746#endif
747
748static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700749SiS_IsDualLink(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
751#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700752 if(SiS_Pr->ChipType >= SIS_315H) {
753 if((SiS_CRT2IsLCD(SiS_Pr)) ||
754 (SiS_IsVAMode(SiS_Pr))) {
755 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
756 }
757 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700759 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760}
761
762#ifdef SIS315H
763static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700764SiS_TVEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700766 if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
767 if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
768 if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
769 }
770 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771}
772#endif
773
774#ifdef SIS315H
775static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700776SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700778 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
779 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780}
781#endif
782
783#ifdef SIS315H
784static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700785SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700787 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
788 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
789 }
790 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791}
792#endif
793
794#ifdef SIS315H
795static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700796SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700798 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700800 if(SiS_Pr->ChipType == SIS_650) {
801 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
802 /* Check for revision != A0 only */
803 if((flag == 0xe0) || (flag == 0xc0) ||
804 (flag == 0xb0) || (flag == 0x90)) return FALSE;
805 } else if(SiS_Pr->ChipType >= SIS_661) return FALSE;
806 return TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807}
808#endif
809
810#ifdef SIS315H
811static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700812SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700814 if(SiS_Pr->ChipType >= SIS_315H) {
815 /* YPrPb = 0x08 */
816 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return TRUE;
817 }
818 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819}
820#endif
821
822#ifdef SIS315H
823static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700824SiS_IsChScart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700826 if(SiS_Pr->ChipType >= SIS_315H) {
827 /* Scart = 0x04 */
828 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return TRUE;
829 }
830 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831}
832#endif
833
834#ifdef SIS315H
835static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700836SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700838 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700840 if(SiS_Pr->ChipType >= SIS_315H) {
841 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
842 if(flag & SetCRT2ToTV) return TRUE;
843 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
844 if(flag & EnableCHYPbPr) return TRUE; /* = YPrPb = 0x08 */
845 if(flag & EnableCHScart) return TRUE; /* = Scart = 0x04 - TW */
846 } else {
847 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
848 if(flag & SetCRT2ToTV) return TRUE;
849 }
850 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851}
852#endif
853
854#ifdef SIS315H
855static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700856SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700858 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700860 if(SiS_Pr->ChipType >= SIS_315H) {
861 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
862 if(flag & SetCRT2ToLCD) return TRUE;
863 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
864 if(flag & SetToLCDA) return TRUE;
865 } else {
866 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
867 if(flag & SetCRT2ToLCD) return TRUE;
868 }
869 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870}
871#endif
872
873static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700874SiS_HaveBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700876 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700878 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
879 return TRUE;
880 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
881 flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
882 if((flag == 1) || (flag == 2)) return TRUE;
883 }
884 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885}
886
887static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700888SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700890 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700892 if(SiS_HaveBridge(SiS_Pr)) {
893 flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
894 if(SiS_Pr->ChipType < SIS_315H) {
895 flag &= 0xa0;
896 if((flag == 0x80) || (flag == 0x20)) return TRUE;
897 } else {
898 flag &= 0x50;
899 if((flag == 0x40) || (flag == 0x10)) return TRUE;
900 }
901 }
902 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903}
904
905static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700906SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700908 unsigned short flag1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700910 flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
911 if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
912 return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913}
914
915/*********************************************/
916/* GET VIDEO BRIDGE CONFIG INFO */
917/*********************************************/
918
919/* Setup general purpose IO for Chrontel communication */
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700920#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700922SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700924 unsigned int acpibase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 unsigned short temp;
926
927 if(!(SiS_Pr->SiS_ChSW)) return;
928
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700929#ifdef SIS_LINUX_KERNEL
930 acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931#else
932 acpibase = pciReadLong(0x00000800, 0x74);
933#endif
934 acpibase &= 0xFFFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700935 if(!acpibase) return;
936 temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 temp &= 0xFEFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700938 SiS_SetRegShort((acpibase + 0x3c), temp);
939 temp = SiS_GetRegShort((acpibase + 0x3c));
940 temp = SiS_GetRegShort((acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 temp &= 0xFEFF;
942 if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700943 SiS_SetRegShort((acpibase + 0x3a), temp);
944 temp = SiS_GetRegShort((acpibase + 0x3a));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945}
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700946#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
948void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700949SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
950 unsigned short ModeIdIndex, int checkcrt2mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700952 unsigned short tempax, tempbx, temp;
953 unsigned short modeflag, resinfo = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700955 SiS_Pr->SiS_SetFlag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700957 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700959 SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700961 if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
962 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
963 }
964
965 tempbx = 0;
966
967 if(SiS_HaveBridge(SiS_Pr)) {
968
969 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
970 tempbx |= temp;
971 tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
972 tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
973 tempbx |= tempax;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
975#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700976 if(SiS_Pr->ChipType >= SIS_315H) {
977 if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 if(ModeNo == 0x03) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700979 /* Mode 0x03 is never in driver mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
981 }
982 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700983 /* Reset LCDA setting if not driver mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
985 }
986 if(IS_SIS650) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700987 if(SiS_Pr->SiS_UseLCDA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
989 if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700990 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 }
992 }
993 }
994 }
995 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700996 if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
997 tempbx |= SetCRT2ToLCDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 }
999 }
1000
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001001 if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001003 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
1004 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
1005 if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
1006 else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1007 tempbx |= SetCRT2ToYPbPr525750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 }
1009 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001010 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
1012 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1013 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1014 if(temp & SetToLCDA) {
1015 tempbx |= SetCRT2ToLCDA;
1016 }
1017 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001018 if(temp & EnableCHYPbPr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 tempbx |= SetCRT2ToCHYPbPr;
1020 }
1021 }
1022 }
1023 }
1024
1025#endif /* SIS315H */
1026
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001027 if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
1028 tempbx &= ~(SetCRT2ToRAMDAC);
1029 }
1030
1031 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 temp = SetCRT2ToSVIDEO |
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001033 SetCRT2ToAVIDEO |
1034 SetCRT2ToSCART |
1035 SetCRT2ToLCDA |
1036 SetCRT2ToLCD |
1037 SetCRT2ToRAMDAC |
1038 SetCRT2ToHiVision |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 SetCRT2ToYPbPr525750;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001040 } else {
1041 if(SiS_Pr->ChipType >= SIS_315H) {
1042 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1043 temp = SetCRT2ToAVIDEO |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 SetCRT2ToSVIDEO |
1045 SetCRT2ToSCART |
1046 SetCRT2ToLCDA |
1047 SetCRT2ToLCD |
1048 SetCRT2ToCHYPbPr;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001049 } else {
1050 temp = SetCRT2ToLCDA |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 SetCRT2ToLCD;
1052 }
1053 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001054 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1055 temp = SetCRT2ToTV | SetCRT2ToLCD;
1056 } else {
1057 temp = SetCRT2ToLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 }
1059 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001060 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001062 if(!(tempbx & temp)) {
1063 tempax = DisableCRT2Display;
1064 tempbx = 0;
1065 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001067 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1068
1069 unsigned short clearmask = ( DriverMode |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 DisableCRT2Display |
1071 LoadDACFlag |
1072 SetNotSimuMode |
1073 SetInSlaveMode |
1074 SetPALTV |
1075 SwitchCRT2 |
1076 SetSimuScanMode );
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001077
1078 if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 if(tempbx & SetCRT2ToRAMDAC) tempbx &= (clearmask | SetCRT2ToRAMDAC);
1080 if(tempbx & SetCRT2ToLCD) tempbx &= (clearmask | SetCRT2ToLCD);
1081 if(tempbx & SetCRT2ToSCART) tempbx &= (clearmask | SetCRT2ToSCART);
1082 if(tempbx & SetCRT2ToHiVision) tempbx &= (clearmask | SetCRT2ToHiVision);
1083 if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001084
1085 } else {
1086
1087 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 if(tempbx & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001089 tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 }
1091 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001092 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1093 if(tempbx & SetCRT2ToTV) {
1094 tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001097 if(tempbx & SetCRT2ToLCD) {
1098 tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
1099 }
1100 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 if(tempbx & SetCRT2ToLCDA) {
1102 tempbx |= SetCRT2ToLCD;
1103 }
1104 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001105
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 }
1107
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001108 if(tempax & DisableCRT2Display) {
1109 if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1110 tempbx = SetSimuScanMode | DisableCRT2Display;
1111 }
1112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001114 if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
1116 /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
1117 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
1118 if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
1119 ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001120 modeflag &= (~CRT2Mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 }
1122 }
1123
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001124 if(!(tempbx & SetSimuScanMode)) {
1125 if(tempbx & SwitchCRT2) {
1126 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1127 if(resinfo != SIS_RI_1600x1200) {
1128 tempbx |= SetSimuScanMode;
1129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001131 } else {
1132 if(SiS_BridgeIsEnabled(SiS_Pr)) {
1133 if(!(tempbx & DriverMode)) {
1134 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 tempbx |= SetSimuScanMode;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001136 }
1137 }
1138 }
1139 }
1140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001142 if(!(tempbx & DisableCRT2Display)) {
1143 if(tempbx & DriverMode) {
1144 if(tempbx & SetSimuScanMode) {
1145 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1146 if(resinfo != SIS_RI_1600x1200) {
1147 tempbx |= SetInSlaveMode;
1148 }
1149 }
1150 }
1151 } else {
1152 tempbx |= SetInSlaveMode;
1153 }
1154 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001158 SiS_Pr->SiS_VBInfo = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001160#ifdef SIS300
1161 if(SiS_Pr->ChipType == SIS_630) {
1162 SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1163 }
1164#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001166#ifdef SIS_LINUX_KERNEL
1167#if 0
1168 printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1170#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001171#endif
1172#ifdef SIS_XORG_XF86
1173#ifdef TWDEBUG
1174 xf86DrvMsg(0, X_PROBED, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1176#endif
1177#endif
1178}
1179
1180/*********************************************/
1181/* DETERMINE YPbPr MODE */
1182/*********************************************/
1183
1184void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001185SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186{
1187
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001188 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001190 /* Note: This variable is only used on 30xLV systems.
1191 * CR38 has a different meaning on LVDS/CH7019 systems.
1192 * On 661 and later, these bits moved to CR35.
1193 *
1194 * On 301, 301B, only HiVision 1080i is supported.
1195 * On 30xLV, 301C, only YPbPr 1080i is supported.
1196 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001198 SiS_Pr->SiS_YPbPr = 0;
1199 if(SiS_Pr->ChipType >= SIS_661) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001201 if(SiS_Pr->SiS_VBType) {
1202 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1203 SiS_Pr->SiS_YPbPr = YPbPrHiVision;
1204 }
1205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001207 if(SiS_Pr->ChipType >= SIS_315H) {
1208 if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1209 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1210 if(temp & 0x08) {
1211 switch((temp >> 4)) {
1212 case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break;
1213 case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break;
1214 case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break;
1215 case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
1216 }
1217 }
1218 }
1219 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220
1221}
1222
1223/*********************************************/
1224/* DETERMINE TVMode flag */
1225/*********************************************/
1226
1227void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001228SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001230 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1231 unsigned short temp, temp1, resinfo = 0, romindex = 0;
1232 unsigned char OutputSelect = *SiS_Pr->pSiS_OutputSelect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001234 SiS_Pr->SiS_TVMode = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001236 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
1237 if(SiS_Pr->UseCustomMode) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001239 if(ModeNo > 0x13) {
1240 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001243 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001245 if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001247 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1248 temp = 0;
1249 if((SiS_Pr->ChipType == SIS_630) ||
1250 (SiS_Pr->ChipType == SIS_730)) {
1251 temp = 0x35;
1252 romindex = 0xfe;
1253 } else if(SiS_Pr->ChipType >= SIS_315H) {
1254 temp = 0x38;
1255 if(SiS_Pr->ChipType < XGI_20) {
1256 romindex = 0xf3;
1257 if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
1258 }
1259 }
1260 if(temp) {
1261 if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
1262 OutputSelect = ROMAddr[romindex];
1263 if(!(OutputSelect & EnablePALMN)) {
1264 SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
1265 }
1266 }
1267 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
1268 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1269 if(temp1 & EnablePALM) { /* 0x40 */
1270 SiS_Pr->SiS_TVMode |= TVSetPALM;
1271 SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1272 } else if(temp1 & EnablePALN) { /* 0x80 */
1273 SiS_Pr->SiS_TVMode |= TVSetPALN;
1274 }
1275 } else {
1276 if(temp1 & EnableNTSCJ) { /* 0x40 */
1277 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1278 }
1279 }
1280 }
1281 /* Translate HiVision/YPbPr to our new flags */
1282 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1283 if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1284 else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1285 else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
1286 else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1287 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
1288 SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
1289 SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
1290 } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
1291 SiS_Pr->SiS_TVMode |= TVSetPAL;
1292 }
1293 }
1294 } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1295 if(SiS_Pr->SiS_CHOverScan) {
1296 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
1297 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1298 if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
1299 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1300 }
1301 } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1302 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
1303 if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
1304 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1305 }
1306 }
1307 if(SiS_Pr->SiS_CHSOverScan) {
1308 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1309 }
1310 }
1311 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1312 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1313 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1314 if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM;
1315 else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
1316 } else {
1317 if(temp & EnableNTSCJ) {
1318 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1319 }
1320 }
1321 }
1322 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001324 } else { /* 661 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001326 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1327 if(temp1 & 0x01) {
1328 SiS_Pr->SiS_TVMode |= TVSetPAL;
1329 if(temp1 & 0x08) {
1330 SiS_Pr->SiS_TVMode |= TVSetPALN;
1331 } else if(temp1 & 0x04) {
1332 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1333 SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1334 }
1335 SiS_Pr->SiS_TVMode |= TVSetPALM;
1336 }
1337 } else {
1338 if(temp1 & 0x02) {
1339 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1340 }
1341 }
1342 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1343 if(SiS_Pr->SiS_CHOverScan) {
1344 if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
1345 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1346 }
1347 }
1348 }
1349 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1350 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1351 temp1 &= 0xe0;
1352 if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1353 else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1354 else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1355 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1356 SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
1357 }
1358 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
1359 if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
1360 SiS_Pr->SiS_TVMode |= TVAspect169;
1361 } else {
1362 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
1363 if(temp1 & 0x02) {
1364 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
1365 SiS_Pr->SiS_TVMode |= TVAspect169;
1366 } else {
1367 SiS_Pr->SiS_TVMode |= TVAspect43LB;
1368 }
1369 } else {
1370 SiS_Pr->SiS_TVMode |= TVAspect43;
1371 }
1372 }
1373 }
1374 }
1375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001377 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001379 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001381 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1382 SiS_Pr->SiS_TVMode |= TVSetPAL;
1383 SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
1384 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1385 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
1386 SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
1387 }
1388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001390 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1391 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
1392 SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1393 }
1394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001396 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
1397 if(resinfo == SIS_RI_1024x768) {
1398 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
1399 SiS_Pr->SiS_TVMode |= TVSet525p1024;
1400 } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
1401 SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
1402 }
1403 }
1404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001406 SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
1407 if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
1408 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
1409 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1410 } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
1411 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1412 } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
1413 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
1414 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1415 }
1416 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001418 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001420 SiS_Pr->SiS_VBInfo &= ~SetPALTV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001422#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423#ifdef TWDEBUG
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001424 xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
1425#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426#endif
1427}
1428
1429/*********************************************/
1430/* GET LCD INFO */
1431/*********************************************/
1432
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001433static unsigned short
1434SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001436 unsigned short temp = SiS_Pr->SiS_LCDResInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 /* Translate my LCDResInfo to BIOS value */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001438 switch(temp) {
1439 case Panel_1280x768_2: temp = Panel_1280x768; break;
1440 case Panel_1280x800_2: temp = Panel_1280x800; break;
1441 case Panel_1280x854: temp = Panel661_1280x854; break;
1442 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 return temp;
1444}
1445
1446static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001447SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448{
1449#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001450 unsigned char *ROMAddr;
1451 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001453#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454#ifdef TWDEBUG
1455 xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001456 SiS_Pr->PanelHT, SiS_Pr->PanelVT,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1458 SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1459 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1460 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1461 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1462#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001463#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001465 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001467 SiS_Pr->SiS_NeedRomModeData = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 SiS_Pr->PanelHT = temp;
1469 }
1470 if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001471 SiS_Pr->SiS_NeedRomModeData = TRUE;
1472 SiS_Pr->PanelVT = temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 }
1474 SiS_Pr->PanelHRS = SISGETROMW(10);
1475 SiS_Pr->PanelHRE = SISGETROMW(12);
1476 SiS_Pr->PanelVRS = SISGETROMW(14);
1477 SiS_Pr->PanelVRE = SISGETROMW(16);
1478 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1479 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001480 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
1482 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
1483 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
1484 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
1485
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001486#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487#ifdef TWDEBUG
1488 xf86DrvMsg(0, X_INFO, "Paneldata BIOS: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001489 SiS_Pr->PanelHT, SiS_Pr->PanelVT,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1491 SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1492 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1493 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1494 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1495#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001496#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497
1498 }
1499#endif
1500}
1501
1502static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001503SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
1504 const unsigned char *nonscalingmodes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001506 int i = 0;
1507 while(nonscalingmodes[i] != 0xff) {
1508 if(nonscalingmodes[i++] == resinfo) {
1509 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
1510 (SiS_Pr->UsePanelScaler == -1)) {
1511 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1512 }
1513 break;
1514 }
1515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516}
1517
1518void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001519SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001521 unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
1522 BOOLEAN panelcanscale = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001524 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1525 static const unsigned char SiS300SeriesLCDRes[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 { 0, 1, 2, 3, 7, 4, 5, 8,
1527 0, 0, 10, 0, 0, 0, 0, 15 };
1528#endif
1529#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001530 unsigned char *myptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
1533 SiS_Pr->SiS_LCDResInfo = 0;
1534 SiS_Pr->SiS_LCDTypeInfo = 0;
1535 SiS_Pr->SiS_LCDInfo = 0;
1536 SiS_Pr->PanelHRS = 999; /* HSync start */
1537 SiS_Pr->PanelHRE = 999; /* HSync end */
1538 SiS_Pr->PanelVRS = 999; /* VSync start */
1539 SiS_Pr->PanelVRE = 999; /* VSync end */
1540 SiS_Pr->SiS_NeedRomModeData = FALSE;
1541
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001542 /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
1543 SiS_Pr->Alternate1600x1200 = FALSE;
1544
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
1546
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001547 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1548
1549 if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1551 modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
1552 modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
1553 }
1554
1555 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
1556
1557 /* For broken BIOSes: Assume 1024x768 */
1558 if(temp == 0) temp = 0x02;
1559
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001560 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001562 } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
1564 } else {
1565 SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1566 }
1567 temp &= 0x0f;
1568#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001569 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
1571 if(SiS_Pr->SiS_VBType & VB_SIS301) {
1572 if(temp < 0x0f) temp &= 0x07;
1573 }
1574 /* Translate 300 series LCDRes to 315 series for unified usage */
1575 temp = SiS300SeriesLCDRes[temp];
1576 }
1577#endif
1578
1579 /* Translate to our internal types */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001580#ifdef SIS315H
1581 if(SiS_Pr->ChipType == SIS_550) {
1582 if (temp == Panel310_1152x768) temp = Panel_320x240_2; /* Verified working */
1583 else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
1584 else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
1585 } else if(SiS_Pr->ChipType >= SIS_661) {
1586 if(temp == Panel661_1280x854) temp = Panel_1280x854;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001588#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001590 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 if(temp == Panel310_1280x768) {
1592 temp = Panel_1280x768_2;
1593 }
1594 if(SiS_Pr->SiS_ROMNew) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001595 if(temp == Panel661_1280x800) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 temp = Panel_1280x800_2;
1597 }
1598 }
1599 }
1600
1601 SiS_Pr->SiS_LCDResInfo = temp;
1602
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001603#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1605 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001606 SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001608 SiS_Pr->SiS_LCDResInfo = Panel_848x480;
1609 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
1610 SiS_Pr->SiS_LCDResInfo = Panel_856x480;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 }
1612 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001613#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614
1615 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1616 if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
1617 SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
1618 } else {
1619 if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
1620 SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
1621 }
1622
1623 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
1624 SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
1625 /* Need temp below! */
1626
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001627 /* These must/can't scale no matter what */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001629 case Panel_320x240_1:
1630 case Panel_320x240_2:
1631 case Panel_320x240_3:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 case Panel_1280x960:
1633 SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001634 break;
1635 case Panel_640x480:
1636 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 }
1638
1639 panelcanscale = (SiS_Pr->SiS_LCDInfo & DontExpandLCD) ? TRUE : FALSE;
1640
1641 if(!SiS_Pr->UsePanelScaler) SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1642 else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1643
1644 /* Dual link, Pass 1:1 BIOS default, etc. */
1645#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001646 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001648 if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001650 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1651 if(SiS_Pr->SiS_ROMNew) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001653 } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
1654 if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 }
1656 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001657 } else if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001659 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 }
1661 if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001662 SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001664 if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
1665 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1667 }
1668 } else if(!(SiS_Pr->SiS_ROMNew)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001669 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1670 if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
1672 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1673 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001674 if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001676 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
1678 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1679 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001680 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 }
1682 }
1683#endif
1684
1685 /* Pass 1:1 */
1686 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
1687 /* Always center screen on LVDS (if scaling is disabled) */
1688 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1689 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1690 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001691 /* Always center screen on SiS LVDS (if scaling is disabled) */
1692 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001694 /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
1695 if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1696 if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 }
1698 }
1699
1700 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1701 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1702
1703 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001704 case Panel_320x240_1:
1705 case Panel_320x240_2:
1706 case Panel_320x240_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
1707 SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 SiS_Pr->PanelVCLKIdx300 = VCLK28;
1709 SiS_Pr->PanelVCLKIdx315 = VCLK28;
1710 break;
1711 case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001712 SiS_Pr->PanelVRE = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 SiS_Pr->PanelVCLKIdx300 = VCLK28;
1714 SiS_Pr->PanelVCLKIdx315 = VCLK28;
1715 break;
1716 case Panel_800x600: SiS_Pr->PanelXRes = 800; SiS_Pr->PanelYRes = 600;
1717 SiS_Pr->PanelHT = 1056; SiS_Pr->PanelVT = 628;
1718 SiS_Pr->PanelHRS = 40; SiS_Pr->PanelHRE = 128;
1719 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 4;
1720 SiS_Pr->PanelVCLKIdx300 = VCLK40;
1721 SiS_Pr->PanelVCLKIdx315 = VCLK40;
1722 break;
1723 case Panel_1024x600: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 600;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001724 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1726 SiS_Pr->PanelVRS = 2 /* 88 */ ; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001727 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001729 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001731 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1733 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001734 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 SiS_Pr->PanelHRS = 23;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001736 SiS_Pr->PanelVRE = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 }
1738 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1739 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001740 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 break;
1742 case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001743 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
1744 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001746 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 SiS_Pr->PanelHRS = 23;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001748 SiS_Pr->PanelVRE = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001750 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001752 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001754 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 case Panel_1280x720: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 720;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001756 SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 SiS_Pr->PanelHRS = 110; SiS_Pr->PanelHRE = 40;
1758 SiS_Pr->PanelVRS = 5; SiS_Pr->PanelVRE = 5;
1759 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
1760 /* Data above for TMDS (projector); get from BIOS for LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001761 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 break;
1763 case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001764 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 806;
1766 SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
1767 SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
1768 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001769 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRS = 112;
1771 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1772 SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
1773 SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
1774 }
1775 break;
1776 case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001777 SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1779 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1780 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001781 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 break;
1783 case Panel_1280x800: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001784 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 SiS_Pr->PanelHRS = 21; SiS_Pr->PanelHRE = 24;
1786 SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
1787 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001788 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 break;
1790 case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001791 SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1793 SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
1794 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001795 SiS_GetLCDInfoBIOS(SiS_Pr);
1796 break;
1797 case Panel_1280x854: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 854;
1798 SiS_Pr->PanelHT = 1664; SiS_Pr->PanelVT = 861;
1799 SiS_Pr->PanelHRS = 16; SiS_Pr->PanelHRE = 112;
1800 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1801 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
1802 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 break;
1804 case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001805 SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1807 SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001808 if(resinfo == SIS_RI_1280x1024) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
1810 SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
1811 }
1812 break;
1813 case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001814 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1816 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1817 SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1818 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001819 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 break;
1821 case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001822 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1823 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1825 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001826 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 break;
1828 case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001829 SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 SiS_Pr->PanelHRS = 64; SiS_Pr->PanelHRE = 192;
1831 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1832 SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001833 if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
1834 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1835 SiS_Pr->PanelHT = 1760; SiS_Pr->PanelVT = 1235;
1836 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 32;
1837 SiS_Pr->PanelVRS = 2; SiS_Pr->PanelVRE = 4;
1838 SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
1839 SiS_Pr->Alternate1600x1200 = TRUE;
1840 }
1841 } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
1842 SiS_Pr->PanelHT = 2048; SiS_Pr->PanelVT = 1320;
1843 SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
1844 SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
1845 }
1846 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 break;
1848 case Panel_1680x1050: SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001849 SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 SiS_Pr->PanelHRS = 26; SiS_Pr->PanelHRE = 76;
1851 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1852 SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001853 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 break;
1855 case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001856 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1857 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001859 SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
1860 break;
1861 case Panel_856x480: SiS_Pr->PanelXRes = 856; SiS_Pr->PanelYRes = 480;
1862 SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
1863 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001865 SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 SiS_Pr->PanelHT = SiS_Pr->CHTotal;
1867 SiS_Pr->PanelVT = SiS_Pr->CVTotal;
1868 if(SiS_Pr->CP_PreferredIndex != -1) {
1869 SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001870 SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 SiS_Pr->PanelHT = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
1872 SiS_Pr->PanelVT = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
1873 SiS_Pr->PanelHRS = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
1874 SiS_Pr->PanelHRE = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
1875 SiS_Pr->PanelVRS = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
1876 SiS_Pr->PanelVRE = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
1877 SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
1878 SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
1879 SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
1880 SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
1881 if(SiS_Pr->CP_PrefClock) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001882 int idx;
1883 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001885 if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 else idx = VCLK_CUSTOM_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001887 SiS_Pr->SiS_VCLKData[idx].CLOCK =
1888 SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
1889 SiS_Pr->SiS_VCLKData[idx].SR2B =
1890 SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
1891 SiS_Pr->SiS_VCLKData[idx].SR2C =
1892 SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 }
1894 }
1895 break;
1896 default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001897 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 break;
1899 }
1900
1901 /* Special cases */
1902 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
1903 (SiS_Pr->SiS_IF_DEF_DSTN) ||
1904 (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1905 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001906 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1907 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 SiS_Pr->PanelHRS = 999;
1909 SiS_Pr->PanelHRE = 999;
1910 }
1911
1912 if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1913 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001914 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1915 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 SiS_Pr->PanelVRS = 999;
1917 SiS_Pr->PanelVRE = 999;
1918 }
1919
1920 /* DontExpand overrule */
1921 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
1922
1923 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
1924 /* No scaling for this mode on any panel (LCD=CRT2)*/
1925 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1926 }
1927
1928 switch(SiS_Pr->SiS_LCDResInfo) {
1929
1930 case Panel_Custom:
1931 case Panel_1152x864:
1932 case Panel_1280x768: /* TMDS only */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001933 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 break;
1935
1936 case Panel_800x600: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001937 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
1939 };
1940 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1941 break;
1942 }
1943 case Panel_1024x768: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001944 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1946 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1947 0xff
1948 };
1949 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1950 break;
1951 }
1952 case Panel_1280x720: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001953 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1955 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1956 0xff
1957 };
1958 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1959 if(SiS_Pr->PanelHT == 1650) {
1960 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1961 }
1962 break;
1963 }
1964 case Panel_1280x768_2: { /* LVDS only */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001965 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1967 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1968 SIS_RI_1152x768,0xff
1969 };
1970 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1971 switch(resinfo) {
1972 case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001973 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1974 }
1975 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001977 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 }
1979 case Panel_1280x800: { /* SiS TMDS special (Averatec 6200 series) */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001980 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1982 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1983 SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
1984 };
1985 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001986 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 }
1988 case Panel_1280x800_2: { /* SiS LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001989 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1991 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1992 SIS_RI_1152x768,0xff
1993 };
1994 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1995 switch(resinfo) {
1996 case SIS_RI_1280x720:
1997 case SIS_RI_1280x768: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001998 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1999 }
2000 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002002 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002004 case Panel_1280x854: { /* SiS LVDS */
2005 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2007 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002008 SIS_RI_1152x768,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 };
2010 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002011 switch(resinfo) {
2012 case SIS_RI_1280x720:
2013 case SIS_RI_1280x768:
2014 case SIS_RI_1280x800: if(SiS_Pr->UsePanelScaler == -1) {
2015 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2016 }
2017 break;
2018 }
2019 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002021 case Panel_1280x960: {
2022 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2024 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2025 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002026 SIS_RI_1280x854,0xff
2027 };
2028 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2029 break;
2030 }
2031 case Panel_1280x1024: {
2032 static const unsigned char nonscalingmodes[] = {
2033 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2034 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2035 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2036 SIS_RI_1280x854,SIS_RI_1280x960,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 };
2038 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2039 break;
2040 }
2041 case Panel_1400x1050: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002042 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2044 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002045 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
2046 SIS_RI_1280x960,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 };
2048 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002049 switch(resinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002051 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2052 }
2053 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002055 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 }
2057 break;
2058 }
2059 case Panel_1600x1200: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002060 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2062 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2063 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002064 SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 };
2066 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002067 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 }
2069 case Panel_1680x1050: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002070 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2072 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002073 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
2074 SIS_RI_1360x1024,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 };
2076 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2077 break;
2078 }
2079 }
2080 }
2081
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002082#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002084 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2085 SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 }
2087 }
2088
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002089 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002091 if(SiS_Pr->SiS_UseROM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002093 if(!(ROMAddr[0x235] & 0x02)) {
2094 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002097 }
2098 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002100 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 }
2102 }
2103 }
2104#endif
2105
2106 /* Special cases */
2107
2108 if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
2109 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2110 }
2111
2112 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
2113 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2114 }
2115
2116 switch(SiS_Pr->SiS_LCDResInfo) {
2117 case Panel_640x480:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002118 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 break;
2120 case Panel_1280x800:
2121 /* Don't pass 1:1 by default (TMDS special) */
2122 if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2123 break;
2124 case Panel_1280x960:
2125 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2126 break;
2127 case Panel_Custom:
2128 if((!SiS_Pr->CP_PrefClock) ||
2129 (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
2130 SiS_Pr->SiS_LCDInfo |= LCDPass11;
2131 }
2132 break;
2133 }
2134
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002135 if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2137 }
2138
2139 /* (In)validate LCDPass11 flag */
2140 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2141 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2142 }
2143
2144 /* LVDS DDA */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002145 if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146
2147 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
2148 if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
2149 if(ModeNo == 0x12) {
2150 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002151 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 }
2153 } else if(ModeNo > 0x13) {
2154 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002155 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2156 if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
2157 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 }
2159 }
2160 }
2161 }
2162 }
2163 }
2164
2165 if(modeflag & HalfDCLK) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002166 if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002168 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2170 } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
2171 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2172 } else if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002173 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
2174 if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2175 } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
2176 if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 }
2179 }
2180
2181 }
2182
2183 /* VESA timing */
2184 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2185 if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002186 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 }
2188 } else {
2189 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2190 }
2191
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002192#ifdef SIS_LINUX_KERNEL
2193#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
2195 SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
2196#endif
2197#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002198#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 xf86DrvMsgVerb(0, X_PROBED, 4,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002200 "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
2202#endif
2203}
2204
2205/*********************************************/
2206/* GET VCLK */
2207/*********************************************/
2208
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002209unsigned short
2210SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2211 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002213 unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
2214 unsigned short modeflag, resinfo, tempbx;
2215 const unsigned char *CHTVVCLKPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216
2217 if(ModeNo <= 0x13) {
2218 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2219 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
2220 CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2221 VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002222 VCLKIndexGENCRT = VCLKIndexGEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 } else {
2224 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2225 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2226 CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2227 VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002228 VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
2229 (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 }
2231
2232 if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 30x/B/LV */
2233
2234 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2235
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002236 CRT2Index >>= 6;
2237 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002239 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2241 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002242 VCLKIndex = VCLKIndexGEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 }
2244 } else {
2245 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2246 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2247 switch(resinfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002248 /* Correct those whose IndexGEN doesn't match VBVCLK array */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 case SIS_RI_720x480: VCLKIndex = VCLK_720x480; break;
2250 case SIS_RI_720x576: VCLKIndex = VCLK_720x576; break;
2251 case SIS_RI_768x576: VCLKIndex = VCLK_768x576; break;
2252 case SIS_RI_848x480: VCLKIndex = VCLK_848x480; break;
2253 case SIS_RI_856x480: VCLKIndex = VCLK_856x480; break;
2254 case SIS_RI_800x480: VCLKIndex = VCLK_800x480; break;
2255 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
2256 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002257 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
2259 default: VCLKIndex = VCLKIndexGEN;
2260 }
2261
2262 if(ModeNo <= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002263 if(SiS_Pr->ChipType <= SIS_315PRO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002265 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
2267 }
2268 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002269 if(SiS_Pr->ChipType <= SIS_315PRO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 if(VCLKIndex == 0) VCLKIndex = 0x41;
2271 if(VCLKIndex == 1) VCLKIndex = 0x43;
2272 if(VCLKIndex == 4) VCLKIndex = 0x44;
2273 }
2274 }
2275 }
2276
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002277 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
2279 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002280 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
2281 else VCLKIndex = HiTVVCLK;
2282 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) VCLKIndex = HiTVSimuVCLK;
2283 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK;
2284 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2;
2285 else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
2286 else VCLKIndex = TVVCLK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002288 if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
2289 else VCLKIndex += TVCLKBASE_315;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002291 } else { /* VGA2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002293 VCLKIndex = VCLKIndexGENCRT;
2294 if(SiS_Pr->ChipType < SIS_315H) {
2295 if(ModeNo > 0x13) {
2296 if( (SiS_Pr->ChipType == SIS_630) &&
2297 (SiS_Pr->ChipRevision >= 0x30)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 if(VCLKIndex == 0x14) VCLKIndex = 0x34;
2299 }
2300 /* Better VGA2 clock for 1280x1024@75 */
2301 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
2302 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002303 }
2304 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
2306 } else { /* If not programming CRT2 */
2307
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002308 VCLKIndex = VCLKIndexGENCRT;
2309 if(SiS_Pr->ChipType < SIS_315H) {
2310 if(ModeNo > 0x13) {
2311 if( (SiS_Pr->ChipType != SIS_630) &&
2312 (SiS_Pr->ChipType != SIS_300) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2314 }
2315 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 }
2318
2319 } else { /* LVDS */
2320
2321 VCLKIndex = CRT2Index;
2322
2323 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2324
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002325 if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326
2327 VCLKIndex &= 0x1f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002328 tempbx = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002330 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 tempbx += 2;
2332 if(SiS_Pr->SiS_ModeType > ModeVGA) {
2333 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
2334 }
2335 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2336 tempbx = 4;
2337 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2338 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2339 tempbx = 6;
2340 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2341 }
2342 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002343 switch(tempbx) {
2344 case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break;
2345 case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break;
2346 case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break;
2347 case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 case 4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002349 case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break;
2350 case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break;
2351 case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 case 8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL; break;
2353 default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002354 }
2355 VCLKIndex = CHTVVCLKPtr[VCLKIndex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002357 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002359 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2361 } else {
2362 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2363 }
2364
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002365#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 /* Special Timing: Barco iQ Pro R series */
2367 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2368
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002369 /* Special Timing: 848x480 and 856x480 parallel lvds panels */
2370 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2371 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 VCLKIndex = VCLK34_300;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002373 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 } else {
2375 VCLKIndex = VCLK34_315;
2376 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2377 }
2378 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002379#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002381 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002383 VCLKIndex = VCLKIndexGENCRT;
2384 if(SiS_Pr->ChipType < SIS_315H) {
2385 if(ModeNo > 0x13) {
2386 if( (SiS_Pr->ChipType == SIS_630) &&
2387 (SiS_Pr->ChipRevision >= 0x30) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002389 }
2390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393
2394 } else { /* if not programming CRT2 */
2395
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002396 VCLKIndex = VCLKIndexGENCRT;
2397 if(SiS_Pr->ChipType < SIS_315H) {
2398 if(ModeNo > 0x13) {
2399 if( (SiS_Pr->ChipType != SIS_630) &&
2400 (SiS_Pr->ChipType != SIS_300) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2402 }
2403#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002404 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 if(VCLKIndex == 0x0b) VCLKIndex = 0x40; /* 1024x768-70 */
2406 if(VCLKIndex == 0x0d) VCLKIndex = 0x41; /* 1024x768-75 */
2407 }
2408#endif
2409 }
2410 }
2411
2412 }
2413
2414 }
2415
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002416#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417#ifdef TWDEBUG
2418 xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
2419#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002420#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002422 return VCLKIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423}
2424
2425/*********************************************/
2426/* SET CRT2 MODE TYPE REGISTERS */
2427/*********************************************/
2428
2429static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002430SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002432 unsigned short i, j, modeflag, tempah=0;
2433 short tempcl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434#if defined(SIS300) || defined(SIS315H)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002435 unsigned short tempbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436#endif
2437#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002438 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
2439 unsigned short tempah2, tempbl2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440#endif
2441
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002442 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443
2444 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2445
2446 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
2447 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
2448
2449 } else {
2450
2451 for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002452 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
2454 }
2455
2456 tempcl = SiS_Pr->SiS_ModeType;
2457
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002458 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459
2460#ifdef SIS300 /* ---- 300 series ---- */
2461
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002462 /* For 301BDH: (with LCD via LVDS) */
2463 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
2465 tempbl &= 0xef;
2466 tempbl |= 0x02;
2467 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2468 tempbl |= 0x10;
2469 tempbl &= 0xfd;
2470 }
2471 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002472 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002474 if(ModeNo > 0x13) {
2475 tempcl -= ModeVGA;
2476 if(tempcl >= 0) {
2477 tempah = ((0x10 >> tempcl) | 0x80);
2478 }
2479 } else tempah = 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002481 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
2483#endif /* SIS300 */
2484
2485 } else {
2486
2487#ifdef SIS315H /* ------- 315/330 series ------ */
2488
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002489 if(ModeNo > 0x13) {
2490 tempcl -= ModeVGA;
2491 if(tempcl >= 0) {
2492 tempah = (0x08 >> tempcl);
2493 if (tempah == 0) tempah = 1;
2494 tempah |= 0x40;
2495 }
2496 } else tempah = 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002498 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
2500#endif /* SIS315H */
2501
2502 }
2503
2504 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2505
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002506 if(SiS_Pr->ChipType < SIS_315H) {
2507 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002509#ifdef SIS315H
2510 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2511 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2512 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2513 if(IS_SIS740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2515 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002516 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002518 }
2519#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 }
2521
2522 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2523
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002524 tempah = 0x01;
2525 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2526 tempah |= 0x02;
2527 }
2528 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2529 tempah ^= 0x05;
2530 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
2531 tempah ^= 0x01;
2532 }
2533 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002535 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002537 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002539 tempah = (tempah << 5) & 0xFF;
2540 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2541 tempah = (tempah >> 5) & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002543 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002545 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x08;
2546 else if(!(SiS_IsDualEdge(SiS_Pr))) tempah |= 0x08;
2547 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
2548 tempah &= ~0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002552 if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
2553 tempah |= 0x10;
2554 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555
2556 tempah |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002557 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002559 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002561 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002563 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2564 tempah |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002566 }
2567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002569 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
2571 tempah = 0x80;
2572 if(SiS_Pr->SiS_VBType & VB_SIS301) {
2573 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
2574 }
2575
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002576 if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002578 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002580 tempah |= 0x40;
2581 }
2582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002584 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585
2586 } else { /* LVDS */
2587
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002588 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589
2590#ifdef SIS315H
2591 /* LVDS can only be slave in 8bpp modes */
2592 tempah = 0x80;
2593 if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
2594 if(SiS_Pr->SiS_VBInfo & DriverMode) {
2595 tempah |= 0x02;
2596 }
2597 }
2598
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002599 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) tempah |= 0x02;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002601 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah ^= 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002603 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002605 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606#endif
2607
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002608 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609
2610#ifdef SIS300
2611 tempah = 0;
2612 if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002613 tempah |= 0x02;
2614 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 tempah <<= 5;
2616
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002617 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618
2619 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2620#endif
2621
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623
2624 }
2625
2626 } /* LCDA */
2627
2628 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2629
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002630 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631
2632#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002633 /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634
2635 /* The following is nearly unpreditable and varies from machine
2636 * to machine. Especially the 301DH seems to be a real trouble
2637 * maker. Some BIOSes simply set the registers (like in the
2638 * NoLCD-if-statements here), some set them according to the
2639 * LCDA stuff. It is very likely that some machines are not
2640 * treated correctly in the following, very case-orientated
2641 * code. What do I do then...?
2642 */
2643
2644 /* 740 variants match for 30xB, 301B-DH, 30xLV */
2645
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002646 if(!(IS_SIS740)) {
2647 tempah = 0x04; /* For all bridges */
2648 tempbl = 0xfb;
2649 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2650 tempah = 0x00;
2651 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 tempbl = 0xff;
2653 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002654 }
2655 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 }
2657
2658 /* The following two are responsible for eventually wrong colors
2659 * in TV output. The DH (VB_NoLCD) conditions are unknown; the
2660 * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
2661 * in a 650 box (Jake). What is the criteria?
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002662 * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
2663 * treatment like the 651+301B-DH(b0) case. Seems more to be the
2664 * chipset than the bridge revision.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 */
2666
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002667 if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 tempah = 0x30;
2669 tempbl = 0xc0;
2670 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2671 ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
2672 tempah = 0x00;
2673 tempbl = 0x00;
2674 }
2675 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
2676 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
2677 } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
2678 /* Fixes "TV-blue-bug" on 315+301 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002679 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002681 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
2682 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002684 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* For 301B-DH */
2685 tempah = 0x30; tempah2 = 0xc0;
2686 tempbl = 0xcf; tempbl2 = 0x3f;
2687 if(SiS_Pr->SiS_TVBlue == 0) {
2688 tempah = tempah2 = 0x00;
2689 } else if(SiS_Pr->SiS_TVBlue == -1) {
2690 /* Set on 651/M650, clear on 315/650 */
2691 if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
2692 tempah = tempah2 = 0x00;
2693 }
2694 }
2695 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2696 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002698 tempah = 0x30; tempah2 = 0xc0; /* For 30xB, 301C */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 tempbl = 0xcf; tempbl2 = 0x3f;
2700 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2701 tempah = tempah2 = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002702 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 tempbl = tempbl2 = 0xff;
2704 }
2705 }
2706 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2707 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2708 }
2709
2710 if(IS_SIS740) {
2711 tempah = 0x80;
2712 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
2713 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
2714 } else {
2715 tempah = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002716 tempbl = 0x7f;
2717 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2718 tempbl = 0xff;
2719 if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
2720 }
2721 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 }
2723
2724#endif /* SIS315H */
2725
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002726 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727
2728#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002729 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002731 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2732 ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
2734 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
2735 } else {
2736 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
2737 }
2738#endif
2739
2740 }
2741
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002742 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2743 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
2744 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
2746 }
2747 }
2748
2749 } else { /* LVDS */
2750
2751#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002752 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002754 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002756 tempah = 0x04;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 tempbl = 0xfb;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002758 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2759 tempah = 0x00;
2760 if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
2761 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2763
2764 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2765 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2766 }
2767
2768 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2769
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002770 } else if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771
2772 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2773 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2774
2775 }
2776
2777 }
2778#endif
2779
2780 }
2781
2782}
2783
2784/*********************************************/
2785/* GET RESOLUTION DATA */
2786/*********************************************/
2787
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002788unsigned short
2789SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002791 if(ModeNo <= 0x13)
2792 return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
2793 else
2794 return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795}
2796
2797static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002798SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002800 unsigned short xres, yres, modeflag=0, resindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002802 if(SiS_Pr->UseCustomMode) {
2803 xres = SiS_Pr->CHDisplay;
2804 if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
2805 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2806 /* DoubleScanMode-check done in CheckCalcCustomMode()! */
2807 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
2808 return;
2809 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002811 resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002813 if(ModeNo <= 0x13) {
2814 xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
2815 yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
2816 } else {
2817 xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
2818 yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
2819 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2820 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002822 if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002824 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
2825 if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
2826 if(yres == 350) yres = 400;
2827 }
2828 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
2829 if(ModeNo == 0x12) yres = 400;
2830 }
2831 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002833 if(modeflag & HalfDCLK) xres <<= 1;
2834 if(modeflag & DoubleScanMode) yres <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002838 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002840 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2841 switch(SiS_Pr->SiS_LCDResInfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 case Panel_1024x768:
2843 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002844 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2845 if(yres == 350) yres = 357;
2846 if(yres == 400) yres = 420;
2847 if(yres == 480) yres = 525;
2848 }
2849 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 break;
2851 case Panel_1280x1024:
2852 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2853 /* BIOS bug - does this regardless of scaling */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002854 if(yres == 400) yres = 405;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002856 if(yres == 350) yres = 360;
2857 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
2858 if(yres == 360) yres = 375;
2859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 break;
2861 case Panel_1600x1200:
2862 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002863 if(yres == 1024) yres = 1056;
2864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002866 }
2867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002869 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002871 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2872 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
2873 if(xres == 720) xres = 640;
2874 }
2875 } else if(xres == 720) xres = 640;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002877 if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
2878 yres = 400;
2879 if(SiS_Pr->ChipType >= SIS_315H) {
2880 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
2881 } else {
2882 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
2883 }
2884 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
2885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002887 }
2888 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2889 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890}
2891
2892/*********************************************/
2893/* GET CRT2 TIMING DATA */
2894/*********************************************/
2895
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002897SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2898 unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
2899 unsigned short *ResIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002901 unsigned short tempbx=0, tempal=0, resinfo=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
2903 if(ModeNo <= 0x13) {
2904 tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2905 } else {
2906 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2907 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2908 }
2909
2910 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
2911
2912 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
2913
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002914 tempbx = SiS_Pr->SiS_LCDResInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
2916
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002917 /* patch index */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918 if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
2919 if (resinfo == SIS_RI_1280x800) tempal = 9;
2920 else if(resinfo == SIS_RI_1400x1050) tempal = 11;
2921 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002922 (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
2923 (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 if (resinfo == SIS_RI_1280x768) tempal = 9;
2925 }
2926
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002927 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 /* Pass 1:1 only (center-screen handled outside) */
2929 /* This is never called for the panel's native resolution */
2930 /* since Pass1:1 will not be set in this case */
2931 tempbx = 100;
2932 if(ModeNo >= 0x13) {
2933 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
2934 }
2935 }
2936
2937#ifdef SIS315H
2938 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
2939 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
2940 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002941 tempbx = 200;
2942 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 }
2944 }
2945 }
2946#endif
2947
2948 } else { /* TV */
2949
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002950 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2951 /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
2952 tempbx = 2;
2953 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 tempbx = 13;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002955 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
2956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002958 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7;
2959 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
2960 else tempbx = 5;
2961 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2962 } else {
2963 if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3;
2964 else tempbx = 4;
2965 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967
2968 }
2969
2970 tempal &= 0x3F;
2971
2972 if(ModeNo > 0x13) {
2973 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002974 switch(resinfo) {
2975 case SIS_RI_720x480:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 tempal = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002977 if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) tempal = 9;
2978 break;
2979 case SIS_RI_720x576:
2980 case SIS_RI_768x576:
2981 case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
2982 tempal = 6;
2983 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2984 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002986 break;
2987 case SIS_RI_800x480:
2988 tempal = 4;
2989 break;
2990 case SIS_RI_512x384:
2991 case SIS_RI_1024x768:
2992 tempal = 7;
2993 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2994 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempal = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002996 break;
2997 case SIS_RI_1280x720:
2998 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2999 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003001 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 }
3003 }
3004 }
3005
3006 *CRT2Index = tempbx;
3007 *ResIndex = tempal;
3008
3009 } else { /* LVDS, 301B-DH (if running on LCD) */
3010
3011 tempbx = 0;
3012 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
3013
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003014 tempbx = 90;
3015 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
3016 tempbx = 92;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 if(SiS_Pr->SiS_ModeType > ModeVGA) {
3018 if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
3019 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003020 if(SiS_Pr->SiS_TVMode & TVSetPALM) tempbx = 94;
3021 else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
3022 }
3023 if(tempbx != 99) {
3024 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
3025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026
3027 } else {
3028
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003029 switch(SiS_Pr->SiS_LCDResInfo) {
3030 case Panel_640x480: tempbx = 12; break;
3031 case Panel_320x240_1: tempbx = 10; break;
3032 case Panel_320x240_2:
3033 case Panel_320x240_3: tempbx = 14; break;
3034 case Panel_800x600: tempbx = 16; break;
3035 case Panel_1024x600: tempbx = 18; break;
3036 case Panel_1152x768:
3037 case Panel_1024x768: tempbx = 20; break;
3038 case Panel_1280x768: tempbx = 22; break;
3039 case Panel_1280x1024: tempbx = 24; break;
3040 case Panel_1400x1050: tempbx = 26; break;
3041 case Panel_1600x1200: tempbx = 28; break;
3042#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 case Panel_Barco1366: tempbx = 80; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003044#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 }
3046
3047 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003048 case Panel_320x240_1:
3049 case Panel_320x240_2:
3050 case Panel_320x240_3:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 case Panel_640x480:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 break;
3053 default:
3054 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3055 }
3056
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003057 if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003059#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3061 tempbx = 82;
3062 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003063 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064 tempbx = 84;
3065 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3066 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003067#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068
3069 }
3070
3071 (*CRT2Index) = tempbx;
3072 (*ResIndex) = tempal & 0x1F;
3073 }
3074}
3075
3076static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003077SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3078 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003080 unsigned short tempax=0, tempbx=0, index, dotclock;
3081 unsigned short temp1=0, modeflag=0, tempcx=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082
3083 SiS_Pr->SiS_RVBHCMAX = 1;
3084 SiS_Pr->SiS_RVBHCFACT = 1;
3085
3086 if(ModeNo <= 0x13) {
3087
3088 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3089 index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
3090
3091 tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
3092 tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
3093 temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
3094
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003095 dotclock = (modeflag & Charx8Dot) ? 8 : 9;
3096
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 } else {
3098
3099 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003100 index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101
3102 tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
3103 tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
3104 tempax &= 0x03FF;
3105 tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
3106 tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
3107 tempcx &= 0x0100;
3108 tempcx <<= 2;
3109 tempbx |= tempcx;
3110 temp1 = SiS_Pr->SiS_CRT1Table[index].CR[7];
3111
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003112 dotclock = 8;
3113
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 }
3115
3116 if(temp1 & 0x01) tempbx |= 0x0100;
3117 if(temp1 & 0x20) tempbx |= 0x0200;
3118
3119 tempax += 5;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003120 tempax *= dotclock;
3121 if(modeflag & HalfDCLK) tempax <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122
3123 tempbx++;
3124
3125 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3126 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
3127}
3128
3129static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003130SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3131 unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003133 unsigned short ResIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003135 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3136 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3137 if(SiS_Pr->UseCustomMode) {
3138 ResIndex = SiS_Pr->CHTotal;
3139 if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
3140 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
3141 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3142 } else {
3143 if(ModeNo < 0x13) {
3144 ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3145 } else {
3146 ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3147 }
3148 if(ResIndex == 0x09) {
3149 if(SiS_Pr->Alternate1600x1200) ResIndex = 0x20; /* 1600x1200 LCDA */
3150 else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
3151 }
3152 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
3153 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
3154 SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
3155 SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
3156 }
3157 } else {
3158 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3159 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3160 }
3161 } else {
3162 /* This handles custom modes and custom panels */
3163 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3164 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3165 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3166 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3167 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
3168 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
3169 }
3170}
3171
3172static void
3173SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3174 unsigned short RefreshRateTableIndex)
3175{
3176 unsigned short CRT2Index, ResIndex, backup;
3177 const struct SiS_LVDSData *LVDSData = NULL;
3178
3179 SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180
3181 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3182 SiS_Pr->SiS_RVBHCMAX = 1;
3183 SiS_Pr->SiS_RVBHCFACT = 1;
3184 SiS_Pr->SiS_NewFlickerMode = 0;
3185 SiS_Pr->SiS_RVBHRS = 50;
3186 SiS_Pr->SiS_RY1COE = 0;
3187 SiS_Pr->SiS_RY2COE = 0;
3188 SiS_Pr->SiS_RY3COE = 0;
3189 SiS_Pr->SiS_RY4COE = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003190 SiS_Pr->SiS_RVBHRS2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 }
3192
3193 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3194
3195#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003196 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3197 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198#endif
3199
3200 } else {
3201
3202 /* 301BDH needs LVDS Data */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003203 backup = SiS_Pr->SiS_IF_DEF_LVDS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3205 SiS_Pr->SiS_IF_DEF_LVDS = 1;
3206 }
3207
3208 SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003209 &CRT2Index, &ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003211 SiS_Pr->SiS_IF_DEF_LVDS = backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003213 switch(CRT2Index) {
3214 case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1; break;
3215 case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2; break;
3216 case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break;
3217 case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
3218 case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
3219 case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
3220#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break;
3222 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break;
3223 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1; break;
3225 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003226#endif
3227 case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break;
3228 case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break;
3229 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData; break;
3230 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData; break;
3231 case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
3232 case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
3233 case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
3234 case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
3235 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236 }
3237
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003238 if(LVDSData) {
3239 SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
3240 SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
3241 SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT;
3242 SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT;
3243 } else {
3244 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3245 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003247 if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
3248 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
3249 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
3250 if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
3251 (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
3252 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3253 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3254#ifdef SIS300
3255 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3256 if(ResIndex < 0x08) {
3257 SiS_Pr->SiS_HDE = 1280;
3258 SiS_Pr->SiS_VDE = 1024;
3259 }
3260 }
3261#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262 }
3263 }
3264 }
3265}
3266
3267static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003268SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3269 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003271 unsigned char *ROMAddr = NULL;
3272 unsigned short tempax, tempbx, modeflag, romptr=0;
3273 unsigned short resinfo, CRT2Index, ResIndex;
3274 const struct SiS_LCDData *LCDPtr = NULL;
3275 const struct SiS_TVData *TVPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003277 short resinfo661;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278#endif
3279
3280 if(ModeNo <= 0x13) {
3281 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3282 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
3283 } else if(SiS_Pr->UseCustomMode) {
3284 modeflag = SiS_Pr->CModeFlag;
3285 resinfo = 0;
3286 } else {
3287 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3288 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
3289#ifdef SIS315H
3290 resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3291 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003292 (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
3293 (resinfo661 >= 0) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294 (SiS_Pr->SiS_NeedRomModeData) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003295 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 if((romptr = (SISGETROMW(21)))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003297 romptr += (resinfo661 * 10);
3298 ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 }
3300 }
3301 }
3302#endif
3303 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003304
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305 SiS_Pr->SiS_NewFlickerMode = 0;
3306 SiS_Pr->SiS_RVBHRS = 50;
3307 SiS_Pr->SiS_RY1COE = 0;
3308 SiS_Pr->SiS_RY2COE = 0;
3309 SiS_Pr->SiS_RY3COE = 0;
3310 SiS_Pr->SiS_RY4COE = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003311 SiS_Pr->SiS_RVBHRS2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003313 SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003315 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316
3317 if(SiS_Pr->UseCustomMode) {
3318
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003319 SiS_Pr->SiS_RVBHCMAX = 1;
3320 SiS_Pr->SiS_RVBHCFACT = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003322 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3323
3324 tempax = SiS_Pr->CHTotal;
3325 if(modeflag & HalfDCLK) tempax <<= 1;
3326 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3327 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328
3329 } else {
3330
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003331 SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332
3333 }
3334
3335 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3336
3337 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003338 &CRT2Index,&ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339
3340 switch(CRT2Index) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003341 case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break;
3342 case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break;
3343 case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
3344 case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break;
3345 case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break;
3346 case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break;
3347 case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
3348 case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
3349 case 10: TVPtr = SiS_Pr->SiS_St525iData; break;
3350 case 11: TVPtr = SiS_Pr->SiS_St525pData; break;
3351 case 12: TVPtr = SiS_Pr->SiS_St750pData; break;
3352 case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break;
3353 case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break;
3354 default: TVPtr = SiS_Pr->SiS_StPALData; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 }
3356
3357 SiS_Pr->SiS_RVBHCMAX = (TVPtr+ResIndex)->RVBHCMAX;
3358 SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
3359 SiS_Pr->SiS_VGAHT = (TVPtr+ResIndex)->VGAHT;
3360 SiS_Pr->SiS_VGAVT = (TVPtr+ResIndex)->VGAVT;
3361 SiS_Pr->SiS_HDE = (TVPtr+ResIndex)->TVHDE;
3362 SiS_Pr->SiS_VDE = (TVPtr+ResIndex)->TVVDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003363 SiS_Pr->SiS_RVBHRS2 = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 if(modeflag & HalfDCLK) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003365 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
3366 if(SiS_Pr->SiS_RVBHRS2) {
3367 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3368 tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
3369 if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
3370 else SiS_Pr->SiS_RVBHRS2 += tempax;
3371 }
3372 } else {
3373 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003375 SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376
3377 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3378
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003379 if((resinfo == SIS_RI_960x600) ||
3380 (resinfo == SIS_RI_1024x768) ||
3381 (resinfo == SIS_RI_1280x1024) ||
3382 (resinfo == SIS_RI_1280x720)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 SiS_Pr->SiS_NewFlickerMode = 0x40;
3384 }
3385
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003386 if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003388 SiS_Pr->SiS_HT = ExtHiTVHT;
3389 SiS_Pr->SiS_VT = ExtHiTVVT;
3390 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3391 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
3392 SiS_Pr->SiS_HT = StHiTVHT;
3393 SiS_Pr->SiS_VT = StHiTVVT;
3394 }
3395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396
3397 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3398
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003399 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3400 SiS_Pr->SiS_HT = 1650;
3401 SiS_Pr->SiS_VT = 750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3403 SiS_Pr->SiS_HT = NTSCHT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003404 if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 SiS_Pr->SiS_VT = NTSCVT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003406 } else {
3407 SiS_Pr->SiS_HT = NTSCHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003409 SiS_Pr->SiS_VT = NTSCVT;
3410 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411
3412 } else {
3413
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003414 SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
3415 SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
3416 SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
3417 SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003419 if(modeflag & HalfDCLK) {
3420 SiS_Pr->SiS_RY1COE = 0x00;
3421 SiS_Pr->SiS_RY2COE = 0xf4;
3422 SiS_Pr->SiS_RY3COE = 0x10;
3423 SiS_Pr->SiS_RY4COE = 0x38;
3424 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003426 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
3427 SiS_Pr->SiS_HT = NTSCHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003429 SiS_Pr->SiS_VT = NTSCVT;
3430 } else {
3431 SiS_Pr->SiS_HT = PALHT;
3432 SiS_Pr->SiS_VT = PALVT;
3433 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434
3435 }
3436
3437 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3438
3439 SiS_Pr->SiS_RVBHCMAX = 1;
3440 SiS_Pr->SiS_RVBHCFACT = 1;
3441
3442 if(SiS_Pr->UseCustomMode) {
3443
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003445 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3446
3447 tempax = SiS_Pr->CHTotal;
3448 if(modeflag & HalfDCLK) tempax <<= 1;
3449 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3450 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451
3452 } else {
3453
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003454 BOOLEAN gotit = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003456 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003458 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
3459 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3460 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3461 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 gotit = TRUE;
3463
3464 } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3465
3466#ifdef SIS315H
3467 SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003468 SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3469 SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
3470 SiS_Pr->SiS_VGAVT = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
3471 SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
3472 SiS_Pr->SiS_VT = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
3473 SiS_Pr->SiS_RVBHRS2 = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
3474 if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
3475 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3476 tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
3477 if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
3478 else SiS_Pr->SiS_RVBHRS2 += tempax;
3479 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
3481 else {
3482 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
3483 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003484 SiS_Pr->SiS_RVBHCMAX = 1;
3485 SiS_Pr->SiS_RVBHCFACT = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003487 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3488 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3489 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3490 SiS_Pr->SiS_RVBHRS2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491 gotit = TRUE;
3492 }
3493#endif
3494
3495 }
3496
3497 if(!gotit) {
3498
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003499 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3500 &CRT2Index,&ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003502 switch(CRT2Index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 case Panel_1024x768 : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3504 case Panel_1024x768 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break;
3505 case Panel_1280x720 :
3506 case Panel_1280x720 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data; break;
3507 case Panel_1280x768_2 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003508 case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 case Panel_1280x800 :
3510 case Panel_1280x800 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data; break;
3511 case Panel_1280x800_2 :
3512 case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003513 case Panel_1280x854 :
3514 case Panel_1280x854 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 case Panel_1280x960 :
3516 case Panel_1280x960 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003517 case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break;
3518 case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3519 case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break;
3520 case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break;
3521 case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break;
3522 case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 case Panel_1680x1050 :
3524 case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break;
3525 case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break;
3526#ifdef SIS315H
3527 case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break;
3528 case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3529#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003530 default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3531 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003533#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534#ifdef TWDEBUG
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003535 xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
3536#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537#endif
3538
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003539 SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
3540 SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3541 SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
3542 SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
3543 SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
3544 SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545
3546 }
3547
3548 tempax = SiS_Pr->PanelXRes;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003549 tempbx = SiS_Pr->PanelYRes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003551 switch(SiS_Pr->SiS_LCDResInfo) {
3552 case Panel_1024x768:
3553 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3554 if(SiS_Pr->ChipType < SIS_315H) {
3555 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3556 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3557 }
3558 } else {
3559 if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
3560 else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
3561 else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
3562 else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
3563 else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3564 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3565 }
3566 break;
3567 case Panel_1280x960:
3568 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
3569 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
3570 else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
3571 break;
3572 case Panel_1280x1024:
3573 if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
3574 else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
3575 else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
3576 break;
3577 case Panel_1600x1200:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003579 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
3580 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
3581 }
3582 break;
3583 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003585 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3586 tempax = SiS_Pr->SiS_VGAHDE;
3587 tempbx = SiS_Pr->SiS_VGAVDE;
3588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003590 SiS_Pr->SiS_HDE = tempax;
3591 SiS_Pr->SiS_VDE = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592 }
3593 }
3594}
3595
3596static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003597SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3598 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599{
3600
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003601 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003603 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3604 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3605 } else {
3606 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3607 /* Need LVDS Data for LCD on 301B-DH */
3608 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3609 } else {
3610 SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3611 }
3612 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003614 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003616 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003618 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619}
3620
3621/*********************************************/
3622/* GET LVDS DES (SKEW) DATA */
3623/*********************************************/
3624
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003625static const struct SiS_LVDSDes *
3626SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003628 const struct SiS_LVDSDes *PanelDesPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003630#ifdef SIS300
3631 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003633 if(SiS_Pr->ChipType < SIS_315H) {
3634 if(SiS_Pr->SiS_LCDTypeInfo == 4) {
3635 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3636 PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
3637 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3638 PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
3639 }
3640 } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3641 PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
3642 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3643 PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
3644 }
3645 }
3646 }
3647 }
3648 }
3649#endif
3650 return PanelDesPtr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651}
3652
3653static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003654SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3655 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003657 unsigned short modeflag, ResIndex;
3658 const struct SiS_LVDSDes *PanelDesPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659
3660 SiS_Pr->SiS_LCDHDES = 0;
3661 SiS_Pr->SiS_LCDVDES = 0;
3662
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003663 /* Some special cases */
3664 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3665
3666 /* Trumpion */
3667 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
3668 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3669 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3670 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3671 }
3672 }
3673 return;
3674 }
3675
3676 /* 640x480 on LVDS */
3677 if(SiS_Pr->ChipType < SIS_315H) {
3678 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
3679 SiS_Pr->SiS_LCDHDES = 8;
3680 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3681 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3682 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3683 return;
3684 }
3685 }
3686
3687 } /* LCD */
3688
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 if( (SiS_Pr->UseCustomMode) ||
3690 (SiS_Pr->SiS_LCDResInfo == Panel_Custom) ||
3691 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003692 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ||
3693 (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 return;
3695 }
3696
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003697 if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3698 else ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3699
3700 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701
3702#ifdef SIS315H
3703 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003704 /* non-pass 1:1 only, see above */
3705 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3706 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 }
3708 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3709 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3710 }
3711 }
3712 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003713 switch(SiS_Pr->SiS_CustomT) {
3714 case CUT_UNIWILL1024:
3715 case CUT_UNIWILL10242:
3716 case CUT_CLEVO1400:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3718 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3719 }
3720 break;
3721 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003722 switch(SiS_Pr->SiS_LCDResInfo) {
3723 case Panel_1280x1024:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
3725 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3726 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003727 break;
3728 case Panel_1280x800: /* Verified for Averatec 6240 */
3729 case Panel_1280x800_2: /* Verified for Asus A4L */
3730 case Panel_1280x854: /* Not verified yet FIXME */
3731 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3732 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 }
3734 }
3735#endif
3736
3737 } else {
3738
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003739 if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003741 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
3742 if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
3743 }
3744
3745 } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
3746
3747 SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
3748 SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
3749
3750 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3751
3752 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3753 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3754 }
3755 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3756 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3757 } else {
3758 if(SiS_Pr->ChipType < SIS_315H) {
3759 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3760 } else {
3761 switch(SiS_Pr->SiS_LCDResInfo) {
3762 case Panel_800x600:
3763 case Panel_1024x768:
3764 case Panel_1280x1024:
3765 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3766 break;
3767 case Panel_1400x1050:
3768 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3769 break;
3770 }
3771 }
3772 }
3773
3774 } else {
3775
3776 if(SiS_Pr->ChipType < SIS_315H) {
3777#ifdef SIS300
3778 switch(SiS_Pr->SiS_LCDResInfo) {
3779 case Panel_800x600:
3780 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3781 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3782 } else {
3783 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
3784 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3785 if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
3786 else SiS_Pr->SiS_LCDVDES -= 4;
3787 }
3788 break;
3789 case Panel_1024x768:
3790 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3791 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3792 } else {
3793 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3794 if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
3795 if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
3796 }
3797 break;
3798 case Panel_1024x600:
3799 default:
3800 if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
3801 (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
3802 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3803 } else {
3804 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3805 }
3806 break;
3807 }
3808
3809 switch(SiS_Pr->SiS_LCDTypeInfo) {
3810 case 1:
3811 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
3812 break;
3813 case 3: /* 640x480 only? */
3814 SiS_Pr->SiS_LCDHDES = 8;
3815 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3816 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3817 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3818 break;
3819 }
3820#endif
3821 } else {
3822#ifdef SIS315H
3823 switch(SiS_Pr->SiS_LCDResInfo) {
3824 case Panel_1024x768:
3825 case Panel_1280x1024:
3826 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3827 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3828 }
3829 break;
3830 case Panel_320x240_1:
3831 case Panel_320x240_2:
3832 case Panel_320x240_3:
3833 SiS_Pr->SiS_LCDVDES = 524;
3834 break;
3835 }
3836#endif
3837 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 }
3839
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003841 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3842 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003844 } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3845 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
3846 if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
3847 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
3849 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003850#ifdef SIS315H
3851 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
3852 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003854 if(!(modeflag & HalfDCLK)) {
3855 SiS_Pr->SiS_LCDHDES = 320;
3856 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003858 }
3859#endif
3860 }
3861 }
3862 }
3863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 }
3865 }
3866}
3867
3868/*********************************************/
3869/* DISABLE VIDEO BRIDGE */
3870/*********************************************/
3871
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003872#ifdef SIS315H
3873static int
3874SiS_HandlePWD(struct SiS_Private *SiS_Pr)
3875{
3876 int ret = 0;
3877#ifdef SET_PWD
3878 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3879 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
3880 unsigned char drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
3881 unsigned short temp;
3882
3883 if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
3884 (romptr) &&
3885 (SiS_Pr->SiS_PWDOffset) ) {
3886 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
3887 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
3888 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
3889 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
3890 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
3891 temp = 0x00;
3892 if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
3893 temp = 0x80;
3894 ret = 1;
3895 }
3896 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
3897#ifdef SIS_XORG_XF86
3898#ifdef TWDEBUG
3899 xf86DrvMsg(0, 0, "Setting PWD %x\n", temp);
3900#endif
3901#endif
3902 }
3903#endif
3904 return ret;
3905}
3906#endif
3907
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908/* NEVER use any variables (VBInfo), this will be called
3909 * from outside the context of modeswitch!
3910 * MUST call getVBType before calling this
3911 */
3912void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003913SiS_DisableBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914{
3915#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003916 unsigned short tempah, pushax=0, modenum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003918 unsigned short temp=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919
3920 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3921
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003922 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ===== For 30xB/C/LV ===== */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003924 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925
3926#ifdef SIS300 /* 300 series */
3927
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003928 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
3929 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3930 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003932 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003934 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 }
3936 if(SiS_Is301B(SiS_Pr)) {
3937 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
3938 SiS_ShortDelay(SiS_Pr,1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003939 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
3941 SiS_DisplayOff(SiS_Pr);
3942 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3943 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003944 SiS_UnLockCRT2(SiS_Pr);
3945 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
3947 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
3948 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003949 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
3950 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
3951 SiS_PanelDelay(SiS_Pr, 2);
3952 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3953 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003955 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 }
3957 }
3958
3959#endif /* SIS300 */
3960
3961 } else {
3962
3963#ifdef SIS315H /* 315 series */
3964
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003965 int didpwd = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
3967 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
3968
3969 modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
3970
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003971 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
3973#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003974 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003976 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 }
3978 }
3979#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003980
3981 didpwd = SiS_HandlePWD(SiS_Pr);
3982
3983 if( (modenum <= 0x13) ||
3984 (SiS_IsVAMode(SiS_Pr)) ||
3985 (!(SiS_IsDualEdge(SiS_Pr))) ) {
3986 if(!didpwd) {
3987 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
3988 if(custom1) SiS_PanelDelay(SiS_Pr, 3);
3989 } else {
3990 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
3991 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 }
3993
3994 if(!custom1) {
3995 SiS_DDC2Delay(SiS_Pr,0xff00);
3996 SiS_DDC2Delay(SiS_Pr,0xe000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003997 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
3998 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999 if(IS_SIS740) {
4000 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4001 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004002 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 }
4004
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005 }
4006
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004007 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4008 /* if(SiS_Pr->ChipType < SIS_340) {*/
4009 tempah = 0xef;
4010 if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
4011 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
4012 /*}*/
4013 }
4014
4015 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
4017 }
4018
4019 tempah = 0x3f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004020 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 tempah = 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004022 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 }
4024 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
4025
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004026 if((SiS_IsVAMode(SiS_Pr)) ||
4027 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028
4029 SiS_DisplayOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004030 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4031 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 }
4033 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4034 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
4035
4036 }
4037
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004038 if((!(SiS_IsVAMode(SiS_Pr))) ||
4039 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004041 if(!(SiS_IsDualEdge(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
4043 SiS_DisplayOff(SiS_Pr);
4044 }
4045 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4046
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004047 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4048 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049 }
4050
4051 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4052 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004053 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4055 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4056
4057 }
4058
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004059 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4061 }
4062
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004063 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4064
4065 if( (!(SiS_IsVAMode(SiS_Pr))) &&
4066 (!(SiS_CRT2IsLCD(SiS_Pr))) &&
4067 (!(SiS_IsDualEdge(SiS_Pr))) ) {
4068
4069 if(custom1) SiS_PanelDelay(SiS_Pr, 2);
4070 if(!didpwd) {
4071 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
4072 }
4073 if(custom1) SiS_PanelDelay(SiS_Pr, 4);
4074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
4076 if(!custom1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004077 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4078 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4079 if(SiS_IsVAorLCD(SiS_Pr)) {
4080 SiS_PanelDelayLoop(SiS_Pr, 3, 20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 }
4082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004084
4085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
4087#endif /* SIS315H */
4088
4089 }
4090
4091 } else { /* ============ For 301 ================ */
4092
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004093 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004095 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4096 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4097 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 }
4099#endif
4100 }
4101
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004102 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
4103 SiS_DisplayOff(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004105 if(SiS_Pr->ChipType >= SIS_315H) {
4106 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 }
4108
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004109 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004111 if(SiS_Pr->ChipType >= SIS_315H) {
4112 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4113 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4115 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4116 } else {
4117#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004118 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
4119 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4120 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4121 SiS_PanelDelay(SiS_Pr, 2);
4122 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 }
4124#endif
4125 }
4126
4127 }
4128
4129 } else { /* ============ For LVDS =============*/
4130
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004131 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
4133#ifdef SIS300 /* 300 series */
4134
4135 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004136 SiS_SetCH700x(SiS_Pr,0x0E,0x09);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 }
4138
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004139 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004141 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004143 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4144 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4145 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 }
4147 } else {
4148 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4149 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004150 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4151 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
4153 SiS_DisplayOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004154 }
4155 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4156 SiS_PanelDelay(SiS_Pr, 3);
4157 }
4158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 }
4160 }
4161
4162 SiS_DisplayOff(SiS_Pr);
4163
4164 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4165
4166 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004167 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4169 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4170
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004171 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4172 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4173 SiS_PanelDelay(SiS_Pr, 2);
4174 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 }
4176
4177#endif /* SIS300 */
4178
4179 } else {
4180
4181#ifdef SIS315H /* 315 series */
4182
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004183 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4184 /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
4185 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
4186 /* } */
4187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188
4189 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4190
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004191 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192 temp = SiS_GetCH701x(SiS_Pr,0x61);
4193 if(temp < 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004194 SiS_SetCH701x(SiS_Pr,0x76,0xac);
4195 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196 }
4197
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004198 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4199 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4200 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201 }
4202 }
4203
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004204 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4205 (SiS_IsVAMode(SiS_Pr)) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206 SiS_Chrontel701xBLOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004207 SiS_Chrontel701xOff(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208 }
4209
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004210 if(SiS_Pr->ChipType != SIS_740) {
4211 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4212 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4213 SiS_SetCH701x(SiS_Pr,0x49,0x01);
4214 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215 }
4216
4217 }
4218
4219 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004220 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4221 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222 }
4223
4224 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004225 (!(SiS_IsDualEdge(SiS_Pr))) ||
4226 (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 SiS_DisplayOff(SiS_Pr);
4228 }
4229
4230 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004231 (!(SiS_IsDualEdge(SiS_Pr))) ||
4232 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4234 }
4235
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004236 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4238 }
4239
4240 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4241
4242 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004243 (!(SiS_IsDualEdge(SiS_Pr))) ||
4244 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4246 }
4247
4248 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004249 if(SiS_CRT2IsLCD(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004251 if(SiS_Pr->ChipType == SIS_550) {
4252 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
4253 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254 }
4255 }
4256 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004257 if(SiS_Pr->ChipType == SIS_740) {
4258 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4259 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004261 } else if(SiS_IsVAMode(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4263 }
4264 }
4265
4266 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004267 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
4269 } else {
4270 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
4271 }
4272 }
4273
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004274 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004276 if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
4278 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
4279 } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004280 (!(SiS_IsDualEdge(SiS_Pr))) ||
4281 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4283 }
4284
4285 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004286 if(SiS_CRT2IsLCD(SiS_Pr)) {
4287 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4288 SiS_PanelDelay(SiS_Pr, 2);
4289 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290 }
4291 }
4292 }
4293
4294#endif /* SIS315H */
4295
4296 } /* 315 series */
4297
4298 } /* LVDS */
4299
4300}
4301
4302/*********************************************/
4303/* ENABLE VIDEO BRIDGE */
4304/*********************************************/
4305
4306/* NEVER use any variables (VBInfo), this will be called
4307 * from outside the context of a mode switch!
4308 * MUST call getVBType before calling this
4309 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004310#ifdef SIS_LINUX_KERNEL
4311static
4312#endif
4313void
4314SiS_EnableBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004316 unsigned short temp=0, tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004318 unsigned short temp1, pushax=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 BOOLEAN delaylong = FALSE;
4320#endif
4321
4322 if(SiS_Pr->SiS_VBType & VB_SISVB) {
4323
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004324 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ====== For 301B et al ====== */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004326 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327
4328#ifdef SIS300 /* 300 series */
4329
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004330 if(SiS_CRT2IsLCD(SiS_Pr)) {
4331 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4333 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004334 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004336 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
4337 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4338 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 }
4340 }
4341 }
4342
4343 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004344 (SiS_CRT2IsLCD(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
4346 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* Enable CRT2 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004347 SiS_DisplayOn(SiS_Pr);
4348 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4350 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004351 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4352 } else {
4353 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4356 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004357 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4358 SiS_PanelDelay(SiS_Pr, 1);
4359 }
4360 SiS_WaitVBRetrace(SiS_Pr);
4361 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363 }
4364
4365 } else {
4366
4367 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004368 if(SiS_BridgeInSlavemode(SiS_Pr)) {
4369 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4370 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4371 }
4372 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4374 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4375 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
4376 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004377 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4378 if(SiS_CRT2IsLCD(SiS_Pr)) {
4379 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4380 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4381 SiS_PanelDelay(SiS_Pr, 1);
4382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 }
4386 }
4387
4388 }
4389
4390
4391#endif /* SIS300 */
4392
4393 } else {
4394
4395#ifdef SIS315H /* 315 series */
4396
4397#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004398 unsigned char r30=0, r31=0, r32=0, r33=0, cr36=0;
4399 int didpwd = 0;
4400 /* unsigned short emidelay=0; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401#endif
4402
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004403 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
4405#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004406 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4408 }
4409#endif
4410 }
4411
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004412 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4413 /*if(SiS_Pr->ChipType < SIS_340) { */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414 tempah = 0x10;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004415 if(SiS_LCDAEnabled(SiS_Pr)) {
4416 if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
4417 else tempah = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 }
4419 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004420 /*}*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 }
4422
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004423 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424
4425 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4426 SiS_DisplayOff(SiS_Pr);
4427 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4428 if(IS_SIS740) {
4429 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4430 }
4431
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004432 didpwd = SiS_HandlePWD(SiS_Pr);
4433
4434 if(SiS_IsVAorLCD(SiS_Pr)) {
4435 if(!didpwd) {
4436 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
4437 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4438 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4439 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4440 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4441 SiS_GenericDelay(SiS_Pr, 17664);
4442 }
4443 }
4444 } else {
4445 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4446 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4447 SiS_GenericDelay(SiS_Pr, 17664);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448 }
4449 }
4450 }
4451
4452 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004453 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454 delaylong = TRUE;
4455 }
4456
4457 }
4458
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004459 if(!(SiS_IsVAMode(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004461 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004463 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4464 if(!(tempah & SetCRT2ToRAMDAC)) {
4465 if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004467 }
4468 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469
4470 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4471
4472 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4473 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4474
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004475 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4476 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477 }
4478
4479 } else {
4480
4481 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
4482
4483 }
4484
4485 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
4486 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4487
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004488 if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
4489 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4490 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4491 /* Enable "LVDS PLL power on" (even on 301C) */
4492 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
4493 /* Enable "LVDS Driver Power on" (even on 301C) */
4494 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
4495 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004498 tempah = 0xc0;
4499 if(SiS_IsDualEdge(SiS_Pr)) {
4500 tempah = 0x80;
4501 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
4502 }
4503 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004505 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4506
4507 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508
4509 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
4510 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4511
4512 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4513#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004514 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4515 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4516 SiS_GenericDelay(SiS_Pr, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004517 }
4518#endif
4519 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
4520
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004521 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522#ifdef SET_EMI
4523 cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
4524
4525 if(SiS_Pr->SiS_ROMNew) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004526 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
4527 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528 if(romptr) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004529 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530 SiS_Pr->EMI_30 = 0;
4531 SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
4532 SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
4533 SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
4534 if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
4535 /* emidelay = SISGETROMW((romptr + 0x22)); */
4536 SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = TRUE;
4537 }
4538 }
4539
4540 /* (P4_30|0x40) */
4541 /* Compal 1400x1050: 0x05, 0x60, 0x00 YES (1.10.7w; CR36=69) */
4542 /* Compal 1400x1050: 0x0d, 0x70, 0x40 YES (1.10.7x; CR36=69) */
4543 /* Acer 1280x1024: 0x12, 0xd0, 0x6b NO (1.10.9k; CR36=73) */
4544 /* Compaq 1280x1024: 0x0d, 0x70, 0x6b YES (1.12.04b; CR36=03) */
4545 /* Clevo 1024x768: 0x05, 0x60, 0x33 NO (1.10.8e; CR36=12, DL!) */
4546 /* Clevo 1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES (1.10.8y; CR36=?2) */
4547 /* Clevo 1024x768: 0x05, 0x60, 0x33 (if type != 3) YES (1.10.8y; CR36=?2) */
4548 /* Asus 1024x768: ? ? (1.10.8o; CR36=?2) */
4549 /* Asus 1024x768: 0x08, 0x10, 0x3c (problematic) YES (1.10.8q; CR36=22) */
4550
4551 if(SiS_Pr->HaveEMI) {
4552 r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
4553 r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
4554 } else {
4555 r30 = 0;
4556 }
4557
4558 /* EMI_30 is read at driver start; however, the BIOS sets this
4559 * (if it is used) only if the LCD is in use. In case we caught
4560 * the machine while on TV output, this bit is not set and we
4561 * don't know if it should be set - hence our detection is wrong.
4562 * Work-around this here:
4563 */
4564
4565 if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
4566 switch((cr36 & 0x0f)) {
4567 case 2:
4568 r30 |= 0x40;
4569 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
4570 if(!SiS_Pr->HaveEMI) {
4571 r31 = 0x05; r32 = 0x60; r33 = 0x33;
4572 if((cr36 & 0xf0) == 0x30) {
4573 r31 = 0x0d; r32 = 0x70; r33 = 0x40;
4574 }
4575 }
4576 break;
4577 case 3: /* 1280x1024 */
4578 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
4579 if(!SiS_Pr->HaveEMI) {
4580 r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4581 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4582 r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
4583 }
4584 }
4585 break;
4586 case 9: /* 1400x1050 */
4587 r30 |= 0x40;
4588 if(!SiS_Pr->HaveEMI) {
4589 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4590 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4591 r31 = 0x0d; r32 = 0x70; r33 = 0x40; /* BIOS values */
4592 }
4593 }
4594 break;
4595 case 11: /* 1600x1200 - unknown */
4596 r30 |= 0x40;
4597 if(!SiS_Pr->HaveEMI) {
4598 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4599 }
4600 }
4601 }
4602
4603 /* BIOS values don't work so well sometimes */
4604 if(!SiS_Pr->OverruleEMI) {
4605#ifdef COMPAL_HACK
4606 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004607 if((cr36 & 0x0f) == 0x09) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608 r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
4609 }
4610 }
4611#endif
4612#ifdef COMPAQ_HACK
4613 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004614 if((cr36 & 0x0f) == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615 r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4616 }
4617 }
4618#endif
4619#ifdef ASUS_HACK
4620 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004621 if((cr36 & 0x0f) == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622 /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 2 */
4623 /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 3 */
4624 /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 4 */
4625 /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 5 */
4626 }
4627 }
4628#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630
4631 if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
4632 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004633 SiS_GenericDelay(SiS_Pr, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634 }
4635 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
4636 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
4637 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
4638#endif /* SET_EMI */
4639
4640 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
4641
4642#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004643 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4644 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4645 if(r30 & 0x40) {
4646 /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
4647 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648 if(delaylong) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004649 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650 delaylong = FALSE;
4651 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004652 SiS_WaitVBRetrace(SiS_Pr);
4653 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004654 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004655 SiS_GenericDelay(SiS_Pr, 1280);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004657 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */
4658 /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
4659 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004660 }
4661#endif
4662 }
4663 }
4664
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004665 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4666 if(SiS_IsVAorLCD(SiS_Pr)) {
4667 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004668 if(delaylong) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004669 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004671 SiS_WaitVBRetrace(SiS_Pr);
4672 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4673 SiS_GenericDelay(SiS_Pr, 2048);
4674 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004675 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004676 if(!didpwd) {
4677 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4678 } else {
4679 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
4680 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681 }
4682 }
4683
4684 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4685 SiS_DisplayOn(SiS_Pr);
4686 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
4687
4688 }
4689
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004690 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4692 }
4693
4694#endif /* SIS315H */
4695
4696 }
4697
4698 } else { /* ============ For 301 ================ */
4699
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004700 if(SiS_Pr->ChipType < SIS_315H) {
4701 if(SiS_CRT2IsLCD(SiS_Pr)) {
4702 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4703 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704 }
4705 }
4706
4707 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
4708 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004709 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4710 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711 }
4712 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4713
4714 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4715
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004716 if(SiS_Pr->ChipType >= SIS_315H) {
4717 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4718 if(!(temp & 0x80)) {
4719 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720 }
4721 }
4722
4723 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4724
4725 SiS_VBLongWait(SiS_Pr);
4726 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004727 if(SiS_Pr->ChipType >= SIS_315H) {
4728 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729 }
4730 SiS_VBLongWait(SiS_Pr);
4731
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004732 if(SiS_Pr->ChipType < SIS_315H) {
4733 if(SiS_CRT2IsLCD(SiS_Pr)) {
4734 SiS_PanelDelay(SiS_Pr, 1);
4735 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736 }
4737 }
4738
4739 }
4740
4741 } else { /* =================== For LVDS ================== */
4742
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004743 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004744
4745#ifdef SIS300 /* 300 series */
4746
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004747 if(SiS_CRT2IsLCD(SiS_Pr)) {
4748 if(SiS_Pr->ChipType == SIS_730) {
4749 SiS_PanelDelay(SiS_Pr, 1);
4750 SiS_PanelDelay(SiS_Pr, 1);
4751 SiS_PanelDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004753 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4754 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4755 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756 }
4757 }
4758
4759 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4760 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004761 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4763 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004764 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004765 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004766 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767 }
4768
4769 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004770 if(!(SiS_CRT2IsLCD(SiS_Pr))) {
4771 SiS_WaitVBRetrace(SiS_Pr);
4772 SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
4773 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774 }
4775
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004776 if(SiS_CRT2IsLCD(SiS_Pr)) {
4777 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4778 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4779 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4780 SiS_PanelDelay(SiS_Pr, 1);
4781 SiS_PanelDelay(SiS_Pr, 1);
4782 }
4783 SiS_WaitVBRetrace(SiS_Pr);
4784 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4785 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004786 }
4787 }
4788
4789#endif /* SIS300 */
4790
4791 } else {
4792
4793#ifdef SIS315H /* 315 series */
4794
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004795 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4796 /*if(SiS_Pr->ChipType < SIS_340) {*/ /* XGI needs this */
4797 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
4798 /*}*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07004799 }
4800
4801 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004802 if(SiS_CRT2IsLCD(SiS_Pr)) {
4803 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4804 SiS_PanelDelay(SiS_Pr, 0);
4805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004806 }
4807
4808 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004809 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004810
4811 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4812
4813 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004814 temp = SiS_GetCH701x(SiS_Pr,0x66);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004815 temp &= 0x20;
4816 SiS_Chrontel701xBLOff(SiS_Pr);
4817 }
4818
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004819 if(SiS_Pr->ChipType != SIS_550) {
4820 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004821 }
4822
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004823 if(SiS_Pr->ChipType == SIS_740) {
4824 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4825 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4826 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004827 }
4828 }
4829 }
4830
4831 temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4832 if(!(temp1 & 0x80)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004833 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834 }
4835
4836 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004837 if(temp) {
4838 SiS_Chrontel701xBLOn(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004839 }
4840 }
4841
4842 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004843 if(SiS_CRT2IsLCD(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004845 if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004846 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
4847 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
4848 }
4849 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004850 } else if(SiS_IsVAMode(SiS_Pr)) {
4851 if(SiS_Pr->ChipType != SIS_740) {
4852 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853 }
4854 }
4855
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004856 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4857 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004858 }
4859
4860 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004861 if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
4862 SiS_Chrontel701xOn(SiS_Pr);
4863 }
4864 if( (SiS_IsVAMode(SiS_Pr)) ||
4865 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4866 SiS_ChrontelDoSomething1(SiS_Pr);
4867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004868 }
4869
4870 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004871 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4872 if( (SiS_IsVAMode(SiS_Pr)) ||
4873 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4874 SiS_Chrontel701xBLOn(SiS_Pr);
4875 SiS_ChrontelInitTVVSync(SiS_Pr);
4876 }
4877 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004878 } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004879 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4880 if(SiS_CRT2IsLCD(SiS_Pr)) {
4881 SiS_PanelDelay(SiS_Pr, 1);
4882 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004883 }
4884 }
4885 }
4886
4887#endif /* SIS315H */
4888
4889 } /* 310 series */
4890
4891 } /* LVDS */
4892
4893}
4894
4895/*********************************************/
4896/* SET PART 1 REGISTER GROUP */
4897/*********************************************/
4898
4899/* Set CRT2 OFFSET / PITCH */
4900static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004901SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
4902 unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004904 unsigned short offset;
4905 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004907 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004908
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004909 offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004910
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004911 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
4912 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004913
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004914 temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
4915 if(offset & 0x07) temp++;
4916 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004917}
4918
4919/* Set CRT2 sync and PanelLink mode */
4920static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004921SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004923 unsigned short tempah=0, tempbl, infoflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004925 tempbl = 0xC0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004927 if(SiS_Pr->UseCustomMode) {
4928 infoflag = SiS_Pr->CInfoFlag;
4929 } else {
4930 infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
4931 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004932
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004933 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004935 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4936 tempah = 0;
4937 } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
4938 tempah = SiS_Pr->SiS_LCDInfo;
4939 } else tempah = infoflag >> 8;
4940 tempah &= 0xC0;
4941 tempah |= 0x20;
4942 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4943 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4944 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
4945 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
4946 tempah |= 0xf0;
4947 }
4948 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4949 (SiS_Pr->SiS_IF_DEF_DSTN) ||
4950 (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
4951 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
4952 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
4953 tempah |= 0x30;
4954 }
4955 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4956 (SiS_Pr->SiS_IF_DEF_DSTN) ) {
4957 tempah &= ~0xc0;
4958 }
4959 }
4960 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4961 if(SiS_Pr->ChipType >= SIS_315H) {
4962 tempah >>= 3;
4963 tempah &= 0x18;
4964 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
4965 /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
4966 } else {
4967 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
4968 }
4969 } else {
4970 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004972
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004973 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004974
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004975 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004976
4977#ifdef SIS300 /* ---- 300 series --- */
4978
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004979 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* 630 - 301B(-DH) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004980
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004981 tempah = infoflag >> 8;
4982 tempbl = 0;
4983 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4984 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4985 tempah = SiS_Pr->SiS_LCDInfo;
4986 tempbl = (tempah >> 6) & 0x03;
4987 }
4988 }
4989 tempah &= 0xC0;
4990 tempah |= 0x20;
4991 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4992 tempah |= 0xc0;
4993 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4994 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
4995 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004998 } else { /* 630 - 301 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004999
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005000 tempah = ((infoflag >> 8) & 0xc0) | 0x20;
5001 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5002 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005004 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005005
5006#endif /* SIS300 */
5007
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005008 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009
5010#ifdef SIS315H /* ------- 315 series ------ */
5011
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005012 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* 315 - LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005013
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005014 tempbl = 0;
5015 if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
5016 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5017 tempah = infoflag >> 8;
5018 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
5019 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
5020 }
5021 } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
5022 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
5023 tempah = infoflag >> 8;
5024 tempbl = 0x03;
5025 } else {
5026 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
5027 tempbl = (tempah >> 6) & 0x03;
5028 tempbl |= 0x08;
5029 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
5030 }
5031 tempah &= 0xC0;
5032 tempah |= 0x20;
5033 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5034 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0;
5035 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
5036 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
5037 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5038 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
5039 }
5040 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005041
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005042 } else { /* 315 - TMDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005044 tempah = tempbl = infoflag >> 8;
5045 if(!SiS_Pr->UseCustomMode) {
5046 tempbl = 0;
5047 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
5048 if(ModeNo <= 0x13) {
5049 tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
5050 }
5051 }
5052 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5053 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5054 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
5055 tempah = SiS_Pr->SiS_LCDInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056 tempbl = (tempah >> 6) & 0x03;
5057 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005058 }
5059 }
5060 }
5061 tempah &= 0xC0;
5062 tempah |= 0x20;
5063 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5064 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
5065 /* Imitate BIOS bug */
5066 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0;
5067 }
5068 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
5069 tempah >>= 3;
5070 tempah &= 0x18;
5071 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
5072 } else {
5073 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
5074 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
5075 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5076 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
5077 }
5078 }
5079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082#endif /* SIS315H */
5083 }
5084 }
5085}
5086
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005087/* Set CRT2 FIFO on 300/540/630/730 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005088#ifdef SIS300
5089static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005090SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005092 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5093 unsigned short temp, index, modeidindex, refreshratetableindex;
5094 unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
5095 unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
5096 unsigned int data, pci50, pciA0;
5097 static const unsigned char colortharray[] = {
5098 1, 1, 2, 2, 3, 4
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099 };
5100
5101 SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
5102
5103 if(!SiS_Pr->CRT1UsesCustomMode) {
5104
5105 CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */
5106 SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
5107 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
5108 SiS_Pr->SiS_SelectCRT2Rate = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005109 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005110
5111 if(CRT1ModeNo >= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005112 /* Get VCLK */
5113 index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
5114 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005116 /* Get colordepth */
5117 colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
5118 if(!colorth) colorth++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119 }
5120
5121 } else {
5122
5123 CRT1ModeNo = 0xfe;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005124
5125 /* Get VCLK */
5126 VCLK = SiS_Pr->CSRClock_CRT1;
5127
5128 /* Get color depth */
5129 colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130
5131 }
5132
5133 if(CRT1ModeNo >= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005134 /* Get MCLK */
5135 if(SiS_Pr->ChipType == SIS_300) {
5136 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
5137 } else {
5138 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
5139 }
5140 index &= 0x07;
5141 MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005143 temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
5144 if(!temp) temp++;
5145 temp <<= 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005146
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005147 data2 = temp - ((colorth * VCLK) / MCLK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005148
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005149 temp = (28 * 16) % data2;
5150 data2 = (28 * 16) / data2;
5151 if(temp) data2++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005153 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005154
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005155 SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
5156 data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005158 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005160#ifdef SIS_LINUX_KERNEL
5161 pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
5162 pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163#else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005164 pci50 = pciReadLong(0x00000000, 0x50);
5165 pciA0 = pciReadLong(0x00000000, 0xA0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005166#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005168 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005170 index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
5171 index += (unsigned short)(((pci50 >> 9)) & 0x03);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005173 /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
5174 index = 0; /* -- do it like the BIOS anyway... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005175
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005176 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005178 pci50 >>= 24;
5179 pciA0 >>= 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005181 index = (pci50 >> 1) & 0x07;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005183 if(pci50 & 0x01) index += 6;
5184 if(!(pciA0 & 0x01)) index += 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005185
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005186 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005190 data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
5191 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005194
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005195 data += data2; /* CRT1 Request Period */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005197 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5198 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005199
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005200 if(!SiS_Pr->UseCustomMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005201
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005202 CRT2ModeNo = ModeNo;
5203 SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005205 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005206
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005207 /* Get VCLK */
5208 index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
5209 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005210
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005211 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5212 if(SiS_Pr->SiS_UseROM) {
5213 if(ROMAddr[0x220] & 0x01) {
5214 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
5215 }
5216 }
5217 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005218
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005219 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005220
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005221 /* Get VCLK */
5222 CRT2ModeNo = 0xfe;
5223 VCLK = SiS_Pr->CSRClock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005225 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005227 /* Get colordepth */
5228 colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
5229 if(!colorth) colorth++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005231 data = data * VCLK * colorth;
5232 temp = data % (MCLK << 4);
5233 data = data / (MCLK << 4);
5234 if(temp) data++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005236 if(data < 6) data = 6;
5237 else if(data > 0x14) data = 0x14;
5238
5239 if(SiS_Pr->ChipType == SIS_300) {
5240 temp = 0x16;
5241 if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
5242 temp = 0x13;
5243 } else {
5244 temp = 0x16;
5245 if(( (SiS_Pr->ChipType == SIS_630) ||
5246 (SiS_Pr->ChipType == SIS_730) ) &&
5247 (SiS_Pr->ChipRevision >= 0x30))
5248 temp = 0x1b;
5249 }
5250 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
5251
5252 if((SiS_Pr->ChipType == SIS_630) &&
5253 (SiS_Pr->ChipRevision >= 0x30)) {
5254 if(data > 0x13) data = 0x13;
5255 }
5256 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005257
5258 } else { /* If mode <= 0x13, we just restore everything */
5259
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005260 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5261 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262
5263 }
5264}
5265#endif
5266
5267/* Set CRT2 FIFO on 315/330 series */
5268#ifdef SIS315H
5269static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005270SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271{
5272 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005273 if( (SiS_Pr->ChipType == SIS_760) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07005274 (SiS_Pr->SiS_SysFlags & SF_760LFB) &&
5275 (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
5276 (SiS_Pr->SiS_VGAHDE >= 1280) &&
5277 (SiS_Pr->SiS_VGAVDE >= 1024) ) {
5278 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
5279 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
5280 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5281 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
5282 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5283 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
5284 } else {
5285 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
5286 }
5287
5288}
5289#endif
5290
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005291static unsigned short
5292SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005294 unsigned int tempax,tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005295
5296 tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
5297 tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
5298 tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005299 return (unsigned short)tempax;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005300}
5301
5302/* Set Part 1 / SiS bridge slave mode */
5303static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005304SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
5305 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005306{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005307 unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
5308 static const unsigned short CRTranslation[] = {
5309 /* CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 */
5310 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
5311 /* CR8 CR9 SR0A SR0B SR0C SR0D SR0E CR0F */
5312 0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
5313 /* CR10 CR11 CR12 CR13 CR14 CR15 CR16 CR17 */
5314 0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
5315 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316
5317 if(ModeNo <= 0x13) {
5318 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319 } else if(SiS_Pr->UseCustomMode) {
5320 modeflag = SiS_Pr->CModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321 xres = SiS_Pr->CHDisplay;
5322 } else {
5323 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005324 xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
5325 }
5326
5327 /* The following is only done if bridge is in slave mode: */
5328
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005329 if(SiS_Pr->ChipType >= SIS_315H) {
5330 if(xres >= 1600) { /* BIOS: == 1600 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005331 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
5332 }
5333 }
5334
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005335 SiS_Pr->CHTotal = 8224; /* Max HT, 0x2020, results in 0x3ff in registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005337 SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
5338 if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005339
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005340 SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005342 SiS_Pr->CHBlankStart += 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343 }
5344
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005345 SiS_Pr->CHBlankEnd = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005347 if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005350 temp = SiS_Pr->SiS_VGAHT - 96;
5351 if(!(modeflag & HalfDCLK)) temp -= 32;
5352 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
5353 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
5354 temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
5355 temp -= 3;
5356 temp <<= 3;
5357 } else {
5358 if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005359 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005360 SiS_Pr->CHSyncStart = temp;
5361
5362 SiS_Pr->CHSyncEnd = 0xffe8; /* results in 0x2000 in registers */
5363
5364 SiS_Pr->CVTotal = 2049; /* Max VT, 0x0801, results in 0x7ff in registers */
5365
5366 VGAVDE = SiS_Pr->SiS_VGAVDE;
5367 if (VGAVDE == 357) VGAVDE = 350;
5368 else if(VGAVDE == 360) VGAVDE = 350;
5369 else if(VGAVDE == 375) VGAVDE = 350;
5370 else if(VGAVDE == 405) VGAVDE = 400;
5371 else if(VGAVDE == 420) VGAVDE = 400;
5372 else if(VGAVDE == 525) VGAVDE = 480;
5373 else if(VGAVDE == 1056) VGAVDE = 1024;
5374 SiS_Pr->CVDisplay = VGAVDE;
5375
5376 SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
5377
5378 SiS_Pr->CVBlankEnd = 1;
5379 if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
5380
5381 temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
5382 SiS_Pr->CVSyncStart = VGAVDE + temp;
5383
5384 temp >>= 3;
5385 SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
5386
5387 SiS_CalcCRRegisters(SiS_Pr, 0);
5388 SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
5389
5390 for(i = 0; i <= 7; i++) {
5391 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
5392 }
5393 for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
5394 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5395 }
5396 for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
5397 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5398 }
5399 for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
5400 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5401 }
5402
5403 temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
5404 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
5405
5406 temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
5407 if(modeflag & DoubleScanMode) temp |= 0x80;
5408 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409
5410 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005411 temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
5412 if(modeflag & HalfDCLK) temp |= 0x08;
5413 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005415 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* CR14: (text mode: underline location) */
5416 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* CR17: n/a */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005418 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005419 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005420 temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005422 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* SR0E, dither[7] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423
5424 temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005425 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); /* ? */
5426
5427#ifdef SIS_XORG_XF86
5428#ifdef TWDEBUG
5429 xf86DrvMsg(0, X_INFO, "%d %d %d %d %d %d %d %d (%d %d %d %d)\n",
5430 SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
5431 SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
5432 SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
5433
5434 xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
5435 SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
5436 SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
5437 SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
5438 SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
5439 xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
5440 SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
5441 SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
5442 SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
5443 SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
5444 xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
5445#endif
5446#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005447}
5448
5449/* Setup panel link
5450 * This is used for LVDS, LCDA and Chrontel TV output
5451 * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
5452 */
5453static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005454SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5455 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005456{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005457 unsigned short modeflag, resinfo = 0;
5458 unsigned short push2, tempax, tempbx, tempcx, temp;
5459 unsigned int tempeax = 0, tempebx, tempecx, tempvcfact = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460 BOOLEAN islvds = FALSE, issis = FALSE, chkdclkfirst = FALSE;
5461#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005462 unsigned short crt2crtc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463#endif
5464#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005465 unsigned short pushcx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005466#endif
5467
5468 if(ModeNo <= 0x13) {
5469 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5470 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
5471#ifdef SIS300
5472 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5473#endif
5474 } else if(SiS_Pr->UseCustomMode) {
5475 modeflag = SiS_Pr->CModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005476 } else {
5477 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5478 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5479#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005480 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005481#endif
5482 }
5483
5484 /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
5485 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
5486 islvds = TRUE;
5487 }
5488
5489 /* is really sis if sis bridge, but not 301B-DH */
5490 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
5491 issis = TRUE;
5492 }
5493
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005494 if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005495 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
5496 chkdclkfirst = TRUE;
5497 }
5498 }
5499
5500#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005501 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005502 if(IS_SIS330) {
5503 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5504 } else if(IS_SIS740) {
5505 if(islvds) {
5506 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5507 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
5508 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5509 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5510 }
5511 } else {
5512 if(islvds) {
5513 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5514 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
5515 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5516 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005517 if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
5519 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5520 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
5521 }
5522 }
5523 }
5524 }
5525 }
5526#endif
5527
5528 /* Horizontal */
5529
5530 tempax = SiS_Pr->SiS_LCDHDES;
5531 if(islvds) {
5532 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005533 if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
5534 if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
5535 (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
5536 tempax -= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005537 }
5538 }
5539 }
5540 }
5541
5542 temp = (tempax & 0x0007);
5543 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* BPLHDESKEW[2:0] */
5544 temp = (tempax >> 3) & 0x00FF;
5545 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* BPLHDESKEW[10:3] */
5546
5547 tempbx = SiS_Pr->SiS_HDE;
5548 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5550 tempbx = SiS_Pr->PanelXRes;
5551 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005552 if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
5553 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
5554 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
5555 tempbx >>= 1;
5556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557 }
5558
5559 tempax += tempbx;
5560 if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
5561
5562 temp = tempax;
5563 if(temp & 0x07) temp += 8;
5564 temp >>= 3;
5565 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp); /* BPLHDEE */
5566
5567 tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
5568
5569 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5570 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5571 if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
5572 }
5573 }
5574
5575 tempcx += tempax;
5576 if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
5577
5578 temp = (tempcx >> 3) & 0x00FF;
5579 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5580 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005581 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5582 switch(ModeNo) {
5583 case 0x04:
5584 case 0x05:
5585 case 0x0d: temp = 0x56; break;
5586 case 0x10: temp = 0x60; break;
5587 case 0x13: temp = 0x5f; break;
5588 case 0x40:
5589 case 0x41:
5590 case 0x4f:
5591 case 0x43:
5592 case 0x44:
5593 case 0x62:
5594 case 0x56:
5595 case 0x53:
5596 case 0x5d:
5597 case 0x5e: temp = 0x54; break;
5598 }
5599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005600 }
5601 }
5602 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp); /* BPLHRS */
5603
5604 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5605 temp += 2;
5606 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005607 temp += 8;
5608 if(SiS_Pr->PanelHRE != 999) {
5609 temp = tempcx + SiS_Pr->PanelHRE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005610 if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
5611 temp >>= 3;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005612 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005613 }
5614 } else {
5615 temp += 10;
5616 }
5617
5618 temp &= 0x1F;
5619 temp |= ((tempcx & 0x07) << 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005620 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp); /* BPLHRE */
5621
5622 /* Vertical */
5623
5624 tempax = SiS_Pr->SiS_VGAVDE;
5625 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5626 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5627 tempax = SiS_Pr->PanelYRes;
5628 }
5629 }
5630
5631 tempbx = SiS_Pr->SiS_LCDVDES + tempax;
5632 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5633
5634 push2 = tempbx;
5635
5636 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005637 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005639 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005640 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
5641 }
5642 }
5643 }
5644 if(islvds) tempcx >>= 1;
5645 else tempcx >>= 2;
5646
5647 if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
5648 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
5649 (SiS_Pr->PanelVRS != 999) ) {
5650 tempcx = SiS_Pr->PanelVRS;
5651 tempbx += tempcx;
5652 if(issis) tempbx++;
5653 } else {
5654 tempbx += tempcx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005655 if(SiS_Pr->ChipType < SIS_315H) tempbx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005656 else if(issis) tempbx++;
5657 }
5658
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005659 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005660
5661 temp = tempbx & 0x00FF;
5662 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5663 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005664 if(ModeNo == 0x10) temp = 0xa9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005665 }
5666 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005667 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp); /* BPLVRS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005668
5669 tempcx >>= 3;
5670 tempcx++;
5671
5672 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5673 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5674 if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
5675 }
5676 }
5677
5678 tempcx += tempbx;
5679 temp = tempcx & 0x000F;
5680 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); /* BPLVRE */
5681
5682 temp = ((tempbx >> 8) & 0x07) << 3;
5683 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5684 if(SiS_Pr->SiS_HDE != 640) {
5685 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5686 }
5687 } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5688 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40;
5689 tempbx = 0x87;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005690 if((SiS_Pr->ChipType >= SIS_315H) ||
5691 (SiS_Pr->ChipRevision >= 0x30)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692 tempbx = 0x07;
5693 if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
5694 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03) temp |= 0x80;
5695 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005696 /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005697 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5698 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5699 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
5700 } else {
5701 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
5702 }
5703 }
5704 }
5705 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
5706
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005707 tempbx = push2; /* BPLVDEE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005709 tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005710
5711 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5712 switch(SiS_Pr->SiS_LCDResInfo) {
5713 case Panel_640x480:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005714 tempbx = SiS_Pr->SiS_VGAVDE - 1;
5715 tempcx = SiS_Pr->SiS_VGAVDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005716 break;
5717 case Panel_800x600:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005718 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5719 if(resinfo == SIS_RI_800x600) tempcx++;
5720 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721 break;
5722 case Panel_1024x600:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005723 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5724 if(resinfo == SIS_RI_1024x600) tempcx++;
5725 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005726 if(resinfo == SIS_RI_800x600) tempcx++;
5727 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729 break;
5730 case Panel_1024x768:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005731 if(SiS_Pr->ChipType < SIS_315H) {
5732 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5733 if(resinfo == SIS_RI_1024x768) tempcx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005734 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005735 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736 break;
5737 }
5738 }
5739
5740 temp = ((tempbx >> 8) & 0x07) << 3;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005741 temp |= ((tempcx >> 8) & 0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005743 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
5744 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
5745
5746 /* Vertical scaling */
5747
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005748 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005749
5750#ifdef SIS300 /* 300 series */
5751 tempeax = SiS_Pr->SiS_VGAVDE << 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005752 temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
5753 tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005754 if(temp) tempeax++;
5755
5756 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
5757
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005758 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005759 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */
5760 tempvcfact = temp;
5761#endif /* SIS300 */
5762
5763 } else {
5764
5765#ifdef SIS315H /* 315 series */
5766 tempeax = SiS_Pr->SiS_VGAVDE << 18;
5767 tempebx = SiS_Pr->SiS_VDE;
5768 temp = (tempeax % tempebx);
5769 tempeax = tempeax / tempebx;
5770 if(temp) tempeax++;
5771 tempvcfact = tempeax;
5772
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005773 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005774 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005775 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005776 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005777 temp = (unsigned short)((tempeax & 0x00030000) >> 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005778 if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
5779 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
5780
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005781 if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
5782 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005784 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005786 temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005787 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
5788 temp = 0;
5789 if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
5790 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
5791 }
5792#endif
5793
5794 }
5795
5796 /* Horizontal scaling */
5797
5798 tempeax = SiS_Pr->SiS_VGAHDE; /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
5799 if(chkdclkfirst) {
5800 if(modeflag & HalfDCLK) tempeax >>= 1;
5801 }
5802 tempebx = tempeax << 16;
5803 if(SiS_Pr->SiS_HDE == tempeax) {
5804 tempecx = 0xFFFF;
5805 } else {
5806 tempecx = tempebx / SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005807 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005808 if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
5809 }
5810 }
5811
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005812 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813 tempeax = (tempebx / tempecx) - 1;
5814 } else {
5815 tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
5816 }
5817 tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005818 temp = (unsigned short)(tempecx & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005819 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
5820
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005821 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005822 tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005823 tempbx = (unsigned short)(tempeax & 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824 } else {
5825 tempeax = SiS_Pr->SiS_VGAVDE << 6;
5826 tempbx = tempvcfact & 0x3f;
5827 if(tempbx == 0) tempbx = 64;
5828 tempeax /= tempbx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005829 tempbx = (unsigned short)(tempeax & 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005830 }
5831 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
5832 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
5833 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
5834 else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) tempbx = 1;
5835 }
5836
5837 temp = ((tempbx >> 8) & 0x07) << 3;
5838 temp = temp | ((tempecx >> 8) & 0x07);
5839 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
5840 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
5841
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005842 tempecx >>= 16; /* BPLHCFACT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005843 if(!chkdclkfirst) {
5844 if(modeflag & HalfDCLK) tempecx >>= 1;
5845 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005846 temp = (unsigned short)((tempecx & 0xFF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005848 temp = (unsigned short)(tempecx & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
5850
5851#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005852 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005853 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005854 if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005855 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
5856 }
5857 } else {
5858 if(islvds) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005859 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005860 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
5861 } else {
5862 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
5863 }
5864 }
5865 }
5866 }
5867#endif
5868
5869#ifdef SIS300
5870 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005871 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5872 unsigned char *trumpdata;
5873 int i, j = crt2crtc;
5874 unsigned char TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 };
5875 unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
5876 unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
5877
5878 if(SiS_Pr->SiS_UseROM) {
5879 trumpdata = &ROMAddr[0x8001 + (j * 80)];
5880 } else {
5881 if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
5882 trumpdata = &SiS300_TrumpionData[j][0];
5883 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884
5885 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
5886 for(i=0; i<5; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005887 SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888 }
5889 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005890 if(ModeNo == 0x13) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005891 for(i=0; i<4; i++) {
5892 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
5893 }
5894 } else if(ModeNo == 0x10) {
5895 for(i=0; i<4; i++) {
5896 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
5897 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
5898 }
5899 }
5900 }
5901 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
5902 }
5903#endif
5904
5905#ifdef SIS315H
5906 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5907 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
5908 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
5909 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
5910 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
5911 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
5912 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
5913 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005914 tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
5915 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5916 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5917 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005918 tempax += 64;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005919 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
5920 temp = (tempax >> 8) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005921 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005922 tempax += 32; /* Blpe = lBlps+32 */
5923 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
5924 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml = 0 */
5925 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005926
5927 tempax = SiS_Pr->SiS_VDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005928 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5929 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5930 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931 tempax >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005932 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
5933 temp = (tempax >> 8) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
5935
5936 tempeax = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005937 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5938 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5939 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
5940 tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
5941 temp = tempeax & 0x7f;
5942 tempeax >>= 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005943 if(temp) tempeax++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005944 temp = tempeax & 0x3f;
5945 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
5946 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
5948 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005949 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005950
5951 tempax = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005952 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5953 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5954 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5955 tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956 pushcx = tempax;
5957 temp = tempax & 0x00FF;
5958 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
5959 temp = ((tempax & 0xFF00) >> 8) << 3;
5960 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
5961
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005962 tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
5963 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5964 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5965 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5966 tempeax = tempax * pushcx;
5967 temp = tempeax & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005968 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005969 temp = (tempeax & 0xFF00) >> 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005971 temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005973 temp = ((tempeax & 0x01000000) >> 24) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
5975
5976 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
5977 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
5978 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
5979 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
5980 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
5981
5982 if(SiS_Pr->SiS_IF_DEF_FSTN) {
5983 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
5984 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
5985 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
5986 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
5987 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
5988 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
5989 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
5990 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
5991 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
5992 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
5993 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
5994 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
5995 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
5996 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
5997 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
5998 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
5999 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
6000 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
6001 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
6002 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
6003 }
6004 }
6005#endif /* SIS315H */
6006}
6007
6008/* Set Part 1 */
6009static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006010SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6011 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006012{
6013#if defined(SIS300) || defined(SIS315H)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006014 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006016 unsigned short temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
6017 unsigned short pushbx=0, CRT1Index=0, modeflag, resinfo=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006019 unsigned short tempbl=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006020#endif
6021
6022 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006023 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006024 return;
6025 }
6026
6027 if(ModeNo <= 0x13) {
6028 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6029 } else if(SiS_Pr->UseCustomMode) {
6030 modeflag = SiS_Pr->CModeFlag;
6031 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006032 CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
6034 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6035 }
6036
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006037 SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006039 if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07006040 (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
6041 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
6042
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006043 if(SiS_Pr->ChipType < SIS_315H ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006044#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006045 SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046#endif
6047 } else {
6048#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006049 SiS_SetCRT2FIFO_310(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006050#endif
6051 }
6052
6053 /* 1. Horizontal setup */
6054
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006055 if(SiS_Pr->ChipType < SIS_315H ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006056
6057#ifdef SIS300 /* ------------- 300 series --------------*/
6058
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006059 temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
6060 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006061
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006062 temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
6063 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006065 temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
6066 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006067
6068 pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA2HRS 0x0B,0x0C */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006069 tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
6070 tempbx = pushbx + tempcx;
6071 tempcx <<= 1;
6072 tempcx += tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006073
6074 bridgeadd = 12;
6075
6076#endif /* SIS300 */
6077
6078 } else {
6079
6080#ifdef SIS315H /* ------------------- 315/330 series --------------- */
6081
6082 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */
6083 if(modeflag & HalfDCLK) {
6084 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6085 tempcx >>= 1;
6086 } else {
6087 tempax = SiS_Pr->SiS_VGAHDE >> 1;
6088 tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
6089 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
6090 tempcx = SiS_Pr->SiS_HT - tempax;
6091 }
6092 }
6093 }
6094 tempcx--;
6095 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx); /* CRT2 Horizontal Total */
6096 temp = (tempcx >> 4) & 0xF0;
6097 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp); /* CRT2 Horizontal Total Overflow [7:4] */
6098
6099 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HDEE 0x0A,0x0C */
6100 tempbx = SiS_Pr->SiS_VGAHDE;
6101 tempcx -= tempbx;
6102 tempcx >>= 2;
6103 if(modeflag & HalfDCLK) {
6104 tempbx >>= 1;
6105 tempcx >>= 1;
6106 }
6107 tempbx += 16;
6108
6109 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx); /* CRT2 Horizontal Display Enable End */
6110
6111 pushbx = tempbx;
6112 tempcx >>= 1;
6113 tempbx += tempcx;
6114 tempcx += tempbx;
6115
6116 bridgeadd = 16;
6117
6118 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006119 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006120 if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
6121 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
6122 if(resinfo == SIS_RI_1280x1024) {
6123 tempcx = (tempcx & 0xff00) | 0x30;
6124 } else if(resinfo == SIS_RI_1600x1200) {
6125 tempcx = (tempcx & 0xff00) | 0xff;
6126 }
6127 }
6128 }
6129 }
6130
6131#endif /* SIS315H */
6132
6133 } /* 315/330 series */
6134
6135 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6136
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006137 if(SiS_Pr->UseCustomMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006138 tempbx = SiS_Pr->CHSyncStart + bridgeadd;
6139 tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
6140 tempax = SiS_Pr->SiS_VGAHT;
6141 if(modeflag & HalfDCLK) tempax >>= 1;
6142 tempax--;
6143 if(tempcx > tempax) tempcx = tempax;
6144 }
6145
6146 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6147 unsigned char cr4, cr14, cr5, cr15;
6148 if(SiS_Pr->UseCustomMode) {
6149 cr4 = SiS_Pr->CCRT1CRTC[4];
6150 cr14 = SiS_Pr->CCRT1CRTC[14];
6151 cr5 = SiS_Pr->CCRT1CRTC[5];
6152 cr15 = SiS_Pr->CCRT1CRTC[15];
6153 } else {
6154 cr4 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
6155 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
6156 cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
6157 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
6158 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006159 tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
6160 tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006161 tempcx &= 0x00FF;
6162 tempcx |= (tempbx & 0xFF00);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006163 tempbx += bridgeadd;
6164 tempcx += bridgeadd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006165 tempax = SiS_Pr->SiS_VGAHT;
6166 if(modeflag & HalfDCLK) tempax >>= 1;
6167 tempax--;
6168 if(tempcx > tempax) tempcx = tempax;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006169 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006170
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006171 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
6172 tempbx = 1040;
6173 tempcx = 1044; /* HWCursor bug! */
6174 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006175
6176 }
6177
6178 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx); /* CRT2 Horizontal Retrace Start */
6179
6180 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx); /* CRT2 Horizontal Retrace End */
6181
6182 temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
6183 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp); /* Overflow */
6184
6185 /* 2. Vertical setup */
6186
6187 tempcx = SiS_Pr->SiS_VGAVT - 1;
6188 temp = tempcx & 0x00FF;
6189
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006190 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006191 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006192 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006193 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6194 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6195 temp--;
6196 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006197 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006198 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006199 temp--;
6200 }
6201 } else if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202 temp--;
6203 }
6204 }
6205 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp); /* CRT2 Vertical Total */
6206
6207 tempbx = SiS_Pr->SiS_VGAVDE - 1;
6208 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx); /* CRT2 Vertical Display Enable End */
6209
6210 temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
6211 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp); /* Overflow */
6212
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006213 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
6214 tempbx++;
6215 tempax = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006216 tempcx++;
6217 tempcx -= tempax;
6218 tempcx >>= 2;
6219 tempbx += tempcx;
6220 if(tempcx < 4) tempcx = 4;
6221 tempcx >>= 2;
6222 tempcx += tempbx;
6223 tempcx++;
6224 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006225 tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
6226 tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006227 }
6228
6229 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6230 if(SiS_Pr->UseCustomMode) {
6231 tempbx = SiS_Pr->CVSyncStart;
6232 tempcx = SiS_Pr->CVSyncEnd;
6233 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006234 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006235 unsigned char cr8, cr7, cr13;
6236 if(SiS_Pr->UseCustomMode) {
6237 cr8 = SiS_Pr->CCRT1CRTC[8];
6238 cr7 = SiS_Pr->CCRT1CRTC[7];
6239 cr13 = SiS_Pr->CCRT1CRTC[13];
6240 tempcx = SiS_Pr->CCRT1CRTC[9];
6241 } else {
6242 cr8 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
6243 cr7 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
6244 cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
6245 tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
6246 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006247 tempbx = cr8;
6248 if(cr7 & 0x04) tempbx |= 0x0100;
6249 if(cr7 & 0x80) tempbx |= 0x0200;
6250 if(cr13 & 0x08) tempbx |= 0x0400;
6251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006252 }
6253 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx); /* CRT2 Vertical Retrace Start */
6254
6255 temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
6256 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp); /* CRT2 Vert. Retrace End; Overflow */
6257
6258 /* 3. Panel delay compensation */
6259
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006260 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006261
6262#ifdef SIS300 /* ---------- 300 series -------------- */
6263
6264 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6265 temp = 0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006266 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006267 temp = 0x10;
6268 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) temp = 0x2c;
6269 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6270 }
6271 if(SiS_Pr->SiS_VBType & VB_SIS301) {
6272 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6273 }
6274 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) temp = 0x24;
6275 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) temp = 0x2c;
6276 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08;
6277 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006278 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
6279 else temp = 0x20;
6280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281 if(SiS_Pr->SiS_UseROM) {
6282 if(ROMAddr[0x220] & 0x80) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006283 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
6284 temp = ROMAddr[0x221];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006285 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
6286 temp = ROMAddr[0x222];
6287 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
6288 temp = ROMAddr[0x223];
6289 else
6290 temp = ROMAddr[0x224];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006291 }
6292 }
6293 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006294 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006295 }
6296
6297 } else {
6298 temp = 0x20;
6299 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6300 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
6301 }
6302 if(SiS_Pr->SiS_UseROM) {
6303 if(ROMAddr[0x220] & 0x80) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006304 temp = ROMAddr[0x220];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006305 }
6306 }
6307 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006308 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006309 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006310 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006311
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006312 temp &= 0x3c;
6313
6314 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006315
6316#endif /* SIS300 */
6317
6318 } else {
6319
6320#ifdef SIS315H /* --------------- 315/330 series ---------------*/
6321
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006322 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006323
6324 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6325
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006326 if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
6327 else temp = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006328
6329 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
6330 tempbl = 0xF0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006331 if(SiS_Pr->ChipType == SIS_650) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006332 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6333 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
6334 }
6335 }
6336
6337 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
6338 temp = 0x08;
6339 tempbl = 0;
6340 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
6341 if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
6342 }
6343 }
6344
6345 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp); /* Panel Link Delay Compensation */
6346 }
6347
6348 } /* < 661 */
6349
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006350 tempax = 0;
6351 if(modeflag & DoubleScanMode) tempax |= 0x80;
6352 if(modeflag & HalfDCLK) tempax |= 0x40;
6353 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006354
6355#endif /* SIS315H */
6356
6357 }
6358
6359 } /* Slavemode */
6360
6361 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6362 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006363 /* For 301BDH with LCD, we set up the Panel Link */
6364 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006365 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006366 SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006367 }
6368 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006369 if(SiS_Pr->ChipType < SIS_315H) {
6370 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006371 } else {
6372 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006373 if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6374 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
6375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006376 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006377 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006378 }
6379 }
6380 }
6381}
6382
6383/*********************************************/
6384/* SET PART 2 REGISTER GROUP */
6385/*********************************************/
6386
6387#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006388static unsigned char *
6389SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006390{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006391 const unsigned char *tableptr = NULL;
6392 unsigned short a, b, p = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006393
6394 a = SiS_Pr->SiS_VGAHDE;
6395 b = SiS_Pr->SiS_HDE;
6396 if(tabletype) {
6397 a = SiS_Pr->SiS_VGAVDE;
6398 b = SiS_Pr->SiS_VDE;
6399 }
6400
6401 if(a < b) {
6402 tableptr = SiS_Part2CLVX_1;
6403 } else if(a == b) {
6404 tableptr = SiS_Part2CLVX_2;
6405 } else {
6406 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6407 tableptr = SiS_Part2CLVX_4;
6408 } else {
6409 tableptr = SiS_Part2CLVX_3;
6410 }
6411 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6412 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) tableptr = SiS_Part2CLVX_3;
6413 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tableptr = SiS_Part2CLVX_3;
6414 else tableptr = SiS_Part2CLVX_5;
6415 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6416 tableptr = SiS_Part2CLVX_6;
6417 }
6418 do {
6419 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
6420 p += 0x42;
6421 } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
6422 if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
6423 }
6424 p += 2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006425 return ((unsigned char *)&tableptr[p]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006426}
6427
6428static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006429SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6430 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006431{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006432 unsigned char *tableptr;
6433 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006435
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006436 if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006437
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006438 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006439 for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
6440 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6441 }
6442 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006443 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006444 for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
6445 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6446 }
6447 }
6448 temp = 0x10;
6449 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
6450 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
6451}
6452
6453static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006454SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
6455 unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
6456 unsigned short *ResIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457{
6458
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006459 if(SiS_Pr->ChipType < SIS_315H) return FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006460
6461 if(ModeNo <= 0x13)
6462 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6463 else
6464 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6465
6466 (*ResIndex) &= 0x3f;
6467 (*CRT2Index) = 0;
6468
6469 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6470 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6471 (*CRT2Index) = 200;
6472 }
6473 }
6474
6475 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
6476 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6477 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
6478 }
6479 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006480 return (((*CRT2Index) != 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006481}
6482#endif
6483
6484#ifdef SIS300
6485static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006486SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006487{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006488 unsigned short tempcx;
6489 static const unsigned char atable[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006490 0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
6491 0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
6492 };
6493
6494 if(!SiS_Pr->UseCustomMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006495 if( ( ( (SiS_Pr->ChipType == SIS_630) ||
6496 (SiS_Pr->ChipType == SIS_730) ) &&
6497 (SiS_Pr->ChipRevision > 2) ) &&
6498 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
6499 (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
6500 (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
6501 if(ModeNo == 0x13) {
6502 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
6503 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
6504 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
6505 } else if((crt2crtc & 0x3F) == 4) {
6506 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
6507 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
6508 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
6509 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
6510 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
6511 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006512 }
6513
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006514 if(SiS_Pr->ChipType < SIS_315H) {
6515 if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
6516 crt2crtc &= 0x1f;
6517 tempcx = 0;
6518 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6519 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6520 tempcx += 7;
6521 }
6522 }
6523 tempcx += crt2crtc;
6524 if(crt2crtc >= 4) {
6525 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
6526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006527
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006528 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6529 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6530 if(crt2crtc == 4) {
6531 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
6532 }
6533 }
6534 }
6535 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
6536 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
6537 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006538 }
6539 }
6540}
6541
6542/* For ECS A907. Highly preliminary. */
6543static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006544SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
6545 unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006546{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006547 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6548 unsigned short crt2crtc, resindex;
6549 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006550
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006551 if(SiS_Pr->ChipType != SIS_300) return;
6552 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006553 if(SiS_Pr->UseCustomMode) return;
6554
6555 if(ModeNo <= 0x13) {
6556 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6557 } else {
6558 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6559 }
6560
6561 resindex = crt2crtc & 0x3F;
6562 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6563 else CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
6564
6565 /* The BIOS code (1.16.51,56) is obviously a fragment! */
6566 if(ModeNo > 0x13) {
6567 CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6568 resindex = 4;
6569 }
6570
6571 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6572 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6573 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006574 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006575 }
6576 for(j = 0x1c; j <= 0x1d; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006577 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006578 }
6579 for(j = 0x1f; j <= 0x21; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006580 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006581 }
6582 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6583 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6584}
6585#endif
6586
6587static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006588SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006589{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006590 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006591 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
6592 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
6593
6594 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6595 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006596 const unsigned char specialtv[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006597 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
6598 0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
6599 0x58,0xe4,0x73,0xda,0x13
6600 };
6601 int i, j;
6602 for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
6603 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
6604 }
6605 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
6606 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
6607 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6608 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
6609 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
6610 } else {
6611 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14); /* 15 */
6612 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a); /* 1b */
6613 }
6614 }
6615 }
6616 } else {
6617 if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
6618 (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
6619 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b); /* 21 */
6620 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54); /* 5a */
6621 } else {
6622 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a); /* 21 */
6623 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53); /* 5a */
6624 }
6625 }
6626}
6627
6628static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006629SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006630{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006631 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006632
6633 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6634 if(SiS_Pr->SiS_VGAVDE == 525) {
6635 temp = 0xc3;
6636 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6637 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006638 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006639 }
6640 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6641 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
6642 } else if(SiS_Pr->SiS_VGAVDE == 420) {
6643 temp = 0x4d;
6644 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6645 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006646 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006647 }
6648 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6649 }
6650 }
6651
6652 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6653 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006654 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006655 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
6656 /* Not always for LV, see SetGrp2 */
6657 }
6658 temp = 1;
6659 if(ModeNo <= 0x13) temp = 3;
6660 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
6661 }
6662#if 0
6663 /* 651+301C, for 1280x768 - do I really need that? */
6664 if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
6665 if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
6666 if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
6667 ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
6668 SiS_SetReg(SiS_Part2Port,0x01,0x2b);
6669 SiS_SetReg(SiS_Part2Port,0x02,0x13);
6670 SiS_SetReg(SiS_Part2Port,0x04,0xe5);
6671 SiS_SetReg(SiS_Part2Port,0x05,0x08);
6672 SiS_SetReg(SiS_Part2Port,0x06,0xe2);
6673 SiS_SetReg(SiS_Part2Port,0x1c,0x21);
6674 SiS_SetReg(SiS_Part2Port,0x1d,0x45);
6675 SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
6676 SiS_SetReg(SiS_Part2Port,0x20,0x00);
6677 SiS_SetReg(SiS_Part2Port,0x21,0xa9);
6678 SiS_SetReg(SiS_Part2Port,0x23,0x0b);
6679 SiS_SetReg(SiS_Part2Port,0x25,0x04);
6680 }
6681 }
6682 }
6683#endif
6684 }
6685}
6686
6687static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006688SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6689 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006690{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006691 unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
6692 unsigned short push2, modeflag, crt2crtc, bridgeoffset;
6693 unsigned int longtemp, PhaseIndex;
6694 BOOLEAN newtvphase;
6695 const unsigned char *TimingPoint;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006696#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006697 unsigned short resindex, CRT2Index;
6698 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006699
6700 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
6701#endif
6702
6703 if(ModeNo <= 0x13) {
6704 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6705 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6706 } else if(SiS_Pr->UseCustomMode) {
6707 modeflag = SiS_Pr->CModeFlag;
6708 crt2crtc = 0;
6709 } else {
6710 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6711 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6712 }
6713
6714 temp = 0;
6715 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
6716 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
6717 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) temp |= 0x02;
6718 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp |= 0x01;
6719
6720 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) temp |= 0x10;
6721
6722 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
6723
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006724 PhaseIndex = 0x01; /* SiS_PALPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006725 TimingPoint = SiS_Pr->SiS_PALTiming;
6726
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006727 newtvphase = FALSE;
6728 if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
6729 ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6730 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6731 newtvphase = TRUE;
6732 }
6733
Linus Torvalds1da177e2005-04-16 15:20:36 -07006734 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6735
6736 TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
6737 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6738 TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
6739 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6740 TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006741 }
6742 }
6743
6744 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6745
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006746 i = 0;
6747 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) i = 2;
6748 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006749
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006750 TimingPoint = &SiS_YPbPrTable[i][0];
6751
6752 PhaseIndex = 0x00; /* SiS_NTSCPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006753
6754 } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6755
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006756 if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006757
6758 } else {
6759
6760 TimingPoint = SiS_Pr->SiS_NTSCTiming;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006761 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00; /* SiS_PALPhase : SiS_NTSCPhase */
6762 if(newtvphase) PhaseIndex += 8; /* SiS_PALPhase2 : SiS_NTSCPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006763
6764 }
6765
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006766 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
6767 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03; /* SiS_PALMPhase : SiS_PALNPhase */
6768 if(newtvphase) PhaseIndex += 8; /* SiS_PALMPhase2 : SiS_PALNPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006769 }
6770
6771 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006772 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006773 PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006774 } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006775 PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
6776 } else {
6777 PhaseIndex = 0x10; /* SiS_SpecialPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006778 }
6779 }
6780
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006781 for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
6782 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006783 }
6784
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006785 for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006786 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6787 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006788 for(i = 0x39; i <= 0x45; i++, j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006789 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6790 }
6791
6792 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6793 if(SiS_Pr->SiS_ModeType != ModeText) {
6794 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
6795 }
6796 }
6797
6798 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
6799
6800 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
6801 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
6802 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
6803 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
6804
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006805 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950;
6806 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempax = 680;
6807 else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520;
6808 else tempax = 440; /* NTSC, YPbPr 525 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006809
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006810 if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07006811 ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
6812 ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
6813
6814 tempax -= SiS_Pr->SiS_VDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006815 tempax >>= 1;
6816 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
6817 tempax >>= 1;
6818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819 tempax &= 0x00ff;
6820
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006821 temp = tempax + (unsigned short)TimingPoint[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006822 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
6823
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006824 temp = tempax + (unsigned short)TimingPoint[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006825 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
6826
6827 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
6828 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006829 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
6830 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006831 } else {
6832 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
6833 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
6834 }
6835 }
6836
6837 }
6838
6839 tempcx = SiS_Pr->SiS_HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006840 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006841 tempcx--;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006842 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006843 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
6844 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
6845
6846 tempcx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006847 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006848 tempcx += 7;
6849 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6850 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
6851
6852 tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
6853 tempbx += tempcx;
6854 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
6855 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
6856
6857 tempbx += 8;
6858 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6859 tempbx -= 4;
6860 tempcx = tempbx;
6861 }
6862 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
6863
6864 j += 2;
6865 tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
6866 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
6867 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
6868
6869 tempcx += 8;
6870 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6871 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
6872
6873 tempcx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006874 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006875 j += 2;
6876 tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
6877 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
6878
6879 tempcx -= 11;
6880 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6881 tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
6882 }
6883 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
6884
6885 tempbx = SiS_Pr->SiS_VDE;
6886 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6887 if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
6888 if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
6889 if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
6890 } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6891 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
6892 tempbx >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006893 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006894 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6895 if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
6896 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6897 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6898 if(crt2crtc == 4) tempbx++;
6899 }
6900 }
6901 }
6902 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6903 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6904 if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
6905 }
6906 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6907 if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
6908 }
6909 }
6910 }
6911 tempbx -= 2;
6912 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
6913
6914 temp = (tempcx >> 8) & 0x0F;
6915 temp |= ((tempbx >> 2) & 0xC0);
6916 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6917 temp |= 0x10;
6918 if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
6919 }
6920 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
6921
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006922 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006923 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
6924 }
6925
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006926 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006927 tempbx = SiS_Pr->SiS_VDE;
6928 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6929 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
6930 tempbx >>= 1;
6931 }
6932 tempbx -= 3;
6933 temp = ((tempbx >> 3) & 0x60) | 0x18;
6934 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
6935 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
6936
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006937 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006938 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
6939 }
6940 }
6941
6942 tempbx = 0;
6943 if(!(modeflag & HalfDCLK)) {
6944 if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
6945 tempax = 0;
6946 tempbx |= 0x20;
6947 }
6948 }
6949
6950 tempch = tempcl = 0x01;
6951 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006952 if(SiS_Pr->SiS_VGAHDE >= 960) {
6953 if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006954 tempcl = 0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006955 if(SiS_Pr->SiS_VGAHDE >= 1280) {
6956 tempch = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006957 tempbx &= ~0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006958 } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
6959 tempch = 25;
6960 } else {
6961 tempch = 25; /* OK */
6962 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006963 }
6964 }
6965 }
6966
6967 if(!(tempbx & 0x20)) {
6968 if(modeflag & HalfDCLK) tempcl <<= 1;
6969 longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006970 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006971 tempax = longtemp / SiS_Pr->SiS_HDE;
6972 if(longtemp % SiS_Pr->SiS_HDE) tempax++;
6973 tempbx |= ((tempax >> 8) & 0x1F);
6974 tempcx = tempax >> 13;
6975 }
6976
6977 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
6978 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
6979
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006980 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006981
6982 tempcx &= 0x07;
6983 if(tempbx & 0x20) tempcx = 0;
6984 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
6985
6986 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6987 tempbx = 0x0382;
6988 tempcx = 0x007e;
6989 } else {
6990 tempbx = 0x0369;
6991 tempcx = 0x0061;
6992 }
6993 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
6994 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
6995 temp = (tempcx & 0x0300) >> 6;
6996 temp |= ((tempbx >> 8) & 0x03);
6997 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6998 temp |= 0x10;
6999 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp |= 0x20;
7000 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
7001 }
7002 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
7003
7004 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7005 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
7006
7007 SiS_SetTVSpecial(SiS_Pr, ModeNo);
7008
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007009 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007010 temp = 0;
7011 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
7012 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
7013 }
7014
7015 }
7016
7017 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7018 if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
7019 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
7020 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
7021 }
7022 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
7023 }
7024
7025 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7026 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
7027 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
7028 }
7029 }
7030
7031 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
7032
7033 /* From here: Part2 LCD setup */
7034
7035 tempbx = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007036 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007037 tempbx--; /* RHACTE = HDE - 1 */
7038 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
7039 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
7040
7041 temp = 0x01;
7042 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7043 if(SiS_Pr->SiS_ModeType == ModeEGA) {
7044 if(SiS_Pr->SiS_VGAHDE >= 1024) {
7045 temp = 0x02;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007046 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7047 temp = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007048 }
7049 }
7050 }
7051 }
7052 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
7053
7054 tempbx = SiS_Pr->SiS_VDE - 1;
7055 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
7056 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
7057
7058 tempcx = SiS_Pr->SiS_VT - 1;
7059 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
7060 temp = (tempcx >> 3) & 0xE0;
7061 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
7062 /* Enable dithering; only do this for 32bpp mode */
7063 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
7064 temp |= 0x10;
7065 }
7066 }
7067 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
7068
7069 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
7070 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
7071
7072 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
7073 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
7074
7075#ifdef SIS315H
7076 if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007077 &CRT2Index, &resindex)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007078 switch(CRT2Index) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007079 case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break;
7080 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07007081 case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007082 }
7083
7084 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
7085 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
7086 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
7087 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7088 }
7089 for(j = 0x1c; j <= 0x1d; i++, j++ ) {
7090 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7091 }
7092 for(j = 0x1f; j <= 0x21; i++, j++ ) {
7093 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7094 }
7095 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
7096 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
7097
7098 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7099
Linus Torvalds1da177e2005-04-16 15:20:36 -07007100 } else {
7101#endif
7102
7103 /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
7104 /* Clevo dual-link 1024x768 */
7105 /* Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct) */
7106 /* Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
7107
7108 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7109 if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7110 tempbx = SiS_Pr->SiS_VDE - 1;
7111 tempcx = SiS_Pr->SiS_VT - 1;
7112 } else {
7113 tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7114 tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7115 }
7116 } else {
7117 tempbx = SiS_Pr->PanelYRes;
7118 tempcx = SiS_Pr->SiS_VT;
7119 tempax = 1;
7120 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7121 tempax = SiS_Pr->PanelYRes;
7122 /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c; */ /* 651+301C */
7123 if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7124 tempax = tempcx = 0;
7125 } else {
7126 tempax -= SiS_Pr->SiS_VDE;
7127 }
7128 tempax >>= 1;
7129 }
7130 tempcx -= tempax; /* lcdvdes */
7131 tempbx -= tempax; /* lcdvdee */
7132 }
7133
7134 /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7135
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007136#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007137#ifdef TWDEBUG
7138 xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
7139#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007140#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007141
7142 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */
7143 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */
7144
7145 temp = (tempbx >> 5) & 0x38;
7146 temp |= ((tempcx >> 8) & 0x07);
7147 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7148
7149 tempax = SiS_Pr->SiS_VDE;
7150 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7151 tempax = SiS_Pr->PanelYRes;
7152 }
7153 tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7154 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7155 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7156 tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7157 }
7158 }
7159
7160 tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7161 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7162 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7163 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7164 tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7165 if(tempax % 4) { tempax >>= 2; tempax++; }
7166 else { tempax >>= 2; }
7167 tempbx -= (tempax - 1);
7168 } else {
7169 tempbx -= 10;
7170 if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7171 }
7172 }
7173 }
7174 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7175 tempbx++;
7176 if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7177 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7178 tempbx = 770;
7179 tempcx = 3;
7180 }
7181 }
7182 }
7183
7184 /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7185
7186 if(SiS_Pr->UseCustomMode) {
7187 tempbx = SiS_Pr->CVSyncStart;
7188 }
7189
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007190#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007191#ifdef TWDEBUG
7192 xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
7193#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007194#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007195
7196 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */
7197
7198 temp = (tempbx >> 4) & 0xF0;
7199 tempbx += (tempcx + 1);
7200 temp |= (tempbx & 0x0F);
7201
7202 if(SiS_Pr->UseCustomMode) {
7203 temp &= 0xf0;
7204 temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7205 }
7206
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007207#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007208#ifdef TWDEBUG
7209 xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
7210#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007211#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007212
7213 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7214
7215#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007216 SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007217#endif
7218
7219 bridgeoffset = 7;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007220 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) bridgeoffset += 2;
7221 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
7222 if(SiS_IsDualLink(SiS_Pr)) bridgeoffset++;
7223 else if(SiS_Pr->SiS_VBType & VB_SIS302LV) bridgeoffset++; /* OK for Asus A4L 1280x800 */
7224 /* Higher bridgeoffset shifts to the LEFT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007225
7226 temp = 0;
7227 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7228 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007229 temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7230 if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007231 }
7232 }
7233 temp += bridgeoffset;
7234 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp); /* lcdhdes */
7235 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7236
7237 tempcx = SiS_Pr->SiS_HT;
7238 tempax = tempbx = SiS_Pr->SiS_HDE;
7239 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7240 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7241 tempax = SiS_Pr->PanelXRes;
7242 tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7243 }
7244 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007245 if(SiS_IsDualLink(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007246 tempcx >>= 1;
7247 tempbx >>= 1;
7248 tempax >>= 1;
7249 }
7250
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007251#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007252#ifdef TWDEBUG
7253 xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
7254#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007255#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007256
7257 tempbx += bridgeoffset;
7258
7259 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx); /* lcdhdee */
7260 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7261
7262 tempcx = (tempcx - tempax) >> 2;
7263
7264 tempbx += tempcx;
7265 push2 = tempbx;
7266
7267 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7268 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7269 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7270 if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7271 }
7272 }
7273 }
7274
7275 if(SiS_Pr->UseCustomMode) {
7276 tempbx = SiS_Pr->CHSyncStart;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007277 if(modeflag & HalfDCLK) tempbx <<= 1;
7278 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007279 tempbx += bridgeoffset;
7280 }
7281
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007282#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007283#ifdef TWDEBUG
7284 xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
7285#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007286#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007287
7288 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */
7289 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7290
7291 tempbx = push2;
7292
7293 tempcx <<= 1;
7294 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7295 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7296 }
7297 tempbx += tempcx;
7298
7299 if(SiS_Pr->UseCustomMode) {
7300 tempbx = SiS_Pr->CHSyncEnd;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007301 if(modeflag & HalfDCLK) tempbx <<= 1;
7302 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007303 tempbx += bridgeoffset;
7304 }
7305
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007306#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007307#ifdef TWDEBUG
7308 xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
7309#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007310#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007311
7312 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */
7313
7314 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7315
7316#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007317 SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007318#endif
7319#ifdef SIS315H
7320 } /* CRT2-LCD from table */
7321#endif
7322}
7323
7324/*********************************************/
7325/* SET PART 3 REGISTER GROUP */
7326/*********************************************/
7327
7328static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007329SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007330{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007331 unsigned short i;
7332 const unsigned char *tempdi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007333
7334 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7335
7336#ifndef SIS_CP
7337 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7338#else
7339 SIS_CP_INIT301_CP
7340#endif
7341
7342 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7343 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7344 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7345 } else {
7346 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7347 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7348 }
7349
7350 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7351 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7352 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7353 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7354 }
7355
7356 tempdi = NULL;
7357 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7358 tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7359 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7360 tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7361 }
7362 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7363 if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7364 tempdi = SiS_HiTVGroup3_1;
7365 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7366 }
7367 }
7368 if(tempdi) {
7369 for(i=0; i<=0x3E; i++) {
7370 SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7371 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007372 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007373 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7374 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7375 }
7376 }
7377 }
7378
7379#ifdef SIS_CP
7380 SIS_CP_INIT301_CP2
7381#endif
7382}
7383
7384/*********************************************/
7385/* SET PART 4 REGISTER GROUP */
7386/*********************************************/
7387
7388#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007389#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07007390static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007391SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007392{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007393 unsigned short temp, temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007394
7395 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7396 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007397 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007398 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7399 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7400 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007401 temp = (unsigned short)((int)(temp) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007402 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7403 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7404 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007405 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007406 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7407 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7408}
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007409#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007410
7411static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007412SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007413{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007414 unsigned short temp, temp1, resinfo = 0;
7415 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007416
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007417 if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007418 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7419
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007420 if(SiS_Pr->ChipType >= XGI_20) return;
7421
7422 if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
7423 if(!(ROMAddr[0x61] & 0x04)) return;
7424 }
7425
Linus Torvalds1da177e2005-04-16 15:20:36 -07007426 if(ModeNo > 0x13) {
7427 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7428 }
7429
7430 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7431 temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7432 if(!(temp & 0x01)) {
7433 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7434 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007435 if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007436 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7437 }
7438 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7439 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp = 0x0000;
7440 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7441 else if(SiS_Pr->SiS_TVMode & TVSetHiVision) temp = 0x0400;
7442 else temp = 0x0402;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007443 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007444 temp1 = 0;
7445 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7446 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7447 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7448 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007449 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7450 if(ModeNo > 0x13) {
7451 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
7452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007453 } else {
7454 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7455 if(temp1 == 0x01) temp |= 0x01;
7456 if(temp1 == 0x03) temp |= 0x04; /* ? why not 0x10? */
7457 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007458 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7459 if(ModeNo > 0x13) {
7460 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7461 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007462 }
7463
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007464#if 0
7465 if(SiS_Pr->ChipType >= SIS_661) { /* ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007466 if(SiS_Pr->SiS_TVMode & TVAspect43) {
7467 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7468 if(resinfo == SIS_RI_1024x768) {
7469 SiS_ShiftXPos(SiS_Pr, 97);
7470 } else {
7471 SiS_ShiftXPos(SiS_Pr, 111);
7472 }
7473 } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7474 SiS_ShiftXPos(SiS_Pr, 136);
7475 }
7476 }
7477 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007478#endif
7479
Linus Torvalds1da177e2005-04-16 15:20:36 -07007480 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007481
Linus Torvalds1da177e2005-04-16 15:20:36 -07007482}
7483#endif
7484
7485static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007486SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7487 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007488{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007489 unsigned short vclkindex, temp, reg1, reg2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007490
7491 if(SiS_Pr->UseCustomMode) {
7492 reg1 = SiS_Pr->CSR2B;
7493 reg2 = SiS_Pr->CSR2C;
7494 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007495 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007496 reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7497 reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7498 }
7499
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007500 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7501 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007502 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7503 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7504 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7505 } else {
7506 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7507 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7508 }
7509 } else {
7510 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7511 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7512 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7513 }
7514 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7515 temp = 0x08;
7516 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7517 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7518}
7519
7520static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007521SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007522{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007523 if(SiS_Pr->ChipType >= SIS_315H) {
7524 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
7525 if((SiS_CRT2IsLCD(SiS_Pr)) ||
7526 (SiS_IsVAMode(SiS_Pr))) {
7527 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
7528 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7529 } else {
7530 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7531 }
7532 }
7533 }
7534 }
7535 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
7536 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7537#ifdef SET_EMI
7538 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7539#endif
7540 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7541 }
7542}
7543
7544static void
7545SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7546 unsigned short RefreshRateTableIndex)
7547{
7548 unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
7549 unsigned int tempebx, tempeax, templong;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007550
7551 if(ModeNo <= 0x13) {
7552 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7553 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7554 } else if(SiS_Pr->UseCustomMode) {
7555 modeflag = SiS_Pr->CModeFlag;
7556 resinfo = 0;
7557 } else {
7558 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7559 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7560 }
7561
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007562 if(SiS_Pr->ChipType >= SIS_315H) {
7563 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7564 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7565 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007566 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007567 }
7568 }
7569
7570 if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
7571 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7572 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
7573 }
7574 }
7575
7576 if(SiS_Pr->ChipType >= SIS_315H) {
7577 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7578 SiS_SetDualLinkEtc(SiS_Pr);
7579 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007580 }
7581 }
7582
7583 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7584
7585 tempbx = SiS_Pr->SiS_RVBHCMAX;
7586 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7587
7588 temp = (tempbx >> 1) & 0x80;
7589
7590 tempcx = SiS_Pr->SiS_VGAHT - 1;
7591 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7592
7593 temp |= ((tempcx >> 5) & 0x78);
7594
7595 tempcx = SiS_Pr->SiS_VGAVT - 1;
7596 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7597 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7598
7599 temp |= ((tempcx >> 8) & 0x07);
7600 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7601
7602 tempbx = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007603 if(modeflag & HalfDCLK) tempbx >>= 1;
7604 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007605
7606 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7607 temp = 0;
7608 if(tempbx > 800) temp = 0x60;
7609 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7610 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007611 if(tempbx > 1024) temp = 0xC0;
7612 else if(tempbx >= 960) temp = 0xA0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007613 } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7614 temp = 0;
7615 if(tempbx >= 1280) temp = 0x40;
7616 else if(tempbx >= 1024) temp = 0x20;
7617 } else {
7618 temp = 0x80;
7619 if(tempbx >= 1024) temp = 0xA0;
7620 }
7621
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007622 temp |= SiS_Pr->Init_P4_0E;
7623
Linus Torvalds1da177e2005-04-16 15:20:36 -07007624 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007625 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
7626 temp &= 0xf0;
7627 temp |= 0x0A;
7628 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007629 }
7630
7631 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7632
7633 tempeax = SiS_Pr->SiS_VGAVDE;
7634 tempebx = SiS_Pr->SiS_VDE;
7635 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7636 if(!(temp & 0xE0)) tempebx >>=1;
7637 }
7638
7639 tempcx = SiS_Pr->SiS_RVBHRS;
7640 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7641 tempcx >>= 8;
7642 tempcx |= 0x40;
7643
7644 if(tempeax <= tempebx) {
7645 tempcx ^= 0x40;
7646 } else {
7647 tempeax -= tempebx;
7648 }
7649
7650 tempeax *= (256 * 1024);
7651 templong = tempeax % tempebx;
7652 tempeax /= tempebx;
7653 if(templong) tempeax++;
7654
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007655 temp = (unsigned short)(tempeax & 0x000000FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007656 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007657 temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007658 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007659 temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007660 temp |= (tempcx & 0x4F);
7661 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7662
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007663 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007664
7665 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7666
7667 /* Calc Linebuffer max address and set/clear decimode */
7668 tempbx = 0;
7669 if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7670 tempax = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007671 if(modeflag & HalfDCLK) tempax >>= 1;
7672 if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007673 if(tempax > 800) {
7674 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7675 tempax -= 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007676 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007677 tempbx = 0x08;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007678 if(tempax == 960) tempax *= 25; /* Correct */
7679 else if(tempax == 1024) tempax *= 25;
7680 else tempax *= 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007681 temp = tempax % 32;
7682 tempax /= 32;
7683 if(temp) tempax++;
7684 tempax++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007685 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7686 if(resinfo == SIS_RI_1024x768 ||
7687 resinfo == SIS_RI_1024x576 ||
7688 resinfo == SIS_RI_1280x1024 ||
7689 resinfo == SIS_RI_1280x720) {
7690 /* Otherwise white line or garbage at right edge */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007691 tempax = (tempax & 0xff00) | 0x20;
7692 }
7693 }
7694 }
7695 }
7696 tempax--;
7697 temp = ((tempax >> 4) & 0x30) | tempbx;
7698 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7699 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7700
7701 temp = 0x0036; tempbx = 0xD0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007702 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007703 temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7704 }
7705 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7706 if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7707 temp |= 0x01;
7708 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7709 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7710 temp &= ~0x01;
7711 }
7712 }
7713 }
7714 }
7715 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7716
7717 tempbx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007718 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007719 tempbx -= 2;
7720 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7721 temp = (tempbx >> 5) & 0x38;
7722 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7723
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007724 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007725 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7726 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7727 /* LCD-too-dark-error-source, see FinalizeLCD() */
7728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007729 }
7730
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007731 SiS_SetDualLinkEtc(SiS_Pr);
7732
Linus Torvalds1da177e2005-04-16 15:20:36 -07007733 } /* 301B */
7734
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007735 SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007736}
7737
7738/*********************************************/
7739/* SET PART 5 REGISTER GROUP */
7740/*********************************************/
7741
7742static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007743SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007744{
7745
7746 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7747
7748 if(SiS_Pr->SiS_ModeType == ModeVGA) {
7749 if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7750 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007751 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007752 }
7753 }
7754}
7755
7756/*********************************************/
7757/* MODIFY CRT1 GROUP FOR SLAVE MODE */
7758/*********************************************/
7759
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007760static BOOLEAN
7761SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7762 unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
7763 unsigned short *DisplayType)
7764 {
7765 unsigned short modeflag = 0;
7766 BOOLEAN checkhd = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007767
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007768 /* Pass 1:1 not supported here */
7769
7770 if(ModeNo <= 0x13) {
7771 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7772 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7773 } else {
7774 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7775 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7776 }
7777
7778 (*ResIndex) &= 0x3F;
7779
7780 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7781
7782 (*DisplayType) = 80;
7783 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
7784 (*DisplayType) = 82;
7785 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7786 if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
7787 }
7788 }
7789 if((*DisplayType) != 84) {
7790 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
7791 }
7792
7793 } else {
7794
7795 (*DisplayType = 0);
7796 switch(SiS_Pr->SiS_LCDResInfo) {
7797 case Panel_320x240_1: (*DisplayType) = 50;
7798 checkhd = FALSE;
7799 break;
7800 case Panel_320x240_2: (*DisplayType) = 14;
7801 break;
7802 case Panel_320x240_3: (*DisplayType) = 18;
7803 break;
7804 case Panel_640x480: (*DisplayType) = 10;
7805 break;
7806 case Panel_1024x600: (*DisplayType) = 26;
7807 break;
7808 default: return TRUE;
7809 }
7810
7811 if(checkhd) {
7812 if(modeflag & HalfDCLK) (*DisplayType)++;
7813 }
7814
7815 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
7816 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
7817 }
7818
7819 }
7820
7821 return TRUE;
7822}
7823
7824static void
7825SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7826 unsigned short RefreshRateTableIndex)
7827{
7828 unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
7829 const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
7830 static const unsigned short CRIdx[] = {
7831 0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
7832 0x07, 0x10, 0x11, 0x15, 0x16
7833 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07007834
7835 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
7836 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007837 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
7838 (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
Linus Torvalds1da177e2005-04-16 15:20:36 -07007839 return;
7840
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007841 if(SiS_Pr->SiS_IF_DEF_LVDS) {
7842 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7843 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7844 }
7845 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
7846 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7847 } else return;
7848
7849 if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
7850
7851 if(SiS_Pr->ChipType < SIS_315H) {
7852 if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
7853 }
7854
Linus Torvalds1da177e2005-04-16 15:20:36 -07007855 if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7856 &ResIndex, &DisplayType))) {
7857 return;
7858 }
7859
Linus Torvalds1da177e2005-04-16 15:20:36 -07007860 switch(DisplayType) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007861 case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1; break; /* xSTN */
7862 case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2; break; /* xSTN */
7863 case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H; break; /* xSTN */
7864 case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3; break; /* xSTN */
7865 case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H; break; /* xSTN */
7866 case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
7867 case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
7868#if 0 /* Works better with calculated numbers */
7869 case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break;
7870 case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break;
7871 case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break;
7872 case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break;
7873#endif
7874 case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break;
7875 case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break;
7876 case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break;
7877 case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
7878 case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007879 }
7880
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007881 if(LVDSCRT1Ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007882
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007883 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007884
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007885 for(i = 0; i <= 10; i++) {
7886 tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
7887 SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
7888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007889
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007890 for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
7891 tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
7892 SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
7893 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007894
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007895 tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
7896 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
7897
7898 if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7899 else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7900
7901 tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
7902 if(modeflag & DoubleScanMode) tempah |= 0x80;
7903 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
7904
7905 } else {
7906
7907 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
7908
7909 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007910}
7911
7912/*********************************************/
7913/* SET CRT2 ECLK */
7914/*********************************************/
7915
7916static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007917SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7918 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007919{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007920 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
7921 unsigned short clkbase, vclkindex = 0;
7922 unsigned char sr2b, sr2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007923
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007924 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7925 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
7926 if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
7927 RefreshRateTableIndex--;
7928 }
7929 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7930 RefreshRateTableIndex);
7931 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007932 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007933 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7934 RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007935 }
7936
7937 sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
7938 sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
7939
7940 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
7941 if(SiS_Pr->SiS_UseROM) {
7942 if(ROMAddr[0x220] & 0x01) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007943 sr2b = ROMAddr[0x227];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007944 sr2c = ROMAddr[0x228];
7945 }
7946 }
7947 }
7948
7949 clkbase = 0x02B;
7950 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7951 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007952 clkbase += 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007953 }
7954 }
7955
7956 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
7957 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7958 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7959 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
7960 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7961 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7962 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
7963 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7964 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7965}
7966
7967/*********************************************/
7968/* SET UP CHRONTEL CHIPS */
7969/*********************************************/
7970
7971static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007972SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7973 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007974{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007975 unsigned short TVType, resindex;
7976 const struct SiS_CHTVRegData *CHTVRegData = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007977
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007978 if(ModeNo <= 0x13)
7979 resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7980 else
7981 resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007982
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007983 resindex &= 0x3F;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007984
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007985 TVType = 0;
7986 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7987 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7988 TVType += 2;
7989 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7990 if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
7991 }
7992 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7993 TVType = 4;
7994 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7995 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
7996 TVType = 6;
7997 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7998 }
7999 }
8000
8001 switch(TVType) {
8002 case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
8003 case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
8004 case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break;
8005 case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
8006 case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
8007 case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
8008 case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
8009 case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
8010 case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
8011 default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
8012 }
8013
8014
8015 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008016
8017#ifdef SIS300
8018
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008019 /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008020
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008021 /* We don't support modes >800x600 */
8022 if (resindex > 5) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008023
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008024 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
8025 SiS_SetCH700x(SiS_Pr,0x04,0x43); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
8026 SiS_SetCH700x(SiS_Pr,0x09,0x69); /* Black level for PAL (105)*/
8027 } else {
8028 SiS_SetCH700x(SiS_Pr,0x04,0x03); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
8029 SiS_SetCH700x(SiS_Pr,0x09,0x71); /* Black level for NTSC (113)*/
8030 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008031
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008032 SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]); /* Mode register */
8033 SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]); /* Start active video register */
8034 SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]); /* Position overflow register */
8035 SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]); /* Horiz Position register */
8036 SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]); /* Vertical Position register */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008037
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008038 /* Set minimum flicker filter for Luma channel (SR1-0=00),
Linus Torvalds1da177e2005-04-16 15:20:36 -07008039 minimum text enhancement (S3-2=10),
8040 maximum flicker filter for Chroma channel (S5-4=10)
8041 =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008042 */
8043 SiS_SetCH700x(SiS_Pr,0x01,0x28);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008044
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008045 /* Set video bandwidth
Linus Torvalds1da177e2005-04-16 15:20:36 -07008046 High bandwith Luma composite video filter(S0=1)
8047 low bandwith Luma S-video filter (S2-1=00)
8048 disable peak filter in S-video channel (S3=0)
8049 high bandwidth Chroma Filter (S5-4=11)
8050 =00110001=0x31
Linus Torvalds1da177e2005-04-16 15:20:36 -07008051 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008052 SiS_SetCH700x(SiS_Pr,0x03,0xb1); /* old: 3103 */
8053
8054 /* Register 0x3D does not exist in non-macrovision register map
8055 (Maybe this is a macrovision register?)
8056 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008057#ifndef SIS_CP
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008058 SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008059#endif
8060
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008061 /* Register 0x10 only contains 1 writable bit (S0) for sensing,
8062 all other bits a read-only. Macrovision?
8063 */
8064 SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008065
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008066 /* Register 0x11 only contains 3 writable bits (S0-S2) for
8067 contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
8068 */
8069 SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008070
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008071 /* Clear DSEN
8072 */
8073 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008074
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008075 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */
8076 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
8077 if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */
8078 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8079 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on, no need to set FSCI */
8080 } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */
8081 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */
8082 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
8083 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
8084 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
8085 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
8086 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
8087 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
8088 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
8089 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF); /* Loop filter on for mode 23 */
8090 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); /* ACIV off, need to set FSCI */
8091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008092 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008093 if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */
8094 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8095 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
8096 } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */
8097#if 0
8098 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
8099 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0); /* FSCI for mode 24 is 428,554,851 */
8100 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0); /* 198b3a63 */
8101 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
8102 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
8103 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
8104 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
8105 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
8106 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off for mode 24 */
8107 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); * ACIV off, need to set FSCI */
8108#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */
8109 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8110 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
8111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008112 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008113 } else { /* ---- PAL ---- */
8114 /* We don't play around with FSCI in PAL mode */
8115 if(resindex == 0x04) {
8116 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8117 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
8118 } else {
8119 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8120 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
8121 }
8122 }
8123
Linus Torvalds1da177e2005-04-16 15:20:36 -07008124#endif /* 300 */
8125
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008126 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008127
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008128 /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008129
8130#ifdef SIS315H
8131
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008132 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008133
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008134 /* We don't support modes >1024x768 */
8135 if (resindex > 6) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008136
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008137 temp = CHTVRegData[resindex].Reg[0];
8138 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
8139 SiS_SetCH701x(SiS_Pr,0x00,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008140
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008141 SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
8142 SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
8143 SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
8144 SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
8145 SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
8146 SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008147
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008148 temp = CHTVRegData[resindex].Reg[7];
8149 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
8150 SiS_SetCH701x(SiS_Pr,0x07,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008151
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008152 SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
8153 SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
8154 SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
8155 SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
8156 SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
8157 SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
8158 SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
8159 SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008160
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008161 temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8162 /* D1 should be set for PAL, PAL-N and NTSC-J,
8163 but I won't do that for PAL unless somebody
8164 tells me to do so. Since the BIOS uses
8165 non-default CIV values and blacklevels,
8166 this might be compensated anyway.
8167 */
8168 if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8169 SiS_SetCH701x(SiS_Pr,0x21,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008170
8171#endif /* 315 */
8172
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008173 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008174
8175#ifdef SIS_CP
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008176 SIS_CP_INIT301_CP3
Linus Torvalds1da177e2005-04-16 15:20:36 -07008177#endif
8178
8179}
8180
Linus Torvalds1da177e2005-04-16 15:20:36 -07008181#ifdef SIS315H /* ----------- 315 series only ---------- */
8182
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008183void
8184SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008185{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008186 unsigned short temp;
8187
8188 /* Enable Chrontel 7019 LCD panel backlight */
8189 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8190 if(SiS_Pr->ChipType == SIS_740) {
8191 SiS_SetCH701x(SiS_Pr,0x66,0x65);
8192 } else {
8193 temp = SiS_GetCH701x(SiS_Pr,0x66);
8194 temp |= 0x20;
8195 SiS_SetCH701x(SiS_Pr,0x66,temp);
8196 }
8197 }
8198}
8199
8200void
8201SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
8202{
8203 unsigned short temp;
8204
8205 /* Disable Chrontel 7019 LCD panel backlight */
8206 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8207 temp = SiS_GetCH701x(SiS_Pr,0x66);
8208 temp &= 0xDF;
8209 SiS_SetCH701x(SiS_Pr,0x66,temp);
8210 }
8211}
8212
8213static void
8214SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
8215{
8216 static const unsigned char regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8217 static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8218 static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8219 static const unsigned char asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8220 static const unsigned char asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8221 static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8222 static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8223 const unsigned char *tableptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008224 int i;
8225
8226 /* Set up Power up/down timing */
8227
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008228 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008229 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008230 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8231 else tableptr = table1024_740;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008232 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008233 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008234 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8235 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8236 else tableptr = table1400_740;
8237 } else return;
8238 } else {
8239 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008240 tableptr = table1024_650;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008241 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008242 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008243 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008244 tableptr = table1400_650;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008245 } else return;
8246 }
8247
8248 for(i=0; i<5; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008249 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008250 }
8251}
8252
8253static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008254SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008255{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008256 const unsigned char *tableptr = NULL;
8257 unsigned short tempbh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008258 int i;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008259 static const unsigned char regtable[] = {
8260 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8261 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
8262 };
8263 static const unsigned char table1024_740[] = {
8264 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8265 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
8266 };
8267 static const unsigned char table1280_740[] = {
8268 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8269 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8270 };
8271 static const unsigned char table1400_740[] = {
8272 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8273 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8274 };
8275 static const unsigned char table1600_740[] = {
8276 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8277 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
8278 };
8279 static const unsigned char table1024_650[] = {
8280 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8281 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
8282 };
8283 static const unsigned char table1280_650[] = {
8284 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8285 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
8286 };
8287 static const unsigned char table1400_650[] = {
8288 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8289 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
8290 };
8291 static const unsigned char table1600_650[] = {
8292 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8293 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
8294 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07008295
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008296 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008297 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_740;
8298 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8299 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8300 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8301 else return;
8302 } else {
8303 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_650;
8304 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8305 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8306 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8307 else return;
8308 }
8309
8310 tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8311 if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8312 tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8313 if(tempbh == 0xc8) {
8314 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8315 } else if(tempbh == 0xdb) {
8316 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8317 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8318 } else if(tempbh == 0xde) {
8319 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8320 }
8321 }
8322
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008323 if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
8324 else tempbh = 0x0c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008325
8326 for(i = 0; i < tempbh; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008327 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008328 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008329 SiS_ChrontelPowerSequencing(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008330 tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8331 tempbh |= 0xc0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008332 SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008333
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008334 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008335 tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8336 tempbh &= 0xfb;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008337 SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008338 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8339 tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8340 tempbh |= 0x40;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008341 SiS_SetCH701x(SiS_Pr,0x64,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008342 tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8343 tempbh &= 0x3f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008344 SiS_SetCH701x(SiS_Pr,0x03,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008345 }
8346}
8347
8348static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008349SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008350{
8351 unsigned char temp, temp1;
8352
8353 temp1 = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008354 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008355 temp = SiS_GetCH701x(SiS_Pr,0x47);
8356 temp &= 0x7f; /* Use external VSYNC */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008357 SiS_SetCH701x(SiS_Pr,0x47,temp);
8358 SiS_LongDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008359 temp = SiS_GetCH701x(SiS_Pr,0x47);
8360 temp |= 0x80; /* Use internal VSYNC */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008361 SiS_SetCH701x(SiS_Pr,0x47,temp);
8362 SiS_SetCH701x(SiS_Pr,0x49,temp1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008363}
8364
8365static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008366SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008367{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008368 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008369
8370 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008371 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008372 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8373 temp |= 0x04; /* Invert XCLK phase */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008374 SiS_SetCH701x(SiS_Pr,0x1c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008375 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008376 if(SiS_IsYPbPr(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008377 temp = SiS_GetCH701x(SiS_Pr,0x01);
8378 temp &= 0x3f;
8379 temp |= 0x80; /* Enable YPrPb (HDTV) */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008380 SiS_SetCH701x(SiS_Pr,0x01,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008381 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008382 if(SiS_IsChScart(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008383 temp = SiS_GetCH701x(SiS_Pr,0x01);
8384 temp &= 0x3f;
8385 temp |= 0xc0; /* Enable SCART + CVBS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008386 SiS_SetCH701x(SiS_Pr,0x01,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008387 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008388 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008389 SiS_ChrontelResetVSync(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008390 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008391 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008392 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008393 temp = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008394 if(SiS_IsYPbPr(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008395 temp = SiS_GetCH701x(SiS_Pr,0x73);
8396 temp |= 0x60;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008397 SiS_SetCH701x(SiS_Pr,0x73,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008398 }
8399 temp = SiS_GetCH701x(SiS_Pr,0x47);
8400 temp &= 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008401 SiS_SetCH701x(SiS_Pr,0x47,temp);
8402 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008403 temp = SiS_GetCH701x(SiS_Pr,0x47);
8404 temp |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008405 SiS_SetCH701x(SiS_Pr,0x47,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008406 }
8407 }
8408}
8409
8410static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008411SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008412{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008413 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008414
8415 /* Complete power down of LVDS */
8416 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008417 if(SiS_Pr->ChipType == SIS_740) {
8418 SiS_LongDelay(SiS_Pr, 1);
8419 SiS_GenericDelay(SiS_Pr, 5887);
8420 SiS_SetCH701x(SiS_Pr,0x76,0xac);
8421 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008422 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008423 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008424 temp = SiS_GetCH701x(SiS_Pr,0x76);
8425 temp &= 0xfc;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008426 SiS_SetCH701x(SiS_Pr,0x76,temp);
8427 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008428 }
8429 }
8430}
8431
8432static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008433SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008434{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008435 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008436
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008437 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008438
8439 temp = SiS_GetCH701x(SiS_Pr,0x4a); /* Version ID */
8440 temp &= 0x01;
8441 if(!temp) {
8442
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008443 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008444 temp = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008445 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008447
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008448 /* Reset Chrontel 7019 datapath */
8449 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8450 SiS_LongDelay(SiS_Pr, 1);
8451 SiS_SetCH701x(SiS_Pr,0x48,0x18);
8452
8453 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008454 SiS_ChrontelResetVSync(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008455 SiS_SetCH701x(SiS_Pr,0x49,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008456 }
8457
8458 } else {
8459
8460 /* Clear/set/clear GPIO */
8461 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8462 temp &= 0xef;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008463 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008464 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8465 temp |= 0x10;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008466 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008467 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8468 temp &= 0xef;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008469 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008470 temp = SiS_GetCH701x(SiS_Pr,0x61);
8471 if(!temp) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008472 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008473 }
8474 }
8475
8476 } else { /* 650 */
8477 /* Reset Chrontel 7019 datapath */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008478 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8479 SiS_LongDelay(SiS_Pr, 1);
8480 SiS_SetCH701x(SiS_Pr,0x48,0x18);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008481 }
8482}
8483
8484static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008485SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008486{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008487 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008488
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008489 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008490
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008491 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008492 SiS_ChrontelResetVSync(SiS_Pr);
8493 }
8494
8495 } else {
8496
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008497 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* Power up LVDS block */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008498 temp = SiS_GetCH701x(SiS_Pr,0x49);
8499 temp &= 1;
8500 if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */
8501 temp = SiS_GetCH701x(SiS_Pr,0x47);
8502 temp &= 0x70;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008503 SiS_SetCH701x(SiS_Pr,0x47,temp); /* enable VSYNC */
8504 SiS_LongDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008505 temp = SiS_GetCH701x(SiS_Pr,0x47);
8506 temp |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008507 SiS_SetCH701x(SiS_Pr,0x47,temp); /* disable VSYNC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008508 }
8509
8510 }
8511}
8512
8513static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008514SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008515{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008516 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008517
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008518 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008519
8520 temp = SiS_GetCH701x(SiS_Pr,0x61);
8521 if(temp < 1) {
8522 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008523 SiS_SetCH701x(SiS_Pr,0x61,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008524 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008525 SiS_SetCH701x(SiS_Pr,0x66,0x45); /* Panel power on */
8526 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on */
8527 SiS_LongDelay(SiS_Pr, 1);
8528 SiS_GenericDelay(SiS_Pr, 5887);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008529
8530 } else { /* 650 */
8531
8532 temp1 = 0;
8533 temp = SiS_GetCH701x(SiS_Pr,0x61);
8534 if(temp < 2) {
8535 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008536 SiS_SetCH701x(SiS_Pr,0x61,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008537 temp1 = 1;
8538 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008539 SiS_SetCH701x(SiS_Pr,0x76,0xac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008540 temp = SiS_GetCH701x(SiS_Pr,0x66);
8541 temp |= 0x5f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008542 SiS_SetCH701x(SiS_Pr,0x66,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008543 if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008544 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8545 SiS_GenericDelay(SiS_Pr, 1023);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008546 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008547 SiS_GenericDelay(SiS_Pr, 767);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008548 }
8549 } else {
8550 if(!temp1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008551 SiS_GenericDelay(SiS_Pr, 767);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008552 }
8553 temp = SiS_GetCH701x(SiS_Pr,0x76);
8554 temp |= 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008555 SiS_SetCH701x(SiS_Pr,0x76,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008556 temp = SiS_GetCH701x(SiS_Pr,0x66);
8557 temp &= 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008558 SiS_SetCH701x(SiS_Pr,0x66,temp);
8559 SiS_LongDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008560
8561 }
8562}
8563
8564static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008565SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008566{
Adrian Bunke4ccde32006-03-27 01:17:41 -08008567 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008568
8569 SiS_LongDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008570
8571 do {
8572 temp = SiS_GetCH701x(SiS_Pr,0x66);
8573 temp &= 0x04; /* PLL stable? -> bail out */
8574 if(temp == 0x04) break;
8575
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008576 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008577 /* Power down LVDS output, PLL normal operation */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008578 SiS_SetCH701x(SiS_Pr,0x76,0xac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008579 }
8580
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008581 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008582
Linus Torvalds1da177e2005-04-16 15:20:36 -07008583 temp = SiS_GetCH701x(SiS_Pr,0x76);
8584 temp &= 0xfb; /* Reset PLL */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008585 SiS_SetCH701x(SiS_Pr,0x76,temp);
8586 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008587 temp = SiS_GetCH701x(SiS_Pr,0x76);
8588 temp |= 0x04; /* PLL normal operation */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008589 SiS_SetCH701x(SiS_Pr,0x76,temp);
8590 if(SiS_Pr->ChipType == SIS_740) {
8591 SiS_SetCH701x(SiS_Pr,0x78,0xe0); /* PLL loop filter */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008592 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008593 SiS_SetCH701x(SiS_Pr,0x78,0x60);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008594 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008595 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008596 } while(0);
8597
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008598 SiS_SetCH701x(SiS_Pr,0x77,0x00); /* MV? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008599}
8600
8601static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008602SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008603{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008604 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008605
8606 temp = SiS_GetCH701x(SiS_Pr,0x03);
8607 temp |= 0x80; /* Set datapath 1 to TV */
8608 temp &= 0xbf; /* Set datapath 2 to LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008609 SiS_SetCH701x(SiS_Pr,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008610
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008611 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008612
8613 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8614 temp &= 0xfb; /* Normal XCLK phase */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008615 SiS_SetCH701x(SiS_Pr,0x1c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008616
8617 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8618
8619 temp = SiS_GetCH701x(SiS_Pr,0x64);
8620 temp |= 0x40; /* ? Bit not defined */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008621 SiS_SetCH701x(SiS_Pr,0x64,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008622
8623 temp = SiS_GetCH701x(SiS_Pr,0x03);
8624 temp &= 0x3f; /* D1 input to both LVDS and TV */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008625 SiS_SetCH701x(SiS_Pr,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008626
8627 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008628 SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008629 SiS_LongDelay(SiS_Pr, 1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008630 SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
8631 SiS_ChrontelResetDB(SiS_Pr);
8632 SiS_ChrontelDoSomething2(SiS_Pr);
8633 SiS_ChrontelDoSomething3(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008634 } else {
8635 temp = SiS_GetCH701x(SiS_Pr,0x66);
8636 if(temp != 0x45) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008637 SiS_ChrontelResetDB(SiS_Pr);
8638 SiS_ChrontelDoSomething2(SiS_Pr);
8639 SiS_ChrontelDoSomething3(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008640 }
8641 }
8642
8643 } else { /* 650 */
8644
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008645 SiS_ChrontelResetDB(SiS_Pr);
8646 SiS_ChrontelDoSomething2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008647 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008648 SiS_ChrontelDoSomething3(SiS_Pr,temp);
8649 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on, LVDS normal operation */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008650
8651 }
8652
8653}
8654#endif /* 315 series */
8655
8656/*********************************************/
8657/* MAIN: SET CRT2 REGISTER GROUP */
8658/*********************************************/
8659
8660BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008661SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008662{
8663#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008664 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008665#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008666 unsigned short ModeIdIndex, RefreshRateTableIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008667
8668 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8669
8670 if(!SiS_Pr->UseCustomMode) {
8671 SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8672 } else {
8673 ModeIdIndex = 0;
8674 }
8675
8676 /* Used for shifting CR33 */
8677 SiS_Pr->SiS_SelectCRT2Rate = 4;
8678
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008679 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008680
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008681 RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008682
8683 SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8684
8685 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008686 SiS_DisableBridge(SiS_Pr);
8687 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008688 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8689 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008690 SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008691 }
8692
8693 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008694 SiS_LockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008695 SiS_DisplayOn(SiS_Pr);
8696 return TRUE;
8697 }
8698
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008699 SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008700
8701 /* Set up Panel Link for LVDS and LCDA */
8702 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8703 if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8704 ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008705 ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
8706 SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008707 }
8708
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008709#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07008710#ifdef TWDEBUG
8711 xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES);
8712 xf86DrvMsg(0, X_INFO, "(init301: HDE 0x%03x VDE 0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE);
8713 xf86DrvMsg(0, X_INFO, "(init301: VGAHDE 0x%03x VGAVDE 0x%03x)\n", SiS_Pr->SiS_VGAHDE, SiS_Pr->SiS_VGAVDE);
8714 xf86DrvMsg(0, X_INFO, "(init301: HT 0x%03x VT 0x%03x)\n", SiS_Pr->SiS_HT, SiS_Pr->SiS_VT);
8715 xf86DrvMsg(0, X_INFO, "(init301: VGAHT 0x%03x VGAVT 0x%03x)\n", SiS_Pr->SiS_VGAHT, SiS_Pr->SiS_VGAVT);
8716#endif
8717#endif
8718
8719 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008720 SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008721 }
8722
8723 if(SiS_Pr->SiS_VBType & VB_SISVB) {
8724
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008725 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008726
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008727 SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008728#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008729 SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008730#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008731 SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
8732 SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008733#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008734 SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008735#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008736 SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008737
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008738 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008739
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008740 /* For 301BDH (Panel link initialization): */
8741 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8742
8743 if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8744 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8745 SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8746 }
8747 }
8748 SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8749 }
8750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008751
8752 } else {
8753
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008754 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008755
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008756 SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008757
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008758 SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008759
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008760 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8761 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8762 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8763 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008764#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008765 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008766#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008767 }
8768 }
8769 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8770 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8771 }
8772 }
8773 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008774
8775 }
8776
8777#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008778 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008779 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8780 if(SiS_Pr->SiS_UseOEM) {
8781 if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8782 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008783 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008784 }
8785 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008786 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008787 }
8788 }
8789 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008790 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008791 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008792 SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008793 }
8794 SiS_DisplayOn(SiS_Pr);
8795 }
8796 }
8797 }
8798#endif
8799
8800#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008801 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008802 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008803 if(SiS_Pr->ChipType < SIS_661) {
8804 SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
8805 SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008806 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008807 SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008808 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008809 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008810 }
8811 }
8812#endif
8813
8814 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008815 SiS_EnableBridge(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008816 }
8817
8818 SiS_DisplayOn(SiS_Pr);
8819
8820 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8821 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8822 /* Disable LCD panel when using TV */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008823 SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008824 } else {
8825 /* Disable TV when using LCD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008826 SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008827 }
8828 }
8829
8830 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008831 SiS_LockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008832 }
8833
8834 return TRUE;
8835}
8836
8837
8838/*********************************************/
8839/* ENABLE/DISABLE LCD BACKLIGHT (SIS) */
8840/*********************************************/
8841
8842void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008843SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008844{
8845 /* Switch on LCD backlight on SiS30xLV */
8846 SiS_DDC2Delay(SiS_Pr,0xff00);
8847 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
8848 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008849 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008850 }
8851 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
8852 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
8853 }
8854}
8855
8856void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008857SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008858{
8859 /* Switch off LCD backlight on SiS30xLV */
8860 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008861 SiS_DDC2Delay(SiS_Pr,0xff00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008862}
8863
8864/*********************************************/
8865/* DDC RELATED FUNCTIONS */
8866/*********************************************/
8867
8868static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008869SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008870{
8871 SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
8872 SiS_Pr->SiS_DDC_NClk = ~SiS_Pr->SiS_DDC_Clk;
8873 if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
8874 SiS_Pr->SiS_DDC_NData &= 0x0f;
8875 SiS_Pr->SiS_DDC_NClk &= 0x0f;
8876 }
8877}
8878
8879#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008880static unsigned char *
8881SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008882{
8883 int i, j, num;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008884 unsigned short tempah,temp;
8885 unsigned char *mydataptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008886
8887 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8888 mydataptr = dataptr;
8889 num = *mydataptr++;
8890 if(!num) return mydataptr;
8891 if(i) {
8892 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008893 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008894 }
8895 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8896 tempah = SiS_Pr->SiS_DDC_DeviceAddr;
8897 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
8898 if(temp) continue; /* (ERROR: no ack) */
8899 tempah = *mydataptr++;
8900 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write register number */
8901 if(temp) continue; /* (ERROR: no ack) */
8902 for(j=0; j<num; j++) {
8903 tempah = *mydataptr++;
8904 temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
8905 if(temp) break;
8906 }
8907 if(temp) continue;
8908 if(SiS_SetStop(SiS_Pr)) continue;
8909 return mydataptr;
8910 }
8911 return NULL;
8912}
8913
8914static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008915SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008916{
8917 SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */
8918 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008919 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8920 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008921 SiS_SetupDDCN(SiS_Pr);
8922
8923 SiS_SetSwitchDDC2(SiS_Pr);
8924
8925 while(*dataptr) {
8926 dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
8927 if(!dataptr) return FALSE;
8928 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008929#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07008930#ifdef TWDEBUG
8931 xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
8932#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008933#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07008934 return TRUE;
8935}
8936#endif
8937
8938/* The Chrontel 700x is connected to the 630/730 via
8939 * the 630/730's DDC/I2C port.
8940 *
8941 * On 630(S)T chipset, the index changed from 0x11 to
8942 * 0x0a, possibly for working around the DDC problems
8943 */
8944
8945static BOOLEAN
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008946SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008947{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008948 unsigned short temp, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008949
8950 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8951 if(i) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008952 SiS_SetStop(SiS_Pr);
8953 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008954 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008955 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8956 temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
8957 if(temp) continue; /* (ERROR: no ack) */
8958 temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor)); /* Write RAB (700x: set bit 7, see datasheet) */
8959 if(temp) continue; /* (ERROR: no ack) */
8960 temp = SiS_WriteDDC2Data(SiS_Pr, val); /* Write data */
8961 if(temp) continue; /* (ERROR: no ack) */
8962 if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008963 SiS_Pr->SiS_ChrontelInit = 1;
8964 return TRUE;
8965 }
8966 return FALSE;
8967}
8968
Linus Torvalds1da177e2005-04-16 15:20:36 -07008969/* Write to Chrontel 700x */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008970void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008971SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008972{
8973 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
8974
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008975 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8976
Linus Torvalds1da177e2005-04-16 15:20:36 -07008977 if(!(SiS_Pr->SiS_ChrontelInit)) {
8978 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008979 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8980 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008981 SiS_SetupDDCN(SiS_Pr);
8982 }
8983
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008984 if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07008985 (!(SiS_Pr->SiS_ChrontelInit)) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008986 SiS_Pr->SiS_DDC_Index = 0x0a;
8987 SiS_Pr->SiS_DDC_Data = 0x80;
8988 SiS_Pr->SiS_DDC_Clk = 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008989 SiS_SetupDDCN(SiS_Pr);
8990
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008991 SiS_SetChReg(SiS_Pr, reg, val, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008992 }
8993}
8994
8995/* Write to Chrontel 701x */
8996/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
8997void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008998SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008999{
9000 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009001 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
9002 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009003 SiS_SetupDDCN(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009004 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
9005 SiS_SetChReg(SiS_Pr, reg, val, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009006}
9007
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009008#ifdef SIS_LINUX_KERNEL
9009static
9010#endif
9011void
9012SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009013{
9014 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009015 SiS_SetCH700x(SiS_Pr, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009016 else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009017 SiS_SetCH701x(SiS_Pr, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009018}
9019
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009020static unsigned short
9021SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009022{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009023 unsigned short tempah, temp, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009024
9025 for(i=0; i<20; i++) { /* Do 20 attempts to read */
9026 if(i) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009027 SiS_SetStop(SiS_Pr);
9028 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009029 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009030 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
9031 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
9032 if(temp) continue; /* (ERROR: no ack) */
9033 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor); /* Write RAB (700x: | 0x80) */
9034 if(temp) continue; /* (ERROR: no ack) */
9035 if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
9036 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
9037 if(temp) continue; /* (ERROR: no ack) */
9038 tempah = SiS_ReadDDC2Data(SiS_Pr); /* Read byte */
9039 if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009040 SiS_Pr->SiS_ChrontelInit = 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009041 return tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009042 }
9043 return 0xFFFF;
9044}
9045
Linus Torvalds1da177e2005-04-16 15:20:36 -07009046/* Read from Chrontel 700x */
9047/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009048unsigned short
9049SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009050{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009051 unsigned short result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009052
9053 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
9054
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009055 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9056
Linus Torvalds1da177e2005-04-16 15:20:36 -07009057 if(!(SiS_Pr->SiS_ChrontelInit)) {
9058 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009059 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
9060 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009061 SiS_SetupDDCN(SiS_Pr);
9062 }
9063
9064 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9065
9066 if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
9067 (!SiS_Pr->SiS_ChrontelInit) ) {
9068
9069 SiS_Pr->SiS_DDC_Index = 0x0a;
9070 SiS_Pr->SiS_DDC_Data = 0x80;
9071 SiS_Pr->SiS_DDC_Clk = 0x40;
9072 SiS_SetupDDCN(SiS_Pr);
9073
9074 result = SiS_GetChReg(SiS_Pr,0x80);
9075 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009076 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009077}
9078
9079/* Read from Chrontel 701x */
9080/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009081unsigned short
9082SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009083{
9084 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009085 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
9086 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009087 SiS_SetupDDCN(SiS_Pr);
9088 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
9089
9090 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9091
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009092 return SiS_GetChReg(SiS_Pr,0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009093}
9094
9095/* Read from Chrontel 70xx */
9096/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009097#ifdef SIS_LINUX_KERNEL
9098static
9099#endif
9100unsigned short
9101SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009102{
9103 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009104 return SiS_GetCH700x(SiS_Pr, tempbx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009105 else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009106 return SiS_GetCH701x(SiS_Pr, tempbx);
9107}
9108
9109void
9110SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
9111 unsigned char myor, unsigned short myand)
9112{
9113 unsigned short tempbl;
9114
9115 tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
9116 SiS_SetCH70xx(SiS_Pr, reg, tempbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009117}
9118
9119/* Our own DDC functions */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009120#ifndef SIS_XORG_XF86
9121static
9122#endif
9123unsigned short
9124SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9125 unsigned short adaptnum, unsigned short DDCdatatype, BOOLEAN checkcr32,
9126 unsigned int VBFlags2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009127{
9128 unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
9129 unsigned char flag, cr32;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009130 unsigned short temp = 0, myadaptnum = adaptnum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009131
9132 if(adaptnum != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009133 if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
9134 if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
9135 }
9136
Linus Torvalds1da177e2005-04-16 15:20:36 -07009137 /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009138
Linus Torvalds1da177e2005-04-16 15:20:36 -07009139 SiS_Pr->SiS_ChrontelInit = 0; /* force re-detection! */
9140
9141 SiS_Pr->SiS_DDC_SecAddr = 0;
9142 SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
9143 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
9144 SiS_Pr->SiS_DDC_Index = 0x11;
9145 flag = 0xff;
9146
9147 cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
9148
9149#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009150 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009151 if(myadaptnum == 0) {
9152 if(!(cr32 & 0x20)) {
9153 myadaptnum = 2;
9154 if(!(cr32 & 0x10)) {
9155 myadaptnum = 1;
9156 if(!(cr32 & 0x08)) {
9157 myadaptnum = 0;
9158 }
9159 }
9160 }
9161 }
9162 }
9163#endif
9164
9165 if(VGAEngine == SIS_300_VGA) { /* 300 series */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009166
Linus Torvalds1da177e2005-04-16 15:20:36 -07009167 if(myadaptnum != 0) {
9168 flag = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009169 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009170 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9171 SiS_Pr->SiS_DDC_Index = 0x0f;
9172 }
9173 }
9174
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009175 if(!(VBFlags2 & VB2_301)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009176 if((cr32 & 0x80) && (checkcr32)) {
9177 if(myadaptnum >= 1) {
9178 if(!(cr32 & 0x08)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009179 myadaptnum = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009180 if(!(cr32 & 0x10)) return 0xFFFF;
9181 }
9182 }
9183 }
9184 }
9185
9186 temp = 4 - (myadaptnum * 2);
9187 if(flag) temp = 0;
9188
9189 } else { /* 315/330 series */
9190
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009191 /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009192
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009193 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009194 if(myadaptnum == 2) {
9195 myadaptnum = 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009197 }
9198
9199 if(myadaptnum == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009200 flag = 0;
9201 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009202 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9203 SiS_Pr->SiS_DDC_Index = 0x0f;
9204 }
9205 }
9206
9207 if((cr32 & 0x80) && (checkcr32)) {
9208 if(myadaptnum >= 1) {
9209 if(!(cr32 & 0x08)) {
9210 myadaptnum = 1;
9211 if(!(cr32 & 0x10)) return 0xFFFF;
9212 }
9213 }
9214 }
9215
9216 temp = myadaptnum;
9217 if(myadaptnum == 1) {
9218 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009219 if(VBFlags2 & VB2_LVDS) flag = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009220 }
9221
9222 if(flag) temp = 0;
9223 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009224
Linus Torvalds1da177e2005-04-16 15:20:36 -07009225 SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9226 SiS_Pr->SiS_DDC_Clk = 0x01 << temp;
9227
9228 SiS_SetupDDCN(SiS_Pr);
9229
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009230#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009231#ifdef TWDEBUG
9232 xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
9233 SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
9234#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009235#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07009236 return 0;
9237}
9238
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009239static unsigned short
9240SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009241{
9242 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9243 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009244 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009245 }
9246 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009247 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009248 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009249 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009250}
9251
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009252static unsigned short
9253SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009254{
9255 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9256 if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009257 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009258 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009259 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009260}
9261
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009262static unsigned short
9263SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009264{
9265 if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009266 if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
9267 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009268}
9269
9270static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009271SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009272{
9273 SiS_SetSCLKLow(SiS_Pr);
9274 if(yesno) {
9275 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009276 SiS_Pr->SiS_DDC_Index,
9277 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009278 SiS_Pr->SiS_DDC_Data);
9279 } else {
9280 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009281 SiS_Pr->SiS_DDC_Index,
9282 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009283 0);
9284 }
9285 SiS_SetSCLKHigh(SiS_Pr);
9286}
9287
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009288static unsigned short
9289SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009290{
9291 unsigned char mask, value;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009292 unsigned short temp, ret=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009293 BOOLEAN failed = FALSE;
9294
9295 SiS_SetSwitchDDC2(SiS_Pr);
9296 if(SiS_PrepareDDC(SiS_Pr)) {
9297 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009298#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009299#ifdef TWDEBUG
9300 xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n");
9301#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009302#endif
9303 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009304 }
9305 mask = 0xf0;
9306 value = 0x20;
9307 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009308 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009309 SiS_SendACK(SiS_Pr, 0);
9310 if(temp == 0) {
9311 mask = 0xff;
9312 value = 0xff;
9313 } else {
9314 failed = TRUE;
9315 ret = 0xFFFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009316#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009317#ifdef TWDEBUG
9318 xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n");
9319#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009320#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07009321 }
9322 }
9323 if(failed == FALSE) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009324 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009325 SiS_SendACK(SiS_Pr, 1);
9326 temp &= mask;
9327 if(temp == value) ret = 0;
9328 else {
9329 ret = 0xFFFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009330#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009331#ifdef TWDEBUG
9332 xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n");
9333#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009334#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07009335 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9336 if(temp == 0x30) ret = 0;
9337 }
9338 }
9339 }
9340 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009341 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009342}
9343
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009344#ifndef SIS_XORG_XF86
9345static
9346#endif
9347unsigned short
9348SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009349{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009350 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009351
9352 flag = 0x180;
9353 SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9354 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9355 SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9356 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9357 SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9358 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9359 if(!(flag & 0x1a)) flag = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009360 return flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009361}
9362
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009363#ifndef SIS_XORG_XF86
9364static
9365#endif
9366unsigned short
9367SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009368{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009369 unsigned short flag, length, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009370 unsigned char chksum,gotcha;
9371
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009372 if(DDCdatatype > 4) return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009373
9374 flag = 0;
9375 SiS_SetSwitchDDC2(SiS_Pr);
9376 if(!(SiS_PrepareDDC(SiS_Pr))) {
9377 length = 127;
9378 if(DDCdatatype != 1) length = 255;
9379 chksum = 0;
9380 gotcha = 0;
9381 for(i=0; i<length; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009382 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009383 chksum += buffer[i];
9384 gotcha |= buffer[i];
9385 SiS_SendACK(SiS_Pr, 0);
9386 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009387 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009388 chksum += buffer[i];
9389 SiS_SendACK(SiS_Pr, 1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009390 if(gotcha) flag = (unsigned short)chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009391 else flag = 0xFFFF;
9392 } else {
9393 flag = 0xFFFF;
9394 }
9395 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009396 return flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009397}
9398
9399/* Our private DDC functions
9400
9401 It complies somewhat with the corresponding VESA function
9402 in arguments and return values.
9403
9404 Since this is probably called before the mode is changed,
9405 we use our pre-detected pSiS-values instead of SiS_Pr as
9406 regards chipset and video bridge type.
9407
9408 Arguments:
9409 adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9410 CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9411 LCDA is CRT1, but DDC is read from CRT2 port.
9412 DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9413 buffer: ptr to 256 data bytes which will be filled with read data.
9414
9415 Returns 0xFFFF if error, otherwise
9416 if DDCdatatype > 0: Returns 0 if reading OK (included a correct checksum)
9417 if DDCdatatype = 0: Returns supported DDC modes
9418
9419 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009420unsigned short
9421SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9422 unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
9423 unsigned int VBFlags2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009424{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009425 unsigned char sr1f, cr17=1;
9426 unsigned short result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009427
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009428 if(adaptnum > 2)
9429 return 0xFFFF;
9430
9431 if(DDCdatatype > 4)
9432 return 0xFFFF;
9433
9434 if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
9435 return 0xFFFF;
9436
9437 if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE, VBFlags2) == 0xFFFF)
9438 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009439
9440 sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9441 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9442 if(VGAEngine == SIS_300_VGA) {
9443 cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9444 if(!cr17) {
9445 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9446 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9447 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9448 }
9449 }
9450 if((sr1f) || (!cr17)) {
9451 SiS_WaitRetrace1(SiS_Pr);
9452 SiS_WaitRetrace1(SiS_Pr);
9453 SiS_WaitRetrace1(SiS_Pr);
9454 SiS_WaitRetrace1(SiS_Pr);
9455 }
9456
9457 if(DDCdatatype == 0) {
9458 result = SiS_ProbeDDC(SiS_Pr);
9459 } else {
9460 result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9461 if((!result) && (DDCdatatype == 1)) {
9462 if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9463 (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9464 (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9465 (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9466 (buffer[0x12] == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009467 if(!SiS_Pr->DDCPortMixup) {
9468 if(adaptnum == 1) {
9469 if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9470 } else {
9471 if(buffer[0x14] & 0x80) result = 0xFFFE;
9472 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009473 }
9474 }
9475 }
9476 }
9477 SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9478 if(VGAEngine == SIS_300_VGA) {
9479 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9480 }
9481 return result;
9482}
9483
Linus Torvalds1da177e2005-04-16 15:20:36 -07009484/* Generic I2C functions for Chrontel & DDC --------- */
9485
9486static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009487SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009488{
9489 SiS_SetSCLKHigh(SiS_Pr);
9490 SiS_WaitRetrace1(SiS_Pr);
9491
9492 SiS_SetSCLKLow(SiS_Pr);
9493 SiS_WaitRetrace1(SiS_Pr);
9494}
9495
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009496unsigned short
9497SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009498{
9499 SiS_WaitRetrace1(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009500 return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009501}
9502
9503/* Set I2C start condition */
9504/* This is done by a SD high-to-low transition while SC is high */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009505static unsigned short
9506SiS_SetStart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009507{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009508 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009509 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009510 SiS_Pr->SiS_DDC_Index,
9511 SiS_Pr->SiS_DDC_NData,
9512 SiS_Pr->SiS_DDC_Data); /* SD->high */
9513 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009514 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009515 SiS_Pr->SiS_DDC_Index,
9516 SiS_Pr->SiS_DDC_NData,
9517 0x00); /* SD->low = start condition */
9518 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009519 return 0;
9520}
9521
9522/* Set I2C stop condition */
9523/* This is done by a SD low-to-high transition while SC is high */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009524static unsigned short
9525SiS_SetStop(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009526{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009527 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009528 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009529 SiS_Pr->SiS_DDC_Index,
9530 SiS_Pr->SiS_DDC_NData,
9531 0x00); /* SD->low */
9532 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009533 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009534 SiS_Pr->SiS_DDC_Index,
9535 SiS_Pr->SiS_DDC_NData,
9536 SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
9537 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009538 return 0;
9539}
9540
9541/* Write 8 bits of data */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009542static unsigned short
9543SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009544{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009545 unsigned short i,flag,temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009546
9547 flag = 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009548 for(i = 0; i < 8; i++) {
9549 SiS_SetSCLKLow(SiS_Pr); /* SC->low */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009550 if(tempax & flag) {
9551 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009552 SiS_Pr->SiS_DDC_Index,
9553 SiS_Pr->SiS_DDC_NData,
9554 SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009555 } else {
9556 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009557 SiS_Pr->SiS_DDC_Index,
9558 SiS_Pr->SiS_DDC_NData,
9559 0x00); /* Write bit (0) to SD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009560 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009561 SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009562 flag >>= 1;
9563 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009564 temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
9565 return temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009566}
9567
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009568static unsigned short
9569SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009570{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009571 unsigned short i, temp, getdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009572
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009573 getdata = 0;
9574 for(i = 0; i < 8; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009575 getdata <<= 1;
9576 SiS_SetSCLKLow(SiS_Pr);
9577 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009578 SiS_Pr->SiS_DDC_Index,
9579 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009580 SiS_Pr->SiS_DDC_Data);
9581 SiS_SetSCLKHigh(SiS_Pr);
9582 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9583 if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
9584 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009585 return getdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009586}
9587
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009588static unsigned short
9589SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009590{
9591 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009592 SiS_Pr->SiS_DDC_Index,
9593 SiS_Pr->SiS_DDC_NClk,
9594 0x00); /* SetSCLKLow() */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009595 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9596 return 0;
9597}
9598
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009599static unsigned short
9600SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009601{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009602 unsigned short temp, watchdog=1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009603
9604 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009605 SiS_Pr->SiS_DDC_Index,
9606 SiS_Pr->SiS_DDC_NClk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009607 SiS_Pr->SiS_DDC_Clk); /* SetSCLKHigh() */
9608 do {
9609 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9610 } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
9611 if (!watchdog) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009612#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009613#ifdef TWDEBUG
9614 xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n");
9615#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009616#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07009617 return 0xFFFF;
9618 }
9619 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9620 return 0;
9621}
9622
9623/* Check I2C acknowledge */
9624/* Returns 0 if ack ok, non-0 if ack not ok */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009625static unsigned short
9626SiS_CheckACK(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009627{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009628 unsigned short tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009629
9630 SiS_SetSCLKLow(SiS_Pr); /* (SC->low) */
9631 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009632 SiS_Pr->SiS_DDC_Index,
9633 SiS_Pr->SiS_DDC_NData,
9634 SiS_Pr->SiS_DDC_Data); /* (SD->high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009635 SiS_SetSCLKHigh(SiS_Pr); /* SC->high = clock impulse for ack */
9636 tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
9637 SiS_SetSCLKLow(SiS_Pr); /* SC->low = end of clock impulse */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009638 if(tempah & SiS_Pr->SiS_DDC_Data) return 1; /* Ack OK if bit = 0 */
9639 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009640}
9641
9642/* End of I2C functions ----------------------- */
9643
9644
9645/* =============== SiS 315/330 O.E.M. ================= */
9646
9647#ifdef SIS315H
9648
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009649static unsigned short
9650GetRAMDACromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009651{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009652 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9653 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009654
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009655 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009656 romptr = SISGETROMW(0x128);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009657 if(SiS_Pr->SiS_VBType & VB_SIS30xB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009658 romptr = SISGETROMW(0x12a);
9659 } else {
9660 romptr = SISGETROMW(0x1a8);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009661 if(SiS_Pr->SiS_VBType & VB_SIS30xB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009662 romptr = SISGETROMW(0x1aa);
9663 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009664 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009665}
9666
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009667static unsigned short
9668GetLCDromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009669{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009670 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9671 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009672
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009673 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009674 romptr = SISGETROMW(0x120);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009675 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009676 romptr = SISGETROMW(0x122);
9677 } else {
9678 romptr = SISGETROMW(0x1a0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009679 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009680 romptr = SISGETROMW(0x1a2);
9681 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009682 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009683}
9684
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009685static unsigned short
9686GetTVromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009687{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009688 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9689 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009690
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009691 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009692 romptr = SISGETROMW(0x114);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009693 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009694 romptr = SISGETROMW(0x11a);
9695 } else {
9696 romptr = SISGETROMW(0x194);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009697 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009698 romptr = SISGETROMW(0x19a);
9699 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009700 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009701}
9702
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009703static unsigned short
9704GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009705{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009706 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009707
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009708 if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9709 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009710 if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
9711 index >>= 4;
9712 index *= 3;
9713 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9714 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9715 return index;
9716 }
9717 }
9718 }
9719
9720 index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
9721 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) index -= 5;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009722 if(SiS_Pr->SiS_VBType & VB_SIS301C) { /* 1.15.20 and later (not VB specific) */
9723 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
9724 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
9725 } else {
9726 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
9727 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009728 index--;
9729 index *= 3;
9730 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9731 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9732 return index;
9733}
9734
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009735static unsigned short
9736GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009737{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009738 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009739
9740 index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
9741 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9742 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9743 return index;
9744}
9745
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009746static unsigned short
9747GetTVPtrIndex(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009748{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009749 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009750
9751 index = 0;
9752 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9753 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
9754
9755 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
9756
9757 index <<= 1;
9758
9759 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
9760 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9761 index++;
9762 }
9763
9764 return index;
9765}
9766
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009767static unsigned int
9768GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009769{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009770 unsigned short index = 0, temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009771
9772 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9773 if(SiS_Pr->SiS_TVMode & TVSetPALM) index = 2;
9774 if(SiS_Pr->SiS_TVMode & TVSetPALN) index = 3;
9775 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
9776 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
9777 index = 4;
9778 if(SiS_Pr->SiS_TVMode & TVSetPALM) index++;
9779 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
9780 }
9781
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009782 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009783 if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
9784 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9785 index += addme;
9786 temp++;
9787 }
9788 temp += 0x0100;
9789 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009790 return (unsigned int)(index | (temp << 16));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009791}
9792
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009793static unsigned int
9794GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009795{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009796 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009797}
9798
9799#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009800static unsigned int
9801GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009802{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009803 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009804}
9805#endif
9806
9807static int
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009808GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009809{
9810 int index = 0;
9811
9812 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 2;
9813 if(SiS_Pr->SiS_ROMNew) {
9814 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
9815 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
9816 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
9817 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 10;
9818 } else {
9819 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 4;
9820 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
9821 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
9822 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
9823 }
9824
9825 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
9826
9827 return index;
9828}
9829
9830static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009831SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009832{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009833 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9834 unsigned short delay=0,index,myindex,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009835 BOOLEAN dochiptest = TRUE;
9836
9837 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9838 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
9839 } else {
9840 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
9841 }
9842
9843 /* Find delay (from ROM, internal tables, PCI subsystem) */
9844
9845 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { /* ------------ VGA */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009846
Linus Torvalds1da177e2005-04-16 15:20:36 -07009847 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009848 romptr = GetRAMDACromptr(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009849 }
9850 if(romptr) delay = ROMAddr[romptr];
9851 else {
9852 delay = 0x04;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009853 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009854 if(IS_SIS650) {
9855 delay = 0x0a;
9856 } else if(IS_SIS740) {
9857 delay = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009858 } else if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009859 delay = 0x0c;
9860 } else {
9861 delay = 0x0c;
9862 }
9863 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9864 delay = 0x00;
9865 }
9866 }
9867
9868 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) { /* ---------- LCD/LCDA */
9869
9870 BOOLEAN gotitfrompci = FALSE;
9871
9872 /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
9873
9874 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
9875 if(SiS_Pr->PDC != -1) {
9876 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
9877 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
9878 return;
9879 }
9880 } else {
9881 if(SiS_Pr->PDCA != -1) {
9882 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
9883 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
9884 return;
9885 }
9886 }
9887
9888 /* Custom Panel? */
9889
9890 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
9891 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9892 delay = 0x00;
9893 if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
9894 delay = 0x20;
9895 }
9896 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
9897 } else {
9898 delay = 0x0c;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009899 if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9900 delay = 0x03;
9901 if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
9902 delay = 0x00;
9903 }
9904 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009905 if(IS_SIS740) delay = 0x01;
9906 else delay = 0x03;
9907 }
9908 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
9909 }
9910 return;
9911 }
9912
9913 /* This is a piece of typical SiS crap: They code the OEM LCD
9914 * delay into the code, at no defined place in the BIOS.
9915 * We now have to start doing a PCI subsystem check here.
9916 */
9917
9918 switch(SiS_Pr->SiS_CustomT) {
9919 case CUT_COMPAQ1280:
9920 case CUT_COMPAQ12802:
9921 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
9922 gotitfrompci = TRUE;
9923 dochiptest = FALSE;
9924 delay = 0x03;
9925 }
9926 break;
9927 case CUT_CLEVO1400:
9928 case CUT_CLEVO14002:
9929 gotitfrompci = TRUE;
9930 dochiptest = FALSE;
9931 delay = 0x02;
9932 break;
9933 case CUT_CLEVO1024:
9934 case CUT_CLEVO10242:
9935 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
9936 gotitfrompci = TRUE;
9937 dochiptest = FALSE;
9938 delay = 0x33;
9939 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9940 delay &= 0x0f;
9941 }
9942 break;
9943 }
9944
9945 /* Could we find it through the PCI ID? If no, use ROM or table */
9946
9947 if(!gotitfrompci) {
9948
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009949 index = GetLCDPtrIndexBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009950 myindex = GetLCDPtrIndex(SiS_Pr);
9951
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009952 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009953
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009954 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009955
9956 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9957 /* Always use the second pointer on 650; some BIOSes */
9958 /* still carry old 301 data at the first location */
9959 /* romptr = SISGETROMW(0x120); */
9960 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
9961 romptr = SISGETROMW(0x122);
9962 if(!romptr) return;
9963 delay = ROMAddr[(romptr + index)];
9964 } else {
9965 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9966 }
9967
9968 } else {
9969
9970 delay = SiS310_LCDDelayCompensation_651301LV[myindex];
9971 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
9972 delay = SiS310_LCDDelayCompensation_651302LV[myindex];
9973
9974 }
9975
9976 } else if(SiS_Pr->SiS_UseROM &&
9977 (!(SiS_Pr->SiS_ROMNew)) &&
9978 (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
9979 (SiS_Pr->SiS_LCDResInfo != Panel_1280x768) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009980 (SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
9981 (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200) &&
9982 ((romptr = GetLCDromptr(SiS_Pr)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009983
9984 /* Data for 1280x1024 wrong in 301B BIOS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009985 /* Data for 1600x1200 wrong in 301C BIOS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009986 delay = ROMAddr[(romptr + index)];
9987
9988 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9989
9990 if(IS_SIS740) delay = 0x03;
9991 else delay = 0x00;
9992
9993 } else {
9994
9995 delay = SiS310_LCDDelayCompensation_301[myindex];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009996 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009997 if(IS_SIS740) delay = 0x01;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009998 else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07009999 else delay = SiS310_LCDDelayCompensation_650301LV[myindex];
10000 } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
10001 if(IS_SIS740) delay = 0x01; /* ? */
10002 else delay = 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010003 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
10004 } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010005 if(IS_SIS740) delay = 0x01;
10006 else delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
10007 }
10008
10009 }
10010
10011 } /* got it from PCI */
10012
10013 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10014 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
10015 dochiptest = FALSE;
10016 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010017
Linus Torvalds1da177e2005-04-16 15:20:36 -070010018 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* ------------ TV */
10019
10020 index = GetTVPtrIndex(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010021
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010022 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
10023
10024 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010025
10026 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10027 /* Always use the second pointer on 650; some BIOSes */
10028 /* still carry old 301 data at the first location */
10029 /* romptr = SISGETROMW(0x114); */
10030 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
10031 romptr = SISGETROMW(0x11a);
10032 if(!romptr) return;
10033 delay = ROMAddr[romptr + index];
10034
10035 } else {
10036
10037 delay = SiS310_TVDelayCompensation_301B[index];
10038
10039 }
10040
10041 } else {
10042
10043 switch(SiS_Pr->SiS_CustomT) {
10044 case CUT_COMPAQ1280:
10045 case CUT_COMPAQ12802:
10046 case CUT_CLEVO1400:
10047 case CUT_CLEVO14002:
10048 delay = 0x02;
10049 dochiptest = FALSE;
10050 break;
10051 case CUT_CLEVO1024:
10052 case CUT_CLEVO10242:
10053 delay = 0x03;
10054 dochiptest = FALSE;
10055 break;
10056 default:
10057 delay = SiS310_TVDelayCompensation_651301LV[index];
10058 if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
10059 delay = SiS310_TVDelayCompensation_651302LV[index];
10060 }
10061 }
10062 }
10063
10064 } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10065
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010066 romptr = GetTVromptr(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010067 if(!romptr) return;
10068 delay = ROMAddr[romptr + index];
10069
10070 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
10071
10072 delay = SiS310_TVDelayCompensation_LVDS[index];
10073
10074 } else {
10075
10076 delay = SiS310_TVDelayCompensation_301[index];
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010077 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010078 if(IS_SIS740) {
10079 delay = SiS310_TVDelayCompensation_740301B[index];
10080 /* LV: use 301 data? BIOS bug? */
10081 } else {
10082 delay = SiS310_TVDelayCompensation_301B[index];
10083 if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
10084 }
10085 }
10086
10087 }
10088
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010089 if(SiS_LCDAEnabled(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010090 delay &= 0x0f;
10091 dochiptest = FALSE;
10092 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010093
Linus Torvalds1da177e2005-04-16 15:20:36 -070010094 } else return;
10095
10096 /* Write delay */
10097
10098 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10099
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010100 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010101
10102 temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
10103 if(temp == 8) { /* 1400x1050 BIOS (COMPAL) */
10104 delay &= 0x0f;
10105 delay |= 0xb0;
10106 } else if(temp == 6) {
10107 delay &= 0x0f;
10108 delay |= 0xc0;
10109 } else if(temp > 7) { /* 1280x1024 BIOS (which one?) */
10110 delay = 0x35;
10111 }
10112 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
10113
10114 } else {
10115
10116 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
10117
10118 }
10119
10120 } else { /* LVDS */
10121
10122 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10123 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
10124 } else {
10125 if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
10126 delay <<= 4;
10127 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
10128 } else {
10129 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
10130 }
10131 }
10132
10133 }
10134
10135}
10136
10137static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010138SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010139{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010140 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10141 unsigned short index,temp,temp1,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010142
10143 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
10144
10145 if(ModeNo<=0x13)
10146 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
10147 else
10148 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
10149
10150 temp = GetTVPtrIndex(SiS_Pr);
10151 temp >>= 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10152 temp1 = temp;
10153
10154 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010155 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010156 temp1 = GetOEMTVPtr661(SiS_Pr);
10157 temp1 >>= 1;
10158 romptr = SISGETROMW(0x260);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010159 if(SiS_Pr->ChipType >= SIS_760) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010160 romptr = SISGETROMW(0x360);
10161 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010162 } else if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010163 romptr = SISGETROMW(0x192);
10164 } else {
10165 romptr = SISGETROMW(0x112);
10166 }
10167 }
10168
10169 if(romptr) {
10170 temp1 <<= 1;
10171 temp = ROMAddr[romptr + temp1 + index];
10172 } else {
10173 temp = SiS310_TVAntiFlick1[temp][index];
10174 }
10175 temp <<= 4;
10176
10177 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp); /* index 0A D[6:4] */
10178}
10179
10180static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010181SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010182{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010183 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10184 unsigned short index,temp,temp1,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010185
10186 temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10187
10188 if(ModeNo <= 0x13)
10189 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
10190 else
10191 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
10192
10193 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010194 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010195 romptr = SISGETROMW(0x26c);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010196 if(SiS_Pr->ChipType >= SIS_760) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010197 romptr = SISGETROMW(0x36c);
10198 }
10199 temp1 = GetOEMTVPtr661(SiS_Pr);
10200 temp1 >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010201 } else if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010202 romptr = SISGETROMW(0x1a4);
10203 } else {
10204 romptr = SISGETROMW(0x124);
10205 }
10206 }
10207
10208 if(romptr) {
10209 temp1 <<= 1;
10210 temp = ROMAddr[romptr + temp1 + index];
10211 } else {
10212 temp = SiS310_TVEdge1[temp][index];
10213 }
10214 temp <<= 5;
10215 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp); /* index 0A D[7:5] */
10216}
10217
10218static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010219SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010220{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010221 unsigned short index, temp, i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010222
10223 if(ModeNo <= 0x13) {
10224 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
10225 } else {
10226 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
10227 }
10228
10229 temp = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10230
10231 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 1; /* NTSC-J uses PAL */
10232 else if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 3; /* PAL-M */
10233 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 4; /* PAL-N */
10234 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1; /* HiVision uses PAL */
10235
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010236 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010237 for(i=0x35, j=0; i<=0x38; i++, j++) {
10238 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10239 }
10240 for(i=0x48; i<=0x4A; i++, j++) {
10241 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10242 }
10243 } else {
10244 for(i=0x35, j=0; i<=0x38; i++, j++) {
10245 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
10246 }
10247 }
10248}
10249
10250static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010251SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010252{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010253 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10254 unsigned short index,temp,i,j,resinfo,romptr=0;
10255 unsigned int lindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010256
10257 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
10258
10259 /* NTSC-J data not in BIOS, and already set in SetGroup2 */
10260 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
10261
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010262 if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010263 lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
10264 lindex <<= 2;
10265 for(j=0, i=0x31; i<=0x34; i++, j++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010266 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010267 }
10268 return;
10269 }
10270
10271 /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
10272 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
10273
10274 if(ModeNo<=0x13) {
10275 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10276 } else {
10277 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10278 }
10279
10280 temp = GetTVPtrIndex(SiS_Pr);
10281 /* 0: NTSC Graphics, 1: NTSC Text, 2: PAL Graphics,
10282 * 3: PAL Text, 4: HiTV Graphics 5: HiTV Text
10283 */
10284 if(SiS_Pr->SiS_UseROM) {
10285 romptr = SISGETROMW(0x116);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010286 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010287 romptr = SISGETROMW(0x196);
10288 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010289 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010290 romptr = SISGETROMW(0x11c);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010291 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010292 romptr = SISGETROMW(0x19c);
10293 }
10294 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
10295 romptr = SISGETROMW(0x116);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010296 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010297 romptr = SISGETROMW(0x196);
10298 }
10299 }
10300 }
10301 }
10302 if(romptr) {
10303 romptr += (temp << 2);
10304 for(j=0, i=0x31; i<=0x34; i++, j++) {
10305 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10306 }
10307 } else {
10308 index = temp % 2;
10309 temp >>= 1; /* 0:NTSC, 1:PAL, 2:HiTV */
10310 for(j=0, i=0x31; i<=0x34; i++, j++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010311 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
Linus Torvalds1da177e2005-04-16 15:20:36 -070010312 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10313 else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
10314 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
10315 else
10316 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10317 }
10318 }
10319
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010320 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010321 if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
10322 if((resinfo == SIS_RI_640x480) ||
10323 (resinfo == SIS_RI_800x600)) {
10324 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
10325 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
10326 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
10327 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
10328 } else if(resinfo == SIS_RI_1024x768) {
10329 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
10330 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
10331 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
10332 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
10333 }
10334 }
10335 }
10336}
10337
10338static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010339SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10340 unsigned short ModeIdIndex, unsigned short RTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010341{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010342 unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
10343 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010344
10345 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
10346 return;
10347
10348 /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
10349 /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
10350
10351 if(SiS_Pr->SiS_ROMNew) {
10352 if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) ||
10353 ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
10354 (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
10355 index = 25;
10356 if(SiS_Pr->UseCustomMode) {
10357 index = SiS_Pr->CSRClock;
10358 } else if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010359 index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010360 index = SiS_Pr->SiS_VCLKData[index].CLOCK;
10361 }
10362 if(index < 25) index = 25;
10363 index = ((index / 25) - 1) << 1;
10364 if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
10365 index++;
10366 }
10367 romptr = SISGETROMW(0x104);
10368 delay = ROMAddr[romptr + index];
10369 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
10370 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10371 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10372 } else {
10373 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10374 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10375 }
10376 return;
10377 }
10378 }
10379
10380 /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
10381
10382 if(SiS_Pr->UseCustomMode) delay = 0x04;
10383 else if(ModeNo <= 0x13) delay = 0x04;
10384 else delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
10385 delay |= (delay << 8);
10386
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010387 if(SiS_Pr->ChipType >= XGI_20) {
10388
10389 delay = 0x0606;
10390 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10391
10392 delay = 0x0404;
10393 if(SiS_Pr->SiS_XGIROM) {
10394 index = GetTVPtrIndex(SiS_Pr);
10395 if((romptr = SISGETROMW(0x35e))) {
10396 delay = (ROMAddr[romptr + index] & 0x0f) << 1;
10397 delay |= (delay << 8);
10398 }
10399 }
10400
10401 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
10402 if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
10403 delay -= 0x0404;
10404 }
10405 }
10406 }
10407
10408 } else if(SiS_Pr->ChipType >= SIS_340) {
10409
10410 delay = 0x0606;
10411 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10412 delay = 0x0404;
10413 }
10414 /* TODO (eventually) */
10415
10416 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010417
10418 /* 3. TV */
10419
10420 index = GetOEMTVPtr661(SiS_Pr);
10421 if(SiS_Pr->SiS_ROMNew) {
10422 romptr = SISGETROMW(0x106);
10423 if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
10424 delay = ROMAddr[romptr + index];
10425 } else {
10426 delay = 0x04;
10427 if(index > 3) delay = 0;
10428 }
10429
10430 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10431
10432 /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
10433
10434 if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010435 ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010436
10437 lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
10438
10439 /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
10440 delay = ROMAddr[romptr + lcdpdcindex + 1]; /* LCD */
10441 delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
10442
10443 } else {
10444
10445 /* TMDS: Set our own, since BIOS has no idea */
10446 /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
10447 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10448 switch(SiS_Pr->SiS_LCDResInfo) {
10449 case Panel_1024x768: delay = 0x0008; break;
10450 case Panel_1280x720: delay = 0x0004; break;
10451 case Panel_1280x768:
10452 case Panel_1280x768_2:delay = 0x0004; break;
10453 case Panel_1280x800:
10454 case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010455 case Panel_1280x854: delay = 0x0004; break; /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010456 case Panel_1280x1024: delay = 0x1e04; break;
10457 case Panel_1400x1050: delay = 0x0004; break;
10458 case Panel_1600x1200: delay = 0x0400; break;
10459 case Panel_1680x1050: delay = 0x0e04; break;
10460 default:
10461 if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
10462 delay = 0x0008;
10463 } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
10464 delay = 0x1e04;
10465 } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
10466 delay = 0x0004;
10467 } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
10468 delay = 0x0400;
10469 } else
10470 delay = 0x0e04;
10471 break;
10472 }
10473 }
10474
10475 /* Override by detected or user-set values */
10476 /* (but only if, for some reason, we can't read value from BIOS) */
10477 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
10478 delay = SiS_Pr->PDC & 0x1f;
10479 }
10480 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
10481 delay = (SiS_Pr->PDCA & 0x1f) << 8;
10482 }
10483
10484 }
10485
10486 }
10487
10488 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10489 delay >>= 8;
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 } else {
10493 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10494 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10495 }
10496}
10497
10498static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010499SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010500{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010501 unsigned short infoflag;
10502 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010503
10504 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10505
10506 if(ModeNo <= 0x13) {
10507 infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
10508 } else if(SiS_Pr->UseCustomMode) {
10509 infoflag = SiS_Pr->CInfoFlag;
10510 } else {
10511 infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
10512 }
10513
10514 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10515 infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
10516 }
10517
10518 infoflag &= 0xc0;
10519
10520 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10521 temp = (infoflag >> 6) | 0x0c;
10522 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10523 temp ^= 0x04;
10524 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
10525 }
10526 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
10527 } else {
10528 temp = 0x30;
10529 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
10530 temp |= infoflag;
10531 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
10532 temp = 0;
10533 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10534 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
10535 }
10536 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
10537 }
10538
10539 }
10540}
10541
10542static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010543SetPanelParms661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010544{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010545 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10546 unsigned short romptr, temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010547
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010548 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
10549 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
10550 }
10551
10552 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010553 if(SiS_Pr->LVDSHL != -1) {
10554 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10555 }
10556 }
10557
10558 if(SiS_Pr->SiS_ROMNew) {
10559
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010560 if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
10561 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010562 temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
10563 temp2 = 0xfc;
10564 if(SiS_Pr->LVDSHL != -1) {
10565 temp1 &= 0xfc;
10566 temp2 = 0xf3;
10567 }
10568 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
10569 }
10570 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10571 temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
10572 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
10573 }
10574 }
10575
10576 }
10577}
10578
10579static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010580SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010581{
10582 if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010583 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010584 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010585 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10586 SetPanelParms661(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010587 }
10588 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010589 SetDelayComp(SiS_Pr,ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010590 }
10591
10592 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010593 SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
10594 SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
10595 SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010596 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010597 SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010598 }
10599 }
10600}
10601
10602static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010603SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10604 unsigned short ModeIdIndex, unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010605{
10606 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10607
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010608 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010609
10610 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010611 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10612 SetPanelParms661(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010613 }
10614
10615 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010616 SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
10617 SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
10618 SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010619 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010620 SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010621 }
10622 }
10623 }
10624}
10625
10626/* FinalizeLCD
10627 * This finalizes some CRT2 registers for the very panel used.
10628 * If we have a backup if these registers, we use it; otherwise
10629 * we set the register according to most BIOSes. However, this
10630 * function looks quite different in every BIOS, so you better
10631 * pray that we have a backup...
10632 */
10633static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010634SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010635{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010636 unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
10637 unsigned short resinfo,modeflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010638
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010639 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010640 if(SiS_Pr->SiS_ROMNew) return;
10641
10642 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10643 if(SiS_Pr->LVDSHL != -1) {
10644 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10645 }
10646 }
10647
10648 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10649 if(SiS_Pr->UseCustomMode) return;
10650
10651 switch(SiS_Pr->SiS_CustomT) {
10652 case CUT_COMPAQ1280:
10653 case CUT_COMPAQ12802:
10654 case CUT_CLEVO1400:
10655 case CUT_CLEVO14002:
10656 return;
10657 }
10658
10659 if(ModeNo <= 0x13) {
10660 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10661 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10662 } else {
10663 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10664 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10665 }
10666
10667 if(IS_SIS650) {
10668 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
10669 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10670 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
10671 } else {
10672 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
10673 }
10674 }
10675 }
10676
10677 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10678 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10679 /* Maybe all panels? */
10680 if(SiS_Pr->LVDSHL == -1) {
10681 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10682 }
10683 return;
10684 }
10685 }
10686
10687 if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
10688 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10689 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10690 if(SiS_Pr->LVDSHL == -1) {
10691 /* Maybe all panels? */
10692 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10693 }
10694 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10695 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10696 if(tempch == 3) {
10697 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10698 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10699 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10700 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10701 }
10702 }
10703 return;
10704 }
10705 }
10706 }
10707
10708 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10709 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010710 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010711 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
10712#ifdef SET_EMI
10713 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
10714#endif
10715 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
10716 }
10717 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10718 if(SiS_Pr->LVDSHL == -1) {
10719 /* Maybe ACER only? */
10720 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10721 }
10722 }
10723 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10724 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10725 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
10726 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
10727 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10728 if(tempch == 0x03) {
10729 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10730 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10731 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10732 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10733 }
10734 if((SiS_Pr->Backup == TRUE) && (SiS_Pr->Backup_Mode == ModeNo)) {
10735 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
10736 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
10737 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
10738 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
10739 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
10740 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
10741 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
10742 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
10743 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
10744 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
10745 } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { /* 1.10.8w */
10746 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
10747 if(ModeNo <= 0x13) {
10748 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
10749 if((resinfo == 0) || (resinfo == 2)) return;
10750 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
10751 if((resinfo == 1) || (resinfo == 3)) return;
10752 }
10753 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10754 if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
10755 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02); /* 1.10.7u */
10756#if 0
10757 tempbx = 806; /* 0x326 */ /* other older BIOSes */
10758 tempbx--;
10759 temp = tempbx & 0xff;
10760 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
10761 temp = (tempbx >> 8) & 0x03;
10762 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
10763#endif
10764 }
10765 } else if(ModeNo <= 0x13) {
10766 if(ModeNo <= 1) {
10767 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
10768 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
10769 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10770 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10771 }
10772 if(!(modeflag & HalfDCLK)) {
10773 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
10774 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
10775 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
10776 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
10777 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
10778 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10779 if(ModeNo == 0x12) {
10780 switch(tempch) {
10781 case 0:
10782 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10783 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10784 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
10785 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10786 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
10787 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10788 break;
10789 case 2:
10790 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10791 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10792 break;
10793 case 3:
10794 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10795 break;
10796 }
10797 }
10798 }
10799 }
10800 }
10801 } else {
10802 tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
10803 tempcl &= 0x0f;
10804 tempbh &= 0x70;
10805 tempbh >>= 4;
10806 tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
10807 tempbx = (tempbh << 8) | tempbl;
10808 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10809 if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
10810 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
10811 tempbx = 770;
10812 } else {
10813 if(tempbx > 770) tempbx = 770;
10814 if(SiS_Pr->SiS_VGAVDE < 600) {
10815 tempax = 768 - SiS_Pr->SiS_VGAVDE;
10816 tempax >>= 4; /* 1.10.7w; 1.10.6s: 3; */
10817 if(SiS_Pr->SiS_VGAVDE <= 480) tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
10818 tempbx -= tempax;
10819 }
10820 }
10821 } else return;
10822 }
10823 temp = tempbx & 0xff;
10824 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
10825 temp = ((tempbx & 0xff00) >> 4) | tempcl;
10826 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
10827 }
10828 }
10829}
10830
10831#endif
10832
10833/* ================= SiS 300 O.E.M. ================== */
10834
10835#ifdef SIS300
10836
10837static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010838SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
10839 unsigned short RefTabIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010840{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010841 unsigned short crt2crtc=0, modeflag, myindex=0;
10842 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010843 int i;
10844
10845 if(ModeNo <= 0x13) {
10846 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10847 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
10848 } else {
10849 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10850 crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
10851 }
10852
10853 crt2crtc &= 0x3f;
10854
10855 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
10856 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
10857 }
10858
10859 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
10860 if(modeflag & HalfDCLK) myindex = 1;
10861
10862 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
10863 for(i=0; i<7; i++) {
10864 if(barco_p1[myindex][crt2crtc][i][0]) {
10865 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
10866 barco_p1[myindex][crt2crtc][i][0],
10867 barco_p1[myindex][crt2crtc][i][2],
10868 barco_p1[myindex][crt2crtc][i][1]);
10869 }
10870 }
10871 }
10872 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
10873 if(temp & 0x80) {
10874 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
10875 temp++;
10876 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
10877 }
10878 }
10879}
10880
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010881static unsigned short
10882GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010883{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010884 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10885 unsigned short tempbx=0,romptr=0;
10886 static const unsigned char customtable300[] = {
10887 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010888 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10889 };
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010890 static const unsigned char customtable630[] = {
10891 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010892 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10893 };
10894
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010895 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010896
10897 tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
10898 if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
10899 tempbx -= 2;
10900 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
10901 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10902 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
10903 }
10904 if(SiS_Pr->SiS_UseROM) {
10905 if(ROMAddr[0x235] & 0x80) {
10906 tempbx = SiS_Pr->SiS_LCDTypeInfo;
10907 if(Flag) {
10908 romptr = SISGETROMW(0x255);
10909 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10910 else tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
10911 if(tempbx == 0xFF) return 0xFFFF;
10912 }
10913 tempbx <<= 1;
10914 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
10915 }
10916 }
10917
10918 } else {
10919
10920 if(Flag) {
10921 if(SiS_Pr->SiS_UseROM) {
10922 romptr = SISGETROMW(0x255);
10923 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10924 else tempbx = 0xff;
10925 } else {
10926 tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
10927 }
10928 if(tempbx == 0xFF) return 0xFFFF;
10929 tempbx <<= 2;
10930 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10931 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10932 return tempbx;
10933 }
10934 tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
10935 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10936 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10937
10938 }
10939
10940 return tempbx;
10941}
10942
10943static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010944SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010945{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010946 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10947 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010948
10949 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10950
10951 if(SiS_Pr->SiS_UseROM) {
10952 if(!(ROMAddr[0x237] & 0x01)) return;
10953 if(!(ROMAddr[0x237] & 0x02)) return;
10954 romptr = SISGETROMW(0x24b);
10955 }
10956
10957 /* The Panel Compensation Delay should be set according to tables
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010958 * here. Unfortunately, various BIOS versions don't care about
Linus Torvalds1da177e2005-04-16 15:20:36 -070010959 * a uniform way using eg. ROM byte 0x220, but use different
10960 * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010961 * Thus we don't set this if the user selected a custom pdc or if
Linus Torvalds1da177e2005-04-16 15:20:36 -070010962 * we otherwise detected a valid pdc.
10963 */
10964 if(SiS_Pr->PDC != -1) return;
10965
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010966 temp = GetOEMLCDPtr(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010967
10968 if(SiS_Pr->UseCustomMode)
10969 index = 0;
10970 else
10971 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
10972
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010973 if(SiS_Pr->ChipType != SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010974 if(romptr) {
10975 romptr += (temp * 2);
10976 romptr = SISGETROMW(romptr);
10977 romptr += index;
10978 temp = ROMAddr[romptr];
10979 } else {
10980 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10981 temp = SiS300_OEMLCDDelay2[temp][index];
10982 } else {
10983 temp = SiS300_OEMLCDDelay3[temp][index];
10984 }
10985 }
10986 } else {
10987 if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
10988 if(romptr) {
10989 romptr += (temp * 2);
10990 romptr = SISGETROMW(romptr);
10991 romptr += index;
10992 temp = ROMAddr[romptr];
10993 } else {
10994 temp = SiS300_OEMLCDDelay5[temp][index];
10995 }
10996 } else {
10997 if(SiS_Pr->SiS_UseROM) {
10998 romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
10999 if(romptr) {
11000 romptr += (temp * 2);
11001 romptr = SISGETROMW(romptr);
11002 romptr += index;
11003 temp = ROMAddr[romptr];
11004 } else {
11005 temp = SiS300_OEMLCDDelay4[temp][index];
11006 }
11007 } else {
11008 temp = SiS300_OEMLCDDelay4[temp][index];
11009 }
11010 }
11011 }
11012 temp &= 0x3c;
11013 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* index 0A D[6:4] */
11014}
11015
11016static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011017SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011018{
11019#if 0 /* Unfinished; Data table missing */
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011020 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11021 unsigned short index,temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011022
11023 if((SiS_Pr->SiS_UseROM) {
11024 if(!(ROMAddr[0x237] & 0x01)) return;
11025 if(!(ROMAddr[0x237] & 0x04)) return;
11026 /* No rom pointer in BIOS header! */
11027 }
11028
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011029 temp = GetOEMLCDPtr(SiS_Pr, 1);
11030 if(temp == 0xFFFF) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011031
11032 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
11033 for(i=0x14, j=0; i<=0x17; i++, j++) {
11034 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
11035 }
11036 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
11037
11038 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
11039 SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
11040 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
11041 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
11042 for(i=0x1b, j=3; i<=0x1d; i++, j++) {
11043 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
11044 }
11045#endif
11046}
11047
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011048static unsigned short
11049GetOEMTVPtr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011050{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011051 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011052
11053 index = 0;
11054 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) index += 4;
11055 if(SiS_Pr->SiS_VBType & VB_SISVB) {
11056 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) index += 2;
11057 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
11058 else if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
11059 } else {
11060 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
11061 if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
11062 }
11063 return index;
11064}
11065
11066static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011067SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011068{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011069 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11070 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011071
11072 if(SiS_Pr->SiS_UseROM) {
11073 if(!(ROMAddr[0x238] & 0x01)) return;
11074 if(!(ROMAddr[0x238] & 0x02)) return;
11075 romptr = SISGETROMW(0x241);
11076 }
11077
11078 temp = GetOEMTVPtr(SiS_Pr);
11079
11080 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
11081
11082 if(romptr) {
11083 romptr += (temp * 2);
11084 romptr = SISGETROMW(romptr);
11085 romptr += index;
11086 temp = ROMAddr[romptr];
11087 } else {
11088 if(SiS_Pr->SiS_VBType & VB_SISVB) {
11089 temp = SiS300_OEMTVDelay301[temp][index];
11090 } else {
11091 temp = SiS300_OEMTVDelayLVDS[temp][index];
11092 }
11093 }
11094 temp &= 0x3c;
11095 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
11096}
11097
11098static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011099SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011100{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011101 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11102 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011103
11104 if(SiS_Pr->SiS_UseROM) {
11105 if(!(ROMAddr[0x238] & 0x01)) return;
11106 if(!(ROMAddr[0x238] & 0x04)) return;
11107 romptr = SISGETROMW(0x243);
11108 }
11109
11110 temp = GetOEMTVPtr(SiS_Pr);
11111
11112 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
11113
11114 if(romptr) {
11115 romptr += (temp * 2);
11116 romptr = SISGETROMW(romptr);
11117 romptr += index;
11118 temp = ROMAddr[romptr];
11119 } else {
11120 temp = SiS300_OEMTVFlicker[temp][index];
11121 }
11122 temp &= 0x70;
11123 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
11124}
11125
11126static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011127SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011128{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011129 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11130 unsigned short index,i,j,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011131
11132 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
11133
11134 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
11135
11136 if(SiS_Pr->SiS_UseROM) {
11137 if(!(ROMAddr[0x238] & 0x01)) return;
11138 if(!(ROMAddr[0x238] & 0x08)) return;
11139 romptr = SISGETROMW(0x245);
11140 }
11141
11142 temp = GetOEMTVPtr(SiS_Pr);
11143
11144 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
11145
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011146 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070011147 for(i=0x31, j=0; i<=0x34; i++, j++) {
11148 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
11149 }
11150 } else {
11151 if(romptr) {
11152 romptr += (temp * 2);
11153 romptr = SISGETROMW(romptr);
11154 romptr += (index * 4);
11155 for(i=0x31, j=0; i<=0x34; i++, j++) {
11156 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11157 }
11158 } else {
11159 for(i=0x31, j=0; i<=0x34; i++, j++) {
11160 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
11161 }
11162 }
11163 }
11164}
11165
11166static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011167SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011168{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011169 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11170 unsigned short index,temp,i,j,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011171
11172 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
11173
11174 if(SiS_Pr->SiS_UseROM) {
11175 if(!(ROMAddr[0x238] & 0x01)) return;
11176 if(!(ROMAddr[0x238] & 0x10)) return;
11177 romptr = SISGETROMW(0x247);
11178 }
11179
11180 temp = GetOEMTVPtr(SiS_Pr);
11181
11182 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
11183 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
11184 /* NTSCJ uses NTSC filters */
11185
11186 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
11187
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011188 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070011189 for(i=0x35, j=0; i<=0x38; i++, j++) {
11190 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11191 }
11192 for(i=0x48; i<=0x4A; i++, j++) {
11193 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11194 }
11195 } else {
11196 if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
11197 romptr += (temp * 2);
11198 romptr = SISGETROMW(romptr);
11199 romptr += (index * 4);
11200 for(i=0x35, j=0; i<=0x38; i++, j++) {
11201 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11202 }
11203 } else {
11204 for(i=0x35, j=0; i<=0x38; i++, j++) {
11205 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
11206 }
11207 }
11208 }
11209}
11210
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011211static unsigned short
11212SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011213{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011214 unsigned short ModeIdIndex;
11215 unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011216
11217 if(*ModeNo <= 5) *ModeNo |= 1;
11218
11219 for(ModeIdIndex=0; ; ModeIdIndex++) {
11220 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
11221 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF) return 0;
11222 }
11223
11224 if(*ModeNo != 0x07) {
11225 if(*ModeNo > 0x03) return ModeIdIndex;
11226 if(VGAINFO & 0x80) return ModeIdIndex;
11227 ModeIdIndex++;
11228 }
11229
11230 if(VGAINFO & 0x10) ModeIdIndex++; /* 400 lines */
11231 /* else 350 lines */
11232 return ModeIdIndex;
11233}
11234
11235static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011236SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
11237 unsigned short RefTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011238{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011239 unsigned short OEMModeIdIndex = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011240
11241 if(!SiS_Pr->UseCustomMode) {
11242 OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
11243 if(!(OEMModeIdIndex)) return;
11244 }
11245
11246 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011247 SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011248 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011249 SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011250 }
11251 }
11252 if(SiS_Pr->UseCustomMode) return;
11253 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011254 SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011255 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011256 SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
11257 SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
11258 SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011259 }
11260 }
11261}
11262#endif
11263