blob: da33d801c22e0c114147335701535c2c69e45d88 [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
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800203static bool
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;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800272 if(infoflag & checkmask) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700273 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;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800282 if(infoflag & checkmask) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700283 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800284 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
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800408static bool
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);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800418 if(temp1 & temp) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700419 }
420 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800421 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422}
423
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800424static bool
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);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800434 if(temp1 & temp) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700435 }
436 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800437 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{
David Rientjesb860e732006-12-08 02:40:19 -0800448 while (delaytime-- > 0)
449 SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450}
451
452#if defined(SIS300) || defined(SIS315H)
453static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700454SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700456 SiS_DDC2Delay(SiS_Pr, delay * 36);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457}
458#endif
459
460#ifdef SIS315H
461static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700462SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700464 while(delay--) {
465 SiS_GenericDelay(SiS_Pr, 6623);
466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467}
468#endif
469
470#if defined(SIS300) || defined(SIS315H)
471static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700472SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700474 while(delay--) {
475 SiS_GenericDelay(SiS_Pr, 66);
476 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477}
478#endif
479
480static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700481SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
483#if defined(SIS300) || defined(SIS315H)
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700484 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
485 unsigned short PanelID, DelayIndex, Delay=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486#endif
487
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700488 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
490#ifdef SIS300
491
492 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
493 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700494 if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
495 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 }
497 DelayIndex = PanelID >> 4;
498 if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700499 Delay = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700501 if(DelayTime >= 2) DelayTime -= 2;
502 if(!(DelayTime & 0x01)) {
503 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
504 } else {
505 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 if(SiS_Pr->SiS_UseROM) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700508 if(ROMAddr[0x220] & 0x40) {
509 if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
510 else Delay = (unsigned short)ROMAddr[0x226];
511 }
512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 }
514 SiS_ShortDelay(SiS_Pr, Delay);
515
516#endif /* SIS300 */
517
518 } else {
519
520#ifdef SIS315H
521
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700522 if((SiS_Pr->ChipType >= SIS_661) ||
523 (SiS_Pr->ChipType <= SIS_315PRO) ||
524 (SiS_Pr->ChipType == SIS_330) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 (SiS_Pr->SiS_ROMNew)) {
526
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700527 if(!(DelayTime & 0x01)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 SiS_DDC2Delay(SiS_Pr, 0x1000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700529 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 SiS_DDC2Delay(SiS_Pr, 0x4000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700531 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
533 } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700534 (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */
536
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700537 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
538 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
540 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
541 }
542 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
543 DelayIndex = PanelID & 0x0f;
544 } else {
545 DelayIndex = PanelID >> 4;
546 }
547 if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700548 Delay = 3;
549 } else {
550 if(DelayTime >= 2) DelayTime -= 2;
551 if(!(DelayTime & 0x01)) {
552 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
553 } else {
554 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
555 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700557 if(ROMAddr[0x13c] & 0x40) {
558 if(!(DelayTime & 0x01)) {
559 Delay = (unsigned short)ROMAddr[0x17e];
560 } else {
561 Delay = (unsigned short)ROMAddr[0x17f];
562 }
563 }
564 }
565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 SiS_ShortDelay(SiS_Pr, Delay);
567 }
568
569 } else if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 315 series, all bridges */
570
571 DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700572 if(!(DelayTime & 0x01)) {
573 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
574 } else {
575 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
576 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 Delay <<= 8;
578 SiS_DDC2Delay(SiS_Pr, Delay);
579
580 }
581
582#endif /* SIS315H */
583
584 }
585}
586
587#ifdef SIS315H
588static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700589SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
591 int i;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700592 for(i = 0; i < DelayLoop; i++) {
593 SiS_PanelDelay(SiS_Pr, DelayTime);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 }
595}
596#endif
597
598/*********************************************/
599/* HELPER: WAIT-FOR-RETRACE FUNCTIONS */
600/*********************************************/
601
602void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700603SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700605 unsigned short watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700607 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
608 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700610 watchdog = 65535;
611 while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
612 watchdog = 65535;
613 while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614}
615
616#if defined(SIS300) || defined(SIS315H)
617static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700618SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700620 unsigned short watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700622 watchdog = 65535;
623 while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
624 watchdog = 65535;
625 while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626}
627#endif
628
629static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700630SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700632 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700634 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
635 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
636 }
637 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
638 SiS_WaitRetrace1(SiS_Pr);
639 } else {
640 SiS_WaitRetrace2(SiS_Pr, 0x25);
641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700643 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700645 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
646 SiS_WaitRetrace1(SiS_Pr);
647 } else {
648 SiS_WaitRetrace2(SiS_Pr, 0x30);
649 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700651 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652}
653
654static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700655SiS_VBWait(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700657 unsigned short tempal,temp,i,j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700659 temp = 0;
660 for(i = 0; i < 3; i++) {
661 for(j = 0; j < 100; j++) {
662 tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
663 if(temp & 0x01) {
664 if((tempal & 0x08)) continue;
665 else break;
666 } else {
667 if(!(tempal & 0x08)) continue;
668 else break;
669 }
670 }
671 temp ^= 0x01;
672 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673}
674
675static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700676SiS_VBLongWait(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700678 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
679 SiS_VBWait(SiS_Pr);
680 } else {
681 SiS_WaitRetrace1(SiS_Pr);
682 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683}
684
685/*********************************************/
686/* HELPER: MISC */
687/*********************************************/
688
689#ifdef SIS300
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800690static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700691SiS_Is301B(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800693 if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
694 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695}
696#endif
697
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800698static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700699SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700701 if(SiS_Pr->ChipType == SIS_730) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800702 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700703 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800704 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
705 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706}
707
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800708bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700709SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710{
711#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700712 if(SiS_Pr->ChipType >= SIS_315H) {
713 if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800714 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700715 }
716 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800718 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719}
720
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800721bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700722SiS_IsVAMode(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723{
724#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700725 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700727 if(SiS_Pr->ChipType >= SIS_315H) {
728 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800729 if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700730 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800732 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733}
734
735#ifdef SIS315H
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800736static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700737SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800739 if(SiS_IsVAMode(SiS_Pr)) return true;
740 if(SiS_CRT2IsLCD(SiS_Pr)) return true;
741 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742}
743#endif
744
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800745static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700746SiS_IsDualLink(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747{
748#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700749 if(SiS_Pr->ChipType >= SIS_315H) {
750 if((SiS_CRT2IsLCD(SiS_Pr)) ||
751 (SiS_IsVAMode(SiS_Pr))) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800752 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700753 }
754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800756 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757}
758
759#ifdef SIS315H
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800760static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700761SiS_TVEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800763 if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700764 if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800765 if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700766 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800767 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768}
769#endif
770
771#ifdef SIS315H
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800772static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700773SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800775 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
776 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777}
778#endif
779
780#ifdef SIS315H
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800781static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700782SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700784 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800785 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700786 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800787 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788}
789#endif
790
791#ifdef SIS315H
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800792static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700793SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700795 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700797 if(SiS_Pr->ChipType == SIS_650) {
798 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
799 /* Check for revision != A0 only */
800 if((flag == 0xe0) || (flag == 0xc0) ||
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800801 (flag == 0xb0) || (flag == 0x90)) return false;
802 } else if(SiS_Pr->ChipType >= SIS_661) return false;
803 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804}
805#endif
806
807#ifdef SIS315H
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800808static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700809SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700811 if(SiS_Pr->ChipType >= SIS_315H) {
812 /* YPrPb = 0x08 */
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800813 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700814 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800815 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816}
817#endif
818
819#ifdef SIS315H
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800820static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700821SiS_IsChScart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700823 if(SiS_Pr->ChipType >= SIS_315H) {
824 /* Scart = 0x04 */
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800825 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700826 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800827 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828}
829#endif
830
831#ifdef SIS315H
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800832static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700833SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700835 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700837 if(SiS_Pr->ChipType >= SIS_315H) {
838 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800839 if(flag & SetCRT2ToTV) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700840 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800841 if(flag & EnableCHYPbPr) return true; /* = YPrPb = 0x08 */
842 if(flag & EnableCHScart) return true; /* = Scart = 0x04 - TW */
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700843 } else {
844 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800845 if(flag & SetCRT2ToTV) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700846 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800847 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848}
849#endif
850
851#ifdef SIS315H
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800852static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700853SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700855 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700857 if(SiS_Pr->ChipType >= SIS_315H) {
858 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800859 if(flag & SetCRT2ToLCD) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700860 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800861 if(flag & SetToLCDA) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700862 } else {
863 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800864 if(flag & SetCRT2ToLCD) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700865 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800866 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867}
868#endif
869
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800870static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700871SiS_HaveBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700873 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700875 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800876 return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700877 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
878 flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800879 if((flag == 1) || (flag == 2)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700880 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800881 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882}
883
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800884static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700885SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700887 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700889 if(SiS_HaveBridge(SiS_Pr)) {
890 flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
891 if(SiS_Pr->ChipType < SIS_315H) {
892 flag &= 0xa0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800893 if((flag == 0x80) || (flag == 0x20)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700894 } else {
895 flag &= 0x50;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800896 if((flag == 0x40) || (flag == 0x10)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700897 }
898 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800899 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900}
901
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800902static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700903SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700905 unsigned short flag1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700907 flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800908 if(flag1 & (SetInSlaveMode >> 8)) return true;
909 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910}
911
912/*********************************************/
913/* GET VIDEO BRIDGE CONFIG INFO */
914/*********************************************/
915
916/* Setup general purpose IO for Chrontel communication */
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700917#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700919SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700921 unsigned int acpibase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 unsigned short temp;
923
924 if(!(SiS_Pr->SiS_ChSW)) return;
925
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700926#ifdef SIS_LINUX_KERNEL
927 acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928#else
929 acpibase = pciReadLong(0x00000800, 0x74);
930#endif
931 acpibase &= 0xFFFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700932 if(!acpibase) return;
933 temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 temp &= 0xFEFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700935 SiS_SetRegShort((acpibase + 0x3c), temp);
936 temp = SiS_GetRegShort((acpibase + 0x3c));
937 temp = SiS_GetRegShort((acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 temp &= 0xFEFF;
939 if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700940 SiS_SetRegShort((acpibase + 0x3a), temp);
941 temp = SiS_GetRegShort((acpibase + 0x3a));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942}
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700943#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
945void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700946SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
947 unsigned short ModeIdIndex, int checkcrt2mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700949 unsigned short tempax, tempbx, temp;
950 unsigned short modeflag, resinfo = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700952 SiS_Pr->SiS_SetFlag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700954 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700956 SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700958 if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
959 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
960 }
961
962 tempbx = 0;
963
964 if(SiS_HaveBridge(SiS_Pr)) {
965
966 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
967 tempbx |= temp;
968 tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
969 tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
970 tempbx |= tempax;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
972#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700973 if(SiS_Pr->ChipType >= SIS_315H) {
974 if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 if(ModeNo == 0x03) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700976 /* Mode 0x03 is never in driver mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
978 }
979 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700980 /* Reset LCDA setting if not driver mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
982 }
983 if(IS_SIS650) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700984 if(SiS_Pr->SiS_UseLCDA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
986 if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700987 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 }
989 }
990 }
991 }
992 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700993 if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
994 tempbx |= SetCRT2ToLCDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 }
996 }
997
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700998 if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001000 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
1001 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
1002 if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
1003 else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1004 tempbx |= SetCRT2ToYPbPr525750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 }
1006 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
1009 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1010 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1011 if(temp & SetToLCDA) {
1012 tempbx |= SetCRT2ToLCDA;
1013 }
1014 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001015 if(temp & EnableCHYPbPr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 tempbx |= SetCRT2ToCHYPbPr;
1017 }
1018 }
1019 }
1020 }
1021
1022#endif /* SIS315H */
1023
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001024 if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
1025 tempbx &= ~(SetCRT2ToRAMDAC);
1026 }
1027
1028 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 temp = SetCRT2ToSVIDEO |
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001030 SetCRT2ToAVIDEO |
1031 SetCRT2ToSCART |
1032 SetCRT2ToLCDA |
1033 SetCRT2ToLCD |
1034 SetCRT2ToRAMDAC |
1035 SetCRT2ToHiVision |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 SetCRT2ToYPbPr525750;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001037 } else {
1038 if(SiS_Pr->ChipType >= SIS_315H) {
1039 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1040 temp = SetCRT2ToAVIDEO |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 SetCRT2ToSVIDEO |
1042 SetCRT2ToSCART |
1043 SetCRT2ToLCDA |
1044 SetCRT2ToLCD |
1045 SetCRT2ToCHYPbPr;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001046 } else {
1047 temp = SetCRT2ToLCDA |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 SetCRT2ToLCD;
1049 }
1050 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001051 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1052 temp = SetCRT2ToTV | SetCRT2ToLCD;
1053 } else {
1054 temp = SetCRT2ToLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 }
1056 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001057 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001059 if(!(tempbx & temp)) {
1060 tempax = DisableCRT2Display;
1061 tempbx = 0;
1062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001064 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1065
1066 unsigned short clearmask = ( DriverMode |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 DisableCRT2Display |
1068 LoadDACFlag |
1069 SetNotSimuMode |
1070 SetInSlaveMode |
1071 SetPALTV |
1072 SwitchCRT2 |
1073 SetSimuScanMode );
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001074
1075 if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 if(tempbx & SetCRT2ToRAMDAC) tempbx &= (clearmask | SetCRT2ToRAMDAC);
1077 if(tempbx & SetCRT2ToLCD) tempbx &= (clearmask | SetCRT2ToLCD);
1078 if(tempbx & SetCRT2ToSCART) tempbx &= (clearmask | SetCRT2ToSCART);
1079 if(tempbx & SetCRT2ToHiVision) tempbx &= (clearmask | SetCRT2ToHiVision);
1080 if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001081
1082 } else {
1083
1084 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 if(tempbx & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001086 tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 }
1088 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001089 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1090 if(tempbx & SetCRT2ToTV) {
1091 tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001094 if(tempbx & SetCRT2ToLCD) {
1095 tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
1096 }
1097 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 if(tempbx & SetCRT2ToLCDA) {
1099 tempbx |= SetCRT2ToLCD;
1100 }
1101 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001102
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 }
1104
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001105 if(tempax & DisableCRT2Display) {
1106 if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1107 tempbx = SetSimuScanMode | DisableCRT2Display;
1108 }
1109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001111 if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
1113 /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
1114 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
1115 if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
1116 ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001117 modeflag &= (~CRT2Mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 }
1119 }
1120
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001121 if(!(tempbx & SetSimuScanMode)) {
1122 if(tempbx & SwitchCRT2) {
1123 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1124 if(resinfo != SIS_RI_1600x1200) {
1125 tempbx |= SetSimuScanMode;
1126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001128 } else {
1129 if(SiS_BridgeIsEnabled(SiS_Pr)) {
1130 if(!(tempbx & DriverMode)) {
1131 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 tempbx |= SetSimuScanMode;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001133 }
1134 }
1135 }
1136 }
1137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001139 if(!(tempbx & DisableCRT2Display)) {
1140 if(tempbx & DriverMode) {
1141 if(tempbx & SetSimuScanMode) {
1142 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1143 if(resinfo != SIS_RI_1600x1200) {
1144 tempbx |= SetInSlaveMode;
1145 }
1146 }
1147 }
1148 } else {
1149 tempbx |= SetInSlaveMode;
1150 }
1151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001155 SiS_Pr->SiS_VBInfo = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001157#ifdef SIS300
1158 if(SiS_Pr->ChipType == SIS_630) {
1159 SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1160 }
1161#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001163#ifdef SIS_LINUX_KERNEL
1164#if 0
1165 printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1167#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001168#endif
1169#ifdef SIS_XORG_XF86
1170#ifdef TWDEBUG
1171 xf86DrvMsg(0, X_PROBED, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1173#endif
1174#endif
1175}
1176
1177/*********************************************/
1178/* DETERMINE YPbPr MODE */
1179/*********************************************/
1180
1181void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001182SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183{
1184
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001185 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001187 /* Note: This variable is only used on 30xLV systems.
1188 * CR38 has a different meaning on LVDS/CH7019 systems.
1189 * On 661 and later, these bits moved to CR35.
1190 *
1191 * On 301, 301B, only HiVision 1080i is supported.
1192 * On 30xLV, 301C, only YPbPr 1080i is supported.
1193 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001195 SiS_Pr->SiS_YPbPr = 0;
1196 if(SiS_Pr->ChipType >= SIS_661) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001198 if(SiS_Pr->SiS_VBType) {
1199 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1200 SiS_Pr->SiS_YPbPr = YPbPrHiVision;
1201 }
1202 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001204 if(SiS_Pr->ChipType >= SIS_315H) {
1205 if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1206 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1207 if(temp & 0x08) {
1208 switch((temp >> 4)) {
1209 case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break;
1210 case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break;
1211 case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break;
1212 case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
1213 }
1214 }
1215 }
1216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218}
1219
1220/*********************************************/
1221/* DETERMINE TVMode flag */
1222/*********************************************/
1223
1224void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001225SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001227 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1228 unsigned short temp, temp1, resinfo = 0, romindex = 0;
1229 unsigned char OutputSelect = *SiS_Pr->pSiS_OutputSelect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001231 SiS_Pr->SiS_TVMode = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001233 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
1234 if(SiS_Pr->UseCustomMode) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001236 if(ModeNo > 0x13) {
1237 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001240 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001242 if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001244 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1245 temp = 0;
1246 if((SiS_Pr->ChipType == SIS_630) ||
1247 (SiS_Pr->ChipType == SIS_730)) {
1248 temp = 0x35;
1249 romindex = 0xfe;
1250 } else if(SiS_Pr->ChipType >= SIS_315H) {
1251 temp = 0x38;
1252 if(SiS_Pr->ChipType < XGI_20) {
1253 romindex = 0xf3;
1254 if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
1255 }
1256 }
1257 if(temp) {
1258 if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
1259 OutputSelect = ROMAddr[romindex];
1260 if(!(OutputSelect & EnablePALMN)) {
1261 SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
1262 }
1263 }
1264 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
1265 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1266 if(temp1 & EnablePALM) { /* 0x40 */
1267 SiS_Pr->SiS_TVMode |= TVSetPALM;
1268 SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1269 } else if(temp1 & EnablePALN) { /* 0x80 */
1270 SiS_Pr->SiS_TVMode |= TVSetPALN;
1271 }
1272 } else {
1273 if(temp1 & EnableNTSCJ) { /* 0x40 */
1274 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1275 }
1276 }
1277 }
1278 /* Translate HiVision/YPbPr to our new flags */
1279 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1280 if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1281 else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1282 else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
1283 else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1284 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
1285 SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
1286 SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
1287 } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
1288 SiS_Pr->SiS_TVMode |= TVSetPAL;
1289 }
1290 }
1291 } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1292 if(SiS_Pr->SiS_CHOverScan) {
1293 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
1294 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1295 if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
1296 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1297 }
1298 } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1299 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
1300 if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
1301 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1302 }
1303 }
1304 if(SiS_Pr->SiS_CHSOverScan) {
1305 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1306 }
1307 }
1308 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1309 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1310 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1311 if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM;
1312 else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
1313 } else {
1314 if(temp & EnableNTSCJ) {
1315 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1316 }
1317 }
1318 }
1319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001321 } else { /* 661 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001323 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1324 if(temp1 & 0x01) {
1325 SiS_Pr->SiS_TVMode |= TVSetPAL;
1326 if(temp1 & 0x08) {
1327 SiS_Pr->SiS_TVMode |= TVSetPALN;
1328 } else if(temp1 & 0x04) {
1329 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1330 SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1331 }
1332 SiS_Pr->SiS_TVMode |= TVSetPALM;
1333 }
1334 } else {
1335 if(temp1 & 0x02) {
1336 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1337 }
1338 }
1339 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1340 if(SiS_Pr->SiS_CHOverScan) {
1341 if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
1342 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1343 }
1344 }
1345 }
1346 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1347 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1348 temp1 &= 0xe0;
1349 if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1350 else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1351 else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1352 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1353 SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
1354 }
1355 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
1356 if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
1357 SiS_Pr->SiS_TVMode |= TVAspect169;
1358 } else {
1359 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
1360 if(temp1 & 0x02) {
1361 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
1362 SiS_Pr->SiS_TVMode |= TVAspect169;
1363 } else {
1364 SiS_Pr->SiS_TVMode |= TVAspect43LB;
1365 }
1366 } else {
1367 SiS_Pr->SiS_TVMode |= TVAspect43;
1368 }
1369 }
1370 }
1371 }
1372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001374 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001376 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001378 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1379 SiS_Pr->SiS_TVMode |= TVSetPAL;
1380 SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
1381 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1382 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
1383 SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
1384 }
1385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001387 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1388 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
1389 SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1390 }
1391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001393 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
1394 if(resinfo == SIS_RI_1024x768) {
1395 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
1396 SiS_Pr->SiS_TVMode |= TVSet525p1024;
1397 } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
1398 SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
1399 }
1400 }
1401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001403 SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
1404 if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
1405 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
1406 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1407 } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
1408 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1409 } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
1410 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
1411 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1412 }
1413 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001415 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001417 SiS_Pr->SiS_VBInfo &= ~SetPALTV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001419#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420#ifdef TWDEBUG
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001421 xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
1422#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423#endif
1424}
1425
1426/*********************************************/
1427/* GET LCD INFO */
1428/*********************************************/
1429
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001430static unsigned short
1431SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001433 unsigned short temp = SiS_Pr->SiS_LCDResInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 /* Translate my LCDResInfo to BIOS value */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001435 switch(temp) {
1436 case Panel_1280x768_2: temp = Panel_1280x768; break;
1437 case Panel_1280x800_2: temp = Panel_1280x800; break;
1438 case Panel_1280x854: temp = Panel661_1280x854; break;
1439 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 return temp;
1441}
1442
1443static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001444SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445{
1446#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001447 unsigned char *ROMAddr;
1448 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001450#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451#ifdef TWDEBUG
1452 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 -07001453 SiS_Pr->PanelHT, SiS_Pr->PanelVT,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1455 SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1456 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1457 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1458 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1459#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001460#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001462 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001464 SiS_Pr->SiS_NeedRomModeData = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 SiS_Pr->PanelHT = temp;
1466 }
1467 if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001468 SiS_Pr->SiS_NeedRomModeData = true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001469 SiS_Pr->PanelVT = temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 }
1471 SiS_Pr->PanelHRS = SISGETROMW(10);
1472 SiS_Pr->PanelHRE = SISGETROMW(12);
1473 SiS_Pr->PanelVRS = SISGETROMW(14);
1474 SiS_Pr->PanelVRE = SISGETROMW(16);
1475 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1476 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001477 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
1479 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
1480 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
1481 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
1482
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001483#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484#ifdef TWDEBUG
1485 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 -07001486 SiS_Pr->PanelHT, SiS_Pr->PanelVT,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1488 SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1489 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1490 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1491 SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1492#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001493#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
1495 }
1496#endif
1497}
1498
1499static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001500SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
1501 const unsigned char *nonscalingmodes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001503 int i = 0;
1504 while(nonscalingmodes[i] != 0xff) {
1505 if(nonscalingmodes[i++] == resinfo) {
1506 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
1507 (SiS_Pr->UsePanelScaler == -1)) {
1508 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1509 }
1510 break;
1511 }
1512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513}
1514
1515void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001516SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001518 unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001519 bool panelcanscale = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001521 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1522 static const unsigned char SiS300SeriesLCDRes[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 { 0, 1, 2, 3, 7, 4, 5, 8,
1524 0, 0, 10, 0, 0, 0, 0, 15 };
1525#endif
1526#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001527 unsigned char *myptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
1530 SiS_Pr->SiS_LCDResInfo = 0;
1531 SiS_Pr->SiS_LCDTypeInfo = 0;
1532 SiS_Pr->SiS_LCDInfo = 0;
1533 SiS_Pr->PanelHRS = 999; /* HSync start */
1534 SiS_Pr->PanelHRE = 999; /* HSync end */
1535 SiS_Pr->PanelVRS = 999; /* VSync start */
1536 SiS_Pr->PanelVRE = 999; /* VSync end */
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001537 SiS_Pr->SiS_NeedRomModeData = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001539 /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001540 SiS_Pr->Alternate1600x1200 = false;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001541
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
1543
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001544 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1545
1546 if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1548 modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
1549 modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
1550 }
1551
1552 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
1553
1554 /* For broken BIOSes: Assume 1024x768 */
1555 if(temp == 0) temp = 0x02;
1556
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001557 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001559 } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
1561 } else {
1562 SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1563 }
1564 temp &= 0x0f;
1565#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001566 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
1568 if(SiS_Pr->SiS_VBType & VB_SIS301) {
1569 if(temp < 0x0f) temp &= 0x07;
1570 }
1571 /* Translate 300 series LCDRes to 315 series for unified usage */
1572 temp = SiS300SeriesLCDRes[temp];
1573 }
1574#endif
1575
1576 /* Translate to our internal types */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001577#ifdef SIS315H
1578 if(SiS_Pr->ChipType == SIS_550) {
1579 if (temp == Panel310_1152x768) temp = Panel_320x240_2; /* Verified working */
1580 else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
1581 else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
1582 } else if(SiS_Pr->ChipType >= SIS_661) {
1583 if(temp == Panel661_1280x854) temp = Panel_1280x854;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001585#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001587 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 if(temp == Panel310_1280x768) {
1589 temp = Panel_1280x768_2;
1590 }
1591 if(SiS_Pr->SiS_ROMNew) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001592 if(temp == Panel661_1280x800) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 temp = Panel_1280x800_2;
1594 }
1595 }
1596 }
1597
1598 SiS_Pr->SiS_LCDResInfo = temp;
1599
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001600#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1602 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001603 SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001605 SiS_Pr->SiS_LCDResInfo = Panel_848x480;
1606 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
1607 SiS_Pr->SiS_LCDResInfo = Panel_856x480;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 }
1609 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001610#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
1612 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1613 if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
1614 SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
1615 } else {
1616 if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
1617 SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
1618 }
1619
1620 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
1621 SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
1622 /* Need temp below! */
1623
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001624 /* These must/can't scale no matter what */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001626 case Panel_320x240_1:
1627 case Panel_320x240_2:
1628 case Panel_320x240_3:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 case Panel_1280x960:
1630 SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001631 break;
1632 case Panel_640x480:
1633 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 }
1635
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001636 panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637
1638 if(!SiS_Pr->UsePanelScaler) SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1639 else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1640
1641 /* Dual link, Pass 1:1 BIOS default, etc. */
1642#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001643 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001645 if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001647 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1648 if(SiS_Pr->SiS_ROMNew) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001650 } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
1651 if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 }
1653 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001654 } else if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001656 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 }
1658 if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001659 SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001661 if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
1662 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1664 }
1665 } else if(!(SiS_Pr->SiS_ROMNew)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001666 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1667 if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
1669 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1670 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001671 if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001673 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
1675 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1676 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 }
1679 }
1680#endif
1681
1682 /* Pass 1:1 */
1683 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
1684 /* Always center screen on LVDS (if scaling is disabled) */
1685 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1686 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1687 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001688 /* Always center screen on SiS LVDS (if scaling is disabled) */
1689 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001691 /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
1692 if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1693 if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 }
1695 }
1696
1697 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1698 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1699
1700 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001701 case Panel_320x240_1:
1702 case Panel_320x240_2:
1703 case Panel_320x240_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
1704 SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 SiS_Pr->PanelVCLKIdx300 = VCLK28;
1706 SiS_Pr->PanelVCLKIdx315 = VCLK28;
1707 break;
1708 case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001709 SiS_Pr->PanelVRE = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 SiS_Pr->PanelVCLKIdx300 = VCLK28;
1711 SiS_Pr->PanelVCLKIdx315 = VCLK28;
1712 break;
1713 case Panel_800x600: SiS_Pr->PanelXRes = 800; SiS_Pr->PanelYRes = 600;
1714 SiS_Pr->PanelHT = 1056; SiS_Pr->PanelVT = 628;
1715 SiS_Pr->PanelHRS = 40; SiS_Pr->PanelHRE = 128;
1716 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 4;
1717 SiS_Pr->PanelVCLKIdx300 = VCLK40;
1718 SiS_Pr->PanelVCLKIdx315 = VCLK40;
1719 break;
1720 case Panel_1024x600: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 600;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001721 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1723 SiS_Pr->PanelVRS = 2 /* 88 */ ; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001724 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001726 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001728 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1730 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001731 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 SiS_Pr->PanelHRS = 23;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001733 SiS_Pr->PanelVRE = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 }
1735 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1736 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001737 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 break;
1739 case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001740 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
1741 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001743 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 SiS_Pr->PanelHRS = 23;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001745 SiS_Pr->PanelVRE = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001747 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001749 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001751 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 case Panel_1280x720: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 720;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001753 SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 SiS_Pr->PanelHRS = 110; SiS_Pr->PanelHRE = 40;
1755 SiS_Pr->PanelVRS = 5; SiS_Pr->PanelVRE = 5;
1756 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
1757 /* Data above for TMDS (projector); get from BIOS for LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001758 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 break;
1760 case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001761 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 806;
1763 SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
1764 SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
1765 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001766 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRS = 112;
1768 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1769 SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
1770 SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
1771 }
1772 break;
1773 case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001774 SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1776 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1777 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001778 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 break;
1780 case Panel_1280x800: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001781 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 SiS_Pr->PanelHRS = 21; SiS_Pr->PanelHRE = 24;
1783 SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
1784 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001785 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 break;
1787 case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001788 SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1790 SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
1791 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001792 SiS_GetLCDInfoBIOS(SiS_Pr);
1793 break;
1794 case Panel_1280x854: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 854;
1795 SiS_Pr->PanelHT = 1664; SiS_Pr->PanelVT = 861;
1796 SiS_Pr->PanelHRS = 16; SiS_Pr->PanelHRE = 112;
1797 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1798 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
1799 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 break;
1801 case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001802 SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1804 SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001805 if(resinfo == SIS_RI_1280x1024) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
1807 SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
1808 }
1809 break;
1810 case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001811 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1813 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1814 SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1815 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001816 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 break;
1818 case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001819 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1820 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1822 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001823 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 break;
1825 case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001826 SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 SiS_Pr->PanelHRS = 64; SiS_Pr->PanelHRE = 192;
1828 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1829 SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001830 if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
1831 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1832 SiS_Pr->PanelHT = 1760; SiS_Pr->PanelVT = 1235;
1833 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 32;
1834 SiS_Pr->PanelVRS = 2; SiS_Pr->PanelVRE = 4;
1835 SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001836 SiS_Pr->Alternate1600x1200 = true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001837 }
1838 } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
1839 SiS_Pr->PanelHT = 2048; SiS_Pr->PanelVT = 1320;
1840 SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
1841 SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
1842 }
1843 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 break;
1845 case Panel_1680x1050: SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001846 SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 SiS_Pr->PanelHRS = 26; SiS_Pr->PanelHRE = 76;
1848 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1849 SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001850 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 break;
1852 case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001853 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1854 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001856 SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
1857 break;
1858 case Panel_856x480: SiS_Pr->PanelXRes = 856; SiS_Pr->PanelYRes = 480;
1859 SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
1860 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001862 SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 SiS_Pr->PanelHT = SiS_Pr->CHTotal;
1864 SiS_Pr->PanelVT = SiS_Pr->CVTotal;
1865 if(SiS_Pr->CP_PreferredIndex != -1) {
1866 SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001867 SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 SiS_Pr->PanelHT = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
1869 SiS_Pr->PanelVT = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
1870 SiS_Pr->PanelHRS = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
1871 SiS_Pr->PanelHRE = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
1872 SiS_Pr->PanelVRS = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
1873 SiS_Pr->PanelVRE = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
1874 SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
1875 SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
1876 SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
1877 SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
1878 if(SiS_Pr->CP_PrefClock) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001879 int idx;
1880 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001882 if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 else idx = VCLK_CUSTOM_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001884 SiS_Pr->SiS_VCLKData[idx].CLOCK =
1885 SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
1886 SiS_Pr->SiS_VCLKData[idx].SR2B =
1887 SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
1888 SiS_Pr->SiS_VCLKData[idx].SR2C =
1889 SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 }
1891 }
1892 break;
1893 default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001894 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 break;
1896 }
1897
1898 /* Special cases */
1899 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
1900 (SiS_Pr->SiS_IF_DEF_DSTN) ||
1901 (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1902 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001903 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1904 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 SiS_Pr->PanelHRS = 999;
1906 SiS_Pr->PanelHRE = 999;
1907 }
1908
1909 if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1910 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001911 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1912 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 SiS_Pr->PanelVRS = 999;
1914 SiS_Pr->PanelVRE = 999;
1915 }
1916
1917 /* DontExpand overrule */
1918 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
1919
1920 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
1921 /* No scaling for this mode on any panel (LCD=CRT2)*/
1922 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1923 }
1924
1925 switch(SiS_Pr->SiS_LCDResInfo) {
1926
1927 case Panel_Custom:
1928 case Panel_1152x864:
1929 case Panel_1280x768: /* TMDS only */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001930 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 break;
1932
1933 case Panel_800x600: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001934 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
1936 };
1937 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1938 break;
1939 }
1940 case Panel_1024x768: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001941 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1943 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1944 0xff
1945 };
1946 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1947 break;
1948 }
1949 case Panel_1280x720: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001950 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1952 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1953 0xff
1954 };
1955 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1956 if(SiS_Pr->PanelHT == 1650) {
1957 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1958 }
1959 break;
1960 }
1961 case Panel_1280x768_2: { /* LVDS only */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001962 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1964 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1965 SIS_RI_1152x768,0xff
1966 };
1967 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1968 switch(resinfo) {
1969 case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001970 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1971 }
1972 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001974 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 }
1976 case Panel_1280x800: { /* SiS TMDS special (Averatec 6200 series) */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001977 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1979 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1980 SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
1981 };
1982 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001983 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 }
1985 case Panel_1280x800_2: { /* SiS LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001986 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1988 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1989 SIS_RI_1152x768,0xff
1990 };
1991 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1992 switch(resinfo) {
1993 case SIS_RI_1280x720:
1994 case SIS_RI_1280x768: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001995 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1996 }
1997 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001999 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002001 case Panel_1280x854: { /* SiS LVDS */
2002 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2004 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002005 SIS_RI_1152x768,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 };
2007 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002008 switch(resinfo) {
2009 case SIS_RI_1280x720:
2010 case SIS_RI_1280x768:
2011 case SIS_RI_1280x800: if(SiS_Pr->UsePanelScaler == -1) {
2012 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2013 }
2014 break;
2015 }
2016 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002018 case Panel_1280x960: {
2019 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2021 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2022 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002023 SIS_RI_1280x854,0xff
2024 };
2025 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2026 break;
2027 }
2028 case Panel_1280x1024: {
2029 static const unsigned char nonscalingmodes[] = {
2030 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2031 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2032 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2033 SIS_RI_1280x854,SIS_RI_1280x960,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 };
2035 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2036 break;
2037 }
2038 case Panel_1400x1050: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002039 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2041 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002042 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
2043 SIS_RI_1280x960,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 };
2045 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002046 switch(resinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002048 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2049 }
2050 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002052 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 }
2054 break;
2055 }
2056 case Panel_1600x1200: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002057 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2059 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2060 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002061 SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 };
2063 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002064 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 }
2066 case Panel_1680x1050: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002067 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2069 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002070 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
2071 SIS_RI_1360x1024,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 };
2073 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2074 break;
2075 }
2076 }
2077 }
2078
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002079#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002081 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2082 SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 }
2084 }
2085
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002086 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002088 if(SiS_Pr->SiS_UseROM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002090 if(!(ROMAddr[0x235] & 0x02)) {
2091 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002094 }
2095 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002097 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 }
2099 }
2100 }
2101#endif
2102
2103 /* Special cases */
2104
2105 if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
2106 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2107 }
2108
2109 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
2110 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2111 }
2112
2113 switch(SiS_Pr->SiS_LCDResInfo) {
2114 case Panel_640x480:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002115 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 break;
2117 case Panel_1280x800:
2118 /* Don't pass 1:1 by default (TMDS special) */
2119 if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2120 break;
2121 case Panel_1280x960:
2122 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2123 break;
2124 case Panel_Custom:
2125 if((!SiS_Pr->CP_PrefClock) ||
2126 (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
2127 SiS_Pr->SiS_LCDInfo |= LCDPass11;
2128 }
2129 break;
2130 }
2131
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002132 if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2134 }
2135
2136 /* (In)validate LCDPass11 flag */
2137 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2138 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2139 }
2140
2141 /* LVDS DDA */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002142 if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143
2144 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
2145 if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
2146 if(ModeNo == 0x12) {
2147 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002148 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 }
2150 } else if(ModeNo > 0x13) {
2151 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002152 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2153 if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
2154 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 }
2156 }
2157 }
2158 }
2159 }
2160 }
2161
2162 if(modeflag & HalfDCLK) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002163 if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002165 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2167 } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
2168 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2169 } else if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002170 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
2171 if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2172 } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
2173 if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2174 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 }
2176 }
2177
2178 }
2179
2180 /* VESA timing */
2181 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2182 if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002183 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 }
2185 } else {
2186 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2187 }
2188
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002189#ifdef SIS_LINUX_KERNEL
2190#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
2192 SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
2193#endif
2194#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002195#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 xf86DrvMsgVerb(0, X_PROBED, 4,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002197 "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
2199#endif
2200}
2201
2202/*********************************************/
2203/* GET VCLK */
2204/*********************************************/
2205
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002206unsigned short
2207SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2208 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002210 unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
2211 unsigned short modeflag, resinfo, tempbx;
2212 const unsigned char *CHTVVCLKPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213
2214 if(ModeNo <= 0x13) {
2215 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2216 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
2217 CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2218 VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002219 VCLKIndexGENCRT = VCLKIndexGEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 } else {
2221 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2222 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2223 CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2224 VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002225 VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
2226 (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 }
2228
2229 if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 30x/B/LV */
2230
2231 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2232
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002233 CRT2Index >>= 6;
2234 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002236 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2238 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002239 VCLKIndex = VCLKIndexGEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 }
2241 } else {
2242 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2243 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2244 switch(resinfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002245 /* Correct those whose IndexGEN doesn't match VBVCLK array */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 case SIS_RI_720x480: VCLKIndex = VCLK_720x480; break;
2247 case SIS_RI_720x576: VCLKIndex = VCLK_720x576; break;
2248 case SIS_RI_768x576: VCLKIndex = VCLK_768x576; break;
2249 case SIS_RI_848x480: VCLKIndex = VCLK_848x480; break;
2250 case SIS_RI_856x480: VCLKIndex = VCLK_856x480; break;
2251 case SIS_RI_800x480: VCLKIndex = VCLK_800x480; break;
2252 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
2253 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002254 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
2256 default: VCLKIndex = VCLKIndexGEN;
2257 }
2258
2259 if(ModeNo <= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002260 if(SiS_Pr->ChipType <= SIS_315PRO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002262 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
2264 }
2265 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002266 if(SiS_Pr->ChipType <= SIS_315PRO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 if(VCLKIndex == 0) VCLKIndex = 0x41;
2268 if(VCLKIndex == 1) VCLKIndex = 0x43;
2269 if(VCLKIndex == 4) VCLKIndex = 0x44;
2270 }
2271 }
2272 }
2273
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002274 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
2276 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002277 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
2278 else VCLKIndex = HiTVVCLK;
2279 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) VCLKIndex = HiTVSimuVCLK;
2280 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK;
2281 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2;
2282 else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
2283 else VCLKIndex = TVVCLK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002285 if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
2286 else VCLKIndex += TVCLKBASE_315;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002288 } else { /* VGA2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002290 VCLKIndex = VCLKIndexGENCRT;
2291 if(SiS_Pr->ChipType < SIS_315H) {
2292 if(ModeNo > 0x13) {
2293 if( (SiS_Pr->ChipType == SIS_630) &&
2294 (SiS_Pr->ChipRevision >= 0x30)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 if(VCLKIndex == 0x14) VCLKIndex = 0x34;
2296 }
2297 /* Better VGA2 clock for 1280x1024@75 */
2298 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
2299 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002300 }
2301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
2303 } else { /* If not programming CRT2 */
2304
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002305 VCLKIndex = VCLKIndexGENCRT;
2306 if(SiS_Pr->ChipType < SIS_315H) {
2307 if(ModeNo > 0x13) {
2308 if( (SiS_Pr->ChipType != SIS_630) &&
2309 (SiS_Pr->ChipType != SIS_300) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2311 }
2312 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 }
2315
2316 } else { /* LVDS */
2317
2318 VCLKIndex = CRT2Index;
2319
2320 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2321
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002322 if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
2324 VCLKIndex &= 0x1f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002325 tempbx = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002327 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 tempbx += 2;
2329 if(SiS_Pr->SiS_ModeType > ModeVGA) {
2330 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
2331 }
2332 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2333 tempbx = 4;
2334 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2335 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2336 tempbx = 6;
2337 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2338 }
2339 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002340 switch(tempbx) {
2341 case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break;
2342 case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break;
2343 case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break;
2344 case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 case 4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002346 case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break;
2347 case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break;
2348 case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 case 8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL; break;
2350 default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002351 }
2352 VCLKIndex = CHTVVCLKPtr[VCLKIndex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002354 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002356 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2358 } else {
2359 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2360 }
2361
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002362#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 /* Special Timing: Barco iQ Pro R series */
2364 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2365
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002366 /* Special Timing: 848x480 and 856x480 parallel lvds panels */
2367 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2368 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 VCLKIndex = VCLK34_300;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002370 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 } else {
2372 VCLKIndex = VCLK34_315;
2373 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2374 }
2375 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002376#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002378 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002380 VCLKIndex = VCLKIndexGENCRT;
2381 if(SiS_Pr->ChipType < SIS_315H) {
2382 if(ModeNo > 0x13) {
2383 if( (SiS_Pr->ChipType == SIS_630) &&
2384 (SiS_Pr->ChipRevision >= 0x30) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002386 }
2387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390
2391 } else { /* if not programming CRT2 */
2392
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002393 VCLKIndex = VCLKIndexGENCRT;
2394 if(SiS_Pr->ChipType < SIS_315H) {
2395 if(ModeNo > 0x13) {
2396 if( (SiS_Pr->ChipType != SIS_630) &&
2397 (SiS_Pr->ChipType != SIS_300) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2399 }
2400#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002401 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 if(VCLKIndex == 0x0b) VCLKIndex = 0x40; /* 1024x768-70 */
2403 if(VCLKIndex == 0x0d) VCLKIndex = 0x41; /* 1024x768-75 */
2404 }
2405#endif
2406 }
2407 }
2408
2409 }
2410
2411 }
2412
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002413#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414#ifdef TWDEBUG
2415 xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
2416#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002417#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002419 return VCLKIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420}
2421
2422/*********************************************/
2423/* SET CRT2 MODE TYPE REGISTERS */
2424/*********************************************/
2425
2426static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002427SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002429 unsigned short i, j, modeflag, tempah=0;
2430 short tempcl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431#if defined(SIS300) || defined(SIS315H)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002432 unsigned short tempbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433#endif
2434#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002435 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
2436 unsigned short tempah2, tempbl2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437#endif
2438
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002439 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
2441 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2442
2443 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
2444 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
2445
2446 } else {
2447
2448 for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002449 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
2451 }
2452
2453 tempcl = SiS_Pr->SiS_ModeType;
2454
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002455 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
2457#ifdef SIS300 /* ---- 300 series ---- */
2458
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002459 /* For 301BDH: (with LCD via LVDS) */
2460 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
2462 tempbl &= 0xef;
2463 tempbl |= 0x02;
2464 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2465 tempbl |= 0x10;
2466 tempbl &= 0xfd;
2467 }
2468 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002469 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002471 if(ModeNo > 0x13) {
2472 tempcl -= ModeVGA;
2473 if(tempcl >= 0) {
2474 tempah = ((0x10 >> tempcl) | 0x80);
2475 }
2476 } else tempah = 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002478 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479
2480#endif /* SIS300 */
2481
2482 } else {
2483
2484#ifdef SIS315H /* ------- 315/330 series ------ */
2485
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002486 if(ModeNo > 0x13) {
2487 tempcl -= ModeVGA;
2488 if(tempcl >= 0) {
2489 tempah = (0x08 >> tempcl);
2490 if (tempah == 0) tempah = 1;
2491 tempah |= 0x40;
2492 }
2493 } else tempah = 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002495 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496
2497#endif /* SIS315H */
2498
2499 }
2500
2501 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2502
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002503 if(SiS_Pr->ChipType < SIS_315H) {
2504 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002506#ifdef SIS315H
2507 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2508 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2509 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2510 if(IS_SIS740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2512 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002513 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002515 }
2516#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 }
2518
2519 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2520
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002521 tempah = 0x01;
2522 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2523 tempah |= 0x02;
2524 }
2525 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2526 tempah ^= 0x05;
2527 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
2528 tempah ^= 0x01;
2529 }
2530 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002532 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002534 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002536 tempah = (tempah << 5) & 0xFF;
2537 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2538 tempah = (tempah >> 5) & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002540 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002542 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x08;
2543 else if(!(SiS_IsDualEdge(SiS_Pr))) tempah |= 0x08;
2544 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
2545 tempah &= ~0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002549 if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
2550 tempah |= 0x10;
2551 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552
2553 tempah |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002554 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002558 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002560 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2561 tempah |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002563 }
2564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002566 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
2568 tempah = 0x80;
2569 if(SiS_Pr->SiS_VBType & VB_SIS301) {
2570 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
2571 }
2572
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002573 if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002575 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002577 tempah |= 0x40;
2578 }
2579 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002581 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
2583 } else { /* LVDS */
2584
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002585 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
2587#ifdef SIS315H
2588 /* LVDS can only be slave in 8bpp modes */
2589 tempah = 0x80;
2590 if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
2591 if(SiS_Pr->SiS_VBInfo & DriverMode) {
2592 tempah |= 0x02;
2593 }
2594 }
2595
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002596 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) tempah |= 0x02;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002598 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah ^= 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002600 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002602 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603#endif
2604
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002605 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
2607#ifdef SIS300
2608 tempah = 0;
2609 if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002610 tempah |= 0x02;
2611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 tempah <<= 5;
2613
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002614 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615
2616 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2617#endif
2618
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
2621 }
2622
2623 } /* LCDA */
2624
2625 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2626
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002627 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628
2629#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002630 /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631
2632 /* The following is nearly unpreditable and varies from machine
2633 * to machine. Especially the 301DH seems to be a real trouble
2634 * maker. Some BIOSes simply set the registers (like in the
2635 * NoLCD-if-statements here), some set them according to the
2636 * LCDA stuff. It is very likely that some machines are not
2637 * treated correctly in the following, very case-orientated
2638 * code. What do I do then...?
2639 */
2640
2641 /* 740 variants match for 30xB, 301B-DH, 30xLV */
2642
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002643 if(!(IS_SIS740)) {
2644 tempah = 0x04; /* For all bridges */
2645 tempbl = 0xfb;
2646 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2647 tempah = 0x00;
2648 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 tempbl = 0xff;
2650 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002651 }
2652 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 }
2654
2655 /* The following two are responsible for eventually wrong colors
2656 * in TV output. The DH (VB_NoLCD) conditions are unknown; the
2657 * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
2658 * in a 650 box (Jake). What is the criteria?
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002659 * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
2660 * treatment like the 651+301B-DH(b0) case. Seems more to be the
2661 * chipset than the bridge revision.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 */
2663
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002664 if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 tempah = 0x30;
2666 tempbl = 0xc0;
2667 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2668 ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
2669 tempah = 0x00;
2670 tempbl = 0x00;
2671 }
2672 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
2673 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
2674 } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
2675 /* Fixes "TV-blue-bug" on 315+301 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002676 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002678 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
2679 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002681 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* For 301B-DH */
2682 tempah = 0x30; tempah2 = 0xc0;
2683 tempbl = 0xcf; tempbl2 = 0x3f;
2684 if(SiS_Pr->SiS_TVBlue == 0) {
2685 tempah = tempah2 = 0x00;
2686 } else if(SiS_Pr->SiS_TVBlue == -1) {
2687 /* Set on 651/M650, clear on 315/650 */
2688 if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
2689 tempah = tempah2 = 0x00;
2690 }
2691 }
2692 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2693 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002695 tempah = 0x30; tempah2 = 0xc0; /* For 30xB, 301C */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 tempbl = 0xcf; tempbl2 = 0x3f;
2697 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2698 tempah = tempah2 = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002699 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 tempbl = tempbl2 = 0xff;
2701 }
2702 }
2703 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2704 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2705 }
2706
2707 if(IS_SIS740) {
2708 tempah = 0x80;
2709 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
2710 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
2711 } else {
2712 tempah = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002713 tempbl = 0x7f;
2714 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2715 tempbl = 0xff;
2716 if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
2717 }
2718 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 }
2720
2721#endif /* SIS315H */
2722
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002723 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
2725#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002726 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002728 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2729 ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
2731 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
2732 } else {
2733 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
2734 }
2735#endif
2736
2737 }
2738
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002739 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2740 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
2741 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
2743 }
2744 }
2745
2746 } else { /* LVDS */
2747
2748#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002749 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002751 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002753 tempah = 0x04;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 tempbl = 0xfb;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002755 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2756 tempah = 0x00;
2757 if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
2758 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2760
2761 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2762 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2763 }
2764
2765 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2766
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002767 } else if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
2769 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2770 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2771
2772 }
2773
2774 }
2775#endif
2776
2777 }
2778
2779}
2780
2781/*********************************************/
2782/* GET RESOLUTION DATA */
2783/*********************************************/
2784
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002785unsigned short
2786SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002788 if(ModeNo <= 0x13)
2789 return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
2790 else
2791 return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792}
2793
2794static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002795SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002797 unsigned short xres, yres, modeflag=0, resindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002799 if(SiS_Pr->UseCustomMode) {
2800 xres = SiS_Pr->CHDisplay;
2801 if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
2802 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2803 /* DoubleScanMode-check done in CheckCalcCustomMode()! */
2804 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
2805 return;
2806 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002808 resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002810 if(ModeNo <= 0x13) {
2811 xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
2812 yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
2813 } else {
2814 xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
2815 yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
2816 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2817 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002819 if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002821 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
2822 if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
2823 if(yres == 350) yres = 400;
2824 }
2825 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
2826 if(ModeNo == 0x12) yres = 400;
2827 }
2828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002830 if(modeflag & HalfDCLK) xres <<= 1;
2831 if(modeflag & DoubleScanMode) yres <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002833 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002835 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002837 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2838 switch(SiS_Pr->SiS_LCDResInfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839 case Panel_1024x768:
2840 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002841 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2842 if(yres == 350) yres = 357;
2843 if(yres == 400) yres = 420;
2844 if(yres == 480) yres = 525;
2845 }
2846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 break;
2848 case Panel_1280x1024:
2849 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2850 /* BIOS bug - does this regardless of scaling */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002851 if(yres == 400) yres = 405;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002853 if(yres == 350) yres = 360;
2854 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
2855 if(yres == 360) yres = 375;
2856 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857 break;
2858 case Panel_1600x1200:
2859 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002860 if(yres == 1024) yres = 1056;
2861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002863 }
2864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002866 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002868 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2869 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
2870 if(xres == 720) xres = 640;
2871 }
2872 } else if(xres == 720) xres = 640;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002874 if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
2875 yres = 400;
2876 if(SiS_Pr->ChipType >= SIS_315H) {
2877 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
2878 } else {
2879 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
2880 }
2881 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
2882 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002884 }
2885 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2886 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887}
2888
2889/*********************************************/
2890/* GET CRT2 TIMING DATA */
2891/*********************************************/
2892
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002894SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2895 unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
2896 unsigned short *ResIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002898 unsigned short tempbx=0, tempal=0, resinfo=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899
2900 if(ModeNo <= 0x13) {
2901 tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2902 } else {
2903 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2904 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2905 }
2906
2907 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
2908
2909 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
2910
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002911 tempbx = SiS_Pr->SiS_LCDResInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
2913
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002914 /* patch index */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
2916 if (resinfo == SIS_RI_1280x800) tempal = 9;
2917 else if(resinfo == SIS_RI_1400x1050) tempal = 11;
2918 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002919 (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
2920 (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 if (resinfo == SIS_RI_1280x768) tempal = 9;
2922 }
2923
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002924 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 /* Pass 1:1 only (center-screen handled outside) */
2926 /* This is never called for the panel's native resolution */
2927 /* since Pass1:1 will not be set in this case */
2928 tempbx = 100;
2929 if(ModeNo >= 0x13) {
2930 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
2931 }
2932 }
2933
2934#ifdef SIS315H
2935 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
2936 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
2937 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002938 tempbx = 200;
2939 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 }
2941 }
2942 }
2943#endif
2944
2945 } else { /* TV */
2946
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002947 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2948 /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
2949 tempbx = 2;
2950 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 tempbx = 13;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002952 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
2953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002955 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7;
2956 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
2957 else tempbx = 5;
2958 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2959 } else {
2960 if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3;
2961 else tempbx = 4;
2962 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2963 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964
2965 }
2966
2967 tempal &= 0x3F;
2968
2969 if(ModeNo > 0x13) {
2970 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002971 switch(resinfo) {
2972 case SIS_RI_720x480:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 tempal = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002974 if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) tempal = 9;
2975 break;
2976 case SIS_RI_720x576:
2977 case SIS_RI_768x576:
2978 case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
2979 tempal = 6;
2980 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2981 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002983 break;
2984 case SIS_RI_800x480:
2985 tempal = 4;
2986 break;
2987 case SIS_RI_512x384:
2988 case SIS_RI_1024x768:
2989 tempal = 7;
2990 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2991 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempal = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002993 break;
2994 case SIS_RI_1280x720:
2995 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2996 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002998 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 }
3000 }
3001 }
3002
3003 *CRT2Index = tempbx;
3004 *ResIndex = tempal;
3005
3006 } else { /* LVDS, 301B-DH (if running on LCD) */
3007
3008 tempbx = 0;
3009 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
3010
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003011 tempbx = 90;
3012 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
3013 tempbx = 92;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 if(SiS_Pr->SiS_ModeType > ModeVGA) {
3015 if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
3016 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003017 if(SiS_Pr->SiS_TVMode & TVSetPALM) tempbx = 94;
3018 else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
3019 }
3020 if(tempbx != 99) {
3021 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
3022 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023
3024 } else {
3025
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003026 switch(SiS_Pr->SiS_LCDResInfo) {
3027 case Panel_640x480: tempbx = 12; break;
3028 case Panel_320x240_1: tempbx = 10; break;
3029 case Panel_320x240_2:
3030 case Panel_320x240_3: tempbx = 14; break;
3031 case Panel_800x600: tempbx = 16; break;
3032 case Panel_1024x600: tempbx = 18; break;
3033 case Panel_1152x768:
3034 case Panel_1024x768: tempbx = 20; break;
3035 case Panel_1280x768: tempbx = 22; break;
3036 case Panel_1280x1024: tempbx = 24; break;
3037 case Panel_1400x1050: tempbx = 26; break;
3038 case Panel_1600x1200: tempbx = 28; break;
3039#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 case Panel_Barco1366: tempbx = 80; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003041#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042 }
3043
3044 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003045 case Panel_320x240_1:
3046 case Panel_320x240_2:
3047 case Panel_320x240_3:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 case Panel_640x480:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049 break;
3050 default:
3051 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3052 }
3053
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003054 if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003056#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3058 tempbx = 82;
3059 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003060 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 tempbx = 84;
3062 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3063 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003064#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
3066 }
3067
3068 (*CRT2Index) = tempbx;
3069 (*ResIndex) = tempal & 0x1F;
3070 }
3071}
3072
3073static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003074SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3075 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003077 unsigned short tempax=0, tempbx=0, index, dotclock;
3078 unsigned short temp1=0, modeflag=0, tempcx=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079
3080 SiS_Pr->SiS_RVBHCMAX = 1;
3081 SiS_Pr->SiS_RVBHCFACT = 1;
3082
3083 if(ModeNo <= 0x13) {
3084
3085 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3086 index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
3087
3088 tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
3089 tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
3090 temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
3091
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003092 dotclock = (modeflag & Charx8Dot) ? 8 : 9;
3093
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 } else {
3095
3096 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003097 index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098
3099 tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
3100 tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
3101 tempax &= 0x03FF;
3102 tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
3103 tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
3104 tempcx &= 0x0100;
3105 tempcx <<= 2;
3106 tempbx |= tempcx;
3107 temp1 = SiS_Pr->SiS_CRT1Table[index].CR[7];
3108
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003109 dotclock = 8;
3110
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 }
3112
3113 if(temp1 & 0x01) tempbx |= 0x0100;
3114 if(temp1 & 0x20) tempbx |= 0x0200;
3115
3116 tempax += 5;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003117 tempax *= dotclock;
3118 if(modeflag & HalfDCLK) tempax <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
3120 tempbx++;
3121
3122 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3123 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
3124}
3125
3126static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003127SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3128 unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003130 unsigned short ResIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003132 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3133 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3134 if(SiS_Pr->UseCustomMode) {
3135 ResIndex = SiS_Pr->CHTotal;
3136 if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
3137 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
3138 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3139 } else {
3140 if(ModeNo < 0x13) {
3141 ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3142 } else {
3143 ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3144 }
3145 if(ResIndex == 0x09) {
3146 if(SiS_Pr->Alternate1600x1200) ResIndex = 0x20; /* 1600x1200 LCDA */
3147 else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
3148 }
3149 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
3150 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
3151 SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
3152 SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
3153 }
3154 } else {
3155 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3156 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3157 }
3158 } else {
3159 /* This handles custom modes and custom panels */
3160 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3161 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3162 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3163 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3164 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
3165 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
3166 }
3167}
3168
3169static void
3170SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3171 unsigned short RefreshRateTableIndex)
3172{
3173 unsigned short CRT2Index, ResIndex, backup;
3174 const struct SiS_LVDSData *LVDSData = NULL;
3175
3176 SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
3178 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3179 SiS_Pr->SiS_RVBHCMAX = 1;
3180 SiS_Pr->SiS_RVBHCFACT = 1;
3181 SiS_Pr->SiS_NewFlickerMode = 0;
3182 SiS_Pr->SiS_RVBHRS = 50;
3183 SiS_Pr->SiS_RY1COE = 0;
3184 SiS_Pr->SiS_RY2COE = 0;
3185 SiS_Pr->SiS_RY3COE = 0;
3186 SiS_Pr->SiS_RY4COE = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003187 SiS_Pr->SiS_RVBHRS2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188 }
3189
3190 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3191
3192#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003193 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3194 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195#endif
3196
3197 } else {
3198
3199 /* 301BDH needs LVDS Data */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003200 backup = SiS_Pr->SiS_IF_DEF_LVDS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3202 SiS_Pr->SiS_IF_DEF_LVDS = 1;
3203 }
3204
3205 SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003206 &CRT2Index, &ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003208 SiS_Pr->SiS_IF_DEF_LVDS = backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003210 switch(CRT2Index) {
3211 case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1; break;
3212 case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2; break;
3213 case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break;
3214 case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
3215 case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
3216 case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
3217#ifdef SIS300
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break;
3219 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break;
3220 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1; break;
3222 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003223#endif
3224 case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break;
3225 case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break;
3226 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData; break;
3227 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData; break;
3228 case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
3229 case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
3230 case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
3231 case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
3232 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233 }
3234
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003235 if(LVDSData) {
3236 SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
3237 SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
3238 SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT;
3239 SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT;
3240 } else {
3241 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003244 if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
3245 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
3246 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
3247 if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
3248 (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
3249 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3250 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3251#ifdef SIS300
3252 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3253 if(ResIndex < 0x08) {
3254 SiS_Pr->SiS_HDE = 1280;
3255 SiS_Pr->SiS_VDE = 1024;
3256 }
3257 }
3258#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 }
3260 }
3261 }
3262}
3263
3264static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003265SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3266 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003268 unsigned char *ROMAddr = NULL;
3269 unsigned short tempax, tempbx, modeflag, romptr=0;
3270 unsigned short resinfo, CRT2Index, ResIndex;
3271 const struct SiS_LCDData *LCDPtr = NULL;
3272 const struct SiS_TVData *TVPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003274 short resinfo661;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275#endif
3276
3277 if(ModeNo <= 0x13) {
3278 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3279 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
3280 } else if(SiS_Pr->UseCustomMode) {
3281 modeflag = SiS_Pr->CModeFlag;
3282 resinfo = 0;
3283 } else {
3284 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3285 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
3286#ifdef SIS315H
3287 resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3288 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003289 (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
3290 (resinfo661 >= 0) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291 (SiS_Pr->SiS_NeedRomModeData) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003292 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293 if((romptr = (SISGETROMW(21)))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003294 romptr += (resinfo661 * 10);
3295 ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 }
3297 }
3298 }
3299#endif
3300 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003301
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302 SiS_Pr->SiS_NewFlickerMode = 0;
3303 SiS_Pr->SiS_RVBHRS = 50;
3304 SiS_Pr->SiS_RY1COE = 0;
3305 SiS_Pr->SiS_RY2COE = 0;
3306 SiS_Pr->SiS_RY3COE = 0;
3307 SiS_Pr->SiS_RY4COE = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003308 SiS_Pr->SiS_RVBHRS2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003310 SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003312 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313
3314 if(SiS_Pr->UseCustomMode) {
3315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003316 SiS_Pr->SiS_RVBHCMAX = 1;
3317 SiS_Pr->SiS_RVBHCFACT = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003319 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3320
3321 tempax = SiS_Pr->CHTotal;
3322 if(modeflag & HalfDCLK) tempax <<= 1;
3323 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3324 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325
3326 } else {
3327
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003328 SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329
3330 }
3331
3332 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3333
3334 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003335 &CRT2Index,&ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336
3337 switch(CRT2Index) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003338 case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break;
3339 case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break;
3340 case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
3341 case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break;
3342 case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break;
3343 case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break;
3344 case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
3345 case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
3346 case 10: TVPtr = SiS_Pr->SiS_St525iData; break;
3347 case 11: TVPtr = SiS_Pr->SiS_St525pData; break;
3348 case 12: TVPtr = SiS_Pr->SiS_St750pData; break;
3349 case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break;
3350 case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break;
3351 default: TVPtr = SiS_Pr->SiS_StPALData; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352 }
3353
3354 SiS_Pr->SiS_RVBHCMAX = (TVPtr+ResIndex)->RVBHCMAX;
3355 SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
3356 SiS_Pr->SiS_VGAHT = (TVPtr+ResIndex)->VGAHT;
3357 SiS_Pr->SiS_VGAVT = (TVPtr+ResIndex)->VGAVT;
3358 SiS_Pr->SiS_HDE = (TVPtr+ResIndex)->TVHDE;
3359 SiS_Pr->SiS_VDE = (TVPtr+ResIndex)->TVVDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003360 SiS_Pr->SiS_RVBHRS2 = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 if(modeflag & HalfDCLK) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003362 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
3363 if(SiS_Pr->SiS_RVBHRS2) {
3364 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3365 tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
3366 if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
3367 else SiS_Pr->SiS_RVBHRS2 += tempax;
3368 }
3369 } else {
3370 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003372 SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373
3374 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3375
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003376 if((resinfo == SIS_RI_960x600) ||
3377 (resinfo == SIS_RI_1024x768) ||
3378 (resinfo == SIS_RI_1280x1024) ||
3379 (resinfo == SIS_RI_1280x720)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 SiS_Pr->SiS_NewFlickerMode = 0x40;
3381 }
3382
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003383 if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003385 SiS_Pr->SiS_HT = ExtHiTVHT;
3386 SiS_Pr->SiS_VT = ExtHiTVVT;
3387 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3388 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
3389 SiS_Pr->SiS_HT = StHiTVHT;
3390 SiS_Pr->SiS_VT = StHiTVVT;
3391 }
3392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393
3394 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3395
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003396 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3397 SiS_Pr->SiS_HT = 1650;
3398 SiS_Pr->SiS_VT = 750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3400 SiS_Pr->SiS_HT = NTSCHT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003401 if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402 SiS_Pr->SiS_VT = NTSCVT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003403 } else {
3404 SiS_Pr->SiS_HT = NTSCHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003406 SiS_Pr->SiS_VT = NTSCVT;
3407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
3409 } else {
3410
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003411 SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
3412 SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
3413 SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
3414 SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003416 if(modeflag & HalfDCLK) {
3417 SiS_Pr->SiS_RY1COE = 0x00;
3418 SiS_Pr->SiS_RY2COE = 0xf4;
3419 SiS_Pr->SiS_RY3COE = 0x10;
3420 SiS_Pr->SiS_RY4COE = 0x38;
3421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003423 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
3424 SiS_Pr->SiS_HT = NTSCHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003426 SiS_Pr->SiS_VT = NTSCVT;
3427 } else {
3428 SiS_Pr->SiS_HT = PALHT;
3429 SiS_Pr->SiS_VT = PALVT;
3430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431
3432 }
3433
3434 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3435
3436 SiS_Pr->SiS_RVBHCMAX = 1;
3437 SiS_Pr->SiS_RVBHCFACT = 1;
3438
3439 if(SiS_Pr->UseCustomMode) {
3440
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003442 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3443
3444 tempax = SiS_Pr->CHTotal;
3445 if(modeflag & HalfDCLK) tempax <<= 1;
3446 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3447 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448
3449 } else {
3450
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003451 bool gotit = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003453 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003455 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
3456 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3457 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3458 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003459 gotit = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
3461 } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3462
3463#ifdef SIS315H
3464 SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003465 SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3466 SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
3467 SiS_Pr->SiS_VGAVT = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
3468 SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
3469 SiS_Pr->SiS_VT = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
3470 SiS_Pr->SiS_RVBHRS2 = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
3471 if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
3472 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3473 tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
3474 if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
3475 else SiS_Pr->SiS_RVBHRS2 += tempax;
3476 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003477 if(SiS_Pr->SiS_VGAHT) gotit = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 else {
3479 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
3480 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003481 SiS_Pr->SiS_RVBHCMAX = 1;
3482 SiS_Pr->SiS_RVBHCFACT = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003484 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3485 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3486 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3487 SiS_Pr->SiS_RVBHRS2 = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003488 gotit = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489 }
3490#endif
3491
3492 }
3493
3494 if(!gotit) {
3495
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003496 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3497 &CRT2Index,&ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003499 switch(CRT2Index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 case Panel_1024x768 : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3501 case Panel_1024x768 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break;
3502 case Panel_1280x720 :
3503 case Panel_1280x720 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data; break;
3504 case Panel_1280x768_2 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003505 case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 case Panel_1280x800 :
3507 case Panel_1280x800 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data; break;
3508 case Panel_1280x800_2 :
3509 case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003510 case Panel_1280x854 :
3511 case Panel_1280x854 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 case Panel_1280x960 :
3513 case Panel_1280x960 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003514 case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break;
3515 case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3516 case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break;
3517 case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break;
3518 case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break;
3519 case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 case Panel_1680x1050 :
3521 case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break;
3522 case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break;
3523#ifdef SIS315H
3524 case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break;
3525 case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3526#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003527 default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003530#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531#ifdef TWDEBUG
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003532 xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
3533#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534#endif
3535
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003536 SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
3537 SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3538 SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
3539 SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
3540 SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
3541 SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542
3543 }
3544
3545 tempax = SiS_Pr->PanelXRes;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003546 tempbx = SiS_Pr->PanelYRes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003548 switch(SiS_Pr->SiS_LCDResInfo) {
3549 case Panel_1024x768:
3550 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3551 if(SiS_Pr->ChipType < SIS_315H) {
3552 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3553 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3554 }
3555 } else {
3556 if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
3557 else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
3558 else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
3559 else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
3560 else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3561 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3562 }
3563 break;
3564 case Panel_1280x960:
3565 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
3566 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
3567 else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
3568 break;
3569 case Panel_1280x1024:
3570 if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
3571 else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
3572 else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
3573 break;
3574 case Panel_1600x1200:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003576 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
3577 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
3578 }
3579 break;
3580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003582 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3583 tempax = SiS_Pr->SiS_VGAHDE;
3584 tempbx = SiS_Pr->SiS_VGAVDE;
3585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003587 SiS_Pr->SiS_HDE = tempax;
3588 SiS_Pr->SiS_VDE = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589 }
3590 }
3591}
3592
3593static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003594SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3595 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596{
3597
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003598 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003600 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3601 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3602 } else {
3603 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3604 /* Need LVDS Data for LCD on 301B-DH */
3605 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3606 } else {
3607 SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3608 }
3609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003611 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003613 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003615 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616}
3617
3618/*********************************************/
3619/* GET LVDS DES (SKEW) DATA */
3620/*********************************************/
3621
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003622static const struct SiS_LVDSDes *
3623SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003625 const struct SiS_LVDSDes *PanelDesPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003627#ifdef SIS300
3628 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003630 if(SiS_Pr->ChipType < SIS_315H) {
3631 if(SiS_Pr->SiS_LCDTypeInfo == 4) {
3632 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3633 PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
3634 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3635 PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
3636 }
3637 } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3638 PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
3639 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3640 PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
3641 }
3642 }
3643 }
3644 }
3645 }
3646#endif
3647 return PanelDesPtr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648}
3649
3650static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003651SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3652 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003654 unsigned short modeflag, ResIndex;
3655 const struct SiS_LVDSDes *PanelDesPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656
3657 SiS_Pr->SiS_LCDHDES = 0;
3658 SiS_Pr->SiS_LCDVDES = 0;
3659
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003660 /* Some special cases */
3661 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3662
3663 /* Trumpion */
3664 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
3665 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3666 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3667 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3668 }
3669 }
3670 return;
3671 }
3672
3673 /* 640x480 on LVDS */
3674 if(SiS_Pr->ChipType < SIS_315H) {
3675 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
3676 SiS_Pr->SiS_LCDHDES = 8;
3677 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3678 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3679 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3680 return;
3681 }
3682 }
3683
3684 } /* LCD */
3685
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 if( (SiS_Pr->UseCustomMode) ||
3687 (SiS_Pr->SiS_LCDResInfo == Panel_Custom) ||
3688 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003689 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ||
3690 (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691 return;
3692 }
3693
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003694 if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3695 else ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3696
3697 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698
3699#ifdef SIS315H
3700 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003701 /* non-pass 1:1 only, see above */
3702 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3703 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 }
3705 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3706 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3707 }
3708 }
3709 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003710 switch(SiS_Pr->SiS_CustomT) {
3711 case CUT_UNIWILL1024:
3712 case CUT_UNIWILL10242:
3713 case CUT_CLEVO1400:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3715 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3716 }
3717 break;
3718 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003719 switch(SiS_Pr->SiS_LCDResInfo) {
3720 case Panel_1280x1024:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721 if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
3722 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3723 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003724 break;
3725 case Panel_1280x800: /* Verified for Averatec 6240 */
3726 case Panel_1280x800_2: /* Verified for Asus A4L */
3727 case Panel_1280x854: /* Not verified yet FIXME */
3728 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3729 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 }
3731 }
3732#endif
3733
3734 } else {
3735
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003736 if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003738 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
3739 if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
3740 }
3741
3742 } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
3743
3744 SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
3745 SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
3746
3747 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3748
3749 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3750 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3751 }
3752 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3753 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3754 } else {
3755 if(SiS_Pr->ChipType < SIS_315H) {
3756 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3757 } else {
3758 switch(SiS_Pr->SiS_LCDResInfo) {
3759 case Panel_800x600:
3760 case Panel_1024x768:
3761 case Panel_1280x1024:
3762 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3763 break;
3764 case Panel_1400x1050:
3765 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3766 break;
3767 }
3768 }
3769 }
3770
3771 } else {
3772
3773 if(SiS_Pr->ChipType < SIS_315H) {
3774#ifdef SIS300
3775 switch(SiS_Pr->SiS_LCDResInfo) {
3776 case Panel_800x600:
3777 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3778 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3779 } else {
3780 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
3781 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3782 if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
3783 else SiS_Pr->SiS_LCDVDES -= 4;
3784 }
3785 break;
3786 case Panel_1024x768:
3787 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3788 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3789 } else {
3790 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3791 if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
3792 if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
3793 }
3794 break;
3795 case Panel_1024x600:
3796 default:
3797 if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
3798 (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
3799 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3800 } else {
3801 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3802 }
3803 break;
3804 }
3805
3806 switch(SiS_Pr->SiS_LCDTypeInfo) {
3807 case 1:
3808 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
3809 break;
3810 case 3: /* 640x480 only? */
3811 SiS_Pr->SiS_LCDHDES = 8;
3812 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3813 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3814 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3815 break;
3816 }
3817#endif
3818 } else {
3819#ifdef SIS315H
3820 switch(SiS_Pr->SiS_LCDResInfo) {
3821 case Panel_1024x768:
3822 case Panel_1280x1024:
3823 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3824 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3825 }
3826 break;
3827 case Panel_320x240_1:
3828 case Panel_320x240_2:
3829 case Panel_320x240_3:
3830 SiS_Pr->SiS_LCDVDES = 524;
3831 break;
3832 }
3833#endif
3834 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 }
3836
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003838 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3839 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003841 } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3842 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
3843 if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
3844 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
3846 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003847#ifdef SIS315H
3848 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
3849 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003851 if(!(modeflag & HalfDCLK)) {
3852 SiS_Pr->SiS_LCDHDES = 320;
3853 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003855 }
3856#endif
3857 }
3858 }
3859 }
3860 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 }
3862 }
3863}
3864
3865/*********************************************/
3866/* DISABLE VIDEO BRIDGE */
3867/*********************************************/
3868
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003869#ifdef SIS315H
3870static int
3871SiS_HandlePWD(struct SiS_Private *SiS_Pr)
3872{
3873 int ret = 0;
3874#ifdef SET_PWD
3875 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3876 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
3877 unsigned char drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
3878 unsigned short temp;
3879
3880 if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
3881 (romptr) &&
3882 (SiS_Pr->SiS_PWDOffset) ) {
3883 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
3884 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
3885 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
3886 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
3887 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
3888 temp = 0x00;
3889 if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
3890 temp = 0x80;
3891 ret = 1;
3892 }
3893 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
3894#ifdef SIS_XORG_XF86
3895#ifdef TWDEBUG
3896 xf86DrvMsg(0, 0, "Setting PWD %x\n", temp);
3897#endif
3898#endif
3899 }
3900#endif
3901 return ret;
3902}
3903#endif
3904
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905/* NEVER use any variables (VBInfo), this will be called
3906 * from outside the context of modeswitch!
3907 * MUST call getVBType before calling this
3908 */
3909void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003910SiS_DisableBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911{
3912#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003913 unsigned short tempah, pushax=0, modenum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003915 unsigned short temp=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916
3917 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3918
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003919 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ===== For 30xB/C/LV ===== */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003921 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
3923#ifdef SIS300 /* 300 series */
3924
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003925 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
3926 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3927 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003929 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003931 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 }
3933 if(SiS_Is301B(SiS_Pr)) {
3934 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
3935 SiS_ShortDelay(SiS_Pr,1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
3938 SiS_DisplayOff(SiS_Pr);
3939 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3940 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003941 SiS_UnLockCRT2(SiS_Pr);
3942 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
3944 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
3945 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003946 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
3947 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
3948 SiS_PanelDelay(SiS_Pr, 2);
3949 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3950 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003952 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 }
3954 }
3955
3956#endif /* SIS300 */
3957
3958 } else {
3959
3960#ifdef SIS315H /* 315 series */
3961
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003962 int didpwd = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003963 bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
3964 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965
3966 modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
3967
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003968 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969
3970#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003971 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003973 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 }
3975 }
3976#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003977
3978 didpwd = SiS_HandlePWD(SiS_Pr);
3979
3980 if( (modenum <= 0x13) ||
3981 (SiS_IsVAMode(SiS_Pr)) ||
3982 (!(SiS_IsDualEdge(SiS_Pr))) ) {
3983 if(!didpwd) {
3984 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
3985 if(custom1) SiS_PanelDelay(SiS_Pr, 3);
3986 } else {
3987 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
3988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 }
3990
3991 if(!custom1) {
3992 SiS_DDC2Delay(SiS_Pr,0xff00);
3993 SiS_DDC2Delay(SiS_Pr,0xe000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003994 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
3995 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 if(IS_SIS740) {
3997 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
3998 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003999 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000 }
4001
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 }
4003
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004004 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4005 /* if(SiS_Pr->ChipType < SIS_340) {*/
4006 tempah = 0xef;
4007 if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
4008 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
4009 /*}*/
4010 }
4011
4012 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
4014 }
4015
4016 tempah = 0x3f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004017 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018 tempah = 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004019 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 }
4021 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
4022
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004023 if((SiS_IsVAMode(SiS_Pr)) ||
4024 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025
4026 SiS_DisplayOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004027 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4028 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 }
4030 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4031 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
4032
4033 }
4034
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004035 if((!(SiS_IsVAMode(SiS_Pr))) ||
4036 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004038 if(!(SiS_IsDualEdge(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
4040 SiS_DisplayOff(SiS_Pr);
4041 }
4042 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4043
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004044 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4045 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 }
4047
4048 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4049 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004050 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4052 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4053
4054 }
4055
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004056 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4058 }
4059
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004060 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4061
4062 if( (!(SiS_IsVAMode(SiS_Pr))) &&
4063 (!(SiS_CRT2IsLCD(SiS_Pr))) &&
4064 (!(SiS_IsDualEdge(SiS_Pr))) ) {
4065
4066 if(custom1) SiS_PanelDelay(SiS_Pr, 2);
4067 if(!didpwd) {
4068 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
4069 }
4070 if(custom1) SiS_PanelDelay(SiS_Pr, 4);
4071 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072
4073 if(!custom1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004074 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4075 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4076 if(SiS_IsVAorLCD(SiS_Pr)) {
4077 SiS_PanelDelayLoop(SiS_Pr, 3, 20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 }
4079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004081
4082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083
4084#endif /* SIS315H */
4085
4086 }
4087
4088 } else { /* ============ For 301 ================ */
4089
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004090 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004092 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4093 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4094 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 }
4096#endif
4097 }
4098
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004099 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
4100 SiS_DisplayOff(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004102 if(SiS_Pr->ChipType >= SIS_315H) {
4103 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 }
4105
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004106 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004108 if(SiS_Pr->ChipType >= SIS_315H) {
4109 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4110 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4112 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4113 } else {
4114#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004115 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
4116 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4117 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4118 SiS_PanelDelay(SiS_Pr, 2);
4119 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 }
4121#endif
4122 }
4123
4124 }
4125
4126 } else { /* ============ For LVDS =============*/
4127
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004128 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
4130#ifdef SIS300 /* 300 series */
4131
4132 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004133 SiS_SetCH700x(SiS_Pr,0x0E,0x09);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 }
4135
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004136 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004138 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004140 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4141 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4142 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 }
4144 } else {
4145 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4146 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004147 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4148 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
4150 SiS_DisplayOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004151 }
4152 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4153 SiS_PanelDelay(SiS_Pr, 3);
4154 }
4155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156 }
4157 }
4158
4159 SiS_DisplayOff(SiS_Pr);
4160
4161 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4162
4163 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004164 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4166 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4167
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004168 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4169 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4170 SiS_PanelDelay(SiS_Pr, 2);
4171 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 }
4173
4174#endif /* SIS300 */
4175
4176 } else {
4177
4178#ifdef SIS315H /* 315 series */
4179
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004180 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4181 /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
4182 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
4183 /* } */
4184 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185
4186 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4187
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004188 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 temp = SiS_GetCH701x(SiS_Pr,0x61);
4190 if(temp < 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004191 SiS_SetCH701x(SiS_Pr,0x76,0xac);
4192 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193 }
4194
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004195 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4196 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4197 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 }
4199 }
4200
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004201 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4202 (SiS_IsVAMode(SiS_Pr)) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203 SiS_Chrontel701xBLOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004204 SiS_Chrontel701xOff(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 }
4206
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004207 if(SiS_Pr->ChipType != SIS_740) {
4208 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4209 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4210 SiS_SetCH701x(SiS_Pr,0x49,0x01);
4211 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212 }
4213
4214 }
4215
4216 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004217 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4218 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219 }
4220
4221 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004222 (!(SiS_IsDualEdge(SiS_Pr))) ||
4223 (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224 SiS_DisplayOff(SiS_Pr);
4225 }
4226
4227 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004228 (!(SiS_IsDualEdge(SiS_Pr))) ||
4229 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4231 }
4232
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004233 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4235 }
4236
4237 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4238
4239 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004240 (!(SiS_IsDualEdge(SiS_Pr))) ||
4241 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4243 }
4244
4245 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004246 if(SiS_CRT2IsLCD(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004248 if(SiS_Pr->ChipType == SIS_550) {
4249 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
4250 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 }
4252 }
4253 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004254 if(SiS_Pr->ChipType == SIS_740) {
4255 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4256 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004258 } else if(SiS_IsVAMode(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4260 }
4261 }
4262
4263 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004264 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265 /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
4266 } else {
4267 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
4268 }
4269 }
4270
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004271 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004273 if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
4275 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
4276 } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004277 (!(SiS_IsDualEdge(SiS_Pr))) ||
4278 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4280 }
4281
4282 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004283 if(SiS_CRT2IsLCD(SiS_Pr)) {
4284 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4285 SiS_PanelDelay(SiS_Pr, 2);
4286 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287 }
4288 }
4289 }
4290
4291#endif /* SIS315H */
4292
4293 } /* 315 series */
4294
4295 } /* LVDS */
4296
4297}
4298
4299/*********************************************/
4300/* ENABLE VIDEO BRIDGE */
4301/*********************************************/
4302
4303/* NEVER use any variables (VBInfo), this will be called
4304 * from outside the context of a mode switch!
4305 * MUST call getVBType before calling this
4306 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004307#ifdef SIS_LINUX_KERNEL
4308static
4309#endif
4310void
4311SiS_EnableBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004313 unsigned short temp=0, tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004315 unsigned short temp1, pushax=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004316 bool delaylong = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317#endif
4318
4319 if(SiS_Pr->SiS_VBType & VB_SISVB) {
4320
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004321 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ====== For 301B et al ====== */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004323 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324
4325#ifdef SIS300 /* 300 series */
4326
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004327 if(SiS_CRT2IsLCD(SiS_Pr)) {
4328 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4330 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004331 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004333 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
4334 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4335 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 }
4337 }
4338 }
4339
4340 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004341 (SiS_CRT2IsLCD(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342
4343 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* Enable CRT2 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004344 SiS_DisplayOn(SiS_Pr);
4345 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4347 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004348 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4349 } else {
4350 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4353 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004354 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4355 SiS_PanelDelay(SiS_Pr, 1);
4356 }
4357 SiS_WaitVBRetrace(SiS_Pr);
4358 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360 }
4361
4362 } else {
4363
4364 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004365 if(SiS_BridgeInSlavemode(SiS_Pr)) {
4366 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4367 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4368 }
4369 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4371 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4372 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
4373 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004374 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4375 if(SiS_CRT2IsLCD(SiS_Pr)) {
4376 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4377 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4378 SiS_PanelDelay(SiS_Pr, 1);
4379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004381 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382 }
4383 }
4384
4385 }
4386
4387
4388#endif /* SIS300 */
4389
4390 } else {
4391
4392#ifdef SIS315H /* 315 series */
4393
4394#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004395 unsigned char r30=0, r31=0, r32=0, r33=0, cr36=0;
4396 int didpwd = 0;
4397 /* unsigned short emidelay=0; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398#endif
4399
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004400 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
4402#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004403 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4405 }
4406#endif
4407 }
4408
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004409 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4410 /*if(SiS_Pr->ChipType < SIS_340) { */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411 tempah = 0x10;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004412 if(SiS_LCDAEnabled(SiS_Pr)) {
4413 if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
4414 else tempah = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 }
4416 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004417 /*}*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 }
4419
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004420 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421
4422 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4423 SiS_DisplayOff(SiS_Pr);
4424 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4425 if(IS_SIS740) {
4426 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4427 }
4428
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004429 didpwd = SiS_HandlePWD(SiS_Pr);
4430
4431 if(SiS_IsVAorLCD(SiS_Pr)) {
4432 if(!didpwd) {
4433 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
4434 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4435 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4436 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4437 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4438 SiS_GenericDelay(SiS_Pr, 17664);
4439 }
4440 }
4441 } else {
4442 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4443 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4444 SiS_GenericDelay(SiS_Pr, 17664);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 }
4446 }
4447 }
4448
4449 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004450 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004451 delaylong = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452 }
4453
4454 }
4455
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004456 if(!(SiS_IsVAMode(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004458 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004460 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4461 if(!(tempah & SetCRT2ToRAMDAC)) {
4462 if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004464 }
4465 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466
4467 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4468
4469 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4470 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4471
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004472 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4473 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474 }
4475
4476 } else {
4477
4478 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
4479
4480 }
4481
4482 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
4483 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4484
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004485 if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
4486 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4487 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4488 /* Enable "LVDS PLL power on" (even on 301C) */
4489 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
4490 /* Enable "LVDS Driver Power on" (even on 301C) */
4491 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
4492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004495 tempah = 0xc0;
4496 if(SiS_IsDualEdge(SiS_Pr)) {
4497 tempah = 0x80;
4498 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
4499 }
4500 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004502 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4503
4504 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505
4506 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
4507 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4508
4509 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4510#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004511 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4512 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4513 SiS_GenericDelay(SiS_Pr, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514 }
4515#endif
4516 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
4517
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004518 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519#ifdef SET_EMI
4520 cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
4521
4522 if(SiS_Pr->SiS_ROMNew) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004523 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
4524 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525 if(romptr) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004526 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 SiS_Pr->EMI_30 = 0;
4528 SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
4529 SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
4530 SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
4531 if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
4532 /* emidelay = SISGETROMW((romptr + 0x22)); */
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004533 SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534 }
4535 }
4536
4537 /* (P4_30|0x40) */
4538 /* Compal 1400x1050: 0x05, 0x60, 0x00 YES (1.10.7w; CR36=69) */
4539 /* Compal 1400x1050: 0x0d, 0x70, 0x40 YES (1.10.7x; CR36=69) */
4540 /* Acer 1280x1024: 0x12, 0xd0, 0x6b NO (1.10.9k; CR36=73) */
4541 /* Compaq 1280x1024: 0x0d, 0x70, 0x6b YES (1.12.04b; CR36=03) */
4542 /* Clevo 1024x768: 0x05, 0x60, 0x33 NO (1.10.8e; CR36=12, DL!) */
4543 /* Clevo 1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES (1.10.8y; CR36=?2) */
4544 /* Clevo 1024x768: 0x05, 0x60, 0x33 (if type != 3) YES (1.10.8y; CR36=?2) */
4545 /* Asus 1024x768: ? ? (1.10.8o; CR36=?2) */
4546 /* Asus 1024x768: 0x08, 0x10, 0x3c (problematic) YES (1.10.8q; CR36=22) */
4547
4548 if(SiS_Pr->HaveEMI) {
4549 r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
4550 r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
4551 } else {
4552 r30 = 0;
4553 }
4554
4555 /* EMI_30 is read at driver start; however, the BIOS sets this
4556 * (if it is used) only if the LCD is in use. In case we caught
4557 * the machine while on TV output, this bit is not set and we
4558 * don't know if it should be set - hence our detection is wrong.
4559 * Work-around this here:
4560 */
4561
4562 if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
4563 switch((cr36 & 0x0f)) {
4564 case 2:
4565 r30 |= 0x40;
4566 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
4567 if(!SiS_Pr->HaveEMI) {
4568 r31 = 0x05; r32 = 0x60; r33 = 0x33;
4569 if((cr36 & 0xf0) == 0x30) {
4570 r31 = 0x0d; r32 = 0x70; r33 = 0x40;
4571 }
4572 }
4573 break;
4574 case 3: /* 1280x1024 */
4575 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
4576 if(!SiS_Pr->HaveEMI) {
4577 r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4578 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4579 r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
4580 }
4581 }
4582 break;
4583 case 9: /* 1400x1050 */
4584 r30 |= 0x40;
4585 if(!SiS_Pr->HaveEMI) {
4586 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4587 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4588 r31 = 0x0d; r32 = 0x70; r33 = 0x40; /* BIOS values */
4589 }
4590 }
4591 break;
4592 case 11: /* 1600x1200 - unknown */
4593 r30 |= 0x40;
4594 if(!SiS_Pr->HaveEMI) {
4595 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4596 }
4597 }
4598 }
4599
4600 /* BIOS values don't work so well sometimes */
4601 if(!SiS_Pr->OverruleEMI) {
4602#ifdef COMPAL_HACK
4603 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004604 if((cr36 & 0x0f) == 0x09) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004605 r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
4606 }
4607 }
4608#endif
4609#ifdef COMPAQ_HACK
4610 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004611 if((cr36 & 0x0f) == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004612 r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4613 }
4614 }
4615#endif
4616#ifdef ASUS_HACK
4617 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004618 if((cr36 & 0x0f) == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004619 /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 2 */
4620 /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 3 */
4621 /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 4 */
4622 /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 5 */
4623 }
4624 }
4625#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004626 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627
4628 if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
4629 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004630 SiS_GenericDelay(SiS_Pr, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004631 }
4632 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
4633 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
4634 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
4635#endif /* SET_EMI */
4636
4637 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
4638
4639#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004640 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4641 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4642 if(r30 & 0x40) {
4643 /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
4644 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645 if(delaylong) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004646 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004647 delaylong = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004649 SiS_WaitVBRetrace(SiS_Pr);
4650 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004651 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004652 SiS_GenericDelay(SiS_Pr, 1280);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004654 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */
4655 /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
4656 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657 }
4658#endif
4659 }
4660 }
4661
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004662 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4663 if(SiS_IsVAorLCD(SiS_Pr)) {
4664 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665 if(delaylong) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004666 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004667 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004668 SiS_WaitVBRetrace(SiS_Pr);
4669 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4670 SiS_GenericDelay(SiS_Pr, 2048);
4671 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004672 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004673 if(!didpwd) {
4674 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4675 } else {
4676 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
4677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004678 }
4679 }
4680
4681 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4682 SiS_DisplayOn(SiS_Pr);
4683 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
4684
4685 }
4686
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004687 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4689 }
4690
4691#endif /* SIS315H */
4692
4693 }
4694
4695 } else { /* ============ For 301 ================ */
4696
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004697 if(SiS_Pr->ChipType < SIS_315H) {
4698 if(SiS_CRT2IsLCD(SiS_Pr)) {
4699 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4700 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004701 }
4702 }
4703
4704 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
4705 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004706 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4707 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708 }
4709 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4710
4711 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4712
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004713 if(SiS_Pr->ChipType >= SIS_315H) {
4714 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4715 if(!(temp & 0x80)) {
4716 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004717 }
4718 }
4719
4720 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4721
4722 SiS_VBLongWait(SiS_Pr);
4723 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004724 if(SiS_Pr->ChipType >= SIS_315H) {
4725 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726 }
4727 SiS_VBLongWait(SiS_Pr);
4728
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004729 if(SiS_Pr->ChipType < SIS_315H) {
4730 if(SiS_CRT2IsLCD(SiS_Pr)) {
4731 SiS_PanelDelay(SiS_Pr, 1);
4732 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733 }
4734 }
4735
4736 }
4737
4738 } else { /* =================== For LVDS ================== */
4739
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004740 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741
4742#ifdef SIS300 /* 300 series */
4743
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004744 if(SiS_CRT2IsLCD(SiS_Pr)) {
4745 if(SiS_Pr->ChipType == SIS_730) {
4746 SiS_PanelDelay(SiS_Pr, 1);
4747 SiS_PanelDelay(SiS_Pr, 1);
4748 SiS_PanelDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004750 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4751 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4752 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004753 }
4754 }
4755
4756 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4757 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004758 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4760 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004761 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004763 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764 }
4765
4766 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004767 if(!(SiS_CRT2IsLCD(SiS_Pr))) {
4768 SiS_WaitVBRetrace(SiS_Pr);
4769 SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
4770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771 }
4772
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004773 if(SiS_CRT2IsLCD(SiS_Pr)) {
4774 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4775 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4776 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4777 SiS_PanelDelay(SiS_Pr, 1);
4778 SiS_PanelDelay(SiS_Pr, 1);
4779 }
4780 SiS_WaitVBRetrace(SiS_Pr);
4781 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783 }
4784 }
4785
4786#endif /* SIS300 */
4787
4788 } else {
4789
4790#ifdef SIS315H /* 315 series */
4791
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004792 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4793 /*if(SiS_Pr->ChipType < SIS_340) {*/ /* XGI needs this */
4794 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
4795 /*}*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796 }
4797
4798 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004799 if(SiS_CRT2IsLCD(SiS_Pr)) {
4800 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4801 SiS_PanelDelay(SiS_Pr, 0);
4802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803 }
4804
4805 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004806 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004807
4808 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4809
4810 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004811 temp = SiS_GetCH701x(SiS_Pr,0x66);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004812 temp &= 0x20;
4813 SiS_Chrontel701xBLOff(SiS_Pr);
4814 }
4815
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004816 if(SiS_Pr->ChipType != SIS_550) {
4817 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004818 }
4819
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004820 if(SiS_Pr->ChipType == SIS_740) {
4821 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4822 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4823 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824 }
4825 }
4826 }
4827
4828 temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4829 if(!(temp1 & 0x80)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004830 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004831 }
4832
4833 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004834 if(temp) {
4835 SiS_Chrontel701xBLOn(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836 }
4837 }
4838
4839 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004840 if(SiS_CRT2IsLCD(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004842 if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004843 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
4844 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
4845 }
4846 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004847 } else if(SiS_IsVAMode(SiS_Pr)) {
4848 if(SiS_Pr->ChipType != SIS_740) {
4849 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004850 }
4851 }
4852
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004853 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4854 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004855 }
4856
4857 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004858 if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
4859 SiS_Chrontel701xOn(SiS_Pr);
4860 }
4861 if( (SiS_IsVAMode(SiS_Pr)) ||
4862 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4863 SiS_ChrontelDoSomething1(SiS_Pr);
4864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004865 }
4866
4867 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004868 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4869 if( (SiS_IsVAMode(SiS_Pr)) ||
4870 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4871 SiS_Chrontel701xBLOn(SiS_Pr);
4872 SiS_ChrontelInitTVVSync(SiS_Pr);
4873 }
4874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004875 } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004876 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4877 if(SiS_CRT2IsLCD(SiS_Pr)) {
4878 SiS_PanelDelay(SiS_Pr, 1);
4879 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004880 }
4881 }
4882 }
4883
4884#endif /* SIS315H */
4885
4886 } /* 310 series */
4887
4888 } /* LVDS */
4889
4890}
4891
4892/*********************************************/
4893/* SET PART 1 REGISTER GROUP */
4894/*********************************************/
4895
4896/* Set CRT2 OFFSET / PITCH */
4897static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004898SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
4899 unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004900{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004901 unsigned short offset;
4902 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004904 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004905
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004906 offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004908 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
4909 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004910
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004911 temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
4912 if(offset & 0x07) temp++;
4913 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914}
4915
4916/* Set CRT2 sync and PanelLink mode */
4917static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004918SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004920 unsigned short tempah=0, tempbl, infoflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004922 tempbl = 0xC0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004924 if(SiS_Pr->UseCustomMode) {
4925 infoflag = SiS_Pr->CInfoFlag;
4926 } else {
4927 infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
4928 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004929
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004930 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004931
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004932 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4933 tempah = 0;
4934 } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
4935 tempah = SiS_Pr->SiS_LCDInfo;
4936 } else tempah = infoflag >> 8;
4937 tempah &= 0xC0;
4938 tempah |= 0x20;
4939 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4940 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4941 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
4942 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
4943 tempah |= 0xf0;
4944 }
4945 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4946 (SiS_Pr->SiS_IF_DEF_DSTN) ||
4947 (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
4948 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
4949 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
4950 tempah |= 0x30;
4951 }
4952 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4953 (SiS_Pr->SiS_IF_DEF_DSTN) ) {
4954 tempah &= ~0xc0;
4955 }
4956 }
4957 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4958 if(SiS_Pr->ChipType >= SIS_315H) {
4959 tempah >>= 3;
4960 tempah &= 0x18;
4961 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
4962 /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
4963 } else {
4964 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
4965 }
4966 } else {
4967 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004970 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004972 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004973
4974#ifdef SIS300 /* ---- 300 series --- */
4975
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004976 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* 630 - 301B(-DH) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004978 tempah = infoflag >> 8;
4979 tempbl = 0;
4980 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4981 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4982 tempah = SiS_Pr->SiS_LCDInfo;
4983 tempbl = (tempah >> 6) & 0x03;
4984 }
4985 }
4986 tempah &= 0xC0;
4987 tempah |= 0x20;
4988 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4989 tempah |= 0xc0;
4990 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4991 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
4992 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004994
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004995 } else { /* 630 - 301 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004996
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004997 tempah = ((infoflag >> 8) & 0xc0) | 0x20;
4998 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4999 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005001 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002
5003#endif /* SIS300 */
5004
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005005 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006
5007#ifdef SIS315H /* ------- 315 series ------ */
5008
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005009 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* 315 - LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005011 tempbl = 0;
5012 if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
5013 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5014 tempah = infoflag >> 8;
5015 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
5016 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
5017 }
5018 } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
5019 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
5020 tempah = infoflag >> 8;
5021 tempbl = 0x03;
5022 } else {
5023 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
5024 tempbl = (tempah >> 6) & 0x03;
5025 tempbl |= 0x08;
5026 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
5027 }
5028 tempah &= 0xC0;
5029 tempah |= 0x20;
5030 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5031 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0;
5032 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
5033 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
5034 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5035 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
5036 }
5037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005039 } else { /* 315 - TMDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005041 tempah = tempbl = infoflag >> 8;
5042 if(!SiS_Pr->UseCustomMode) {
5043 tempbl = 0;
5044 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
5045 if(ModeNo <= 0x13) {
5046 tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
5047 }
5048 }
5049 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5050 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5051 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
5052 tempah = SiS_Pr->SiS_LCDInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005053 tempbl = (tempah >> 6) & 0x03;
5054 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005055 }
5056 }
5057 }
5058 tempah &= 0xC0;
5059 tempah |= 0x20;
5060 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
5061 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
5062 /* Imitate BIOS bug */
5063 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0;
5064 }
5065 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
5066 tempah >>= 3;
5067 tempah &= 0x18;
5068 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
5069 } else {
5070 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
5071 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
5072 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5073 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
5074 }
5075 }
5076 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005077
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005079#endif /* SIS315H */
5080 }
5081 }
5082}
5083
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005084/* Set CRT2 FIFO on 300/540/630/730 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085#ifdef SIS300
5086static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005087SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005088{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005089 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5090 unsigned short temp, index, modeidindex, refreshratetableindex;
5091 unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
5092 unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
5093 unsigned int data, pci50, pciA0;
5094 static const unsigned char colortharray[] = {
5095 1, 1, 2, 2, 3, 4
Linus Torvalds1da177e2005-04-16 15:20:36 -07005096 };
5097
5098 SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
5099
5100 if(!SiS_Pr->CRT1UsesCustomMode) {
5101
5102 CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */
5103 SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
5104 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
5105 SiS_Pr->SiS_SelectCRT2Rate = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005106 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107
5108 if(CRT1ModeNo >= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005109 /* Get VCLK */
5110 index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
5111 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005113 /* Get colordepth */
5114 colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
5115 if(!colorth) colorth++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116 }
5117
5118 } else {
5119
5120 CRT1ModeNo = 0xfe;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005121
5122 /* Get VCLK */
5123 VCLK = SiS_Pr->CSRClock_CRT1;
5124
5125 /* Get color depth */
5126 colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127
5128 }
5129
5130 if(CRT1ModeNo >= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005131 /* Get MCLK */
5132 if(SiS_Pr->ChipType == SIS_300) {
5133 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
5134 } else {
5135 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
5136 }
5137 index &= 0x07;
5138 MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005139
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005140 temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
5141 if(!temp) temp++;
5142 temp <<= 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005143
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005144 data2 = temp - ((colorth * VCLK) / MCLK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005145
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005146 temp = (28 * 16) % data2;
5147 data2 = (28 * 16) / data2;
5148 if(temp) data2++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005149
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005150 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005151
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005152 SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
5153 data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005154
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005155 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005157#ifdef SIS_LINUX_KERNEL
5158 pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
5159 pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160#else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005161 pci50 = pciReadLong(0x00000000, 0x50);
5162 pciA0 = pciReadLong(0x00000000, 0xA0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005165 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005166
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005167 index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
5168 index += (unsigned short)(((pci50 >> 9)) & 0x03);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005170 /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
5171 index = 0; /* -- do it like the BIOS anyway... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005173 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005174
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005175 pci50 >>= 24;
5176 pciA0 >>= 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005178 index = (pci50 >> 1) & 0x07;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005179
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005180 if(pci50 & 0x01) index += 6;
5181 if(!(pciA0 & 0x01)) index += 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005183 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005186
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005187 data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
5188 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005192 data += data2; /* CRT1 Request Period */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005193
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005194 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5195 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005197 if(!SiS_Pr->UseCustomMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005198
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005199 CRT2ModeNo = ModeNo;
5200 SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005201
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005202 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005204 /* Get VCLK */
5205 index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
5206 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005207
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005208 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5209 if(SiS_Pr->SiS_UseROM) {
5210 if(ROMAddr[0x220] & 0x01) {
5211 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
5212 }
5213 }
5214 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005216 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005218 /* Get VCLK */
5219 CRT2ModeNo = 0xfe;
5220 VCLK = SiS_Pr->CSRClock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005221
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005223
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005224 /* Get colordepth */
5225 colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
5226 if(!colorth) colorth++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005227
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005228 data = data * VCLK * colorth;
5229 temp = data % (MCLK << 4);
5230 data = data / (MCLK << 4);
5231 if(temp) data++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005233 if(data < 6) data = 6;
5234 else if(data > 0x14) data = 0x14;
5235
5236 if(SiS_Pr->ChipType == SIS_300) {
5237 temp = 0x16;
5238 if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
5239 temp = 0x13;
5240 } else {
5241 temp = 0x16;
5242 if(( (SiS_Pr->ChipType == SIS_630) ||
5243 (SiS_Pr->ChipType == SIS_730) ) &&
5244 (SiS_Pr->ChipRevision >= 0x30))
5245 temp = 0x1b;
5246 }
5247 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
5248
5249 if((SiS_Pr->ChipType == SIS_630) &&
5250 (SiS_Pr->ChipRevision >= 0x30)) {
5251 if(data > 0x13) data = 0x13;
5252 }
5253 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254
5255 } else { /* If mode <= 0x13, we just restore everything */
5256
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005257 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5258 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259
5260 }
5261}
5262#endif
5263
5264/* Set CRT2 FIFO on 315/330 series */
5265#ifdef SIS315H
5266static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005267SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005268{
5269 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005270 if( (SiS_Pr->ChipType == SIS_760) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271 (SiS_Pr->SiS_SysFlags & SF_760LFB) &&
5272 (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
5273 (SiS_Pr->SiS_VGAHDE >= 1280) &&
5274 (SiS_Pr->SiS_VGAVDE >= 1024) ) {
5275 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
5276 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
5277 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5278 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
5279 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5280 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
5281 } else {
5282 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
5283 }
5284
5285}
5286#endif
5287
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005288static unsigned short
5289SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005291 unsigned int tempax,tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005292
5293 tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
5294 tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
5295 tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005296 return (unsigned short)tempax;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297}
5298
5299/* Set Part 1 / SiS bridge slave mode */
5300static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005301SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
5302 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005303{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005304 unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
5305 static const unsigned short CRTranslation[] = {
5306 /* CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 */
5307 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
5308 /* CR8 CR9 SR0A SR0B SR0C SR0D SR0E CR0F */
5309 0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
5310 /* CR10 CR11 CR12 CR13 CR14 CR15 CR16 CR17 */
5311 0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
5312 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07005313
5314 if(ModeNo <= 0x13) {
5315 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316 } else if(SiS_Pr->UseCustomMode) {
5317 modeflag = SiS_Pr->CModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005318 xres = SiS_Pr->CHDisplay;
5319 } else {
5320 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321 xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
5322 }
5323
5324 /* The following is only done if bridge is in slave mode: */
5325
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005326 if(SiS_Pr->ChipType >= SIS_315H) {
5327 if(xres >= 1600) { /* BIOS: == 1600 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005328 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
5329 }
5330 }
5331
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005332 SiS_Pr->CHTotal = 8224; /* Max HT, 0x2020, results in 0x3ff in registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005334 SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
5335 if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005337 SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005339 SiS_Pr->CHBlankStart += 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005340 }
5341
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005342 SiS_Pr->CHBlankEnd = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005344 if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005347 temp = SiS_Pr->SiS_VGAHT - 96;
5348 if(!(modeflag & HalfDCLK)) temp -= 32;
5349 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
5350 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
5351 temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
5352 temp -= 3;
5353 temp <<= 3;
5354 } else {
5355 if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005356 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005357 SiS_Pr->CHSyncStart = temp;
5358
5359 SiS_Pr->CHSyncEnd = 0xffe8; /* results in 0x2000 in registers */
5360
5361 SiS_Pr->CVTotal = 2049; /* Max VT, 0x0801, results in 0x7ff in registers */
5362
5363 VGAVDE = SiS_Pr->SiS_VGAVDE;
5364 if (VGAVDE == 357) VGAVDE = 350;
5365 else if(VGAVDE == 360) VGAVDE = 350;
5366 else if(VGAVDE == 375) VGAVDE = 350;
5367 else if(VGAVDE == 405) VGAVDE = 400;
5368 else if(VGAVDE == 420) VGAVDE = 400;
5369 else if(VGAVDE == 525) VGAVDE = 480;
5370 else if(VGAVDE == 1056) VGAVDE = 1024;
5371 SiS_Pr->CVDisplay = VGAVDE;
5372
5373 SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
5374
5375 SiS_Pr->CVBlankEnd = 1;
5376 if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
5377
5378 temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
5379 SiS_Pr->CVSyncStart = VGAVDE + temp;
5380
5381 temp >>= 3;
5382 SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
5383
5384 SiS_CalcCRRegisters(SiS_Pr, 0);
5385 SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
5386
5387 for(i = 0; i <= 7; i++) {
5388 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
5389 }
5390 for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
5391 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5392 }
5393 for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
5394 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5395 }
5396 for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
5397 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5398 }
5399
5400 temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
5401 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
5402
5403 temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
5404 if(modeflag & DoubleScanMode) temp |= 0x80;
5405 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406
5407 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005408 temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
5409 if(modeflag & HalfDCLK) temp |= 0x08;
5410 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005412 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* CR14: (text mode: underline location) */
5413 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* CR17: n/a */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005415 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005417 temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005419 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* SR0E, dither[7] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420
5421 temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005422 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); /* ? */
5423
5424#ifdef SIS_XORG_XF86
5425#ifdef TWDEBUG
5426 xf86DrvMsg(0, X_INFO, "%d %d %d %d %d %d %d %d (%d %d %d %d)\n",
5427 SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
5428 SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
5429 SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
5430
5431 xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
5432 SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
5433 SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
5434 SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
5435 SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
5436 xf86DrvMsg(0, X_INFO, " 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
5437 SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
5438 SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
5439 SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
5440 SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
5441 xf86DrvMsg(0, X_INFO, " 0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
5442#endif
5443#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005444}
5445
5446/* Setup panel link
5447 * This is used for LVDS, LCDA and Chrontel TV output
5448 * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
5449 */
5450static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005451SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5452 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005453{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005454 unsigned short modeflag, resinfo = 0;
5455 unsigned short push2, tempax, tempbx, tempcx, temp;
5456 unsigned int tempeax = 0, tempebx, tempecx, tempvcfact = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005457 bool islvds = false, issis = false, chkdclkfirst = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005459 unsigned short crt2crtc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460#endif
5461#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005462 unsigned short pushcx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463#endif
5464
5465 if(ModeNo <= 0x13) {
5466 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5467 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
5468#ifdef SIS300
5469 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5470#endif
5471 } else if(SiS_Pr->UseCustomMode) {
5472 modeflag = SiS_Pr->CModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473 } else {
5474 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5475 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5476#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005477 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478#endif
5479 }
5480
5481 /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
5482 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005483 islvds = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484 }
5485
5486 /* is really sis if sis bridge, but not 301B-DH */
5487 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005488 issis = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005489 }
5490
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005491 if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005492 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005493 chkdclkfirst = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494 }
5495 }
5496
5497#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005498 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499 if(IS_SIS330) {
5500 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5501 } else if(IS_SIS740) {
5502 if(islvds) {
5503 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5504 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
5505 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5506 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5507 }
5508 } else {
5509 if(islvds) {
5510 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5511 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
5512 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5513 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005514 if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
5516 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5517 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
5518 }
5519 }
5520 }
5521 }
5522 }
5523#endif
5524
5525 /* Horizontal */
5526
5527 tempax = SiS_Pr->SiS_LCDHDES;
5528 if(islvds) {
5529 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005530 if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
5531 if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
5532 (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
5533 tempax -= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005534 }
5535 }
5536 }
5537 }
5538
5539 temp = (tempax & 0x0007);
5540 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* BPLHDESKEW[2:0] */
5541 temp = (tempax >> 3) & 0x00FF;
5542 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* BPLHDESKEW[10:3] */
5543
5544 tempbx = SiS_Pr->SiS_HDE;
5545 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5547 tempbx = SiS_Pr->PanelXRes;
5548 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005549 if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
5550 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
5551 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
5552 tempbx >>= 1;
5553 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554 }
5555
5556 tempax += tempbx;
5557 if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
5558
5559 temp = tempax;
5560 if(temp & 0x07) temp += 8;
5561 temp >>= 3;
5562 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp); /* BPLHDEE */
5563
5564 tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
5565
5566 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5567 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5568 if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
5569 }
5570 }
5571
5572 tempcx += tempax;
5573 if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
5574
5575 temp = (tempcx >> 3) & 0x00FF;
5576 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5577 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005578 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5579 switch(ModeNo) {
5580 case 0x04:
5581 case 0x05:
5582 case 0x0d: temp = 0x56; break;
5583 case 0x10: temp = 0x60; break;
5584 case 0x13: temp = 0x5f; break;
5585 case 0x40:
5586 case 0x41:
5587 case 0x4f:
5588 case 0x43:
5589 case 0x44:
5590 case 0x62:
5591 case 0x56:
5592 case 0x53:
5593 case 0x5d:
5594 case 0x5e: temp = 0x54; break;
5595 }
5596 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005597 }
5598 }
5599 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp); /* BPLHRS */
5600
5601 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5602 temp += 2;
5603 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005604 temp += 8;
5605 if(SiS_Pr->PanelHRE != 999) {
5606 temp = tempcx + SiS_Pr->PanelHRE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005607 if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
5608 temp >>= 3;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005610 }
5611 } else {
5612 temp += 10;
5613 }
5614
5615 temp &= 0x1F;
5616 temp |= ((tempcx & 0x07) << 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp); /* BPLHRE */
5618
5619 /* Vertical */
5620
5621 tempax = SiS_Pr->SiS_VGAVDE;
5622 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5623 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5624 tempax = SiS_Pr->PanelYRes;
5625 }
5626 }
5627
5628 tempbx = SiS_Pr->SiS_LCDVDES + tempax;
5629 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5630
5631 push2 = tempbx;
5632
5633 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005634 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005636 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
5638 }
5639 }
5640 }
5641 if(islvds) tempcx >>= 1;
5642 else tempcx >>= 2;
5643
5644 if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
5645 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
5646 (SiS_Pr->PanelVRS != 999) ) {
5647 tempcx = SiS_Pr->PanelVRS;
5648 tempbx += tempcx;
5649 if(issis) tempbx++;
5650 } else {
5651 tempbx += tempcx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005652 if(SiS_Pr->ChipType < SIS_315H) tempbx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005653 else if(issis) tempbx++;
5654 }
5655
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005656 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005657
5658 temp = tempbx & 0x00FF;
5659 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5660 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005661 if(ModeNo == 0x10) temp = 0xa9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005662 }
5663 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005664 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp); /* BPLVRS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005665
5666 tempcx >>= 3;
5667 tempcx++;
5668
5669 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5670 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5671 if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
5672 }
5673 }
5674
5675 tempcx += tempbx;
5676 temp = tempcx & 0x000F;
5677 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); /* BPLVRE */
5678
5679 temp = ((tempbx >> 8) & 0x07) << 3;
5680 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5681 if(SiS_Pr->SiS_HDE != 640) {
5682 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5683 }
5684 } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5685 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40;
5686 tempbx = 0x87;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005687 if((SiS_Pr->ChipType >= SIS_315H) ||
5688 (SiS_Pr->ChipRevision >= 0x30)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005689 tempbx = 0x07;
5690 if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
5691 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03) temp |= 0x80;
5692 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005693 /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005694 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5695 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5696 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
5697 } else {
5698 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
5699 }
5700 }
5701 }
5702 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
5703
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005704 tempbx = push2; /* BPLVDEE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005706 tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005707
5708 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5709 switch(SiS_Pr->SiS_LCDResInfo) {
5710 case Panel_640x480:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005711 tempbx = SiS_Pr->SiS_VGAVDE - 1;
5712 tempcx = SiS_Pr->SiS_VGAVDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005713 break;
5714 case Panel_800x600:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005715 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5716 if(resinfo == SIS_RI_800x600) tempcx++;
5717 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718 break;
5719 case Panel_1024x600:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005720 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5721 if(resinfo == SIS_RI_1024x600) tempcx++;
5722 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005723 if(resinfo == SIS_RI_800x600) tempcx++;
5724 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005726 break;
5727 case Panel_1024x768:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005728 if(SiS_Pr->ChipType < SIS_315H) {
5729 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5730 if(resinfo == SIS_RI_1024x768) tempcx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005731 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005732 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005733 break;
5734 }
5735 }
5736
5737 temp = ((tempbx >> 8) & 0x07) << 3;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005738 temp |= ((tempcx >> 8) & 0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005740 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
5741 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
5742
5743 /* Vertical scaling */
5744
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005745 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005746
5747#ifdef SIS300 /* 300 series */
5748 tempeax = SiS_Pr->SiS_VGAVDE << 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005749 temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
5750 tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751 if(temp) tempeax++;
5752
5753 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
5754
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005755 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005756 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */
5757 tempvcfact = temp;
5758#endif /* SIS300 */
5759
5760 } else {
5761
5762#ifdef SIS315H /* 315 series */
5763 tempeax = SiS_Pr->SiS_VGAVDE << 18;
5764 tempebx = SiS_Pr->SiS_VDE;
5765 temp = (tempeax % tempebx);
5766 tempeax = tempeax / tempebx;
5767 if(temp) tempeax++;
5768 tempvcfact = tempeax;
5769
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005770 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005771 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005772 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005773 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005774 temp = (unsigned short)((tempeax & 0x00030000) >> 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775 if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
5776 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
5777
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005778 if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
5779 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005781 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005782 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005783 temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
5785 temp = 0;
5786 if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
5787 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
5788 }
5789#endif
5790
5791 }
5792
5793 /* Horizontal scaling */
5794
5795 tempeax = SiS_Pr->SiS_VGAHDE; /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
5796 if(chkdclkfirst) {
5797 if(modeflag & HalfDCLK) tempeax >>= 1;
5798 }
5799 tempebx = tempeax << 16;
5800 if(SiS_Pr->SiS_HDE == tempeax) {
5801 tempecx = 0xFFFF;
5802 } else {
5803 tempecx = tempebx / SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005804 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805 if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
5806 }
5807 }
5808
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005809 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810 tempeax = (tempebx / tempecx) - 1;
5811 } else {
5812 tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
5813 }
5814 tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005815 temp = (unsigned short)(tempecx & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005816 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
5817
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005818 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005819 tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005820 tempbx = (unsigned short)(tempeax & 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821 } else {
5822 tempeax = SiS_Pr->SiS_VGAVDE << 6;
5823 tempbx = tempvcfact & 0x3f;
5824 if(tempbx == 0) tempbx = 64;
5825 tempeax /= tempbx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005826 tempbx = (unsigned short)(tempeax & 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827 }
5828 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
5829 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
5830 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
5831 else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) tempbx = 1;
5832 }
5833
5834 temp = ((tempbx >> 8) & 0x07) << 3;
5835 temp = temp | ((tempecx >> 8) & 0x07);
5836 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
5837 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
5838
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005839 tempecx >>= 16; /* BPLHCFACT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005840 if(!chkdclkfirst) {
5841 if(modeflag & HalfDCLK) tempecx >>= 1;
5842 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005843 temp = (unsigned short)((tempecx & 0xFF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005844 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005845 temp = (unsigned short)(tempecx & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
5847
5848#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005849 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005850 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005851 if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005852 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
5853 }
5854 } else {
5855 if(islvds) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005856 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005857 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
5858 } else {
5859 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
5860 }
5861 }
5862 }
5863 }
5864#endif
5865
5866#ifdef SIS300
5867 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005868 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5869 unsigned char *trumpdata;
5870 int i, j = crt2crtc;
5871 unsigned char TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 };
5872 unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
5873 unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
5874
5875 if(SiS_Pr->SiS_UseROM) {
5876 trumpdata = &ROMAddr[0x8001 + (j * 80)];
5877 } else {
5878 if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
5879 trumpdata = &SiS300_TrumpionData[j][0];
5880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881
5882 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
5883 for(i=0; i<5; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005884 SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005885 }
5886 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005887 if(ModeNo == 0x13) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888 for(i=0; i<4; i++) {
5889 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
5890 }
5891 } else if(ModeNo == 0x10) {
5892 for(i=0; i<4; i++) {
5893 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
5894 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
5895 }
5896 }
5897 }
5898 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
5899 }
5900#endif
5901
5902#ifdef SIS315H
5903 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5904 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
5905 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
5906 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
5907 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
5908 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
5909 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
5910 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005911 tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
5912 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5913 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5914 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915 tempax += 64;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005916 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
5917 temp = (tempax >> 8) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005918 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005919 tempax += 32; /* Blpe = lBlps+32 */
5920 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
5921 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml = 0 */
5922 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005923
5924 tempax = SiS_Pr->SiS_VDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005925 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5926 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5927 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928 tempax >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005929 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
5930 temp = (tempax >> 8) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
5932
5933 tempeax = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005934 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5935 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5936 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
5937 tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
5938 temp = tempeax & 0x7f;
5939 tempeax >>= 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005940 if(temp) tempeax++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005941 temp = tempeax & 0x3f;
5942 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
5943 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
5945 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005946 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947
5948 tempax = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005949 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5950 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5951 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5952 tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005953 pushcx = tempax;
5954 temp = tempax & 0x00FF;
5955 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
5956 temp = ((tempax & 0xFF00) >> 8) << 3;
5957 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
5958
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005959 tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
5960 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5961 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5962 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5963 tempeax = tempax * pushcx;
5964 temp = tempeax & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005966 temp = (tempeax & 0xFF00) >> 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005967 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005968 temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005969 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005970 temp = ((tempeax & 0x01000000) >> 24) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005971 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
5972
5973 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
5974 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
5975 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
5976 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
5977 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
5978
5979 if(SiS_Pr->SiS_IF_DEF_FSTN) {
5980 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
5981 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
5982 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
5983 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
5984 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
5985 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
5986 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
5987 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
5988 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
5989 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
5990 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
5991 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
5992 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
5993 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
5994 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
5995 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
5996 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
5997 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
5998 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
5999 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
6000 }
6001 }
6002#endif /* SIS315H */
6003}
6004
6005/* Set Part 1 */
6006static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006007SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6008 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006009{
6010#if defined(SIS300) || defined(SIS315H)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006011 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006012#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006013 unsigned short temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
6014 unsigned short pushbx=0, CRT1Index=0, modeflag, resinfo=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006016 unsigned short tempbl=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017#endif
6018
6019 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006020 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021 return;
6022 }
6023
6024 if(ModeNo <= 0x13) {
6025 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6026 } else if(SiS_Pr->UseCustomMode) {
6027 modeflag = SiS_Pr->CModeFlag;
6028 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006029 CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006030 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
6031 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6032 }
6033
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006034 SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006035
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006036 if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037 (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
6038 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
6039
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006040 if(SiS_Pr->ChipType < SIS_315H ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006041#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006042 SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006043#endif
6044 } else {
6045#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006046 SiS_SetCRT2FIFO_310(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006047#endif
6048 }
6049
6050 /* 1. Horizontal setup */
6051
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006052 if(SiS_Pr->ChipType < SIS_315H ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006053
6054#ifdef SIS300 /* ------------- 300 series --------------*/
6055
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006056 temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
6057 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006059 temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
6060 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006061
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006062 temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
6063 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064
6065 pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA2HRS 0x0B,0x0C */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006066 tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
6067 tempbx = pushbx + tempcx;
6068 tempcx <<= 1;
6069 tempcx += tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006070
6071 bridgeadd = 12;
6072
6073#endif /* SIS300 */
6074
6075 } else {
6076
6077#ifdef SIS315H /* ------------------- 315/330 series --------------- */
6078
6079 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */
6080 if(modeflag & HalfDCLK) {
6081 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6082 tempcx >>= 1;
6083 } else {
6084 tempax = SiS_Pr->SiS_VGAHDE >> 1;
6085 tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
6086 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
6087 tempcx = SiS_Pr->SiS_HT - tempax;
6088 }
6089 }
6090 }
6091 tempcx--;
6092 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx); /* CRT2 Horizontal Total */
6093 temp = (tempcx >> 4) & 0xF0;
6094 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp); /* CRT2 Horizontal Total Overflow [7:4] */
6095
6096 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HDEE 0x0A,0x0C */
6097 tempbx = SiS_Pr->SiS_VGAHDE;
6098 tempcx -= tempbx;
6099 tempcx >>= 2;
6100 if(modeflag & HalfDCLK) {
6101 tempbx >>= 1;
6102 tempcx >>= 1;
6103 }
6104 tempbx += 16;
6105
6106 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx); /* CRT2 Horizontal Display Enable End */
6107
6108 pushbx = tempbx;
6109 tempcx >>= 1;
6110 tempbx += tempcx;
6111 tempcx += tempbx;
6112
6113 bridgeadd = 16;
6114
6115 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006116 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117 if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
6118 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
6119 if(resinfo == SIS_RI_1280x1024) {
6120 tempcx = (tempcx & 0xff00) | 0x30;
6121 } else if(resinfo == SIS_RI_1600x1200) {
6122 tempcx = (tempcx & 0xff00) | 0xff;
6123 }
6124 }
6125 }
6126 }
6127
6128#endif /* SIS315H */
6129
6130 } /* 315/330 series */
6131
6132 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6133
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006134 if(SiS_Pr->UseCustomMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006135 tempbx = SiS_Pr->CHSyncStart + bridgeadd;
6136 tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
6137 tempax = SiS_Pr->SiS_VGAHT;
6138 if(modeflag & HalfDCLK) tempax >>= 1;
6139 tempax--;
6140 if(tempcx > tempax) tempcx = tempax;
6141 }
6142
6143 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6144 unsigned char cr4, cr14, cr5, cr15;
6145 if(SiS_Pr->UseCustomMode) {
6146 cr4 = SiS_Pr->CCRT1CRTC[4];
6147 cr14 = SiS_Pr->CCRT1CRTC[14];
6148 cr5 = SiS_Pr->CCRT1CRTC[5];
6149 cr15 = SiS_Pr->CCRT1CRTC[15];
6150 } else {
6151 cr4 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
6152 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
6153 cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
6154 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
6155 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006156 tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
6157 tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006158 tempcx &= 0x00FF;
6159 tempcx |= (tempbx & 0xFF00);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006160 tempbx += bridgeadd;
6161 tempcx += bridgeadd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162 tempax = SiS_Pr->SiS_VGAHT;
6163 if(modeflag & HalfDCLK) tempax >>= 1;
6164 tempax--;
6165 if(tempcx > tempax) tempcx = tempax;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006166 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006167
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006168 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
6169 tempbx = 1040;
6170 tempcx = 1044; /* HWCursor bug! */
6171 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006172
6173 }
6174
6175 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx); /* CRT2 Horizontal Retrace Start */
6176
6177 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx); /* CRT2 Horizontal Retrace End */
6178
6179 temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
6180 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp); /* Overflow */
6181
6182 /* 2. Vertical setup */
6183
6184 tempcx = SiS_Pr->SiS_VGAVT - 1;
6185 temp = tempcx & 0x00FF;
6186
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006187 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006188 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006189 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006190 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6191 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6192 temp--;
6193 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006195 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006196 temp--;
6197 }
6198 } else if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006199 temp--;
6200 }
6201 }
6202 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp); /* CRT2 Vertical Total */
6203
6204 tempbx = SiS_Pr->SiS_VGAVDE - 1;
6205 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx); /* CRT2 Vertical Display Enable End */
6206
6207 temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
6208 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp); /* Overflow */
6209
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006210 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
6211 tempbx++;
6212 tempax = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006213 tempcx++;
6214 tempcx -= tempax;
6215 tempcx >>= 2;
6216 tempbx += tempcx;
6217 if(tempcx < 4) tempcx = 4;
6218 tempcx >>= 2;
6219 tempcx += tempbx;
6220 tempcx++;
6221 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006222 tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
6223 tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224 }
6225
6226 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6227 if(SiS_Pr->UseCustomMode) {
6228 tempbx = SiS_Pr->CVSyncStart;
6229 tempcx = SiS_Pr->CVSyncEnd;
6230 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006231 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006232 unsigned char cr8, cr7, cr13;
6233 if(SiS_Pr->UseCustomMode) {
6234 cr8 = SiS_Pr->CCRT1CRTC[8];
6235 cr7 = SiS_Pr->CCRT1CRTC[7];
6236 cr13 = SiS_Pr->CCRT1CRTC[13];
6237 tempcx = SiS_Pr->CCRT1CRTC[9];
6238 } else {
6239 cr8 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
6240 cr7 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
6241 cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
6242 tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
6243 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006244 tempbx = cr8;
6245 if(cr7 & 0x04) tempbx |= 0x0100;
6246 if(cr7 & 0x80) tempbx |= 0x0200;
6247 if(cr13 & 0x08) tempbx |= 0x0400;
6248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249 }
6250 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx); /* CRT2 Vertical Retrace Start */
6251
6252 temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
6253 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp); /* CRT2 Vert. Retrace End; Overflow */
6254
6255 /* 3. Panel delay compensation */
6256
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006257 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258
6259#ifdef SIS300 /* ---------- 300 series -------------- */
6260
6261 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6262 temp = 0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006263 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264 temp = 0x10;
6265 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) temp = 0x2c;
6266 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6267 }
6268 if(SiS_Pr->SiS_VBType & VB_SIS301) {
6269 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6270 }
6271 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) temp = 0x24;
6272 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) temp = 0x2c;
6273 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08;
6274 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006275 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
6276 else temp = 0x20;
6277 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006278 if(SiS_Pr->SiS_UseROM) {
6279 if(ROMAddr[0x220] & 0x80) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006280 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
6281 temp = ROMAddr[0x221];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006282 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
6283 temp = ROMAddr[0x222];
6284 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
6285 temp = ROMAddr[0x223];
6286 else
6287 temp = ROMAddr[0x224];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006288 }
6289 }
6290 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006291 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006292 }
6293
6294 } else {
6295 temp = 0x20;
6296 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6297 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
6298 }
6299 if(SiS_Pr->SiS_UseROM) {
6300 if(ROMAddr[0x220] & 0x80) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006301 temp = ROMAddr[0x220];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006302 }
6303 }
6304 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006305 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006306 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006307 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006308
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006309 temp &= 0x3c;
6310
6311 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 -07006312
6313#endif /* SIS300 */
6314
6315 } else {
6316
6317#ifdef SIS315H /* --------------- 315/330 series ---------------*/
6318
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006319 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006320
6321 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6322
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006323 if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
6324 else temp = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006325
6326 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
6327 tempbl = 0xF0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006328 if(SiS_Pr->ChipType == SIS_650) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006329 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6330 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
6331 }
6332 }
6333
6334 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
6335 temp = 0x08;
6336 tempbl = 0;
6337 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
6338 if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
6339 }
6340 }
6341
6342 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp); /* Panel Link Delay Compensation */
6343 }
6344
6345 } /* < 661 */
6346
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006347 tempax = 0;
6348 if(modeflag & DoubleScanMode) tempax |= 0x80;
6349 if(modeflag & HalfDCLK) tempax |= 0x40;
6350 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006351
6352#endif /* SIS315H */
6353
6354 }
6355
6356 } /* Slavemode */
6357
6358 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6359 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006360 /* For 301BDH with LCD, we set up the Panel Link */
6361 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006362 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006363 SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006364 }
6365 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006366 if(SiS_Pr->ChipType < SIS_315H) {
6367 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006368 } else {
6369 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006370 if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6371 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
6372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006373 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006374 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006375 }
6376 }
6377 }
6378}
6379
6380/*********************************************/
6381/* SET PART 2 REGISTER GROUP */
6382/*********************************************/
6383
6384#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006385static unsigned char *
6386SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006387{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006388 const unsigned char *tableptr = NULL;
6389 unsigned short a, b, p = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006390
6391 a = SiS_Pr->SiS_VGAHDE;
6392 b = SiS_Pr->SiS_HDE;
6393 if(tabletype) {
6394 a = SiS_Pr->SiS_VGAVDE;
6395 b = SiS_Pr->SiS_VDE;
6396 }
6397
6398 if(a < b) {
6399 tableptr = SiS_Part2CLVX_1;
6400 } else if(a == b) {
6401 tableptr = SiS_Part2CLVX_2;
6402 } else {
6403 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6404 tableptr = SiS_Part2CLVX_4;
6405 } else {
6406 tableptr = SiS_Part2CLVX_3;
6407 }
6408 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6409 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) tableptr = SiS_Part2CLVX_3;
6410 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tableptr = SiS_Part2CLVX_3;
6411 else tableptr = SiS_Part2CLVX_5;
6412 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6413 tableptr = SiS_Part2CLVX_6;
6414 }
6415 do {
6416 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
6417 p += 0x42;
6418 } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
6419 if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
6420 }
6421 p += 2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006422 return ((unsigned char *)&tableptr[p]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006423}
6424
6425static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006426SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6427 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006428{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006429 unsigned char *tableptr;
6430 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006431 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006432
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006433 if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006435 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006436 for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
6437 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6438 }
6439 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006440 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006441 for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
6442 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6443 }
6444 }
6445 temp = 0x10;
6446 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
6447 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
6448}
6449
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006450static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006451SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
6452 unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
6453 unsigned short *ResIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006454{
6455
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006456 if(SiS_Pr->ChipType < SIS_315H) return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457
6458 if(ModeNo <= 0x13)
6459 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6460 else
6461 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6462
6463 (*ResIndex) &= 0x3f;
6464 (*CRT2Index) = 0;
6465
6466 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6467 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6468 (*CRT2Index) = 200;
6469 }
6470 }
6471
6472 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
6473 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6474 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
6475 }
6476 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006477 return (((*CRT2Index) != 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006478}
6479#endif
6480
6481#ifdef SIS300
6482static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006483SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006484{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006485 unsigned short tempcx;
6486 static const unsigned char atable[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006487 0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
6488 0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
6489 };
6490
6491 if(!SiS_Pr->UseCustomMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006492 if( ( ( (SiS_Pr->ChipType == SIS_630) ||
6493 (SiS_Pr->ChipType == SIS_730) ) &&
6494 (SiS_Pr->ChipRevision > 2) ) &&
6495 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
6496 (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
6497 (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
6498 if(ModeNo == 0x13) {
6499 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
6500 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
6501 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
6502 } else if((crt2crtc & 0x3F) == 4) {
6503 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
6504 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
6505 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
6506 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
6507 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
6508 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006509 }
6510
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006511 if(SiS_Pr->ChipType < SIS_315H) {
6512 if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
6513 crt2crtc &= 0x1f;
6514 tempcx = 0;
6515 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6516 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6517 tempcx += 7;
6518 }
6519 }
6520 tempcx += crt2crtc;
6521 if(crt2crtc >= 4) {
6522 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
6523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006524
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006525 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6526 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6527 if(crt2crtc == 4) {
6528 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
6529 }
6530 }
6531 }
6532 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
6533 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
6534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006535 }
6536 }
6537}
6538
6539/* For ECS A907. Highly preliminary. */
6540static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006541SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
6542 unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006543{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006544 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6545 unsigned short crt2crtc, resindex;
6546 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006547
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006548 if(SiS_Pr->ChipType != SIS_300) return;
6549 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006550 if(SiS_Pr->UseCustomMode) return;
6551
6552 if(ModeNo <= 0x13) {
6553 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6554 } else {
6555 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6556 }
6557
6558 resindex = crt2crtc & 0x3F;
6559 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6560 else CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
6561
6562 /* The BIOS code (1.16.51,56) is obviously a fragment! */
6563 if(ModeNo > 0x13) {
6564 CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6565 resindex = 4;
6566 }
6567
6568 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6569 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6570 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006571 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006572 }
6573 for(j = 0x1c; j <= 0x1d; 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 = 0x1f; j <= 0x21; 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 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6580 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6581}
6582#endif
6583
6584static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006585SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006586{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006587 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006588 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
6589 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
6590
6591 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6592 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006593 const unsigned char specialtv[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006594 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
6595 0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
6596 0x58,0xe4,0x73,0xda,0x13
6597 };
6598 int i, j;
6599 for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
6600 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
6601 }
6602 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
6603 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
6604 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6605 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
6606 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
6607 } else {
6608 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14); /* 15 */
6609 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a); /* 1b */
6610 }
6611 }
6612 }
6613 } else {
6614 if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
6615 (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
6616 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b); /* 21 */
6617 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54); /* 5a */
6618 } else {
6619 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a); /* 21 */
6620 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53); /* 5a */
6621 }
6622 }
6623}
6624
6625static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006626SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006627{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006628 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006629
6630 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6631 if(SiS_Pr->SiS_VGAVDE == 525) {
6632 temp = 0xc3;
6633 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6634 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006635 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006636 }
6637 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6638 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
6639 } else if(SiS_Pr->SiS_VGAVDE == 420) {
6640 temp = 0x4d;
6641 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6642 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006643 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006644 }
6645 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6646 }
6647 }
6648
6649 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6650 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006651 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006652 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
6653 /* Not always for LV, see SetGrp2 */
6654 }
6655 temp = 1;
6656 if(ModeNo <= 0x13) temp = 3;
6657 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
6658 }
6659#if 0
6660 /* 651+301C, for 1280x768 - do I really need that? */
6661 if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
6662 if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
6663 if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
6664 ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
6665 SiS_SetReg(SiS_Part2Port,0x01,0x2b);
6666 SiS_SetReg(SiS_Part2Port,0x02,0x13);
6667 SiS_SetReg(SiS_Part2Port,0x04,0xe5);
6668 SiS_SetReg(SiS_Part2Port,0x05,0x08);
6669 SiS_SetReg(SiS_Part2Port,0x06,0xe2);
6670 SiS_SetReg(SiS_Part2Port,0x1c,0x21);
6671 SiS_SetReg(SiS_Part2Port,0x1d,0x45);
6672 SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
6673 SiS_SetReg(SiS_Part2Port,0x20,0x00);
6674 SiS_SetReg(SiS_Part2Port,0x21,0xa9);
6675 SiS_SetReg(SiS_Part2Port,0x23,0x0b);
6676 SiS_SetReg(SiS_Part2Port,0x25,0x04);
6677 }
6678 }
6679 }
6680#endif
6681 }
6682}
6683
6684static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006685SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6686 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006687{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006688 unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
6689 unsigned short push2, modeflag, crt2crtc, bridgeoffset;
6690 unsigned int longtemp, PhaseIndex;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006691 bool newtvphase;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006692 const unsigned char *TimingPoint;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006693#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006694 unsigned short resindex, CRT2Index;
6695 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006696
6697 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
6698#endif
6699
6700 if(ModeNo <= 0x13) {
6701 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6702 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6703 } else if(SiS_Pr->UseCustomMode) {
6704 modeflag = SiS_Pr->CModeFlag;
6705 crt2crtc = 0;
6706 } else {
6707 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6708 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6709 }
6710
6711 temp = 0;
6712 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
6713 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
6714 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) temp |= 0x02;
6715 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp |= 0x01;
6716
6717 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) temp |= 0x10;
6718
6719 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
6720
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006721 PhaseIndex = 0x01; /* SiS_PALPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006722 TimingPoint = SiS_Pr->SiS_PALTiming;
6723
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006724 newtvphase = false;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006725 if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
6726 ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6727 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006728 newtvphase = true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006729 }
6730
Linus Torvalds1da177e2005-04-16 15:20:36 -07006731 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6732
6733 TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
6734 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6735 TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
6736 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6737 TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006738 }
6739 }
6740
6741 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6742
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006743 i = 0;
6744 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) i = 2;
6745 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006746
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006747 TimingPoint = &SiS_YPbPrTable[i][0];
6748
6749 PhaseIndex = 0x00; /* SiS_NTSCPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006750
6751 } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6752
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006753 if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006754
6755 } else {
6756
6757 TimingPoint = SiS_Pr->SiS_NTSCTiming;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006758 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00; /* SiS_PALPhase : SiS_NTSCPhase */
6759 if(newtvphase) PhaseIndex += 8; /* SiS_PALPhase2 : SiS_NTSCPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006760
6761 }
6762
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006763 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
6764 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03; /* SiS_PALMPhase : SiS_PALNPhase */
6765 if(newtvphase) PhaseIndex += 8; /* SiS_PALMPhase2 : SiS_PALNPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006766 }
6767
6768 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006769 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006770 PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006771 } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006772 PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
6773 } else {
6774 PhaseIndex = 0x10; /* SiS_SpecialPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006775 }
6776 }
6777
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006778 for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
6779 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006780 }
6781
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006782 for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006783 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6784 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006785 for(i = 0x39; i <= 0x45; i++, j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006786 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6787 }
6788
6789 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6790 if(SiS_Pr->SiS_ModeType != ModeText) {
6791 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
6792 }
6793 }
6794
6795 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
6796
6797 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
6798 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
6799 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
6800 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
6801
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006802 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950;
6803 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempax = 680;
6804 else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520;
6805 else tempax = 440; /* NTSC, YPbPr 525 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006806
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006807 if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07006808 ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
6809 ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
6810
6811 tempax -= SiS_Pr->SiS_VDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006812 tempax >>= 1;
6813 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
6814 tempax >>= 1;
6815 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006816 tempax &= 0x00ff;
6817
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006818 temp = tempax + (unsigned short)TimingPoint[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
6820
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006821 temp = tempax + (unsigned short)TimingPoint[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006822 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
6823
6824 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
6825 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006826 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
6827 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006828 } else {
6829 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
6830 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
6831 }
6832 }
6833
6834 }
6835
6836 tempcx = SiS_Pr->SiS_HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006837 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006838 tempcx--;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006839 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006840 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
6841 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
6842
6843 tempcx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006844 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006845 tempcx += 7;
6846 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6847 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
6848
6849 tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
6850 tempbx += tempcx;
6851 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
6852 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
6853
6854 tempbx += 8;
6855 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6856 tempbx -= 4;
6857 tempcx = tempbx;
6858 }
6859 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
6860
6861 j += 2;
6862 tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
6863 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
6864 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
6865
6866 tempcx += 8;
6867 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6868 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
6869
6870 tempcx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006871 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006872 j += 2;
6873 tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
6874 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
6875
6876 tempcx -= 11;
6877 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6878 tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
6879 }
6880 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
6881
6882 tempbx = SiS_Pr->SiS_VDE;
6883 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6884 if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
6885 if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
6886 if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
6887 } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6888 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
6889 tempbx >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006890 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006891 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6892 if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
6893 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6894 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6895 if(crt2crtc == 4) tempbx++;
6896 }
6897 }
6898 }
6899 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6900 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6901 if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
6902 }
6903 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6904 if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
6905 }
6906 }
6907 }
6908 tempbx -= 2;
6909 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
6910
6911 temp = (tempcx >> 8) & 0x0F;
6912 temp |= ((tempbx >> 2) & 0xC0);
6913 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6914 temp |= 0x10;
6915 if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
6916 }
6917 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
6918
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006919 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006920 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
6921 }
6922
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006923 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006924 tempbx = SiS_Pr->SiS_VDE;
6925 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6926 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
6927 tempbx >>= 1;
6928 }
6929 tempbx -= 3;
6930 temp = ((tempbx >> 3) & 0x60) | 0x18;
6931 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
6932 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
6933
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006934 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006935 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
6936 }
6937 }
6938
6939 tempbx = 0;
6940 if(!(modeflag & HalfDCLK)) {
6941 if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
6942 tempax = 0;
6943 tempbx |= 0x20;
6944 }
6945 }
6946
6947 tempch = tempcl = 0x01;
6948 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006949 if(SiS_Pr->SiS_VGAHDE >= 960) {
6950 if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006951 tempcl = 0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006952 if(SiS_Pr->SiS_VGAHDE >= 1280) {
6953 tempch = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006954 tempbx &= ~0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006955 } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
6956 tempch = 25;
6957 } else {
6958 tempch = 25; /* OK */
6959 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006960 }
6961 }
6962 }
6963
6964 if(!(tempbx & 0x20)) {
6965 if(modeflag & HalfDCLK) tempcl <<= 1;
6966 longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006967 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006968 tempax = longtemp / SiS_Pr->SiS_HDE;
6969 if(longtemp % SiS_Pr->SiS_HDE) tempax++;
6970 tempbx |= ((tempax >> 8) & 0x1F);
6971 tempcx = tempax >> 13;
6972 }
6973
6974 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
6975 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
6976
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006977 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006978
6979 tempcx &= 0x07;
6980 if(tempbx & 0x20) tempcx = 0;
6981 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
6982
6983 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6984 tempbx = 0x0382;
6985 tempcx = 0x007e;
6986 } else {
6987 tempbx = 0x0369;
6988 tempcx = 0x0061;
6989 }
6990 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
6991 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
6992 temp = (tempcx & 0x0300) >> 6;
6993 temp |= ((tempbx >> 8) & 0x03);
6994 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6995 temp |= 0x10;
6996 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp |= 0x20;
6997 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
6998 }
6999 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
7000
7001 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7002 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
7003
7004 SiS_SetTVSpecial(SiS_Pr, ModeNo);
7005
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007006 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007007 temp = 0;
7008 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
7009 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
7010 }
7011
7012 }
7013
7014 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7015 if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
7016 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
7017 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
7018 }
7019 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
7020 }
7021
7022 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7023 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
7024 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
7025 }
7026 }
7027
7028 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
7029
7030 /* From here: Part2 LCD setup */
7031
7032 tempbx = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007033 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007034 tempbx--; /* RHACTE = HDE - 1 */
7035 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
7036 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
7037
7038 temp = 0x01;
7039 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7040 if(SiS_Pr->SiS_ModeType == ModeEGA) {
7041 if(SiS_Pr->SiS_VGAHDE >= 1024) {
7042 temp = 0x02;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007043 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7044 temp = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007045 }
7046 }
7047 }
7048 }
7049 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
7050
7051 tempbx = SiS_Pr->SiS_VDE - 1;
7052 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
7053 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
7054
7055 tempcx = SiS_Pr->SiS_VT - 1;
7056 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
7057 temp = (tempcx >> 3) & 0xE0;
7058 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
7059 /* Enable dithering; only do this for 32bpp mode */
7060 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
7061 temp |= 0x10;
7062 }
7063 }
7064 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
7065
7066 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
7067 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
7068
7069 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
7070 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
7071
7072#ifdef SIS315H
7073 if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007074 &CRT2Index, &resindex)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007075 switch(CRT2Index) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007076 case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break;
7077 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07007078 case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007079 }
7080
7081 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
7082 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
7083 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
7084 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7085 }
7086 for(j = 0x1c; j <= 0x1d; i++, j++ ) {
7087 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7088 }
7089 for(j = 0x1f; j <= 0x21; i++, j++ ) {
7090 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7091 }
7092 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
7093 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
7094
7095 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7096
Linus Torvalds1da177e2005-04-16 15:20:36 -07007097 } else {
7098#endif
7099
7100 /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
7101 /* Clevo dual-link 1024x768 */
7102 /* Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct) */
7103 /* Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
7104
7105 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7106 if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7107 tempbx = SiS_Pr->SiS_VDE - 1;
7108 tempcx = SiS_Pr->SiS_VT - 1;
7109 } else {
7110 tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7111 tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7112 }
7113 } else {
7114 tempbx = SiS_Pr->PanelYRes;
7115 tempcx = SiS_Pr->SiS_VT;
7116 tempax = 1;
7117 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7118 tempax = SiS_Pr->PanelYRes;
7119 /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c; */ /* 651+301C */
7120 if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7121 tempax = tempcx = 0;
7122 } else {
7123 tempax -= SiS_Pr->SiS_VDE;
7124 }
7125 tempax >>= 1;
7126 }
7127 tempcx -= tempax; /* lcdvdes */
7128 tempbx -= tempax; /* lcdvdee */
7129 }
7130
7131 /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7132
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007133#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007134#ifdef TWDEBUG
7135 xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
7136#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007137#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007138
7139 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */
7140 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */
7141
7142 temp = (tempbx >> 5) & 0x38;
7143 temp |= ((tempcx >> 8) & 0x07);
7144 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7145
7146 tempax = SiS_Pr->SiS_VDE;
7147 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7148 tempax = SiS_Pr->PanelYRes;
7149 }
7150 tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7151 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7152 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7153 tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7154 }
7155 }
7156
7157 tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7158 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7159 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7160 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7161 tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7162 if(tempax % 4) { tempax >>= 2; tempax++; }
7163 else { tempax >>= 2; }
7164 tempbx -= (tempax - 1);
7165 } else {
7166 tempbx -= 10;
7167 if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7168 }
7169 }
7170 }
7171 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7172 tempbx++;
7173 if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7174 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7175 tempbx = 770;
7176 tempcx = 3;
7177 }
7178 }
7179 }
7180
7181 /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7182
7183 if(SiS_Pr->UseCustomMode) {
7184 tempbx = SiS_Pr->CVSyncStart;
7185 }
7186
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007187#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007188#ifdef TWDEBUG
7189 xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
7190#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007191#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007192
7193 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */
7194
7195 temp = (tempbx >> 4) & 0xF0;
7196 tempbx += (tempcx + 1);
7197 temp |= (tempbx & 0x0F);
7198
7199 if(SiS_Pr->UseCustomMode) {
7200 temp &= 0xf0;
7201 temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7202 }
7203
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007204#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007205#ifdef TWDEBUG
7206 xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
7207#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007208#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007209
7210 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7211
7212#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007213 SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007214#endif
7215
7216 bridgeoffset = 7;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007217 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) bridgeoffset += 2;
7218 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
7219 if(SiS_IsDualLink(SiS_Pr)) bridgeoffset++;
7220 else if(SiS_Pr->SiS_VBType & VB_SIS302LV) bridgeoffset++; /* OK for Asus A4L 1280x800 */
7221 /* Higher bridgeoffset shifts to the LEFT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007222
7223 temp = 0;
7224 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7225 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007226 temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7227 if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007228 }
7229 }
7230 temp += bridgeoffset;
7231 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp); /* lcdhdes */
7232 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7233
7234 tempcx = SiS_Pr->SiS_HT;
7235 tempax = tempbx = SiS_Pr->SiS_HDE;
7236 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7237 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7238 tempax = SiS_Pr->PanelXRes;
7239 tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7240 }
7241 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007242 if(SiS_IsDualLink(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007243 tempcx >>= 1;
7244 tempbx >>= 1;
7245 tempax >>= 1;
7246 }
7247
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007248#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007249#ifdef TWDEBUG
7250 xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
7251#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007252#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007253
7254 tempbx += bridgeoffset;
7255
7256 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx); /* lcdhdee */
7257 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7258
7259 tempcx = (tempcx - tempax) >> 2;
7260
7261 tempbx += tempcx;
7262 push2 = tempbx;
7263
7264 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7265 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7266 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7267 if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7268 }
7269 }
7270 }
7271
7272 if(SiS_Pr->UseCustomMode) {
7273 tempbx = SiS_Pr->CHSyncStart;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007274 if(modeflag & HalfDCLK) tempbx <<= 1;
7275 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007276 tempbx += bridgeoffset;
7277 }
7278
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007279#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007280#ifdef TWDEBUG
7281 xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
7282#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007283#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007284
7285 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */
7286 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7287
7288 tempbx = push2;
7289
7290 tempcx <<= 1;
7291 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7292 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7293 }
7294 tempbx += tempcx;
7295
7296 if(SiS_Pr->UseCustomMode) {
7297 tempbx = SiS_Pr->CHSyncEnd;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007298 if(modeflag & HalfDCLK) tempbx <<= 1;
7299 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007300 tempbx += bridgeoffset;
7301 }
7302
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007303#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07007304#ifdef TWDEBUG
7305 xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
7306#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007307#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007308
7309 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */
7310
7311 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7312
7313#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007314 SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007315#endif
7316#ifdef SIS315H
7317 } /* CRT2-LCD from table */
7318#endif
7319}
7320
7321/*********************************************/
7322/* SET PART 3 REGISTER GROUP */
7323/*********************************************/
7324
7325static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007326SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007327{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007328 unsigned short i;
7329 const unsigned char *tempdi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007330
7331 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7332
7333#ifndef SIS_CP
7334 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7335#else
7336 SIS_CP_INIT301_CP
7337#endif
7338
7339 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7340 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7341 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7342 } else {
7343 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7344 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7345 }
7346
7347 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7348 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7349 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7350 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7351 }
7352
7353 tempdi = NULL;
7354 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7355 tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7356 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7357 tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7358 }
7359 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7360 if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7361 tempdi = SiS_HiTVGroup3_1;
7362 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7363 }
7364 }
7365 if(tempdi) {
7366 for(i=0; i<=0x3E; i++) {
7367 SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7368 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007369 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007370 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7371 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7372 }
7373 }
7374 }
7375
7376#ifdef SIS_CP
7377 SIS_CP_INIT301_CP2
7378#endif
7379}
7380
7381/*********************************************/
7382/* SET PART 4 REGISTER GROUP */
7383/*********************************************/
7384
7385#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007386#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07007387static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007388SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007389{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007390 unsigned short temp, temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007391
7392 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7393 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007394 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007395 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7396 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7397 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007398 temp = (unsigned short)((int)(temp) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007399 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7400 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7401 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007402 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007403 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7404 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7405}
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007406#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007407
7408static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007409SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007410{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007411 unsigned short temp, temp1, resinfo = 0;
7412 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007413
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007414 if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007415 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7416
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007417 if(SiS_Pr->ChipType >= XGI_20) return;
7418
7419 if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
7420 if(!(ROMAddr[0x61] & 0x04)) return;
7421 }
7422
Linus Torvalds1da177e2005-04-16 15:20:36 -07007423 if(ModeNo > 0x13) {
7424 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7425 }
7426
7427 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7428 temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7429 if(!(temp & 0x01)) {
7430 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7431 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007432 if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007433 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7434 }
7435 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7436 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp = 0x0000;
7437 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7438 else if(SiS_Pr->SiS_TVMode & TVSetHiVision) temp = 0x0400;
7439 else temp = 0x0402;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007440 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007441 temp1 = 0;
7442 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7443 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7444 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7445 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007446 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7447 if(ModeNo > 0x13) {
7448 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
7449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007450 } else {
7451 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7452 if(temp1 == 0x01) temp |= 0x01;
7453 if(temp1 == 0x03) temp |= 0x04; /* ? why not 0x10? */
7454 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007455 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7456 if(ModeNo > 0x13) {
7457 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7458 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007459 }
7460
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007461#if 0
7462 if(SiS_Pr->ChipType >= SIS_661) { /* ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007463 if(SiS_Pr->SiS_TVMode & TVAspect43) {
7464 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7465 if(resinfo == SIS_RI_1024x768) {
7466 SiS_ShiftXPos(SiS_Pr, 97);
7467 } else {
7468 SiS_ShiftXPos(SiS_Pr, 111);
7469 }
7470 } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7471 SiS_ShiftXPos(SiS_Pr, 136);
7472 }
7473 }
7474 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007475#endif
7476
Linus Torvalds1da177e2005-04-16 15:20:36 -07007477 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007478
Linus Torvalds1da177e2005-04-16 15:20:36 -07007479}
7480#endif
7481
7482static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007483SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7484 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007485{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007486 unsigned short vclkindex, temp, reg1, reg2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007487
7488 if(SiS_Pr->UseCustomMode) {
7489 reg1 = SiS_Pr->CSR2B;
7490 reg2 = SiS_Pr->CSR2C;
7491 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007492 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007493 reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7494 reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7495 }
7496
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007497 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7498 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007499 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7500 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7501 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7502 } else {
7503 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7504 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7505 }
7506 } else {
7507 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7508 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7509 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7510 }
7511 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7512 temp = 0x08;
7513 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7514 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7515}
7516
7517static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007518SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007519{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007520 if(SiS_Pr->ChipType >= SIS_315H) {
7521 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
7522 if((SiS_CRT2IsLCD(SiS_Pr)) ||
7523 (SiS_IsVAMode(SiS_Pr))) {
7524 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
7525 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7526 } else {
7527 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7528 }
7529 }
7530 }
7531 }
7532 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
7533 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7534#ifdef SET_EMI
7535 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7536#endif
7537 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7538 }
7539}
7540
7541static void
7542SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7543 unsigned short RefreshRateTableIndex)
7544{
7545 unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
7546 unsigned int tempebx, tempeax, templong;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007547
7548 if(ModeNo <= 0x13) {
7549 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7550 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7551 } else if(SiS_Pr->UseCustomMode) {
7552 modeflag = SiS_Pr->CModeFlag;
7553 resinfo = 0;
7554 } else {
7555 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7556 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7557 }
7558
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007559 if(SiS_Pr->ChipType >= SIS_315H) {
7560 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7561 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7562 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007563 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007564 }
7565 }
7566
7567 if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
7568 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7569 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
7570 }
7571 }
7572
7573 if(SiS_Pr->ChipType >= SIS_315H) {
7574 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7575 SiS_SetDualLinkEtc(SiS_Pr);
7576 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007577 }
7578 }
7579
7580 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7581
7582 tempbx = SiS_Pr->SiS_RVBHCMAX;
7583 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7584
7585 temp = (tempbx >> 1) & 0x80;
7586
7587 tempcx = SiS_Pr->SiS_VGAHT - 1;
7588 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7589
7590 temp |= ((tempcx >> 5) & 0x78);
7591
7592 tempcx = SiS_Pr->SiS_VGAVT - 1;
7593 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7594 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7595
7596 temp |= ((tempcx >> 8) & 0x07);
7597 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7598
7599 tempbx = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007600 if(modeflag & HalfDCLK) tempbx >>= 1;
7601 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007602
7603 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7604 temp = 0;
7605 if(tempbx > 800) temp = 0x60;
7606 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7607 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007608 if(tempbx > 1024) temp = 0xC0;
7609 else if(tempbx >= 960) temp = 0xA0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007610 } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7611 temp = 0;
7612 if(tempbx >= 1280) temp = 0x40;
7613 else if(tempbx >= 1024) temp = 0x20;
7614 } else {
7615 temp = 0x80;
7616 if(tempbx >= 1024) temp = 0xA0;
7617 }
7618
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007619 temp |= SiS_Pr->Init_P4_0E;
7620
Linus Torvalds1da177e2005-04-16 15:20:36 -07007621 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007622 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
7623 temp &= 0xf0;
7624 temp |= 0x0A;
7625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007626 }
7627
7628 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7629
7630 tempeax = SiS_Pr->SiS_VGAVDE;
7631 tempebx = SiS_Pr->SiS_VDE;
7632 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7633 if(!(temp & 0xE0)) tempebx >>=1;
7634 }
7635
7636 tempcx = SiS_Pr->SiS_RVBHRS;
7637 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7638 tempcx >>= 8;
7639 tempcx |= 0x40;
7640
7641 if(tempeax <= tempebx) {
7642 tempcx ^= 0x40;
7643 } else {
7644 tempeax -= tempebx;
7645 }
7646
7647 tempeax *= (256 * 1024);
7648 templong = tempeax % tempebx;
7649 tempeax /= tempebx;
7650 if(templong) tempeax++;
7651
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007652 temp = (unsigned short)(tempeax & 0x000000FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007653 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007654 temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007655 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007656 temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007657 temp |= (tempcx & 0x4F);
7658 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7659
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007660 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007661
7662 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7663
7664 /* Calc Linebuffer max address and set/clear decimode */
7665 tempbx = 0;
7666 if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7667 tempax = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007668 if(modeflag & HalfDCLK) tempax >>= 1;
7669 if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007670 if(tempax > 800) {
7671 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7672 tempax -= 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007673 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007674 tempbx = 0x08;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007675 if(tempax == 960) tempax *= 25; /* Correct */
7676 else if(tempax == 1024) tempax *= 25;
7677 else tempax *= 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007678 temp = tempax % 32;
7679 tempax /= 32;
7680 if(temp) tempax++;
7681 tempax++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007682 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7683 if(resinfo == SIS_RI_1024x768 ||
7684 resinfo == SIS_RI_1024x576 ||
7685 resinfo == SIS_RI_1280x1024 ||
7686 resinfo == SIS_RI_1280x720) {
7687 /* Otherwise white line or garbage at right edge */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007688 tempax = (tempax & 0xff00) | 0x20;
7689 }
7690 }
7691 }
7692 }
7693 tempax--;
7694 temp = ((tempax >> 4) & 0x30) | tempbx;
7695 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7696 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7697
7698 temp = 0x0036; tempbx = 0xD0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007699 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007700 temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7701 }
7702 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7703 if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7704 temp |= 0x01;
7705 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7706 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7707 temp &= ~0x01;
7708 }
7709 }
7710 }
7711 }
7712 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7713
7714 tempbx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007715 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007716 tempbx -= 2;
7717 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7718 temp = (tempbx >> 5) & 0x38;
7719 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7720
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007721 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007722 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7723 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7724 /* LCD-too-dark-error-source, see FinalizeLCD() */
7725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007726 }
7727
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007728 SiS_SetDualLinkEtc(SiS_Pr);
7729
Linus Torvalds1da177e2005-04-16 15:20:36 -07007730 } /* 301B */
7731
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007732 SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007733}
7734
7735/*********************************************/
7736/* SET PART 5 REGISTER GROUP */
7737/*********************************************/
7738
7739static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007740SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007741{
7742
7743 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7744
7745 if(SiS_Pr->SiS_ModeType == ModeVGA) {
7746 if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7747 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007748 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007749 }
7750 }
7751}
7752
7753/*********************************************/
7754/* MODIFY CRT1 GROUP FOR SLAVE MODE */
7755/*********************************************/
7756
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007757static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007758SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7759 unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
7760 unsigned short *DisplayType)
7761 {
7762 unsigned short modeflag = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007763 bool checkhd = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007764
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007765 /* Pass 1:1 not supported here */
7766
7767 if(ModeNo <= 0x13) {
7768 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7769 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7770 } else {
7771 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7772 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7773 }
7774
7775 (*ResIndex) &= 0x3F;
7776
7777 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7778
7779 (*DisplayType) = 80;
7780 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
7781 (*DisplayType) = 82;
7782 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7783 if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
7784 }
7785 }
7786 if((*DisplayType) != 84) {
7787 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
7788 }
7789
7790 } else {
7791
7792 (*DisplayType = 0);
7793 switch(SiS_Pr->SiS_LCDResInfo) {
7794 case Panel_320x240_1: (*DisplayType) = 50;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007795 checkhd = false;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007796 break;
7797 case Panel_320x240_2: (*DisplayType) = 14;
7798 break;
7799 case Panel_320x240_3: (*DisplayType) = 18;
7800 break;
7801 case Panel_640x480: (*DisplayType) = 10;
7802 break;
7803 case Panel_1024x600: (*DisplayType) = 26;
7804 break;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007805 default: return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007806 }
7807
7808 if(checkhd) {
7809 if(modeflag & HalfDCLK) (*DisplayType)++;
7810 }
7811
7812 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
7813 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
7814 }
7815
7816 }
7817
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007818 return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007819}
7820
7821static void
7822SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7823 unsigned short RefreshRateTableIndex)
7824{
7825 unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
7826 const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
7827 static const unsigned short CRIdx[] = {
7828 0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
7829 0x07, 0x10, 0x11, 0x15, 0x16
7830 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07007831
7832 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
7833 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007834 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
7835 (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
Linus Torvalds1da177e2005-04-16 15:20:36 -07007836 return;
7837
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007838 if(SiS_Pr->SiS_IF_DEF_LVDS) {
7839 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7840 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7841 }
7842 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
7843 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7844 } else return;
7845
7846 if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
7847
7848 if(SiS_Pr->ChipType < SIS_315H) {
7849 if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
7850 }
7851
Linus Torvalds1da177e2005-04-16 15:20:36 -07007852 if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7853 &ResIndex, &DisplayType))) {
7854 return;
7855 }
7856
Linus Torvalds1da177e2005-04-16 15:20:36 -07007857 switch(DisplayType) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007858 case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1; break; /* xSTN */
7859 case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2; break; /* xSTN */
7860 case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H; break; /* xSTN */
7861 case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3; break; /* xSTN */
7862 case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H; break; /* xSTN */
7863 case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
7864 case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
7865#if 0 /* Works better with calculated numbers */
7866 case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break;
7867 case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break;
7868 case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break;
7869 case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break;
7870#endif
7871 case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break;
7872 case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break;
7873 case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break;
7874 case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
7875 case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007876 }
7877
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007878 if(LVDSCRT1Ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007879
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007880 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007881
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007882 for(i = 0; i <= 10; i++) {
7883 tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
7884 SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
7885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007886
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007887 for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
7888 tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
7889 SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
7890 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007891
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007892 tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
7893 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
7894
7895 if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7896 else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7897
7898 tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
7899 if(modeflag & DoubleScanMode) tempah |= 0x80;
7900 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
7901
7902 } else {
7903
7904 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
7905
7906 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007907}
7908
7909/*********************************************/
7910/* SET CRT2 ECLK */
7911/*********************************************/
7912
7913static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007914SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7915 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007916{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007917 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
7918 unsigned short clkbase, vclkindex = 0;
7919 unsigned char sr2b, sr2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007920
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007921 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7922 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
7923 if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
7924 RefreshRateTableIndex--;
7925 }
7926 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7927 RefreshRateTableIndex);
7928 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007929 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007930 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7931 RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007932 }
7933
7934 sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
7935 sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
7936
7937 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
7938 if(SiS_Pr->SiS_UseROM) {
7939 if(ROMAddr[0x220] & 0x01) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007940 sr2b = ROMAddr[0x227];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007941 sr2c = ROMAddr[0x228];
7942 }
7943 }
7944 }
7945
7946 clkbase = 0x02B;
7947 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7948 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007949 clkbase += 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007950 }
7951 }
7952
7953 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
7954 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7955 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7956 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
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,0x00);
7960 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7961 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7962}
7963
7964/*********************************************/
7965/* SET UP CHRONTEL CHIPS */
7966/*********************************************/
7967
7968static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007969SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7970 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007971{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007972 unsigned short TVType, resindex;
7973 const struct SiS_CHTVRegData *CHTVRegData = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007974
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007975 if(ModeNo <= 0x13)
7976 resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7977 else
7978 resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007979
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007980 resindex &= 0x3F;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007981
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007982 TVType = 0;
7983 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7984 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7985 TVType += 2;
7986 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7987 if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
7988 }
7989 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7990 TVType = 4;
7991 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7992 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
7993 TVType = 6;
7994 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7995 }
7996 }
7997
7998 switch(TVType) {
7999 case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
8000 case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
8001 case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break;
8002 case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
8003 case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
8004 case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
8005 case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
8006 case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
8007 case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
8008 default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
8009 }
8010
8011
8012 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008013
8014#ifdef SIS300
8015
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008016 /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008017
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008018 /* We don't support modes >800x600 */
8019 if (resindex > 5) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008020
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008021 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
8022 SiS_SetCH700x(SiS_Pr,0x04,0x43); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
8023 SiS_SetCH700x(SiS_Pr,0x09,0x69); /* Black level for PAL (105)*/
8024 } else {
8025 SiS_SetCH700x(SiS_Pr,0x04,0x03); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
8026 SiS_SetCH700x(SiS_Pr,0x09,0x71); /* Black level for NTSC (113)*/
8027 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008028
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008029 SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]); /* Mode register */
8030 SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]); /* Start active video register */
8031 SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]); /* Position overflow register */
8032 SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]); /* Horiz Position register */
8033 SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]); /* Vertical Position register */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008034
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008035 /* Set minimum flicker filter for Luma channel (SR1-0=00),
Linus Torvalds1da177e2005-04-16 15:20:36 -07008036 minimum text enhancement (S3-2=10),
8037 maximum flicker filter for Chroma channel (S5-4=10)
8038 =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008039 */
8040 SiS_SetCH700x(SiS_Pr,0x01,0x28);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008041
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008042 /* Set video bandwidth
Adrian Bunk9aaeded2006-06-30 18:19:55 +02008043 High bandwidth Luma composite video filter(S0=1)
8044 low bandwidth Luma S-video filter (S2-1=00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008045 disable peak filter in S-video channel (S3=0)
8046 high bandwidth Chroma Filter (S5-4=11)
8047 =00110001=0x31
Linus Torvalds1da177e2005-04-16 15:20:36 -07008048 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008049 SiS_SetCH700x(SiS_Pr,0x03,0xb1); /* old: 3103 */
8050
8051 /* Register 0x3D does not exist in non-macrovision register map
8052 (Maybe this is a macrovision register?)
8053 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008054#ifndef SIS_CP
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008055 SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008056#endif
8057
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008058 /* Register 0x10 only contains 1 writable bit (S0) for sensing,
8059 all other bits a read-only. Macrovision?
8060 */
8061 SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008062
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008063 /* Register 0x11 only contains 3 writable bits (S0-S2) for
8064 contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
8065 */
8066 SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008067
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008068 /* Clear DSEN
8069 */
8070 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008071
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008072 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */
8073 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
8074 if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */
8075 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8076 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on, no need to set FSCI */
8077 } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */
8078 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */
8079 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
8080 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
8081 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
8082 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
8083 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
8084 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
8085 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
8086 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF); /* Loop filter on for mode 23 */
8087 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); /* ACIV off, need to set FSCI */
8088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008089 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008090 if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */
8091 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8092 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
8093 } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */
8094#if 0
8095 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
8096 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0); /* FSCI for mode 24 is 428,554,851 */
8097 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0); /* 198b3a63 */
8098 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
8099 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
8100 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
8101 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
8102 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
8103 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off for mode 24 */
8104 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); * ACIV off, need to set FSCI */
8105#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */
8106 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8107 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
8108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008109 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008110 } else { /* ---- PAL ---- */
8111 /* We don't play around with FSCI in PAL mode */
8112 if(resindex == 0x04) {
8113 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8114 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
8115 } else {
8116 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
8117 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
8118 }
8119 }
8120
Linus Torvalds1da177e2005-04-16 15:20:36 -07008121#endif /* 300 */
8122
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008123 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008124
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008125 /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008126
8127#ifdef SIS315H
8128
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008129 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008130
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008131 /* We don't support modes >1024x768 */
8132 if (resindex > 6) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008133
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008134 temp = CHTVRegData[resindex].Reg[0];
8135 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
8136 SiS_SetCH701x(SiS_Pr,0x00,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008137
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008138 SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
8139 SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
8140 SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
8141 SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
8142 SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
8143 SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008144
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008145 temp = CHTVRegData[resindex].Reg[7];
8146 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
8147 SiS_SetCH701x(SiS_Pr,0x07,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008148
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008149 SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
8150 SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
8151 SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
8152 SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
8153 SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
8154 SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
8155 SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
8156 SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008157
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008158 temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8159 /* D1 should be set for PAL, PAL-N and NTSC-J,
8160 but I won't do that for PAL unless somebody
8161 tells me to do so. Since the BIOS uses
8162 non-default CIV values and blacklevels,
8163 this might be compensated anyway.
8164 */
8165 if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8166 SiS_SetCH701x(SiS_Pr,0x21,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008167
8168#endif /* 315 */
8169
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008171
8172#ifdef SIS_CP
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008173 SIS_CP_INIT301_CP3
Linus Torvalds1da177e2005-04-16 15:20:36 -07008174#endif
8175
8176}
8177
Linus Torvalds1da177e2005-04-16 15:20:36 -07008178#ifdef SIS315H /* ----------- 315 series only ---------- */
8179
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008180void
8181SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008182{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008183 unsigned short temp;
8184
8185 /* Enable Chrontel 7019 LCD panel backlight */
8186 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8187 if(SiS_Pr->ChipType == SIS_740) {
8188 SiS_SetCH701x(SiS_Pr,0x66,0x65);
8189 } else {
8190 temp = SiS_GetCH701x(SiS_Pr,0x66);
8191 temp |= 0x20;
8192 SiS_SetCH701x(SiS_Pr,0x66,temp);
8193 }
8194 }
8195}
8196
8197void
8198SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
8199{
8200 unsigned short temp;
8201
8202 /* Disable Chrontel 7019 LCD panel backlight */
8203 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8204 temp = SiS_GetCH701x(SiS_Pr,0x66);
8205 temp &= 0xDF;
8206 SiS_SetCH701x(SiS_Pr,0x66,temp);
8207 }
8208}
8209
8210static void
8211SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
8212{
8213 static const unsigned char regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8214 static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8215 static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8216 static const unsigned char asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8217 static const unsigned char asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8218 static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8219 static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8220 const unsigned char *tableptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008221 int i;
8222
8223 /* Set up Power up/down timing */
8224
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008225 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008226 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008227 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8228 else tableptr = table1024_740;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008229 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008230 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008231 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8232 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8233 else tableptr = table1400_740;
8234 } else return;
8235 } else {
8236 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008237 tableptr = table1024_650;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008238 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008239 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008240 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008241 tableptr = table1400_650;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008242 } else return;
8243 }
8244
8245 for(i=0; i<5; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008246 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008247 }
8248}
8249
8250static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008251SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008252{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008253 const unsigned char *tableptr = NULL;
8254 unsigned short tempbh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008255 int i;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008256 static const unsigned char regtable[] = {
8257 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8258 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
8259 };
8260 static const unsigned char table1024_740[] = {
8261 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8262 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
8263 };
8264 static const unsigned char table1280_740[] = {
8265 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8266 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8267 };
8268 static const unsigned char table1400_740[] = {
8269 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8270 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8271 };
8272 static const unsigned char table1600_740[] = {
8273 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8274 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
8275 };
8276 static const unsigned char table1024_650[] = {
8277 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8278 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
8279 };
8280 static const unsigned char table1280_650[] = {
8281 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8282 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
8283 };
8284 static const unsigned char table1400_650[] = {
8285 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8286 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
8287 };
8288 static const unsigned char table1600_650[] = {
8289 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8290 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
8291 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07008292
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008293 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008294 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_740;
8295 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8296 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8297 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8298 else return;
8299 } else {
8300 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_650;
8301 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8302 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8303 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8304 else return;
8305 }
8306
8307 tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8308 if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8309 tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8310 if(tempbh == 0xc8) {
8311 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8312 } else if(tempbh == 0xdb) {
8313 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8314 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8315 } else if(tempbh == 0xde) {
8316 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8317 }
8318 }
8319
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008320 if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
8321 else tempbh = 0x0c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008322
8323 for(i = 0; i < tempbh; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008324 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008325 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008326 SiS_ChrontelPowerSequencing(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008327 tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8328 tempbh |= 0xc0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008329 SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008330
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008331 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008332 tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8333 tempbh &= 0xfb;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008334 SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008335 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8336 tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8337 tempbh |= 0x40;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008338 SiS_SetCH701x(SiS_Pr,0x64,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008339 tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8340 tempbh &= 0x3f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008341 SiS_SetCH701x(SiS_Pr,0x03,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008342 }
8343}
8344
8345static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008346SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008347{
8348 unsigned char temp, temp1;
8349
8350 temp1 = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008351 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008352 temp = SiS_GetCH701x(SiS_Pr,0x47);
8353 temp &= 0x7f; /* Use external VSYNC */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008354 SiS_SetCH701x(SiS_Pr,0x47,temp);
8355 SiS_LongDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008356 temp = SiS_GetCH701x(SiS_Pr,0x47);
8357 temp |= 0x80; /* Use internal VSYNC */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008358 SiS_SetCH701x(SiS_Pr,0x47,temp);
8359 SiS_SetCH701x(SiS_Pr,0x49,temp1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008360}
8361
8362static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008363SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008364{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008365 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008366
8367 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008368 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008369 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8370 temp |= 0x04; /* Invert XCLK phase */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008371 SiS_SetCH701x(SiS_Pr,0x1c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008372 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008373 if(SiS_IsYPbPr(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008374 temp = SiS_GetCH701x(SiS_Pr,0x01);
8375 temp &= 0x3f;
8376 temp |= 0x80; /* Enable YPrPb (HDTV) */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008377 SiS_SetCH701x(SiS_Pr,0x01,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008378 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008379 if(SiS_IsChScart(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008380 temp = SiS_GetCH701x(SiS_Pr,0x01);
8381 temp &= 0x3f;
8382 temp |= 0xc0; /* Enable SCART + CVBS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008383 SiS_SetCH701x(SiS_Pr,0x01,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008384 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008385 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008386 SiS_ChrontelResetVSync(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008387 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008388 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008389 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008390 temp = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008391 if(SiS_IsYPbPr(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008392 temp = SiS_GetCH701x(SiS_Pr,0x73);
8393 temp |= 0x60;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008394 SiS_SetCH701x(SiS_Pr,0x73,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008395 }
8396 temp = SiS_GetCH701x(SiS_Pr,0x47);
8397 temp &= 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008398 SiS_SetCH701x(SiS_Pr,0x47,temp);
8399 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008400 temp = SiS_GetCH701x(SiS_Pr,0x47);
8401 temp |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008402 SiS_SetCH701x(SiS_Pr,0x47,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008403 }
8404 }
8405}
8406
8407static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008408SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008409{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008410 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008411
8412 /* Complete power down of LVDS */
8413 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008414 if(SiS_Pr->ChipType == SIS_740) {
8415 SiS_LongDelay(SiS_Pr, 1);
8416 SiS_GenericDelay(SiS_Pr, 5887);
8417 SiS_SetCH701x(SiS_Pr,0x76,0xac);
8418 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008419 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008420 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008421 temp = SiS_GetCH701x(SiS_Pr,0x76);
8422 temp &= 0xfc;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008423 SiS_SetCH701x(SiS_Pr,0x76,temp);
8424 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008425 }
8426 }
8427}
8428
8429static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008430SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008431{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008432 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008433
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008434 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008435
8436 temp = SiS_GetCH701x(SiS_Pr,0x4a); /* Version ID */
8437 temp &= 0x01;
8438 if(!temp) {
8439
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008440 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008441 temp = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008442 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008444
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008445 /* Reset Chrontel 7019 datapath */
8446 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8447 SiS_LongDelay(SiS_Pr, 1);
8448 SiS_SetCH701x(SiS_Pr,0x48,0x18);
8449
8450 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008451 SiS_ChrontelResetVSync(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008452 SiS_SetCH701x(SiS_Pr,0x49,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008453 }
8454
8455 } else {
8456
8457 /* Clear/set/clear GPIO */
8458 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8459 temp &= 0xef;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008460 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008461 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8462 temp |= 0x10;
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 &= 0xef;
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,0x61);
8468 if(!temp) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008469 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008470 }
8471 }
8472
8473 } else { /* 650 */
8474 /* Reset Chrontel 7019 datapath */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008475 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8476 SiS_LongDelay(SiS_Pr, 1);
8477 SiS_SetCH701x(SiS_Pr,0x48,0x18);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008478 }
8479}
8480
8481static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008482SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008483{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008484 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008485
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008486 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008487
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008488 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008489 SiS_ChrontelResetVSync(SiS_Pr);
8490 }
8491
8492 } else {
8493
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008494 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* Power up LVDS block */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008495 temp = SiS_GetCH701x(SiS_Pr,0x49);
8496 temp &= 1;
8497 if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */
8498 temp = SiS_GetCH701x(SiS_Pr,0x47);
8499 temp &= 0x70;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008500 SiS_SetCH701x(SiS_Pr,0x47,temp); /* enable VSYNC */
8501 SiS_LongDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008502 temp = SiS_GetCH701x(SiS_Pr,0x47);
8503 temp |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008504 SiS_SetCH701x(SiS_Pr,0x47,temp); /* disable VSYNC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008505 }
8506
8507 }
8508}
8509
8510static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008511SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008512{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008513 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008514
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008515 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008516
8517 temp = SiS_GetCH701x(SiS_Pr,0x61);
8518 if(temp < 1) {
8519 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008520 SiS_SetCH701x(SiS_Pr,0x61,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008521 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008522 SiS_SetCH701x(SiS_Pr,0x66,0x45); /* Panel power on */
8523 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on */
8524 SiS_LongDelay(SiS_Pr, 1);
8525 SiS_GenericDelay(SiS_Pr, 5887);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008526
8527 } else { /* 650 */
8528
8529 temp1 = 0;
8530 temp = SiS_GetCH701x(SiS_Pr,0x61);
8531 if(temp < 2) {
8532 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008533 SiS_SetCH701x(SiS_Pr,0x61,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008534 temp1 = 1;
8535 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008536 SiS_SetCH701x(SiS_Pr,0x76,0xac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008537 temp = SiS_GetCH701x(SiS_Pr,0x66);
8538 temp |= 0x5f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008539 SiS_SetCH701x(SiS_Pr,0x66,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008540 if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008541 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8542 SiS_GenericDelay(SiS_Pr, 1023);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008543 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008544 SiS_GenericDelay(SiS_Pr, 767);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008545 }
8546 } else {
8547 if(!temp1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008548 SiS_GenericDelay(SiS_Pr, 767);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008549 }
8550 temp = SiS_GetCH701x(SiS_Pr,0x76);
8551 temp |= 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008552 SiS_SetCH701x(SiS_Pr,0x76,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008553 temp = SiS_GetCH701x(SiS_Pr,0x66);
8554 temp &= 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008555 SiS_SetCH701x(SiS_Pr,0x66,temp);
8556 SiS_LongDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008557
8558 }
8559}
8560
8561static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008562SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008563{
Adrian Bunke4ccde32006-03-27 01:17:41 -08008564 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008565
8566 SiS_LongDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008567
8568 do {
8569 temp = SiS_GetCH701x(SiS_Pr,0x66);
8570 temp &= 0x04; /* PLL stable? -> bail out */
8571 if(temp == 0x04) break;
8572
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008573 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008574 /* Power down LVDS output, PLL normal operation */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008575 SiS_SetCH701x(SiS_Pr,0x76,0xac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008576 }
8577
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008578 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008579
Linus Torvalds1da177e2005-04-16 15:20:36 -07008580 temp = SiS_GetCH701x(SiS_Pr,0x76);
8581 temp &= 0xfb; /* Reset PLL */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008582 SiS_SetCH701x(SiS_Pr,0x76,temp);
8583 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008584 temp = SiS_GetCH701x(SiS_Pr,0x76);
8585 temp |= 0x04; /* PLL normal operation */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008586 SiS_SetCH701x(SiS_Pr,0x76,temp);
8587 if(SiS_Pr->ChipType == SIS_740) {
8588 SiS_SetCH701x(SiS_Pr,0x78,0xe0); /* PLL loop filter */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008589 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008590 SiS_SetCH701x(SiS_Pr,0x78,0x60);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008591 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008592 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008593 } while(0);
8594
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008595 SiS_SetCH701x(SiS_Pr,0x77,0x00); /* MV? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008596}
8597
8598static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008599SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008600{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008601 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008602
8603 temp = SiS_GetCH701x(SiS_Pr,0x03);
8604 temp |= 0x80; /* Set datapath 1 to TV */
8605 temp &= 0xbf; /* Set datapath 2 to LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008606 SiS_SetCH701x(SiS_Pr,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008607
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008608 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008609
8610 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8611 temp &= 0xfb; /* Normal XCLK phase */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008612 SiS_SetCH701x(SiS_Pr,0x1c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008613
8614 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8615
8616 temp = SiS_GetCH701x(SiS_Pr,0x64);
8617 temp |= 0x40; /* ? Bit not defined */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008618 SiS_SetCH701x(SiS_Pr,0x64,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008619
8620 temp = SiS_GetCH701x(SiS_Pr,0x03);
8621 temp &= 0x3f; /* D1 input to both LVDS and TV */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008622 SiS_SetCH701x(SiS_Pr,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008623
8624 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008625 SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008626 SiS_LongDelay(SiS_Pr, 1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008627 SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
8628 SiS_ChrontelResetDB(SiS_Pr);
8629 SiS_ChrontelDoSomething2(SiS_Pr);
8630 SiS_ChrontelDoSomething3(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008631 } else {
8632 temp = SiS_GetCH701x(SiS_Pr,0x66);
8633 if(temp != 0x45) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008634 SiS_ChrontelResetDB(SiS_Pr);
8635 SiS_ChrontelDoSomething2(SiS_Pr);
8636 SiS_ChrontelDoSomething3(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008637 }
8638 }
8639
8640 } else { /* 650 */
8641
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008642 SiS_ChrontelResetDB(SiS_Pr);
8643 SiS_ChrontelDoSomething2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008644 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008645 SiS_ChrontelDoSomething3(SiS_Pr,temp);
8646 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on, LVDS normal operation */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008647
8648 }
8649
8650}
8651#endif /* 315 series */
8652
8653/*********************************************/
8654/* MAIN: SET CRT2 REGISTER GROUP */
8655/*********************************************/
8656
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008657bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008658SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008659{
8660#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008661 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008662#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008663 unsigned short ModeIdIndex, RefreshRateTableIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008664
8665 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8666
8667 if(!SiS_Pr->UseCustomMode) {
8668 SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8669 } else {
8670 ModeIdIndex = 0;
8671 }
8672
8673 /* Used for shifting CR33 */
8674 SiS_Pr->SiS_SelectCRT2Rate = 4;
8675
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008676 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008677
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008678 RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008679
8680 SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8681
8682 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008683 SiS_DisableBridge(SiS_Pr);
8684 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008685 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8686 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008687 SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008688 }
8689
8690 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008691 SiS_LockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008692 SiS_DisplayOn(SiS_Pr);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008693 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008694 }
8695
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008696 SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008697
8698 /* Set up Panel Link for LVDS and LCDA */
8699 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8700 if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8701 ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008702 ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
8703 SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008704 }
8705
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008706#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07008707#ifdef TWDEBUG
8708 xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES);
8709 xf86DrvMsg(0, X_INFO, "(init301: HDE 0x%03x VDE 0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE);
8710 xf86DrvMsg(0, X_INFO, "(init301: VGAHDE 0x%03x VGAVDE 0x%03x)\n", SiS_Pr->SiS_VGAHDE, SiS_Pr->SiS_VGAVDE);
8711 xf86DrvMsg(0, X_INFO, "(init301: HT 0x%03x VT 0x%03x)\n", SiS_Pr->SiS_HT, SiS_Pr->SiS_VT);
8712 xf86DrvMsg(0, X_INFO, "(init301: VGAHT 0x%03x VGAVT 0x%03x)\n", SiS_Pr->SiS_VGAHT, SiS_Pr->SiS_VGAVT);
8713#endif
8714#endif
8715
8716 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008717 SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008718 }
8719
8720 if(SiS_Pr->SiS_VBType & VB_SISVB) {
8721
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008722 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008723
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008724 SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008725#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008726 SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008727#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008728 SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
8729 SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008730#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008731 SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008732#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008733 SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008734
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008735 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008736
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008737 /* For 301BDH (Panel link initialization): */
8738 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8739
8740 if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8741 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8742 SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8743 }
8744 }
8745 SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8746 }
8747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008748
8749 } else {
8750
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008751 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008752
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008753 SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008754
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008755 SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008756
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008757 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8758 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8759 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8760 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008761#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008762 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008763#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008764 }
8765 }
8766 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8767 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8768 }
8769 }
8770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008771
8772 }
8773
8774#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008775 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008776 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8777 if(SiS_Pr->SiS_UseOEM) {
8778 if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8779 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008780 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008781 }
8782 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008783 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008784 }
8785 }
8786 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008787 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008788 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008789 SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008790 }
8791 SiS_DisplayOn(SiS_Pr);
8792 }
8793 }
8794 }
8795#endif
8796
8797#ifdef SIS315H
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008798 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008799 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008800 if(SiS_Pr->ChipType < SIS_661) {
8801 SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
8802 SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008803 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008804 SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008805 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008806 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008807 }
8808 }
8809#endif
8810
8811 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008812 SiS_EnableBridge(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008813 }
8814
8815 SiS_DisplayOn(SiS_Pr);
8816
8817 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8818 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8819 /* Disable LCD panel when using TV */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008820 SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008821 } else {
8822 /* Disable TV when using LCD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008823 SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008824 }
8825 }
8826
8827 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008828 SiS_LockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008829 }
8830
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008831 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008832}
8833
8834
8835/*********************************************/
8836/* ENABLE/DISABLE LCD BACKLIGHT (SIS) */
8837/*********************************************/
8838
8839void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008840SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008841{
8842 /* Switch on LCD backlight on SiS30xLV */
8843 SiS_DDC2Delay(SiS_Pr,0xff00);
8844 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
8845 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008846 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008847 }
8848 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
8849 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
8850 }
8851}
8852
8853void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008854SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008855{
8856 /* Switch off LCD backlight on SiS30xLV */
8857 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008858 SiS_DDC2Delay(SiS_Pr,0xff00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008859}
8860
8861/*********************************************/
8862/* DDC RELATED FUNCTIONS */
8863/*********************************************/
8864
8865static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008866SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008867{
8868 SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
8869 SiS_Pr->SiS_DDC_NClk = ~SiS_Pr->SiS_DDC_Clk;
8870 if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
8871 SiS_Pr->SiS_DDC_NData &= 0x0f;
8872 SiS_Pr->SiS_DDC_NClk &= 0x0f;
8873 }
8874}
8875
8876#ifdef SIS300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008877static unsigned char *
8878SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008879{
8880 int i, j, num;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008881 unsigned short tempah,temp;
8882 unsigned char *mydataptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008883
8884 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8885 mydataptr = dataptr;
8886 num = *mydataptr++;
8887 if(!num) return mydataptr;
8888 if(i) {
8889 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008890 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008891 }
8892 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8893 tempah = SiS_Pr->SiS_DDC_DeviceAddr;
8894 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
8895 if(temp) continue; /* (ERROR: no ack) */
8896 tempah = *mydataptr++;
8897 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write register number */
8898 if(temp) continue; /* (ERROR: no ack) */
8899 for(j=0; j<num; j++) {
8900 tempah = *mydataptr++;
8901 temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
8902 if(temp) break;
8903 }
8904 if(temp) continue;
8905 if(SiS_SetStop(SiS_Pr)) continue;
8906 return mydataptr;
8907 }
8908 return NULL;
8909}
8910
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008911static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008912SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008913{
8914 SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */
8915 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008916 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8917 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008918 SiS_SetupDDCN(SiS_Pr);
8919
8920 SiS_SetSwitchDDC2(SiS_Pr);
8921
8922 while(*dataptr) {
8923 dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008924 if(!dataptr) return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008925 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008926#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07008927#ifdef TWDEBUG
8928 xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
8929#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008930#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008931 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008932}
8933#endif
8934
8935/* The Chrontel 700x is connected to the 630/730 via
8936 * the 630/730's DDC/I2C port.
8937 *
8938 * On 630(S)T chipset, the index changed from 0x11 to
8939 * 0x0a, possibly for working around the DDC problems
8940 */
8941
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008942static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008943SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008944{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008945 unsigned short temp, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008946
8947 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8948 if(i) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008949 SiS_SetStop(SiS_Pr);
8950 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008951 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008952 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8953 temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
8954 if(temp) continue; /* (ERROR: no ack) */
8955 temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor)); /* Write RAB (700x: set bit 7, see datasheet) */
8956 if(temp) continue; /* (ERROR: no ack) */
8957 temp = SiS_WriteDDC2Data(SiS_Pr, val); /* Write data */
8958 if(temp) continue; /* (ERROR: no ack) */
8959 if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008960 SiS_Pr->SiS_ChrontelInit = 1;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008961 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008962 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008963 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008964}
8965
Linus Torvalds1da177e2005-04-16 15:20:36 -07008966/* Write to Chrontel 700x */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008967void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008968SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008969{
8970 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
8971
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008972 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8973
Linus Torvalds1da177e2005-04-16 15:20:36 -07008974 if(!(SiS_Pr->SiS_ChrontelInit)) {
8975 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008976 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8977 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008978 SiS_SetupDDCN(SiS_Pr);
8979 }
8980
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008981 if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07008982 (!(SiS_Pr->SiS_ChrontelInit)) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008983 SiS_Pr->SiS_DDC_Index = 0x0a;
8984 SiS_Pr->SiS_DDC_Data = 0x80;
8985 SiS_Pr->SiS_DDC_Clk = 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008986 SiS_SetupDDCN(SiS_Pr);
8987
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008988 SiS_SetChReg(SiS_Pr, reg, val, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008989 }
8990}
8991
8992/* Write to Chrontel 701x */
8993/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
8994void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008995SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008996{
8997 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008998 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
8999 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009000 SiS_SetupDDCN(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009001 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
9002 SiS_SetChReg(SiS_Pr, reg, val, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009003}
9004
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009005#ifdef SIS_LINUX_KERNEL
9006static
9007#endif
9008void
9009SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009010{
9011 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009012 SiS_SetCH700x(SiS_Pr, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009013 else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009014 SiS_SetCH701x(SiS_Pr, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009015}
9016
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009017static unsigned short
9018SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009019{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009020 unsigned short tempah, temp, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009021
9022 for(i=0; i<20; i++) { /* Do 20 attempts to read */
9023 if(i) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009024 SiS_SetStop(SiS_Pr);
9025 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009026 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009027 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
9028 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
9029 if(temp) continue; /* (ERROR: no ack) */
9030 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor); /* Write RAB (700x: | 0x80) */
9031 if(temp) continue; /* (ERROR: no ack) */
9032 if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
9033 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
9034 if(temp) continue; /* (ERROR: no ack) */
9035 tempah = SiS_ReadDDC2Data(SiS_Pr); /* Read byte */
9036 if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009037 SiS_Pr->SiS_ChrontelInit = 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009038 return tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009039 }
9040 return 0xFFFF;
9041}
9042
Linus Torvalds1da177e2005-04-16 15:20:36 -07009043/* Read from Chrontel 700x */
9044/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009045unsigned short
9046SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009047{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009048 unsigned short result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009049
9050 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
9051
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009052 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9053
Linus Torvalds1da177e2005-04-16 15:20:36 -07009054 if(!(SiS_Pr->SiS_ChrontelInit)) {
9055 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009056 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
9057 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009058 SiS_SetupDDCN(SiS_Pr);
9059 }
9060
9061 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9062
9063 if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
9064 (!SiS_Pr->SiS_ChrontelInit) ) {
9065
9066 SiS_Pr->SiS_DDC_Index = 0x0a;
9067 SiS_Pr->SiS_DDC_Data = 0x80;
9068 SiS_Pr->SiS_DDC_Clk = 0x40;
9069 SiS_SetupDDCN(SiS_Pr);
9070
9071 result = SiS_GetChReg(SiS_Pr,0x80);
9072 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009073 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009074}
9075
9076/* Read from Chrontel 701x */
9077/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009078unsigned short
9079SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009080{
9081 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009082 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
9083 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009084 SiS_SetupDDCN(SiS_Pr);
9085 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
9086
9087 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9088
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009089 return SiS_GetChReg(SiS_Pr,0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009090}
9091
9092/* Read from Chrontel 70xx */
9093/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009094#ifdef SIS_LINUX_KERNEL
9095static
9096#endif
9097unsigned short
9098SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009099{
9100 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009101 return SiS_GetCH700x(SiS_Pr, tempbx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009102 else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009103 return SiS_GetCH701x(SiS_Pr, tempbx);
9104}
9105
9106void
9107SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
9108 unsigned char myor, unsigned short myand)
9109{
9110 unsigned short tempbl;
9111
9112 tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
9113 SiS_SetCH70xx(SiS_Pr, reg, tempbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009114}
9115
9116/* Our own DDC functions */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009117#ifndef SIS_XORG_XF86
9118static
9119#endif
9120unsigned short
9121SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009122 unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009123 unsigned int VBFlags2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009124{
9125 unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
9126 unsigned char flag, cr32;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009127 unsigned short temp = 0, myadaptnum = adaptnum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009128
9129 if(adaptnum != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009130 if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
9131 if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
9132 }
9133
Linus Torvalds1da177e2005-04-16 15:20:36 -07009134 /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009135
Linus Torvalds1da177e2005-04-16 15:20:36 -07009136 SiS_Pr->SiS_ChrontelInit = 0; /* force re-detection! */
9137
9138 SiS_Pr->SiS_DDC_SecAddr = 0;
9139 SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
9140 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
9141 SiS_Pr->SiS_DDC_Index = 0x11;
9142 flag = 0xff;
9143
9144 cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
9145
9146#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009147 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009148 if(myadaptnum == 0) {
9149 if(!(cr32 & 0x20)) {
9150 myadaptnum = 2;
9151 if(!(cr32 & 0x10)) {
9152 myadaptnum = 1;
9153 if(!(cr32 & 0x08)) {
9154 myadaptnum = 0;
9155 }
9156 }
9157 }
9158 }
9159 }
9160#endif
9161
9162 if(VGAEngine == SIS_300_VGA) { /* 300 series */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009163
Linus Torvalds1da177e2005-04-16 15:20:36 -07009164 if(myadaptnum != 0) {
9165 flag = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009166 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009167 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9168 SiS_Pr->SiS_DDC_Index = 0x0f;
9169 }
9170 }
9171
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009172 if(!(VBFlags2 & VB2_301)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009173 if((cr32 & 0x80) && (checkcr32)) {
9174 if(myadaptnum >= 1) {
9175 if(!(cr32 & 0x08)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009176 myadaptnum = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009177 if(!(cr32 & 0x10)) return 0xFFFF;
9178 }
9179 }
9180 }
9181 }
9182
9183 temp = 4 - (myadaptnum * 2);
9184 if(flag) temp = 0;
9185
9186 } else { /* 315/330 series */
9187
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009188 /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009189
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009190 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009191 if(myadaptnum == 2) {
9192 myadaptnum = 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009194 }
9195
9196 if(myadaptnum == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009197 flag = 0;
9198 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009199 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9200 SiS_Pr->SiS_DDC_Index = 0x0f;
9201 }
9202 }
9203
9204 if((cr32 & 0x80) && (checkcr32)) {
9205 if(myadaptnum >= 1) {
9206 if(!(cr32 & 0x08)) {
9207 myadaptnum = 1;
9208 if(!(cr32 & 0x10)) return 0xFFFF;
9209 }
9210 }
9211 }
9212
9213 temp = myadaptnum;
9214 if(myadaptnum == 1) {
9215 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009216 if(VBFlags2 & VB2_LVDS) flag = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009217 }
9218
9219 if(flag) temp = 0;
9220 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009221
Linus Torvalds1da177e2005-04-16 15:20:36 -07009222 SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9223 SiS_Pr->SiS_DDC_Clk = 0x01 << temp;
9224
9225 SiS_SetupDDCN(SiS_Pr);
9226
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009227#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009228#ifdef TWDEBUG
9229 xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
9230 SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
9231#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009232#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07009233 return 0;
9234}
9235
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009236static unsigned short
9237SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009238{
9239 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9240 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009241 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009242 }
9243 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009244 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009245 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009246 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009247}
9248
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009249static unsigned short
9250SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009251{
9252 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9253 if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009254 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009255 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009256 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009257}
9258
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009259static unsigned short
9260SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009261{
9262 if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009263 if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
9264 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009265}
9266
9267static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009268SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009269{
9270 SiS_SetSCLKLow(SiS_Pr);
9271 if(yesno) {
9272 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009273 SiS_Pr->SiS_DDC_Index,
9274 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009275 SiS_Pr->SiS_DDC_Data);
9276 } else {
9277 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009278 SiS_Pr->SiS_DDC_Index,
9279 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009280 0);
9281 }
9282 SiS_SetSCLKHigh(SiS_Pr);
9283}
9284
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009285static unsigned short
9286SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009287{
9288 unsigned char mask, value;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009289 unsigned short temp, ret=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009290 bool failed = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009291
9292 SiS_SetSwitchDDC2(SiS_Pr);
9293 if(SiS_PrepareDDC(SiS_Pr)) {
9294 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009295#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009296#ifdef TWDEBUG
9297 xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n");
9298#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009299#endif
9300 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009301 }
9302 mask = 0xf0;
9303 value = 0x20;
9304 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009305 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009306 SiS_SendACK(SiS_Pr, 0);
9307 if(temp == 0) {
9308 mask = 0xff;
9309 value = 0xff;
9310 } else {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009311 failed = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009312 ret = 0xFFFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009313#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009314#ifdef TWDEBUG
9315 xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n");
9316#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009317#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07009318 }
9319 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009320 if(!failed) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009321 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009322 SiS_SendACK(SiS_Pr, 1);
9323 temp &= mask;
9324 if(temp == value) ret = 0;
9325 else {
9326 ret = 0xFFFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009327#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009328#ifdef TWDEBUG
9329 xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n");
9330#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009331#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07009332 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9333 if(temp == 0x30) ret = 0;
9334 }
9335 }
9336 }
9337 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009338 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009339}
9340
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009341#ifndef SIS_XORG_XF86
9342static
9343#endif
9344unsigned short
9345SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009346{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009347 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009348
9349 flag = 0x180;
9350 SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9351 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9352 SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9353 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9354 SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9355 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9356 if(!(flag & 0x1a)) flag = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009357 return flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009358}
9359
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009360#ifndef SIS_XORG_XF86
9361static
9362#endif
9363unsigned short
9364SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009365{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009366 unsigned short flag, length, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009367 unsigned char chksum,gotcha;
9368
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009369 if(DDCdatatype > 4) return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009370
9371 flag = 0;
9372 SiS_SetSwitchDDC2(SiS_Pr);
9373 if(!(SiS_PrepareDDC(SiS_Pr))) {
9374 length = 127;
9375 if(DDCdatatype != 1) length = 255;
9376 chksum = 0;
9377 gotcha = 0;
9378 for(i=0; i<length; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009379 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009380 chksum += buffer[i];
9381 gotcha |= buffer[i];
9382 SiS_SendACK(SiS_Pr, 0);
9383 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009384 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009385 chksum += buffer[i];
9386 SiS_SendACK(SiS_Pr, 1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009387 if(gotcha) flag = (unsigned short)chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009388 else flag = 0xFFFF;
9389 } else {
9390 flag = 0xFFFF;
9391 }
9392 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009393 return flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009394}
9395
9396/* Our private DDC functions
9397
9398 It complies somewhat with the corresponding VESA function
9399 in arguments and return values.
9400
9401 Since this is probably called before the mode is changed,
9402 we use our pre-detected pSiS-values instead of SiS_Pr as
9403 regards chipset and video bridge type.
9404
9405 Arguments:
9406 adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9407 CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9408 LCDA is CRT1, but DDC is read from CRT2 port.
9409 DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9410 buffer: ptr to 256 data bytes which will be filled with read data.
9411
9412 Returns 0xFFFF if error, otherwise
9413 if DDCdatatype > 0: Returns 0 if reading OK (included a correct checksum)
9414 if DDCdatatype = 0: Returns supported DDC modes
9415
9416 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009417unsigned short
9418SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9419 unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
9420 unsigned int VBFlags2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009421{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009422 unsigned char sr1f, cr17=1;
9423 unsigned short result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009424
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009425 if(adaptnum > 2)
9426 return 0xFFFF;
9427
9428 if(DDCdatatype > 4)
9429 return 0xFFFF;
9430
9431 if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
9432 return 0xFFFF;
9433
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009434 if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009435 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009436
9437 sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9438 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9439 if(VGAEngine == SIS_300_VGA) {
9440 cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9441 if(!cr17) {
9442 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9443 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9444 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9445 }
9446 }
9447 if((sr1f) || (!cr17)) {
9448 SiS_WaitRetrace1(SiS_Pr);
9449 SiS_WaitRetrace1(SiS_Pr);
9450 SiS_WaitRetrace1(SiS_Pr);
9451 SiS_WaitRetrace1(SiS_Pr);
9452 }
9453
9454 if(DDCdatatype == 0) {
9455 result = SiS_ProbeDDC(SiS_Pr);
9456 } else {
9457 result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9458 if((!result) && (DDCdatatype == 1)) {
9459 if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9460 (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9461 (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9462 (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9463 (buffer[0x12] == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009464 if(!SiS_Pr->DDCPortMixup) {
9465 if(adaptnum == 1) {
9466 if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9467 } else {
9468 if(buffer[0x14] & 0x80) result = 0xFFFE;
9469 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009470 }
9471 }
9472 }
9473 }
9474 SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9475 if(VGAEngine == SIS_300_VGA) {
9476 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9477 }
9478 return result;
9479}
9480
Linus Torvalds1da177e2005-04-16 15:20:36 -07009481/* Generic I2C functions for Chrontel & DDC --------- */
9482
9483static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009484SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009485{
9486 SiS_SetSCLKHigh(SiS_Pr);
9487 SiS_WaitRetrace1(SiS_Pr);
9488
9489 SiS_SetSCLKLow(SiS_Pr);
9490 SiS_WaitRetrace1(SiS_Pr);
9491}
9492
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009493unsigned short
9494SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009495{
9496 SiS_WaitRetrace1(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009497 return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009498}
9499
9500/* Set I2C start condition */
9501/* This is done by a SD high-to-low transition while SC is high */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009502static unsigned short
9503SiS_SetStart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009504{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009505 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009506 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009507 SiS_Pr->SiS_DDC_Index,
9508 SiS_Pr->SiS_DDC_NData,
9509 SiS_Pr->SiS_DDC_Data); /* SD->high */
9510 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009511 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009512 SiS_Pr->SiS_DDC_Index,
9513 SiS_Pr->SiS_DDC_NData,
9514 0x00); /* SD->low = start condition */
9515 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009516 return 0;
9517}
9518
9519/* Set I2C stop condition */
9520/* This is done by a SD low-to-high transition while SC is high */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009521static unsigned short
9522SiS_SetStop(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009523{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009524 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009525 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009526 SiS_Pr->SiS_DDC_Index,
9527 SiS_Pr->SiS_DDC_NData,
9528 0x00); /* SD->low */
9529 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009530 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009531 SiS_Pr->SiS_DDC_Index,
9532 SiS_Pr->SiS_DDC_NData,
9533 SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
9534 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009535 return 0;
9536}
9537
9538/* Write 8 bits of data */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009539static unsigned short
9540SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009541{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009542 unsigned short i,flag,temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009543
9544 flag = 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009545 for(i = 0; i < 8; i++) {
9546 SiS_SetSCLKLow(SiS_Pr); /* SC->low */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009547 if(tempax & flag) {
9548 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009549 SiS_Pr->SiS_DDC_Index,
9550 SiS_Pr->SiS_DDC_NData,
9551 SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009552 } else {
9553 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009554 SiS_Pr->SiS_DDC_Index,
9555 SiS_Pr->SiS_DDC_NData,
9556 0x00); /* Write bit (0) to SD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009557 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009558 SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009559 flag >>= 1;
9560 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009561 temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
9562 return temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009563}
9564
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009565static unsigned short
9566SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009567{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009568 unsigned short i, temp, getdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009569
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009570 getdata = 0;
9571 for(i = 0; i < 8; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009572 getdata <<= 1;
9573 SiS_SetSCLKLow(SiS_Pr);
9574 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009575 SiS_Pr->SiS_DDC_Index,
9576 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009577 SiS_Pr->SiS_DDC_Data);
9578 SiS_SetSCLKHigh(SiS_Pr);
9579 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9580 if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
9581 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009582 return getdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009583}
9584
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009585static unsigned short
9586SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009587{
9588 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009589 SiS_Pr->SiS_DDC_Index,
9590 SiS_Pr->SiS_DDC_NClk,
9591 0x00); /* SetSCLKLow() */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009592 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9593 return 0;
9594}
9595
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009596static unsigned short
9597SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009598{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009599 unsigned short temp, watchdog=1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009600
9601 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009602 SiS_Pr->SiS_DDC_Index,
9603 SiS_Pr->SiS_DDC_NClk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009604 SiS_Pr->SiS_DDC_Clk); /* SetSCLKHigh() */
9605 do {
9606 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9607 } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
9608 if (!watchdog) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009609#ifdef SIS_XORG_XF86
Linus Torvalds1da177e2005-04-16 15:20:36 -07009610#ifdef TWDEBUG
9611 xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n");
9612#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009613#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07009614 return 0xFFFF;
9615 }
9616 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9617 return 0;
9618}
9619
9620/* Check I2C acknowledge */
9621/* Returns 0 if ack ok, non-0 if ack not ok */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009622static unsigned short
9623SiS_CheckACK(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009624{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009625 unsigned short tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009626
9627 SiS_SetSCLKLow(SiS_Pr); /* (SC->low) */
9628 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009629 SiS_Pr->SiS_DDC_Index,
9630 SiS_Pr->SiS_DDC_NData,
9631 SiS_Pr->SiS_DDC_Data); /* (SD->high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009632 SiS_SetSCLKHigh(SiS_Pr); /* SC->high = clock impulse for ack */
9633 tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
9634 SiS_SetSCLKLow(SiS_Pr); /* SC->low = end of clock impulse */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009635 if(tempah & SiS_Pr->SiS_DDC_Data) return 1; /* Ack OK if bit = 0 */
9636 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009637}
9638
9639/* End of I2C functions ----------------------- */
9640
9641
9642/* =============== SiS 315/330 O.E.M. ================= */
9643
9644#ifdef SIS315H
9645
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009646static unsigned short
9647GetRAMDACromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009648{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009649 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9650 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009651
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009652 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009653 romptr = SISGETROMW(0x128);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009654 if(SiS_Pr->SiS_VBType & VB_SIS30xB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009655 romptr = SISGETROMW(0x12a);
9656 } else {
9657 romptr = SISGETROMW(0x1a8);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009658 if(SiS_Pr->SiS_VBType & VB_SIS30xB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009659 romptr = SISGETROMW(0x1aa);
9660 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009661 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009662}
9663
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009664static unsigned short
9665GetLCDromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009666{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009667 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9668 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009669
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009670 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009671 romptr = SISGETROMW(0x120);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009672 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009673 romptr = SISGETROMW(0x122);
9674 } else {
9675 romptr = SISGETROMW(0x1a0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009676 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009677 romptr = SISGETROMW(0x1a2);
9678 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009679 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009680}
9681
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009682static unsigned short
9683GetTVromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009684{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009685 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9686 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009687
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009688 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009689 romptr = SISGETROMW(0x114);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009690 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009691 romptr = SISGETROMW(0x11a);
9692 } else {
9693 romptr = SISGETROMW(0x194);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009694 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009695 romptr = SISGETROMW(0x19a);
9696 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009697 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009698}
9699
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009700static unsigned short
9701GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009702{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009703 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009704
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009705 if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9706 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009707 if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
9708 index >>= 4;
9709 index *= 3;
9710 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9711 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9712 return index;
9713 }
9714 }
9715 }
9716
9717 index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
9718 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) index -= 5;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009719 if(SiS_Pr->SiS_VBType & VB_SIS301C) { /* 1.15.20 and later (not VB specific) */
9720 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
9721 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
9722 } else {
9723 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
9724 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009725 index--;
9726 index *= 3;
9727 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9728 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9729 return index;
9730}
9731
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009732static unsigned short
9733GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009734{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009735 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009736
9737 index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
9738 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9739 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9740 return index;
9741}
9742
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009743static unsigned short
9744GetTVPtrIndex(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009745{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009746 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009747
9748 index = 0;
9749 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9750 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
9751
9752 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
9753
9754 index <<= 1;
9755
9756 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
9757 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9758 index++;
9759 }
9760
9761 return index;
9762}
9763
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009764static unsigned int
9765GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009766{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009767 unsigned short index = 0, temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009768
9769 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9770 if(SiS_Pr->SiS_TVMode & TVSetPALM) index = 2;
9771 if(SiS_Pr->SiS_TVMode & TVSetPALN) index = 3;
9772 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
9773 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
9774 index = 4;
9775 if(SiS_Pr->SiS_TVMode & TVSetPALM) index++;
9776 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
9777 }
9778
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009779 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009780 if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
9781 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9782 index += addme;
9783 temp++;
9784 }
9785 temp += 0x0100;
9786 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009787 return (unsigned int)(index | (temp << 16));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009788}
9789
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009790static unsigned int
9791GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009792{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009793 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009794}
9795
9796#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009797static unsigned int
9798GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009799{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009800 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009801}
9802#endif
9803
9804static int
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009805GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009806{
9807 int index = 0;
9808
9809 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 2;
9810 if(SiS_Pr->SiS_ROMNew) {
9811 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
9812 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
9813 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
9814 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 10;
9815 } else {
9816 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 4;
9817 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
9818 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
9819 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
9820 }
9821
9822 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
9823
9824 return index;
9825}
9826
9827static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009828SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009829{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009830 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9831 unsigned short delay=0,index,myindex,temp,romptr=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009832 bool dochiptest = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009833
9834 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9835 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
9836 } else {
9837 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
9838 }
9839
9840 /* Find delay (from ROM, internal tables, PCI subsystem) */
9841
9842 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { /* ------------ VGA */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009843
Linus Torvalds1da177e2005-04-16 15:20:36 -07009844 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009845 romptr = GetRAMDACromptr(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009846 }
9847 if(romptr) delay = ROMAddr[romptr];
9848 else {
9849 delay = 0x04;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009850 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009851 if(IS_SIS650) {
9852 delay = 0x0a;
9853 } else if(IS_SIS740) {
9854 delay = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009855 } else if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009856 delay = 0x0c;
9857 } else {
9858 delay = 0x0c;
9859 }
9860 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9861 delay = 0x00;
9862 }
9863 }
9864
9865 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) { /* ---------- LCD/LCDA */
9866
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009867 bool gotitfrompci = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009868
9869 /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
9870
9871 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
9872 if(SiS_Pr->PDC != -1) {
9873 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
9874 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
9875 return;
9876 }
9877 } else {
9878 if(SiS_Pr->PDCA != -1) {
9879 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
9880 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
9881 return;
9882 }
9883 }
9884
9885 /* Custom Panel? */
9886
9887 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
9888 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9889 delay = 0x00;
9890 if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
9891 delay = 0x20;
9892 }
9893 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
9894 } else {
9895 delay = 0x0c;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009896 if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9897 delay = 0x03;
9898 if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
9899 delay = 0x00;
9900 }
9901 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009902 if(IS_SIS740) delay = 0x01;
9903 else delay = 0x03;
9904 }
9905 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
9906 }
9907 return;
9908 }
9909
9910 /* This is a piece of typical SiS crap: They code the OEM LCD
9911 * delay into the code, at no defined place in the BIOS.
9912 * We now have to start doing a PCI subsystem check here.
9913 */
9914
9915 switch(SiS_Pr->SiS_CustomT) {
9916 case CUT_COMPAQ1280:
9917 case CUT_COMPAQ12802:
9918 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009919 gotitfrompci = true;
9920 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009921 delay = 0x03;
9922 }
9923 break;
9924 case CUT_CLEVO1400:
9925 case CUT_CLEVO14002:
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009926 gotitfrompci = true;
9927 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009928 delay = 0x02;
9929 break;
9930 case CUT_CLEVO1024:
9931 case CUT_CLEVO10242:
9932 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009933 gotitfrompci = true;
9934 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009935 delay = 0x33;
9936 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9937 delay &= 0x0f;
9938 }
9939 break;
9940 }
9941
9942 /* Could we find it through the PCI ID? If no, use ROM or table */
9943
9944 if(!gotitfrompci) {
9945
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009946 index = GetLCDPtrIndexBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009947 myindex = GetLCDPtrIndex(SiS_Pr);
9948
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009949 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009950
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009951 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009952
9953 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9954 /* Always use the second pointer on 650; some BIOSes */
9955 /* still carry old 301 data at the first location */
9956 /* romptr = SISGETROMW(0x120); */
9957 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
9958 romptr = SISGETROMW(0x122);
9959 if(!romptr) return;
9960 delay = ROMAddr[(romptr + index)];
9961 } else {
9962 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9963 }
9964
9965 } else {
9966
9967 delay = SiS310_LCDDelayCompensation_651301LV[myindex];
9968 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
9969 delay = SiS310_LCDDelayCompensation_651302LV[myindex];
9970
9971 }
9972
9973 } else if(SiS_Pr->SiS_UseROM &&
9974 (!(SiS_Pr->SiS_ROMNew)) &&
9975 (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
9976 (SiS_Pr->SiS_LCDResInfo != Panel_1280x768) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009977 (SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
9978 (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200) &&
9979 ((romptr = GetLCDromptr(SiS_Pr)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009980
9981 /* Data for 1280x1024 wrong in 301B BIOS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009982 /* Data for 1600x1200 wrong in 301C BIOS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009983 delay = ROMAddr[(romptr + index)];
9984
9985 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9986
9987 if(IS_SIS740) delay = 0x03;
9988 else delay = 0x00;
9989
9990 } else {
9991
9992 delay = SiS310_LCDDelayCompensation_301[myindex];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009993 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009994 if(IS_SIS740) delay = 0x01;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009995 else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07009996 else delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9997 } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9998 if(IS_SIS740) delay = 0x01; /* ? */
9999 else delay = 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010000 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
10001 } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010002 if(IS_SIS740) delay = 0x01;
10003 else delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
10004 }
10005
10006 }
10007
10008 } /* got it from PCI */
10009
10010 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10011 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
Richard Knutssonc30660ea2007-02-12 00:55:06 -080010012 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010013 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010014
Linus Torvalds1da177e2005-04-16 15:20:36 -070010015 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* ------------ TV */
10016
10017 index = GetTVPtrIndex(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010018
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010019 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
10020
10021 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010022
10023 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10024 /* Always use the second pointer on 650; some BIOSes */
10025 /* still carry old 301 data at the first location */
10026 /* romptr = SISGETROMW(0x114); */
10027 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
10028 romptr = SISGETROMW(0x11a);
10029 if(!romptr) return;
10030 delay = ROMAddr[romptr + index];
10031
10032 } else {
10033
10034 delay = SiS310_TVDelayCompensation_301B[index];
10035
10036 }
10037
10038 } else {
10039
10040 switch(SiS_Pr->SiS_CustomT) {
10041 case CUT_COMPAQ1280:
10042 case CUT_COMPAQ12802:
10043 case CUT_CLEVO1400:
10044 case CUT_CLEVO14002:
10045 delay = 0x02;
Richard Knutssonc30660ea2007-02-12 00:55:06 -080010046 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010047 break;
10048 case CUT_CLEVO1024:
10049 case CUT_CLEVO10242:
10050 delay = 0x03;
Richard Knutssonc30660ea2007-02-12 00:55:06 -080010051 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010052 break;
10053 default:
10054 delay = SiS310_TVDelayCompensation_651301LV[index];
10055 if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
10056 delay = SiS310_TVDelayCompensation_651302LV[index];
10057 }
10058 }
10059 }
10060
10061 } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10062
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010063 romptr = GetTVromptr(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010064 if(!romptr) return;
10065 delay = ROMAddr[romptr + index];
10066
10067 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
10068
10069 delay = SiS310_TVDelayCompensation_LVDS[index];
10070
10071 } else {
10072
10073 delay = SiS310_TVDelayCompensation_301[index];
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010074 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010075 if(IS_SIS740) {
10076 delay = SiS310_TVDelayCompensation_740301B[index];
10077 /* LV: use 301 data? BIOS bug? */
10078 } else {
10079 delay = SiS310_TVDelayCompensation_301B[index];
10080 if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
10081 }
10082 }
10083
10084 }
10085
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010086 if(SiS_LCDAEnabled(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010087 delay &= 0x0f;
Richard Knutssonc30660ea2007-02-12 00:55:06 -080010088 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010089 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010090
Linus Torvalds1da177e2005-04-16 15:20:36 -070010091 } else return;
10092
10093 /* Write delay */
10094
10095 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10096
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010097 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010098
10099 temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
10100 if(temp == 8) { /* 1400x1050 BIOS (COMPAL) */
10101 delay &= 0x0f;
10102 delay |= 0xb0;
10103 } else if(temp == 6) {
10104 delay &= 0x0f;
10105 delay |= 0xc0;
10106 } else if(temp > 7) { /* 1280x1024 BIOS (which one?) */
10107 delay = 0x35;
10108 }
10109 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
10110
10111 } else {
10112
10113 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
10114
10115 }
10116
10117 } else { /* LVDS */
10118
10119 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10120 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
10121 } else {
10122 if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
10123 delay <<= 4;
10124 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
10125 } else {
10126 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
10127 }
10128 }
10129
10130 }
10131
10132}
10133
10134static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010135SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010136{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010137 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10138 unsigned short index,temp,temp1,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010139
10140 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
10141
10142 if(ModeNo<=0x13)
10143 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
10144 else
10145 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
10146
10147 temp = GetTVPtrIndex(SiS_Pr);
10148 temp >>= 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10149 temp1 = temp;
10150
10151 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010152 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010153 temp1 = GetOEMTVPtr661(SiS_Pr);
10154 temp1 >>= 1;
10155 romptr = SISGETROMW(0x260);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010156 if(SiS_Pr->ChipType >= SIS_760) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010157 romptr = SISGETROMW(0x360);
10158 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010159 } else if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010160 romptr = SISGETROMW(0x192);
10161 } else {
10162 romptr = SISGETROMW(0x112);
10163 }
10164 }
10165
10166 if(romptr) {
10167 temp1 <<= 1;
10168 temp = ROMAddr[romptr + temp1 + index];
10169 } else {
10170 temp = SiS310_TVAntiFlick1[temp][index];
10171 }
10172 temp <<= 4;
10173
10174 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp); /* index 0A D[6:4] */
10175}
10176
10177static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010178SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010179{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010180 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10181 unsigned short index,temp,temp1,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010182
10183 temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10184
10185 if(ModeNo <= 0x13)
10186 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
10187 else
10188 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
10189
10190 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010191 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010192 romptr = SISGETROMW(0x26c);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010193 if(SiS_Pr->ChipType >= SIS_760) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010194 romptr = SISGETROMW(0x36c);
10195 }
10196 temp1 = GetOEMTVPtr661(SiS_Pr);
10197 temp1 >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010198 } else if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010199 romptr = SISGETROMW(0x1a4);
10200 } else {
10201 romptr = SISGETROMW(0x124);
10202 }
10203 }
10204
10205 if(romptr) {
10206 temp1 <<= 1;
10207 temp = ROMAddr[romptr + temp1 + index];
10208 } else {
10209 temp = SiS310_TVEdge1[temp][index];
10210 }
10211 temp <<= 5;
10212 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp); /* index 0A D[7:5] */
10213}
10214
10215static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010216SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010217{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010218 unsigned short index, temp, i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010219
10220 if(ModeNo <= 0x13) {
10221 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
10222 } else {
10223 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
10224 }
10225
10226 temp = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10227
10228 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 1; /* NTSC-J uses PAL */
10229 else if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 3; /* PAL-M */
10230 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 4; /* PAL-N */
10231 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1; /* HiVision uses PAL */
10232
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010233 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010234 for(i=0x35, j=0; i<=0x38; i++, j++) {
10235 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10236 }
10237 for(i=0x48; i<=0x4A; i++, j++) {
10238 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10239 }
10240 } else {
10241 for(i=0x35, j=0; i<=0x38; i++, j++) {
10242 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
10243 }
10244 }
10245}
10246
10247static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010248SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010249{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010250 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10251 unsigned short index,temp,i,j,resinfo,romptr=0;
10252 unsigned int lindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010253
10254 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
10255
10256 /* NTSC-J data not in BIOS, and already set in SetGroup2 */
10257 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
10258
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010259 if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010260 lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
10261 lindex <<= 2;
10262 for(j=0, i=0x31; i<=0x34; i++, j++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010263 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010264 }
10265 return;
10266 }
10267
10268 /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
10269 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
10270
10271 if(ModeNo<=0x13) {
10272 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10273 } else {
10274 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10275 }
10276
10277 temp = GetTVPtrIndex(SiS_Pr);
10278 /* 0: NTSC Graphics, 1: NTSC Text, 2: PAL Graphics,
10279 * 3: PAL Text, 4: HiTV Graphics 5: HiTV Text
10280 */
10281 if(SiS_Pr->SiS_UseROM) {
10282 romptr = SISGETROMW(0x116);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010283 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010284 romptr = SISGETROMW(0x196);
10285 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010286 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010287 romptr = SISGETROMW(0x11c);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010288 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010289 romptr = SISGETROMW(0x19c);
10290 }
10291 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
10292 romptr = SISGETROMW(0x116);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010293 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010294 romptr = SISGETROMW(0x196);
10295 }
10296 }
10297 }
10298 }
10299 if(romptr) {
10300 romptr += (temp << 2);
10301 for(j=0, i=0x31; i<=0x34; i++, j++) {
10302 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10303 }
10304 } else {
10305 index = temp % 2;
10306 temp >>= 1; /* 0:NTSC, 1:PAL, 2:HiTV */
10307 for(j=0, i=0x31; i<=0x34; i++, j++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010308 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
Linus Torvalds1da177e2005-04-16 15:20:36 -070010309 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10310 else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
10311 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
10312 else
10313 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10314 }
10315 }
10316
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010317 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010318 if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
10319 if((resinfo == SIS_RI_640x480) ||
10320 (resinfo == SIS_RI_800x600)) {
10321 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
10322 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
10323 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
10324 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
10325 } else if(resinfo == SIS_RI_1024x768) {
10326 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
10327 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
10328 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
10329 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
10330 }
10331 }
10332 }
10333}
10334
10335static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010336SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10337 unsigned short ModeIdIndex, unsigned short RTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010338{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010339 unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
10340 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010341
10342 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
10343 return;
10344
10345 /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
10346 /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
10347
10348 if(SiS_Pr->SiS_ROMNew) {
10349 if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) ||
10350 ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
10351 (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
10352 index = 25;
10353 if(SiS_Pr->UseCustomMode) {
10354 index = SiS_Pr->CSRClock;
10355 } else if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010356 index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010357 index = SiS_Pr->SiS_VCLKData[index].CLOCK;
10358 }
10359 if(index < 25) index = 25;
10360 index = ((index / 25) - 1) << 1;
10361 if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
10362 index++;
10363 }
10364 romptr = SISGETROMW(0x104);
10365 delay = ROMAddr[romptr + index];
10366 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
10367 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10368 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10369 } else {
10370 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10371 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10372 }
10373 return;
10374 }
10375 }
10376
10377 /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
10378
10379 if(SiS_Pr->UseCustomMode) delay = 0x04;
10380 else if(ModeNo <= 0x13) delay = 0x04;
10381 else delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
10382 delay |= (delay << 8);
10383
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010384 if(SiS_Pr->ChipType >= XGI_20) {
10385
10386 delay = 0x0606;
10387 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10388
10389 delay = 0x0404;
10390 if(SiS_Pr->SiS_XGIROM) {
10391 index = GetTVPtrIndex(SiS_Pr);
10392 if((romptr = SISGETROMW(0x35e))) {
10393 delay = (ROMAddr[romptr + index] & 0x0f) << 1;
10394 delay |= (delay << 8);
10395 }
10396 }
10397
10398 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
10399 if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
10400 delay -= 0x0404;
10401 }
10402 }
10403 }
10404
10405 } else if(SiS_Pr->ChipType >= SIS_340) {
10406
10407 delay = 0x0606;
10408 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10409 delay = 0x0404;
10410 }
10411 /* TODO (eventually) */
10412
10413 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010414
10415 /* 3. TV */
10416
10417 index = GetOEMTVPtr661(SiS_Pr);
10418 if(SiS_Pr->SiS_ROMNew) {
10419 romptr = SISGETROMW(0x106);
10420 if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
10421 delay = ROMAddr[romptr + index];
10422 } else {
10423 delay = 0x04;
10424 if(index > 3) delay = 0;
10425 }
10426
10427 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10428
10429 /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
10430
10431 if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010432 ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010433
10434 lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
10435
10436 /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
10437 delay = ROMAddr[romptr + lcdpdcindex + 1]; /* LCD */
10438 delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
10439
10440 } else {
10441
10442 /* TMDS: Set our own, since BIOS has no idea */
10443 /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
10444 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10445 switch(SiS_Pr->SiS_LCDResInfo) {
10446 case Panel_1024x768: delay = 0x0008; break;
10447 case Panel_1280x720: delay = 0x0004; break;
10448 case Panel_1280x768:
10449 case Panel_1280x768_2:delay = 0x0004; break;
10450 case Panel_1280x800:
10451 case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010452 case Panel_1280x854: delay = 0x0004; break; /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010453 case Panel_1280x1024: delay = 0x1e04; break;
10454 case Panel_1400x1050: delay = 0x0004; break;
10455 case Panel_1600x1200: delay = 0x0400; break;
10456 case Panel_1680x1050: delay = 0x0e04; break;
10457 default:
10458 if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
10459 delay = 0x0008;
10460 } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
10461 delay = 0x1e04;
10462 } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
10463 delay = 0x0004;
10464 } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
10465 delay = 0x0400;
10466 } else
10467 delay = 0x0e04;
10468 break;
10469 }
10470 }
10471
10472 /* Override by detected or user-set values */
10473 /* (but only if, for some reason, we can't read value from BIOS) */
10474 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
10475 delay = SiS_Pr->PDC & 0x1f;
10476 }
10477 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
10478 delay = (SiS_Pr->PDCA & 0x1f) << 8;
10479 }
10480
10481 }
10482
10483 }
10484
10485 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10486 delay >>= 8;
10487 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10488 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10489 } else {
10490 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10491 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10492 }
10493}
10494
10495static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010496SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010497{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010498 unsigned short infoflag;
10499 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010500
10501 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10502
10503 if(ModeNo <= 0x13) {
10504 infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
10505 } else if(SiS_Pr->UseCustomMode) {
10506 infoflag = SiS_Pr->CInfoFlag;
10507 } else {
10508 infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
10509 }
10510
10511 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10512 infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
10513 }
10514
10515 infoflag &= 0xc0;
10516
10517 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10518 temp = (infoflag >> 6) | 0x0c;
10519 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10520 temp ^= 0x04;
10521 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
10522 }
10523 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
10524 } else {
10525 temp = 0x30;
10526 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
10527 temp |= infoflag;
10528 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
10529 temp = 0;
10530 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10531 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
10532 }
10533 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
10534 }
10535
10536 }
10537}
10538
10539static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010540SetPanelParms661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010541{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010542 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10543 unsigned short romptr, temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010544
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010545 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
10546 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
10547 }
10548
10549 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010550 if(SiS_Pr->LVDSHL != -1) {
10551 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10552 }
10553 }
10554
10555 if(SiS_Pr->SiS_ROMNew) {
10556
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010557 if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
10558 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010559 temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
10560 temp2 = 0xfc;
10561 if(SiS_Pr->LVDSHL != -1) {
10562 temp1 &= 0xfc;
10563 temp2 = 0xf3;
10564 }
10565 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
10566 }
10567 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10568 temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
10569 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
10570 }
10571 }
10572
10573 }
10574}
10575
10576static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010577SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010578{
10579 if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010580 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010581 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010582 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10583 SetPanelParms661(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010584 }
10585 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010586 SetDelayComp(SiS_Pr,ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010587 }
10588
10589 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010590 SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
10591 SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
10592 SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010593 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010594 SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010595 }
10596 }
10597}
10598
10599static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010600SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10601 unsigned short ModeIdIndex, unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010602{
10603 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10604
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010605 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010606
10607 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010608 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10609 SetPanelParms661(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010610 }
10611
10612 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010613 SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
10614 SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
10615 SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010616 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010617 SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010618 }
10619 }
10620 }
10621}
10622
10623/* FinalizeLCD
10624 * This finalizes some CRT2 registers for the very panel used.
10625 * If we have a backup if these registers, we use it; otherwise
10626 * we set the register according to most BIOSes. However, this
10627 * function looks quite different in every BIOS, so you better
10628 * pray that we have a backup...
10629 */
10630static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010631SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010632{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010633 unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
10634 unsigned short resinfo,modeflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010635
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010636 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010637 if(SiS_Pr->SiS_ROMNew) return;
10638
10639 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10640 if(SiS_Pr->LVDSHL != -1) {
10641 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10642 }
10643 }
10644
10645 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10646 if(SiS_Pr->UseCustomMode) return;
10647
10648 switch(SiS_Pr->SiS_CustomT) {
10649 case CUT_COMPAQ1280:
10650 case CUT_COMPAQ12802:
10651 case CUT_CLEVO1400:
10652 case CUT_CLEVO14002:
10653 return;
10654 }
10655
10656 if(ModeNo <= 0x13) {
10657 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10658 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10659 } else {
10660 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10661 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10662 }
10663
10664 if(IS_SIS650) {
10665 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
10666 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10667 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
10668 } else {
10669 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
10670 }
10671 }
10672 }
10673
10674 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10675 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10676 /* Maybe all panels? */
10677 if(SiS_Pr->LVDSHL == -1) {
10678 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10679 }
10680 return;
10681 }
10682 }
10683
10684 if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
10685 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10686 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10687 if(SiS_Pr->LVDSHL == -1) {
10688 /* Maybe all panels? */
10689 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10690 }
10691 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10692 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10693 if(tempch == 3) {
10694 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10695 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10696 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10697 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10698 }
10699 }
10700 return;
10701 }
10702 }
10703 }
10704
10705 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10706 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010707 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010708 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
10709#ifdef SET_EMI
10710 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
10711#endif
10712 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
10713 }
10714 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10715 if(SiS_Pr->LVDSHL == -1) {
10716 /* Maybe ACER only? */
10717 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10718 }
10719 }
10720 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10721 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10722 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
10723 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
10724 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10725 if(tempch == 0x03) {
10726 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10727 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10728 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10729 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10730 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -080010731 if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010732 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
10733 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
10734 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
10735 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
10736 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
10737 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
10738 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
10739 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
10740 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
10741 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
10742 } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { /* 1.10.8w */
10743 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
10744 if(ModeNo <= 0x13) {
10745 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
10746 if((resinfo == 0) || (resinfo == 2)) return;
10747 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
10748 if((resinfo == 1) || (resinfo == 3)) return;
10749 }
10750 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10751 if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
10752 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02); /* 1.10.7u */
10753#if 0
10754 tempbx = 806; /* 0x326 */ /* other older BIOSes */
10755 tempbx--;
10756 temp = tempbx & 0xff;
10757 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
10758 temp = (tempbx >> 8) & 0x03;
10759 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
10760#endif
10761 }
10762 } else if(ModeNo <= 0x13) {
10763 if(ModeNo <= 1) {
10764 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
10765 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
10766 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10767 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10768 }
10769 if(!(modeflag & HalfDCLK)) {
10770 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
10771 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
10772 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
10773 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
10774 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
10775 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10776 if(ModeNo == 0x12) {
10777 switch(tempch) {
10778 case 0:
10779 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10780 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10781 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
10782 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10783 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
10784 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10785 break;
10786 case 2:
10787 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10788 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10789 break;
10790 case 3:
10791 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10792 break;
10793 }
10794 }
10795 }
10796 }
10797 }
10798 } else {
10799 tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
10800 tempcl &= 0x0f;
10801 tempbh &= 0x70;
10802 tempbh >>= 4;
10803 tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
10804 tempbx = (tempbh << 8) | tempbl;
10805 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10806 if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
10807 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
10808 tempbx = 770;
10809 } else {
10810 if(tempbx > 770) tempbx = 770;
10811 if(SiS_Pr->SiS_VGAVDE < 600) {
10812 tempax = 768 - SiS_Pr->SiS_VGAVDE;
10813 tempax >>= 4; /* 1.10.7w; 1.10.6s: 3; */
10814 if(SiS_Pr->SiS_VGAVDE <= 480) tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
10815 tempbx -= tempax;
10816 }
10817 }
10818 } else return;
10819 }
10820 temp = tempbx & 0xff;
10821 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
10822 temp = ((tempbx & 0xff00) >> 4) | tempcl;
10823 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
10824 }
10825 }
10826}
10827
10828#endif
10829
10830/* ================= SiS 300 O.E.M. ================== */
10831
10832#ifdef SIS300
10833
10834static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010835SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
10836 unsigned short RefTabIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010837{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010838 unsigned short crt2crtc=0, modeflag, myindex=0;
10839 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010840 int i;
10841
10842 if(ModeNo <= 0x13) {
10843 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10844 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
10845 } else {
10846 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10847 crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
10848 }
10849
10850 crt2crtc &= 0x3f;
10851
10852 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
10853 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
10854 }
10855
10856 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
10857 if(modeflag & HalfDCLK) myindex = 1;
10858
10859 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
10860 for(i=0; i<7; i++) {
10861 if(barco_p1[myindex][crt2crtc][i][0]) {
10862 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
10863 barco_p1[myindex][crt2crtc][i][0],
10864 barco_p1[myindex][crt2crtc][i][2],
10865 barco_p1[myindex][crt2crtc][i][1]);
10866 }
10867 }
10868 }
10869 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
10870 if(temp & 0x80) {
10871 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
10872 temp++;
10873 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
10874 }
10875 }
10876}
10877
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010878static unsigned short
10879GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010880{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010881 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10882 unsigned short tempbx=0,romptr=0;
10883 static const unsigned char customtable300[] = {
10884 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010885 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10886 };
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010887 static const unsigned char customtable630[] = {
10888 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010889 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10890 };
10891
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010892 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010893
10894 tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
10895 if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
10896 tempbx -= 2;
10897 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
10898 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10899 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
10900 }
10901 if(SiS_Pr->SiS_UseROM) {
10902 if(ROMAddr[0x235] & 0x80) {
10903 tempbx = SiS_Pr->SiS_LCDTypeInfo;
10904 if(Flag) {
10905 romptr = SISGETROMW(0x255);
10906 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10907 else tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
10908 if(tempbx == 0xFF) return 0xFFFF;
10909 }
10910 tempbx <<= 1;
10911 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
10912 }
10913 }
10914
10915 } else {
10916
10917 if(Flag) {
10918 if(SiS_Pr->SiS_UseROM) {
10919 romptr = SISGETROMW(0x255);
10920 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10921 else tempbx = 0xff;
10922 } else {
10923 tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
10924 }
10925 if(tempbx == 0xFF) return 0xFFFF;
10926 tempbx <<= 2;
10927 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10928 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10929 return tempbx;
10930 }
10931 tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
10932 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10933 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10934
10935 }
10936
10937 return tempbx;
10938}
10939
10940static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010941SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010942{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010943 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10944 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010945
10946 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10947
10948 if(SiS_Pr->SiS_UseROM) {
10949 if(!(ROMAddr[0x237] & 0x01)) return;
10950 if(!(ROMAddr[0x237] & 0x02)) return;
10951 romptr = SISGETROMW(0x24b);
10952 }
10953
10954 /* The Panel Compensation Delay should be set according to tables
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010955 * here. Unfortunately, various BIOS versions don't care about
Linus Torvalds1da177e2005-04-16 15:20:36 -070010956 * a uniform way using eg. ROM byte 0x220, but use different
10957 * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010958 * Thus we don't set this if the user selected a custom pdc or if
Linus Torvalds1da177e2005-04-16 15:20:36 -070010959 * we otherwise detected a valid pdc.
10960 */
10961 if(SiS_Pr->PDC != -1) return;
10962
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010963 temp = GetOEMLCDPtr(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010964
10965 if(SiS_Pr->UseCustomMode)
10966 index = 0;
10967 else
10968 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
10969
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010970 if(SiS_Pr->ChipType != SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010971 if(romptr) {
10972 romptr += (temp * 2);
10973 romptr = SISGETROMW(romptr);
10974 romptr += index;
10975 temp = ROMAddr[romptr];
10976 } else {
10977 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10978 temp = SiS300_OEMLCDDelay2[temp][index];
10979 } else {
10980 temp = SiS300_OEMLCDDelay3[temp][index];
10981 }
10982 }
10983 } else {
10984 if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
10985 if(romptr) {
10986 romptr += (temp * 2);
10987 romptr = SISGETROMW(romptr);
10988 romptr += index;
10989 temp = ROMAddr[romptr];
10990 } else {
10991 temp = SiS300_OEMLCDDelay5[temp][index];
10992 }
10993 } else {
10994 if(SiS_Pr->SiS_UseROM) {
10995 romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
10996 if(romptr) {
10997 romptr += (temp * 2);
10998 romptr = SISGETROMW(romptr);
10999 romptr += index;
11000 temp = ROMAddr[romptr];
11001 } else {
11002 temp = SiS300_OEMLCDDelay4[temp][index];
11003 }
11004 } else {
11005 temp = SiS300_OEMLCDDelay4[temp][index];
11006 }
11007 }
11008 }
11009 temp &= 0x3c;
11010 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* index 0A D[6:4] */
11011}
11012
11013static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011014SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011015{
11016#if 0 /* Unfinished; Data table missing */
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011017 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11018 unsigned short index,temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011019
11020 if((SiS_Pr->SiS_UseROM) {
11021 if(!(ROMAddr[0x237] & 0x01)) return;
11022 if(!(ROMAddr[0x237] & 0x04)) return;
11023 /* No rom pointer in BIOS header! */
11024 }
11025
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011026 temp = GetOEMLCDPtr(SiS_Pr, 1);
11027 if(temp == 0xFFFF) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011028
11029 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
11030 for(i=0x14, j=0; i<=0x17; i++, j++) {
11031 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
11032 }
11033 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
11034
11035 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
11036 SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
11037 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
11038 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
11039 for(i=0x1b, j=3; i<=0x1d; i++, j++) {
11040 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
11041 }
11042#endif
11043}
11044
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011045static unsigned short
11046GetOEMTVPtr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011047{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011048 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011049
11050 index = 0;
11051 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) index += 4;
11052 if(SiS_Pr->SiS_VBType & VB_SISVB) {
11053 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) index += 2;
11054 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
11055 else if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
11056 } else {
11057 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
11058 if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
11059 }
11060 return index;
11061}
11062
11063static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011064SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011065{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011066 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11067 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011068
11069 if(SiS_Pr->SiS_UseROM) {
11070 if(!(ROMAddr[0x238] & 0x01)) return;
11071 if(!(ROMAddr[0x238] & 0x02)) return;
11072 romptr = SISGETROMW(0x241);
11073 }
11074
11075 temp = GetOEMTVPtr(SiS_Pr);
11076
11077 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
11078
11079 if(romptr) {
11080 romptr += (temp * 2);
11081 romptr = SISGETROMW(romptr);
11082 romptr += index;
11083 temp = ROMAddr[romptr];
11084 } else {
11085 if(SiS_Pr->SiS_VBType & VB_SISVB) {
11086 temp = SiS300_OEMTVDelay301[temp][index];
11087 } else {
11088 temp = SiS300_OEMTVDelayLVDS[temp][index];
11089 }
11090 }
11091 temp &= 0x3c;
11092 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
11093}
11094
11095static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011096SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011097{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011098 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11099 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011100
11101 if(SiS_Pr->SiS_UseROM) {
11102 if(!(ROMAddr[0x238] & 0x01)) return;
11103 if(!(ROMAddr[0x238] & 0x04)) return;
11104 romptr = SISGETROMW(0x243);
11105 }
11106
11107 temp = GetOEMTVPtr(SiS_Pr);
11108
11109 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
11110
11111 if(romptr) {
11112 romptr += (temp * 2);
11113 romptr = SISGETROMW(romptr);
11114 romptr += index;
11115 temp = ROMAddr[romptr];
11116 } else {
11117 temp = SiS300_OEMTVFlicker[temp][index];
11118 }
11119 temp &= 0x70;
11120 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
11121}
11122
11123static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011124SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011125{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011126 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11127 unsigned short index,i,j,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011128
11129 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
11130
11131 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
11132
11133 if(SiS_Pr->SiS_UseROM) {
11134 if(!(ROMAddr[0x238] & 0x01)) return;
11135 if(!(ROMAddr[0x238] & 0x08)) return;
11136 romptr = SISGETROMW(0x245);
11137 }
11138
11139 temp = GetOEMTVPtr(SiS_Pr);
11140
11141 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
11142
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011143 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070011144 for(i=0x31, j=0; i<=0x34; i++, j++) {
11145 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
11146 }
11147 } else {
11148 if(romptr) {
11149 romptr += (temp * 2);
11150 romptr = SISGETROMW(romptr);
11151 romptr += (index * 4);
11152 for(i=0x31, j=0; i<=0x34; i++, j++) {
11153 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11154 }
11155 } else {
11156 for(i=0x31, j=0; i<=0x34; i++, j++) {
11157 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
11158 }
11159 }
11160 }
11161}
11162
11163static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011164SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011165{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011166 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
11167 unsigned short index,temp,i,j,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011168
11169 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
11170
11171 if(SiS_Pr->SiS_UseROM) {
11172 if(!(ROMAddr[0x238] & 0x01)) return;
11173 if(!(ROMAddr[0x238] & 0x10)) return;
11174 romptr = SISGETROMW(0x247);
11175 }
11176
11177 temp = GetOEMTVPtr(SiS_Pr);
11178
11179 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
11180 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
11181 /* NTSCJ uses NTSC filters */
11182
11183 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
11184
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011185 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070011186 for(i=0x35, j=0; i<=0x38; i++, j++) {
11187 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11188 }
11189 for(i=0x48; i<=0x4A; i++, j++) {
11190 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11191 }
11192 } else {
11193 if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
11194 romptr += (temp * 2);
11195 romptr = SISGETROMW(romptr);
11196 romptr += (index * 4);
11197 for(i=0x35, j=0; i<=0x38; i++, j++) {
11198 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11199 }
11200 } else {
11201 for(i=0x35, j=0; i<=0x38; i++, j++) {
11202 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
11203 }
11204 }
11205 }
11206}
11207
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011208static unsigned short
11209SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011210{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011211 unsigned short ModeIdIndex;
11212 unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011213
11214 if(*ModeNo <= 5) *ModeNo |= 1;
11215
11216 for(ModeIdIndex=0; ; ModeIdIndex++) {
11217 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
11218 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF) return 0;
11219 }
11220
11221 if(*ModeNo != 0x07) {
11222 if(*ModeNo > 0x03) return ModeIdIndex;
11223 if(VGAINFO & 0x80) return ModeIdIndex;
11224 ModeIdIndex++;
11225 }
11226
11227 if(VGAINFO & 0x10) ModeIdIndex++; /* 400 lines */
11228 /* else 350 lines */
11229 return ModeIdIndex;
11230}
11231
11232static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011233SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
11234 unsigned short RefTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011235{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011236 unsigned short OEMModeIdIndex = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011237
11238 if(!SiS_Pr->UseCustomMode) {
11239 OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
11240 if(!(OEMModeIdIndex)) return;
11241 }
11242
11243 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011244 SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011245 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011246 SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011247 }
11248 }
11249 if(SiS_Pr->UseCustomMode) return;
11250 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011251 SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011252 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011253 SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
11254 SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
11255 SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011256 }
11257 }
11258}
11259#endif
11260