blob: 9fa66fd4052acfaf5833a2e12e6c88f97aa9e72e [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
Aaro Koskinenf7854e52010-11-19 21:58:47 +000078#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -070079#include "oem300.h"
80#endif
81
Aaro Koskinenf7854e52010-11-19 21:58:47 +000082#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -070083#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);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070090static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
92/*********************************************/
93/* HELPER: Lock/Unlock CRT2 */
94/*********************************************/
95
96void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070097SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070099 if(SiS_Pr->ChipType == XGI_20)
100 return;
101 else if(SiS_Pr->ChipType >= SIS_315H)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
103 else
104 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
105}
106
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700107static
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700108void
109SiS_LockCRT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700111 if(SiS_Pr->ChipType == XGI_20)
112 return;
113 else if(SiS_Pr->ChipType >= SIS_315H)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
115 else
116 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
117}
118
119/*********************************************/
120/* HELPER: Write SR11 */
121/*********************************************/
122
123static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700124SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700126 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 DataAND &= 0x0f;
128 DataOR &= 0x0f;
129 }
130 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
131}
132
133/*********************************************/
134/* HELPER: Get Pointer to LCD structure */
135/*********************************************/
136
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000137#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700138static unsigned char *
139GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700141 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
142 unsigned char *myptr = NULL;
143 unsigned short romindex = 0, reg = 0, idx = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
145 /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
146 * due to the variaty of panels the BIOS doesn't know about.
147 * Exception: If the BIOS has better knowledge (such as in case
148 * of machines with a 301C and a panel that does not support DDC)
149 * use the BIOS data as well.
150 */
151
152 if((SiS_Pr->SiS_ROMNew) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700153 ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700155 if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
156 else reg = 0x7d;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
158 idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
159
160 if(idx < (8*26)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700161 myptr = (unsigned char *)&SiS_LCDStruct661[idx];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 }
163 romindex = SISGETROMW(0x100);
164 if(romindex) {
165 romindex += idx;
166 myptr = &ROMAddr[romindex];
167 }
168 }
169 return myptr;
170}
171
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700172static unsigned short
173GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700175 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
176 unsigned short romptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
178 /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
179 * due to the variaty of panels the BIOS doesn't know about.
180 * Exception: If the BIOS has better knowledge (such as in case
181 * of machines with a 301C and a panel that does not support DDC)
182 * use the BIOS data as well.
183 */
184
185 if((SiS_Pr->SiS_ROMNew) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700186 ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 romptr = SISGETROMW(0x102);
188 romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
189 }
190
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700191 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192}
193#endif
194
195/*********************************************/
196/* Adjust Rate for CRT2 */
197/*********************************************/
198
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800199static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700200SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
201 unsigned short RRTI, unsigned short *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700203 unsigned short checkmask=0, modeid, infoflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700205 modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700207 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700209 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700211 checkmask |= SupportRAMDAC2;
212 if(SiS_Pr->ChipType >= SIS_315H) {
213 checkmask |= SupportRAMDAC2_135;
214 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
215 checkmask |= SupportRAMDAC2_162;
216 if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
217 checkmask |= SupportRAMDAC2_202;
218 }
219 }
220 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700222 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700224 checkmask |= SupportLCD;
225 if(SiS_Pr->ChipType >= SIS_315H) {
226 if(SiS_Pr->SiS_VBType & VB_SISVB) {
227 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
228 if(modeid == 0x2e) checkmask |= Support64048060Hz;
229 }
230 }
231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700233 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700235 checkmask |= SupportHiVision;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700237 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700239 checkmask |= SupportTV;
240 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
241 checkmask |= SupportTV1024;
242 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
243 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
244 checkmask |= SupportYPbPr750p;
245 }
246 }
247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700251 } else { /* LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700253 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
254 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
255 checkmask |= SupportCHTV;
256 }
257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700259 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
260 checkmask |= SupportLCD;
261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700265 /* Look backwards in table for matching CRT2 mode */
266 for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
267 infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800268 if(infoflag & checkmask) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700269 if((*i) == 0) break;
270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700272 /* Look through the whole mode-section of the table from the beginning
273 * for a matching CRT2 mode if no mode was found yet.
274 */
275 for((*i) = 0; ; (*i)++) {
276 if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
277 infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800278 if(infoflag & checkmask) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700279 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800280 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281}
282
283/*********************************************/
284/* Get rate index */
285/*********************************************/
286
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700287unsigned short
288SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700290 unsigned short RRTI,i,backup_i;
291 unsigned short modeflag,index,temp,backupindex;
292 static const unsigned short LCDRefreshIndex[] = {
293 0x00, 0x00, 0x01, 0x01,
294 0x01, 0x01, 0x01, 0x01,
295 0x01, 0x01, 0x01, 0x01,
296 0x01, 0x01, 0x01, 0x01,
297 0x00, 0x00, 0x00, 0x00
298 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700300 /* Do NOT check for UseCustomMode here, will skrew up FIFO */
301 if(ModeNo == 0xfe) return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700303 if(ModeNo <= 0x13) {
304 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
305 } else {
306 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
307 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700309 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
310 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
311 if(modeflag & HalfDCLK) return 0;
312 }
313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700315 if(ModeNo < 0x14) return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700317 index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
318 backupindex = index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700320 if(index > 0) index--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700322 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
323 if(SiS_Pr->SiS_VBType & VB_SISVB) {
324 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
325 if(SiS_Pr->SiS_VBType & VB_NoLCD) index = 0;
326 else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
327 }
328 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
329 if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
330 temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
331 if(index > temp) index = temp;
332 }
333 }
334 } else {
335 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
336 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
337 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
338 }
339 }
340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700342 RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
343 ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700345 if(SiS_Pr->ChipType >= SIS_315H) {
346 if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
347 if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
348 (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
349 if(backupindex <= 1) RRTI++;
350 }
351 }
352 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700354 i = 0;
355 do {
356 if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
357 temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
358 temp &= ModeTypeMask;
359 if(temp < SiS_Pr->SiS_ModeType) break;
360 i++;
361 index--;
362 } while(index != 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700364 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
365 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
366 temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
367 if(temp & InterlaceMode) i++;
368 }
369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700371 i--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700373 if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
374 backup_i = i;
375 if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
376 i = backup_i;
377 }
378 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700380 return (RRTI + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381}
382
383/*********************************************/
384/* STORE CRT2 INFO in CR34 */
385/*********************************************/
386
387static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700388SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700390 unsigned short temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700392 /* Store CRT1 ModeNo in CR34 */
393 SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
394 temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
395 temp2 = ~(SetInSlaveMode >> 8);
396 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397}
398
399/*********************************************/
400/* HELPER: GET SOME DATA FROM BIOS ROM */
401/*********************************************/
402
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000403#ifdef CONFIG_FB_SIS_300
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800404static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700405SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700407 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
408 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700410 if(SiS_Pr->SiS_UseROM) {
411 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
412 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
413 temp1 = SISGETROMW(0x23b);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800414 if(temp1 & temp) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700415 }
416 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800417 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418}
419
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800420static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700421SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700423 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
424 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700426 if(SiS_Pr->SiS_UseROM) {
427 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
428 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
429 temp1 = SISGETROMW(0x23d);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800430 if(temp1 & temp) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700431 }
432 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800433 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434}
435#endif
436
437/*********************************************/
438/* HELPER: DELAY FUNCTIONS */
439/*********************************************/
440
441void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700442SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443{
David Rientjesb860e732006-12-08 02:40:19 -0800444 while (delaytime-- > 0)
445 SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446}
447
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000448#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700450SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700452 SiS_DDC2Delay(SiS_Pr, delay * 36);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453}
454#endif
455
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000456#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700458SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700460 while(delay--) {
461 SiS_GenericDelay(SiS_Pr, 6623);
462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463}
464#endif
465
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000466#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700468SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700470 while(delay--) {
471 SiS_GenericDelay(SiS_Pr, 66);
472 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473}
474#endif
475
476static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700477SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478{
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000479#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700480 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
481 unsigned short PanelID, DelayIndex, Delay=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482#endif
483
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700484 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000486#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
489 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700490 if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
491 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 }
493 DelayIndex = PanelID >> 4;
494 if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700495 Delay = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700497 if(DelayTime >= 2) DelayTime -= 2;
498 if(!(DelayTime & 0x01)) {
499 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
500 } else {
501 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
502 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 if(SiS_Pr->SiS_UseROM) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700504 if(ROMAddr[0x220] & 0x40) {
505 if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
506 else Delay = (unsigned short)ROMAddr[0x226];
507 }
508 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 }
510 SiS_ShortDelay(SiS_Pr, Delay);
511
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000512#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
514 } else {
515
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000516#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700518 if((SiS_Pr->ChipType >= SIS_661) ||
519 (SiS_Pr->ChipType <= SIS_315PRO) ||
520 (SiS_Pr->ChipType == SIS_330) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 (SiS_Pr->SiS_ROMNew)) {
522
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700523 if(!(DelayTime & 0x01)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 SiS_DDC2Delay(SiS_Pr, 0x1000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700525 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 SiS_DDC2Delay(SiS_Pr, 0x4000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528
529 } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700530 (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */
532
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700533 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
534 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
536 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
537 }
538 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
539 DelayIndex = PanelID & 0x0f;
540 } else {
541 DelayIndex = PanelID >> 4;
542 }
543 if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700544 Delay = 3;
545 } else {
546 if(DelayTime >= 2) DelayTime -= 2;
547 if(!(DelayTime & 0x01)) {
548 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
549 } else {
550 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
551 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700553 if(ROMAddr[0x13c] & 0x40) {
554 if(!(DelayTime & 0x01)) {
555 Delay = (unsigned short)ROMAddr[0x17e];
556 } else {
557 Delay = (unsigned short)ROMAddr[0x17f];
558 }
559 }
560 }
561 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 SiS_ShortDelay(SiS_Pr, Delay);
563 }
564
565 } else if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 315 series, all bridges */
566
567 DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700568 if(!(DelayTime & 0x01)) {
569 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
570 } else {
571 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 Delay <<= 8;
574 SiS_DDC2Delay(SiS_Pr, Delay);
575
576 }
577
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000578#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
580 }
581}
582
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000583#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700585SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586{
587 int i;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700588 for(i = 0; i < DelayLoop; i++) {
589 SiS_PanelDelay(SiS_Pr, DelayTime);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 }
591}
592#endif
593
594/*********************************************/
595/* HELPER: WAIT-FOR-RETRACE FUNCTIONS */
596/*********************************************/
597
598void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700599SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700601 unsigned short watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700603 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
604 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700606 watchdog = 65535;
607 while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
608 watchdog = 65535;
609 while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
611
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000612#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700614SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700616 unsigned short watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700618 watchdog = 65535;
619 while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
620 watchdog = 65535;
621 while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622}
623#endif
624
625static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700626SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700628 if(SiS_Pr->ChipType < SIS_315H) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000629#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700630 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
631 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
632 }
633 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
634 SiS_WaitRetrace1(SiS_Pr);
635 } else {
636 SiS_WaitRetrace2(SiS_Pr, 0x25);
637 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700639 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000640#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700641 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
642 SiS_WaitRetrace1(SiS_Pr);
643 } else {
644 SiS_WaitRetrace2(SiS_Pr, 0x30);
645 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700647 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648}
649
650static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700651SiS_VBWait(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700653 unsigned short tempal,temp,i,j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700655 temp = 0;
656 for(i = 0; i < 3; i++) {
657 for(j = 0; j < 100; j++) {
658 tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
659 if(temp & 0x01) {
660 if((tempal & 0x08)) continue;
661 else break;
662 } else {
663 if(!(tempal & 0x08)) continue;
664 else break;
665 }
666 }
667 temp ^= 0x01;
668 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669}
670
671static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700672SiS_VBLongWait(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700674 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
675 SiS_VBWait(SiS_Pr);
676 } else {
677 SiS_WaitRetrace1(SiS_Pr);
678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679}
680
681/*********************************************/
682/* HELPER: MISC */
683/*********************************************/
684
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000685#ifdef CONFIG_FB_SIS_300
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800686static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700687SiS_Is301B(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800689 if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
690 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691}
692#endif
693
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800694static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700695SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700697 if(SiS_Pr->ChipType == SIS_730) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800698 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700699 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800700 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
701 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702}
703
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800704bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700705SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706{
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000707#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700708 if(SiS_Pr->ChipType >= SIS_315H) {
709 if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800710 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700711 }
712 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800714 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715}
716
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800717bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700718SiS_IsVAMode(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719{
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000720#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700721 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700723 if(SiS_Pr->ChipType >= SIS_315H) {
724 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800725 if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700726 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800728 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729}
730
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000731#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800732static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700733SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800735 if(SiS_IsVAMode(SiS_Pr)) return true;
736 if(SiS_CRT2IsLCD(SiS_Pr)) return true;
737 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738}
739#endif
740
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800741static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700742SiS_IsDualLink(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743{
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000744#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700745 if(SiS_Pr->ChipType >= SIS_315H) {
746 if((SiS_CRT2IsLCD(SiS_Pr)) ||
747 (SiS_IsVAMode(SiS_Pr))) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800748 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700749 }
750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800752 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753}
754
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000755#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800756static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700757SiS_TVEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800759 if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700760 if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800761 if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700762 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800763 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764}
765#endif
766
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000767#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800768static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700769SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800771 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
772 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773}
774#endif
775
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000776#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800777static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700778SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700780 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800781 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700782 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800783 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784}
785#endif
786
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000787#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800788static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700789SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700791 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700793 if(SiS_Pr->ChipType == SIS_650) {
794 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
795 /* Check for revision != A0 only */
796 if((flag == 0xe0) || (flag == 0xc0) ||
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800797 (flag == 0xb0) || (flag == 0x90)) return false;
798 } else if(SiS_Pr->ChipType >= SIS_661) return false;
799 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800}
801#endif
802
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000803#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800804static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700805SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700807 if(SiS_Pr->ChipType >= SIS_315H) {
808 /* YPrPb = 0x08 */
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800809 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700810 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800811 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812}
813#endif
814
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000815#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800816static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700817SiS_IsChScart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700819 if(SiS_Pr->ChipType >= SIS_315H) {
820 /* Scart = 0x04 */
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800821 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700822 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800823 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824}
825#endif
826
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000827#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800828static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700829SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700831 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700833 if(SiS_Pr->ChipType >= SIS_315H) {
834 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800835 if(flag & SetCRT2ToTV) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700836 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800837 if(flag & EnableCHYPbPr) return true; /* = YPrPb = 0x08 */
838 if(flag & EnableCHScart) return true; /* = Scart = 0x04 - TW */
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700839 } else {
840 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800841 if(flag & SetCRT2ToTV) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700842 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800843 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844}
845#endif
846
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000847#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800848static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700849SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700851 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700853 if(SiS_Pr->ChipType >= SIS_315H) {
854 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800855 if(flag & SetCRT2ToLCD) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700856 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800857 if(flag & SetToLCDA) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700858 } else {
859 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800860 if(flag & SetCRT2ToLCD) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700861 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800862 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863}
864#endif
865
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800866static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700867SiS_HaveBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700869 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700871 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800872 return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700873 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
874 flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800875 if((flag == 1) || (flag == 2)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700876 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800877 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878}
879
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800880static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700881SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700883 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700885 if(SiS_HaveBridge(SiS_Pr)) {
886 flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
887 if(SiS_Pr->ChipType < SIS_315H) {
888 flag &= 0xa0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800889 if((flag == 0x80) || (flag == 0x20)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700890 } else {
891 flag &= 0x50;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800892 if((flag == 0x40) || (flag == 0x10)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700893 }
894 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800895 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896}
897
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800898static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700899SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700901 unsigned short flag1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700903 flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800904 if(flag1 & (SetInSlaveMode >> 8)) return true;
905 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906}
907
908/*********************************************/
909/* GET VIDEO BRIDGE CONFIG INFO */
910/*********************************************/
911
912/* Setup general purpose IO for Chrontel communication */
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000913#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700915SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700917 unsigned int acpibase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 unsigned short temp;
919
920 if(!(SiS_Pr->SiS_ChSW)) return;
921
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700922 acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 acpibase &= 0xFFFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700924 if(!acpibase) return;
925 temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 temp &= 0xFEFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700927 SiS_SetRegShort((acpibase + 0x3c), temp);
928 temp = SiS_GetRegShort((acpibase + 0x3c));
929 temp = SiS_GetRegShort((acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 temp &= 0xFEFF;
931 if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700932 SiS_SetRegShort((acpibase + 0x3a), temp);
933 temp = SiS_GetRegShort((acpibase + 0x3a));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934}
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700935#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936
937void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700938SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
939 unsigned short ModeIdIndex, int checkcrt2mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700941 unsigned short tempax, tempbx, temp;
942 unsigned short modeflag, resinfo = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700944 SiS_Pr->SiS_SetFlag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700946 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700948 SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700950 if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
951 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
952 }
953
954 tempbx = 0;
955
956 if(SiS_HaveBridge(SiS_Pr)) {
957
958 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
959 tempbx |= temp;
960 tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
961 tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
962 tempbx |= tempax;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000964#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700965 if(SiS_Pr->ChipType >= SIS_315H) {
966 if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 if(ModeNo == 0x03) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700968 /* Mode 0x03 is never in driver mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
970 }
971 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700972 /* Reset LCDA setting if not driver mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
974 }
975 if(IS_SIS650) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700976 if(SiS_Pr->SiS_UseLCDA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
978 if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700979 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 }
981 }
982 }
983 }
984 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700985 if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
986 tempbx |= SetCRT2ToLCDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 }
988 }
989
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700990 if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700992 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
993 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
994 if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
995 else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
996 tempbx |= SetCRT2ToYPbPr525750;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 }
998 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700999 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000
1001 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1002 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1003 if(temp & SetToLCDA) {
1004 tempbx |= SetCRT2ToLCDA;
1005 }
1006 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001007 if(temp & EnableCHYPbPr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 tempbx |= SetCRT2ToCHYPbPr;
1009 }
1010 }
1011 }
1012 }
1013
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001014#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001016 if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
1017 tempbx &= ~(SetCRT2ToRAMDAC);
1018 }
1019
1020 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 temp = SetCRT2ToSVIDEO |
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001022 SetCRT2ToAVIDEO |
1023 SetCRT2ToSCART |
1024 SetCRT2ToLCDA |
1025 SetCRT2ToLCD |
1026 SetCRT2ToRAMDAC |
1027 SetCRT2ToHiVision |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 SetCRT2ToYPbPr525750;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001029 } else {
1030 if(SiS_Pr->ChipType >= SIS_315H) {
1031 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1032 temp = SetCRT2ToAVIDEO |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 SetCRT2ToSVIDEO |
1034 SetCRT2ToSCART |
1035 SetCRT2ToLCDA |
1036 SetCRT2ToLCD |
1037 SetCRT2ToCHYPbPr;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001038 } else {
1039 temp = SetCRT2ToLCDA |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 SetCRT2ToLCD;
1041 }
1042 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001043 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1044 temp = SetCRT2ToTV | SetCRT2ToLCD;
1045 } else {
1046 temp = SetCRT2ToLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 }
1048 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001051 if(!(tempbx & temp)) {
1052 tempax = DisableCRT2Display;
1053 tempbx = 0;
1054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001056 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1057
1058 unsigned short clearmask = ( DriverMode |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 DisableCRT2Display |
1060 LoadDACFlag |
1061 SetNotSimuMode |
1062 SetInSlaveMode |
1063 SetPALTV |
1064 SwitchCRT2 |
1065 SetSimuScanMode );
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001066
1067 if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 if(tempbx & SetCRT2ToRAMDAC) tempbx &= (clearmask | SetCRT2ToRAMDAC);
1069 if(tempbx & SetCRT2ToLCD) tempbx &= (clearmask | SetCRT2ToLCD);
1070 if(tempbx & SetCRT2ToSCART) tempbx &= (clearmask | SetCRT2ToSCART);
1071 if(tempbx & SetCRT2ToHiVision) tempbx &= (clearmask | SetCRT2ToHiVision);
1072 if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001073
1074 } else {
1075
1076 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 if(tempbx & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001078 tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 }
1080 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001081 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1082 if(tempbx & SetCRT2ToTV) {
1083 tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001086 if(tempbx & SetCRT2ToLCD) {
1087 tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
1088 }
1089 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 if(tempbx & SetCRT2ToLCDA) {
1091 tempbx |= SetCRT2ToLCD;
1092 }
1093 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001094
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 }
1096
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001097 if(tempax & DisableCRT2Display) {
1098 if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1099 tempbx = SetSimuScanMode | DisableCRT2Display;
1100 }
1101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001103 if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
1105 /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
1106 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
1107 if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
1108 ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001109 modeflag &= (~CRT2Mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 }
1111 }
1112
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001113 if(!(tempbx & SetSimuScanMode)) {
1114 if(tempbx & SwitchCRT2) {
1115 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1116 if(resinfo != SIS_RI_1600x1200) {
1117 tempbx |= SetSimuScanMode;
1118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001120 } else {
1121 if(SiS_BridgeIsEnabled(SiS_Pr)) {
1122 if(!(tempbx & DriverMode)) {
1123 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 tempbx |= SetSimuScanMode;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001125 }
1126 }
1127 }
1128 }
1129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001131 if(!(tempbx & DisableCRT2Display)) {
1132 if(tempbx & DriverMode) {
1133 if(tempbx & SetSimuScanMode) {
1134 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1135 if(resinfo != SIS_RI_1600x1200) {
1136 tempbx |= SetInSlaveMode;
1137 }
1138 }
1139 }
1140 } else {
1141 tempbx |= SetInSlaveMode;
1142 }
1143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001145 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001147 SiS_Pr->SiS_VBInfo = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001149#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001150 if(SiS_Pr->ChipType == SIS_630) {
1151 SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1152 }
1153#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001155#if 0
1156 printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1158#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159}
1160
1161/*********************************************/
1162/* DETERMINE YPbPr MODE */
1163/*********************************************/
1164
1165void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001166SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167{
1168
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001169 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001171 /* Note: This variable is only used on 30xLV systems.
1172 * CR38 has a different meaning on LVDS/CH7019 systems.
1173 * On 661 and later, these bits moved to CR35.
1174 *
1175 * On 301, 301B, only HiVision 1080i is supported.
1176 * On 30xLV, 301C, only YPbPr 1080i is supported.
1177 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001179 SiS_Pr->SiS_YPbPr = 0;
1180 if(SiS_Pr->ChipType >= SIS_661) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001182 if(SiS_Pr->SiS_VBType) {
1183 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1184 SiS_Pr->SiS_YPbPr = YPbPrHiVision;
1185 }
1186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001188 if(SiS_Pr->ChipType >= SIS_315H) {
1189 if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1190 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1191 if(temp & 0x08) {
1192 switch((temp >> 4)) {
1193 case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break;
1194 case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break;
1195 case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break;
1196 case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
1197 }
1198 }
1199 }
1200 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
1202}
1203
1204/*********************************************/
1205/* DETERMINE TVMode flag */
1206/*********************************************/
1207
1208void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001209SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001211 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1212 unsigned short temp, temp1, resinfo = 0, romindex = 0;
1213 unsigned char OutputSelect = *SiS_Pr->pSiS_OutputSelect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001215 SiS_Pr->SiS_TVMode = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001217 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
1218 if(SiS_Pr->UseCustomMode) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001220 if(ModeNo > 0x13) {
1221 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001224 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001226 if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001228 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1229 temp = 0;
1230 if((SiS_Pr->ChipType == SIS_630) ||
1231 (SiS_Pr->ChipType == SIS_730)) {
1232 temp = 0x35;
1233 romindex = 0xfe;
1234 } else if(SiS_Pr->ChipType >= SIS_315H) {
1235 temp = 0x38;
1236 if(SiS_Pr->ChipType < XGI_20) {
1237 romindex = 0xf3;
1238 if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
1239 }
1240 }
1241 if(temp) {
1242 if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
1243 OutputSelect = ROMAddr[romindex];
1244 if(!(OutputSelect & EnablePALMN)) {
1245 SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
1246 }
1247 }
1248 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
1249 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1250 if(temp1 & EnablePALM) { /* 0x40 */
1251 SiS_Pr->SiS_TVMode |= TVSetPALM;
1252 SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1253 } else if(temp1 & EnablePALN) { /* 0x80 */
1254 SiS_Pr->SiS_TVMode |= TVSetPALN;
1255 }
1256 } else {
1257 if(temp1 & EnableNTSCJ) { /* 0x40 */
1258 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1259 }
1260 }
1261 }
1262 /* Translate HiVision/YPbPr to our new flags */
1263 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1264 if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1265 else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1266 else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
1267 else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1268 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
1269 SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
1270 SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
1271 } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
1272 SiS_Pr->SiS_TVMode |= TVSetPAL;
1273 }
1274 }
1275 } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1276 if(SiS_Pr->SiS_CHOverScan) {
1277 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
1278 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1279 if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
1280 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1281 }
1282 } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1283 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
1284 if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
1285 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1286 }
1287 }
1288 if(SiS_Pr->SiS_CHSOverScan) {
1289 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1290 }
1291 }
1292 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1293 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1294 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1295 if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM;
1296 else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
1297 } else {
1298 if(temp & EnableNTSCJ) {
1299 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1300 }
1301 }
1302 }
1303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001305 } else { /* 661 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001307 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1308 if(temp1 & 0x01) {
1309 SiS_Pr->SiS_TVMode |= TVSetPAL;
1310 if(temp1 & 0x08) {
1311 SiS_Pr->SiS_TVMode |= TVSetPALN;
1312 } else if(temp1 & 0x04) {
1313 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1314 SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1315 }
1316 SiS_Pr->SiS_TVMode |= TVSetPALM;
1317 }
1318 } else {
1319 if(temp1 & 0x02) {
1320 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1321 }
1322 }
1323 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1324 if(SiS_Pr->SiS_CHOverScan) {
1325 if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
1326 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1327 }
1328 }
1329 }
1330 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1331 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1332 temp1 &= 0xe0;
1333 if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1334 else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1335 else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1336 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1337 SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
1338 }
1339 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
1340 if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
1341 SiS_Pr->SiS_TVMode |= TVAspect169;
1342 } else {
1343 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
1344 if(temp1 & 0x02) {
1345 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
1346 SiS_Pr->SiS_TVMode |= TVAspect169;
1347 } else {
1348 SiS_Pr->SiS_TVMode |= TVAspect43LB;
1349 }
1350 } else {
1351 SiS_Pr->SiS_TVMode |= TVAspect43;
1352 }
1353 }
1354 }
1355 }
1356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001358 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001360 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001362 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1363 SiS_Pr->SiS_TVMode |= TVSetPAL;
1364 SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
1365 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1366 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
1367 SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
1368 }
1369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001371 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1372 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
1373 SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1374 }
1375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001377 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
1378 if(resinfo == SIS_RI_1024x768) {
1379 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
1380 SiS_Pr->SiS_TVMode |= TVSet525p1024;
1381 } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
1382 SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
1383 }
1384 }
1385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001387 SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
1388 if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
1389 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
1390 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1391 } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
1392 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1393 } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
1394 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
1395 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1396 }
1397 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001399 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001401 SiS_Pr->SiS_VBInfo &= ~SetPALTV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402}
1403
1404/*********************************************/
1405/* GET LCD INFO */
1406/*********************************************/
1407
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001408static unsigned short
1409SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001411 unsigned short temp = SiS_Pr->SiS_LCDResInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 /* Translate my LCDResInfo to BIOS value */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001413 switch(temp) {
1414 case Panel_1280x768_2: temp = Panel_1280x768; break;
1415 case Panel_1280x800_2: temp = Panel_1280x800; break;
1416 case Panel_1280x854: temp = Panel661_1280x854; break;
1417 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 return temp;
1419}
1420
1421static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001422SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423{
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001424#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001425 unsigned char *ROMAddr;
1426 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001428 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001430 SiS_Pr->SiS_NeedRomModeData = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 SiS_Pr->PanelHT = temp;
1432 }
1433 if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001434 SiS_Pr->SiS_NeedRomModeData = true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001435 SiS_Pr->PanelVT = temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 }
1437 SiS_Pr->PanelHRS = SISGETROMW(10);
1438 SiS_Pr->PanelHRE = SISGETROMW(12);
1439 SiS_Pr->PanelVRS = SISGETROMW(14);
1440 SiS_Pr->PanelVRE = SISGETROMW(16);
1441 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1442 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001443 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
1445 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
1446 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
1447 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
1448
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 }
1450#endif
1451}
1452
1453static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001454SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
1455 const unsigned char *nonscalingmodes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001457 int i = 0;
1458 while(nonscalingmodes[i] != 0xff) {
1459 if(nonscalingmodes[i++] == resinfo) {
1460 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
1461 (SiS_Pr->UsePanelScaler == -1)) {
1462 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1463 }
1464 break;
1465 }
1466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467}
1468
1469void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001470SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001472 unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001473 bool panelcanscale = false;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001474#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001475 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1476 static const unsigned char SiS300SeriesLCDRes[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 { 0, 1, 2, 3, 7, 4, 5, 8,
1478 0, 0, 10, 0, 0, 0, 0, 15 };
1479#endif
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001480#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001481 unsigned char *myptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
1484 SiS_Pr->SiS_LCDResInfo = 0;
1485 SiS_Pr->SiS_LCDTypeInfo = 0;
1486 SiS_Pr->SiS_LCDInfo = 0;
1487 SiS_Pr->PanelHRS = 999; /* HSync start */
1488 SiS_Pr->PanelHRE = 999; /* HSync end */
1489 SiS_Pr->PanelVRS = 999; /* VSync start */
1490 SiS_Pr->PanelVRE = 999; /* VSync end */
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001491 SiS_Pr->SiS_NeedRomModeData = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001493 /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001494 SiS_Pr->Alternate1600x1200 = false;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001495
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
1497
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001498 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1499
1500 if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1502 modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
1503 modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
1504 }
1505
1506 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
1507
1508 /* For broken BIOSes: Assume 1024x768 */
1509 if(temp == 0) temp = 0x02;
1510
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001511 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001513 } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
1515 } else {
1516 SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1517 }
1518 temp &= 0x0f;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001519#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001520 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
1522 if(SiS_Pr->SiS_VBType & VB_SIS301) {
1523 if(temp < 0x0f) temp &= 0x07;
1524 }
1525 /* Translate 300 series LCDRes to 315 series for unified usage */
1526 temp = SiS300SeriesLCDRes[temp];
1527 }
1528#endif
1529
1530 /* Translate to our internal types */
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001531#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001532 if(SiS_Pr->ChipType == SIS_550) {
1533 if (temp == Panel310_1152x768) temp = Panel_320x240_2; /* Verified working */
1534 else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
1535 else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
1536 } else if(SiS_Pr->ChipType >= SIS_661) {
1537 if(temp == Panel661_1280x854) temp = Panel_1280x854;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001539#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001541 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 if(temp == Panel310_1280x768) {
1543 temp = Panel_1280x768_2;
1544 }
1545 if(SiS_Pr->SiS_ROMNew) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001546 if(temp == Panel661_1280x800) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 temp = Panel_1280x800_2;
1548 }
1549 }
1550 }
1551
1552 SiS_Pr->SiS_LCDResInfo = temp;
1553
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001554#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1556 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001557 SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001559 SiS_Pr->SiS_LCDResInfo = Panel_848x480;
1560 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
1561 SiS_Pr->SiS_LCDResInfo = Panel_856x480;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 }
1563 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001564#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
1566 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1567 if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
1568 SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
1569 } else {
1570 if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
1571 SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
1572 }
1573
1574 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
1575 SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
1576 /* Need temp below! */
1577
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001578 /* These must/can't scale no matter what */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001580 case Panel_320x240_1:
1581 case Panel_320x240_2:
1582 case Panel_320x240_3:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 case Panel_1280x960:
1584 SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001585 break;
1586 case Panel_640x480:
1587 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 }
1589
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001590 panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
1592 if(!SiS_Pr->UsePanelScaler) SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1593 else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1594
1595 /* Dual link, Pass 1:1 BIOS default, etc. */
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001596#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001597 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001599 if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001601 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1602 if(SiS_Pr->SiS_ROMNew) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001604 } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
1605 if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 }
1607 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001608 } else if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001610 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 }
1612 if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001613 SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001615 if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
1616 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1618 }
1619 } else if(!(SiS_Pr->SiS_ROMNew)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001620 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1621 if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
1623 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1624 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001625 if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001627 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
1629 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1630 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001631 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 }
1633 }
1634#endif
1635
1636 /* Pass 1:1 */
1637 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
1638 /* Always center screen on LVDS (if scaling is disabled) */
1639 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1640 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1641 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001642 /* Always center screen on SiS LVDS (if scaling is disabled) */
1643 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001645 /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
1646 if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1647 if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 }
1649 }
1650
1651 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1652 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1653
1654 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001655 case Panel_320x240_1:
1656 case Panel_320x240_2:
1657 case Panel_320x240_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
1658 SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 SiS_Pr->PanelVCLKIdx300 = VCLK28;
1660 SiS_Pr->PanelVCLKIdx315 = VCLK28;
1661 break;
1662 case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001663 SiS_Pr->PanelVRE = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 SiS_Pr->PanelVCLKIdx300 = VCLK28;
1665 SiS_Pr->PanelVCLKIdx315 = VCLK28;
1666 break;
1667 case Panel_800x600: SiS_Pr->PanelXRes = 800; SiS_Pr->PanelYRes = 600;
1668 SiS_Pr->PanelHT = 1056; SiS_Pr->PanelVT = 628;
1669 SiS_Pr->PanelHRS = 40; SiS_Pr->PanelHRE = 128;
1670 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 4;
1671 SiS_Pr->PanelVCLKIdx300 = VCLK40;
1672 SiS_Pr->PanelVCLKIdx315 = VCLK40;
1673 break;
1674 case Panel_1024x600: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 600;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001675 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1677 SiS_Pr->PanelVRS = 2 /* 88 */ ; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001678 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001680 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001682 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1684 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001685 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 SiS_Pr->PanelHRS = 23;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001687 SiS_Pr->PanelVRE = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 }
1689 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1690 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001691 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 break;
1693 case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001694 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
1695 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001697 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 SiS_Pr->PanelHRS = 23;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001699 SiS_Pr->PanelVRE = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001701 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001703 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001705 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 case Panel_1280x720: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 720;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001707 SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 SiS_Pr->PanelHRS = 110; SiS_Pr->PanelHRE = 40;
1709 SiS_Pr->PanelVRS = 5; SiS_Pr->PanelVRE = 5;
1710 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
1711 /* Data above for TMDS (projector); get from BIOS for LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001712 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 break;
1714 case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001715 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 806;
1717 SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
1718 SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
1719 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001720 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRS = 112;
1722 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1723 SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
1724 SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
1725 }
1726 break;
1727 case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001728 SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1730 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1731 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001732 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 break;
1734 case Panel_1280x800: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001735 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 SiS_Pr->PanelHRS = 21; SiS_Pr->PanelHRE = 24;
1737 SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
1738 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001739 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 break;
1741 case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001742 SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1744 SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
1745 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001746 SiS_GetLCDInfoBIOS(SiS_Pr);
1747 break;
1748 case Panel_1280x854: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 854;
1749 SiS_Pr->PanelHT = 1664; SiS_Pr->PanelVT = 861;
1750 SiS_Pr->PanelHRS = 16; SiS_Pr->PanelHRE = 112;
1751 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1752 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
1753 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 break;
1755 case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001756 SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1758 SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001759 if(resinfo == SIS_RI_1280x1024) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
1761 SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
1762 }
1763 break;
1764 case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001765 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1767 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1768 SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1769 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001770 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 break;
1772 case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001773 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1774 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1776 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001777 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 break;
1779 case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001780 SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 SiS_Pr->PanelHRS = 64; SiS_Pr->PanelHRE = 192;
1782 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1783 SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001784 if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
1785 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1786 SiS_Pr->PanelHT = 1760; SiS_Pr->PanelVT = 1235;
1787 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 32;
1788 SiS_Pr->PanelVRS = 2; SiS_Pr->PanelVRE = 4;
1789 SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001790 SiS_Pr->Alternate1600x1200 = true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001791 }
1792 } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
1793 SiS_Pr->PanelHT = 2048; SiS_Pr->PanelVT = 1320;
1794 SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
1795 SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
1796 }
1797 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 break;
1799 case Panel_1680x1050: SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001800 SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 SiS_Pr->PanelHRS = 26; SiS_Pr->PanelHRE = 76;
1802 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1803 SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001804 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 break;
1806 case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001807 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1808 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001810 SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
1811 break;
1812 case Panel_856x480: SiS_Pr->PanelXRes = 856; SiS_Pr->PanelYRes = 480;
1813 SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
1814 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001816 SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 SiS_Pr->PanelHT = SiS_Pr->CHTotal;
1818 SiS_Pr->PanelVT = SiS_Pr->CVTotal;
1819 if(SiS_Pr->CP_PreferredIndex != -1) {
1820 SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001821 SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 SiS_Pr->PanelHT = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
1823 SiS_Pr->PanelVT = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
1824 SiS_Pr->PanelHRS = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
1825 SiS_Pr->PanelHRE = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
1826 SiS_Pr->PanelVRS = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
1827 SiS_Pr->PanelVRE = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
1828 SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
1829 SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
1830 SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
1831 SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
1832 if(SiS_Pr->CP_PrefClock) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001833 int idx;
1834 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001836 if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 else idx = VCLK_CUSTOM_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001838 SiS_Pr->SiS_VCLKData[idx].CLOCK =
1839 SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
1840 SiS_Pr->SiS_VCLKData[idx].SR2B =
1841 SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
1842 SiS_Pr->SiS_VCLKData[idx].SR2C =
1843 SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 }
1845 }
1846 break;
1847 default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001848 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 break;
1850 }
1851
1852 /* Special cases */
1853 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
1854 (SiS_Pr->SiS_IF_DEF_DSTN) ||
1855 (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1856 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001857 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1858 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 SiS_Pr->PanelHRS = 999;
1860 SiS_Pr->PanelHRE = 999;
1861 }
1862
1863 if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1864 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001865 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1866 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 SiS_Pr->PanelVRS = 999;
1868 SiS_Pr->PanelVRE = 999;
1869 }
1870
1871 /* DontExpand overrule */
1872 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
1873
1874 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
1875 /* No scaling for this mode on any panel (LCD=CRT2)*/
1876 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1877 }
1878
1879 switch(SiS_Pr->SiS_LCDResInfo) {
1880
1881 case Panel_Custom:
1882 case Panel_1152x864:
1883 case Panel_1280x768: /* TMDS only */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001884 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 break;
1886
1887 case Panel_800x600: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001888 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
1890 };
1891 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1892 break;
1893 }
1894 case Panel_1024x768: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001895 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1897 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1898 0xff
1899 };
1900 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1901 break;
1902 }
1903 case Panel_1280x720: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001904 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1906 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1907 0xff
1908 };
1909 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1910 if(SiS_Pr->PanelHT == 1650) {
1911 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1912 }
1913 break;
1914 }
1915 case Panel_1280x768_2: { /* LVDS only */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001916 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1918 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1919 SIS_RI_1152x768,0xff
1920 };
1921 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1922 switch(resinfo) {
1923 case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001924 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1925 }
1926 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001928 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 }
1930 case Panel_1280x800: { /* SiS TMDS special (Averatec 6200 series) */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001931 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1933 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1934 SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
1935 };
1936 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001937 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 }
1939 case Panel_1280x800_2: { /* SiS LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001940 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1942 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1943 SIS_RI_1152x768,0xff
1944 };
1945 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1946 switch(resinfo) {
1947 case SIS_RI_1280x720:
1948 case SIS_RI_1280x768: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001949 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1950 }
1951 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001953 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001955 case Panel_1280x854: { /* SiS LVDS */
1956 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1958 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001959 SIS_RI_1152x768,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 };
1961 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001962 switch(resinfo) {
1963 case SIS_RI_1280x720:
1964 case SIS_RI_1280x768:
1965 case SIS_RI_1280x800: if(SiS_Pr->UsePanelScaler == -1) {
1966 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1967 }
1968 break;
1969 }
1970 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001972 case Panel_1280x960: {
1973 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1975 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1976 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001977 SIS_RI_1280x854,0xff
1978 };
1979 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1980 break;
1981 }
1982 case Panel_1280x1024: {
1983 static const unsigned char nonscalingmodes[] = {
1984 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1985 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1986 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
1987 SIS_RI_1280x854,SIS_RI_1280x960,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 };
1989 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1990 break;
1991 }
1992 case Panel_1400x1050: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001993 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1995 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001996 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
1997 SIS_RI_1280x960,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 };
1999 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002000 switch(resinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002002 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2003 }
2004 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002006 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 }
2008 break;
2009 }
2010 case Panel_1600x1200: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002011 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2013 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2014 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002015 SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 };
2017 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002018 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 }
2020 case Panel_1680x1050: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002021 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2023 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002024 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
2025 SIS_RI_1360x1024,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 };
2027 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2028 break;
2029 }
2030 }
2031 }
2032
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002033#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002035 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2036 SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 }
2038 }
2039
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002040 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002042 if(SiS_Pr->SiS_UseROM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002044 if(!(ROMAddr[0x235] & 0x02)) {
2045 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2046 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002048 }
2049 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002051 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 }
2053 }
2054 }
2055#endif
2056
2057 /* Special cases */
2058
2059 if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
2060 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2061 }
2062
2063 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
2064 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2065 }
2066
2067 switch(SiS_Pr->SiS_LCDResInfo) {
2068 case Panel_640x480:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002069 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 break;
2071 case Panel_1280x800:
2072 /* Don't pass 1:1 by default (TMDS special) */
2073 if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2074 break;
2075 case Panel_1280x960:
2076 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2077 break;
2078 case Panel_Custom:
2079 if((!SiS_Pr->CP_PrefClock) ||
2080 (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
2081 SiS_Pr->SiS_LCDInfo |= LCDPass11;
2082 }
2083 break;
2084 }
2085
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002086 if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2088 }
2089
2090 /* (In)validate LCDPass11 flag */
2091 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2092 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2093 }
2094
2095 /* LVDS DDA */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002096 if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
2098 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
2099 if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
2100 if(ModeNo == 0x12) {
2101 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002102 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 }
2104 } else if(ModeNo > 0x13) {
2105 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002106 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2107 if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
2108 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 }
2110 }
2111 }
2112 }
2113 }
2114 }
2115
2116 if(modeflag & HalfDCLK) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002117 if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002119 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2121 } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
2122 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2123 } else if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002124 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
2125 if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2126 } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
2127 if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 }
2130 }
2131
2132 }
2133
2134 /* VESA timing */
2135 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2136 if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002137 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 }
2139 } else {
2140 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2141 }
2142
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002143#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
2145 SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
2146#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147}
2148
2149/*********************************************/
2150/* GET VCLK */
2151/*********************************************/
2152
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002153unsigned short
2154SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2155 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002157 unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
2158 unsigned short modeflag, resinfo, tempbx;
2159 const unsigned char *CHTVVCLKPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
2161 if(ModeNo <= 0x13) {
2162 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2163 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
2164 CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2165 VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002166 VCLKIndexGENCRT = VCLKIndexGEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 } else {
2168 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2169 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2170 CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2171 VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002172 VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
2173 (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 }
2175
2176 if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 30x/B/LV */
2177
2178 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2179
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002180 CRT2Index >>= 6;
2181 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002183 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2185 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002186 VCLKIndex = VCLKIndexGEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 }
2188 } else {
2189 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2190 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2191 switch(resinfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002192 /* Correct those whose IndexGEN doesn't match VBVCLK array */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 case SIS_RI_720x480: VCLKIndex = VCLK_720x480; break;
2194 case SIS_RI_720x576: VCLKIndex = VCLK_720x576; break;
2195 case SIS_RI_768x576: VCLKIndex = VCLK_768x576; break;
2196 case SIS_RI_848x480: VCLKIndex = VCLK_848x480; break;
2197 case SIS_RI_856x480: VCLKIndex = VCLK_856x480; break;
2198 case SIS_RI_800x480: VCLKIndex = VCLK_800x480; break;
2199 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
2200 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002201 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
2203 default: VCLKIndex = VCLKIndexGEN;
2204 }
2205
2206 if(ModeNo <= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002207 if(SiS_Pr->ChipType <= SIS_315PRO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002209 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
2211 }
2212 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002213 if(SiS_Pr->ChipType <= SIS_315PRO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 if(VCLKIndex == 0) VCLKIndex = 0x41;
2215 if(VCLKIndex == 1) VCLKIndex = 0x43;
2216 if(VCLKIndex == 4) VCLKIndex = 0x44;
2217 }
2218 }
2219 }
2220
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002221 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
2223 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002224 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
2225 else VCLKIndex = HiTVVCLK;
2226 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) VCLKIndex = HiTVSimuVCLK;
2227 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK;
2228 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2;
2229 else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
2230 else VCLKIndex = TVVCLK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002232 if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
2233 else VCLKIndex += TVCLKBASE_315;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002235 } else { /* VGA2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002237 VCLKIndex = VCLKIndexGENCRT;
2238 if(SiS_Pr->ChipType < SIS_315H) {
2239 if(ModeNo > 0x13) {
2240 if( (SiS_Pr->ChipType == SIS_630) &&
2241 (SiS_Pr->ChipRevision >= 0x30)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 if(VCLKIndex == 0x14) VCLKIndex = 0x34;
2243 }
2244 /* Better VGA2 clock for 1280x1024@75 */
2245 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
2246 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002247 }
2248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
2250 } else { /* If not programming CRT2 */
2251
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002252 VCLKIndex = VCLKIndexGENCRT;
2253 if(SiS_Pr->ChipType < SIS_315H) {
2254 if(ModeNo > 0x13) {
2255 if( (SiS_Pr->ChipType != SIS_630) &&
2256 (SiS_Pr->ChipType != SIS_300) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2258 }
2259 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 }
2262
2263 } else { /* LVDS */
2264
2265 VCLKIndex = CRT2Index;
2266
2267 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2268
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002269 if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
2271 VCLKIndex &= 0x1f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002272 tempbx = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002274 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 tempbx += 2;
2276 if(SiS_Pr->SiS_ModeType > ModeVGA) {
2277 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
2278 }
2279 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2280 tempbx = 4;
2281 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2282 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2283 tempbx = 6;
2284 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2285 }
2286 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002287 switch(tempbx) {
2288 case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break;
2289 case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break;
2290 case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break;
2291 case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 case 4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002293 case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break;
2294 case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break;
2295 case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 case 8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL; break;
2297 default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002298 }
2299 VCLKIndex = CHTVVCLKPtr[VCLKIndex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002301 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002303 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2305 } else {
2306 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2307 }
2308
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002309#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 /* Special Timing: Barco iQ Pro R series */
2311 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2312
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002313 /* Special Timing: 848x480 and 856x480 parallel lvds panels */
2314 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2315 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 VCLKIndex = VCLK34_300;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002317 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 } else {
2319 VCLKIndex = VCLK34_315;
2320 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2321 }
2322 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002323#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002325 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002327 VCLKIndex = VCLKIndexGENCRT;
2328 if(SiS_Pr->ChipType < SIS_315H) {
2329 if(ModeNo > 0x13) {
2330 if( (SiS_Pr->ChipType == SIS_630) &&
2331 (SiS_Pr->ChipRevision >= 0x30) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002333 }
2334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337
2338 } else { /* if not programming CRT2 */
2339
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002340 VCLKIndex = VCLKIndexGENCRT;
2341 if(SiS_Pr->ChipType < SIS_315H) {
2342 if(ModeNo > 0x13) {
2343 if( (SiS_Pr->ChipType != SIS_630) &&
2344 (SiS_Pr->ChipType != SIS_300) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2346 }
2347#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002348 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 if(VCLKIndex == 0x0b) VCLKIndex = 0x40; /* 1024x768-70 */
2350 if(VCLKIndex == 0x0d) VCLKIndex = 0x41; /* 1024x768-75 */
2351 }
2352#endif
2353 }
2354 }
2355
2356 }
2357
2358 }
2359
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002360 return VCLKIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361}
2362
2363/*********************************************/
2364/* SET CRT2 MODE TYPE REGISTERS */
2365/*********************************************/
2366
2367static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002368SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002370 unsigned short i, j, modeflag, tempah=0;
2371 short tempcl;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002372#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002373 unsigned short tempbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374#endif
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002375#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002376 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
2377 unsigned short tempah2, tempbl2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378#endif
2379
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002380 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
2382 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2383
2384 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
2385 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
2386
2387 } else {
2388
2389 for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002390 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
2392 }
2393
2394 tempcl = SiS_Pr->SiS_ModeType;
2395
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002396 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002398#ifdef CONFIG_FB_SIS_300 /* ---- 300 series ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002400 /* For 301BDH: (with LCD via LVDS) */
2401 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
2403 tempbl &= 0xef;
2404 tempbl |= 0x02;
2405 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2406 tempbl |= 0x10;
2407 tempbl &= 0xfd;
2408 }
2409 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002410 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002412 if(ModeNo > 0x13) {
2413 tempcl -= ModeVGA;
2414 if(tempcl >= 0) {
2415 tempah = ((0x10 >> tempcl) | 0x80);
2416 }
2417 } else tempah = 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002419 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002421#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
2423 } else {
2424
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002425#ifdef CONFIG_FB_SIS_315 /* ------- 315/330 series ------ */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002427 if(ModeNo > 0x13) {
2428 tempcl -= ModeVGA;
2429 if(tempcl >= 0) {
2430 tempah = (0x08 >> tempcl);
2431 if (tempah == 0) tempah = 1;
2432 tempah |= 0x40;
2433 }
2434 } else tempah = 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002436 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002438#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
2440 }
2441
2442 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2443
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002444 if(SiS_Pr->ChipType < SIS_315H) {
2445 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002447#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002448 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2449 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2450 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2451 if(IS_SIS740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2453 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002454 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002456 }
2457#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 }
2459
2460 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2461
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002462 tempah = 0x01;
2463 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2464 tempah |= 0x02;
2465 }
2466 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2467 tempah ^= 0x05;
2468 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
2469 tempah ^= 0x01;
2470 }
2471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002473 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002475 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002477 tempah = (tempah << 5) & 0xFF;
2478 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2479 tempah = (tempah >> 5) & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002481 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002483 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x08;
2484 else if(!(SiS_IsDualEdge(SiS_Pr))) tempah |= 0x08;
2485 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
2486 tempah &= ~0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002488 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002490 if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
2491 tempah |= 0x10;
2492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
2494 tempah |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002495 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002497 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002499 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002501 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2502 tempah |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002504 }
2505 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002507 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508
2509 tempah = 0x80;
2510 if(SiS_Pr->SiS_VBType & VB_SIS301) {
2511 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
2512 }
2513
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002514 if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002516 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002518 tempah |= 0x40;
2519 }
2520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002522 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523
2524 } else { /* LVDS */
2525
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002526 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002528#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 /* LVDS can only be slave in 8bpp modes */
2530 tempah = 0x80;
2531 if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
2532 if(SiS_Pr->SiS_VBInfo & DriverMode) {
2533 tempah |= 0x02;
2534 }
2535 }
2536
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002537 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) tempah |= 0x02;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002539 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah ^= 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002541 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002543 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544#endif
2545
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002546 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002548#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 tempah = 0;
2550 if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002551 tempah |= 0x02;
2552 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 tempah <<= 5;
2554
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002555 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
2557 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2558#endif
2559
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
2562 }
2563
2564 } /* LCDA */
2565
2566 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2567
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002568 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002570#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002571 /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572
2573 /* The following is nearly unpreditable and varies from machine
2574 * to machine. Especially the 301DH seems to be a real trouble
2575 * maker. Some BIOSes simply set the registers (like in the
2576 * NoLCD-if-statements here), some set them according to the
2577 * LCDA stuff. It is very likely that some machines are not
2578 * treated correctly in the following, very case-orientated
2579 * code. What do I do then...?
2580 */
2581
2582 /* 740 variants match for 30xB, 301B-DH, 30xLV */
2583
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002584 if(!(IS_SIS740)) {
2585 tempah = 0x04; /* For all bridges */
2586 tempbl = 0xfb;
2587 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2588 tempah = 0x00;
2589 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 tempbl = 0xff;
2591 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002592 }
2593 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 }
2595
2596 /* The following two are responsible for eventually wrong colors
2597 * in TV output. The DH (VB_NoLCD) conditions are unknown; the
2598 * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
2599 * in a 650 box (Jake). What is the criteria?
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002600 * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
2601 * treatment like the 651+301B-DH(b0) case. Seems more to be the
2602 * chipset than the bridge revision.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 */
2604
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002605 if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 tempah = 0x30;
2607 tempbl = 0xc0;
2608 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2609 ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
2610 tempah = 0x00;
2611 tempbl = 0x00;
2612 }
2613 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
2614 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
2615 } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
2616 /* Fixes "TV-blue-bug" on 315+301 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002617 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002619 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
2620 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002622 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* For 301B-DH */
2623 tempah = 0x30; tempah2 = 0xc0;
2624 tempbl = 0xcf; tempbl2 = 0x3f;
2625 if(SiS_Pr->SiS_TVBlue == 0) {
2626 tempah = tempah2 = 0x00;
2627 } else if(SiS_Pr->SiS_TVBlue == -1) {
2628 /* Set on 651/M650, clear on 315/650 */
2629 if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
2630 tempah = tempah2 = 0x00;
2631 }
2632 }
2633 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2634 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002636 tempah = 0x30; tempah2 = 0xc0; /* For 30xB, 301C */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 tempbl = 0xcf; tempbl2 = 0x3f;
2638 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2639 tempah = tempah2 = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002640 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 tempbl = tempbl2 = 0xff;
2642 }
2643 }
2644 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2645 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2646 }
2647
2648 if(IS_SIS740) {
2649 tempah = 0x80;
2650 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
2651 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
2652 } else {
2653 tempah = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002654 tempbl = 0x7f;
2655 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2656 tempbl = 0xff;
2657 if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
2658 }
2659 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 }
2661
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002662#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002664 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002666#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002667 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002669 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2670 ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
2672 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
2673 } else {
2674 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
2675 }
2676#endif
2677
2678 }
2679
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002680 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2681 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
2682 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
2684 }
2685 }
2686
2687 } else { /* LVDS */
2688
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002689#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002690 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002692 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002694 tempah = 0x04;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 tempbl = 0xfb;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002696 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2697 tempah = 0x00;
2698 if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
2699 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2701
2702 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2703 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2704 }
2705
2706 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2707
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002708 } else if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
2710 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2711 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2712
2713 }
2714
2715 }
2716#endif
2717
2718 }
2719
2720}
2721
2722/*********************************************/
2723/* GET RESOLUTION DATA */
2724/*********************************************/
2725
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002726unsigned short
2727SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002729 if(ModeNo <= 0x13)
2730 return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
2731 else
2732 return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733}
2734
2735static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002736SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002738 unsigned short xres, yres, modeflag=0, resindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002740 if(SiS_Pr->UseCustomMode) {
2741 xres = SiS_Pr->CHDisplay;
2742 if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
2743 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2744 /* DoubleScanMode-check done in CheckCalcCustomMode()! */
2745 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
2746 return;
2747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002749 resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002751 if(ModeNo <= 0x13) {
2752 xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
2753 yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
2754 } else {
2755 xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
2756 yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
2757 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2758 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002760 if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002762 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
2763 if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
2764 if(yres == 350) yres = 400;
2765 }
2766 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
2767 if(ModeNo == 0x12) yres = 400;
2768 }
2769 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002771 if(modeflag & HalfDCLK) xres <<= 1;
2772 if(modeflag & DoubleScanMode) yres <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002774 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002776 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002778 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2779 switch(SiS_Pr->SiS_LCDResInfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 case Panel_1024x768:
2781 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002782 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2783 if(yres == 350) yres = 357;
2784 if(yres == 400) yres = 420;
2785 if(yres == 480) yres = 525;
2786 }
2787 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 break;
2789 case Panel_1280x1024:
2790 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2791 /* BIOS bug - does this regardless of scaling */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002792 if(yres == 400) yres = 405;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002794 if(yres == 350) yres = 360;
2795 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
2796 if(yres == 360) yres = 375;
2797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 break;
2799 case Panel_1600x1200:
2800 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002801 if(yres == 1024) yres = 1056;
2802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002804 }
2805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002807 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002809 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2810 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
2811 if(xres == 720) xres = 640;
2812 }
2813 } else if(xres == 720) xres = 640;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002815 if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
2816 yres = 400;
2817 if(SiS_Pr->ChipType >= SIS_315H) {
2818 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
2819 } else {
2820 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
2821 }
2822 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
2823 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002825 }
2826 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2827 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828}
2829
2830/*********************************************/
2831/* GET CRT2 TIMING DATA */
2832/*********************************************/
2833
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002835SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2836 unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
2837 unsigned short *ResIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002839 unsigned short tempbx=0, tempal=0, resinfo=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840
2841 if(ModeNo <= 0x13) {
2842 tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2843 } else {
2844 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2845 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2846 }
2847
2848 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
2849
2850 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
2851
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002852 tempbx = SiS_Pr->SiS_LCDResInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
2854
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002855 /* patch index */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
2857 if (resinfo == SIS_RI_1280x800) tempal = 9;
2858 else if(resinfo == SIS_RI_1400x1050) tempal = 11;
2859 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002860 (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
2861 (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 if (resinfo == SIS_RI_1280x768) tempal = 9;
2863 }
2864
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002865 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 /* Pass 1:1 only (center-screen handled outside) */
2867 /* This is never called for the panel's native resolution */
2868 /* since Pass1:1 will not be set in this case */
2869 tempbx = 100;
2870 if(ModeNo >= 0x13) {
2871 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
2872 }
2873 }
2874
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002875#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
2877 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
2878 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002879 tempbx = 200;
2880 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 }
2882 }
2883 }
2884#endif
2885
2886 } else { /* TV */
2887
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002888 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2889 /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
2890 tempbx = 2;
2891 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 tempbx = 13;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002893 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
2894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002896 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7;
2897 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
2898 else tempbx = 5;
2899 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2900 } else {
2901 if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3;
2902 else tempbx = 4;
2903 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905
2906 }
2907
2908 tempal &= 0x3F;
2909
2910 if(ModeNo > 0x13) {
2911 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002912 switch(resinfo) {
2913 case SIS_RI_720x480:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914 tempal = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002915 if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) tempal = 9;
2916 break;
2917 case SIS_RI_720x576:
2918 case SIS_RI_768x576:
2919 case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
2920 tempal = 6;
2921 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2922 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002924 break;
2925 case SIS_RI_800x480:
2926 tempal = 4;
2927 break;
2928 case SIS_RI_512x384:
2929 case SIS_RI_1024x768:
2930 tempal = 7;
2931 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2932 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempal = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002934 break;
2935 case SIS_RI_1280x720:
2936 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2937 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002939 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 }
2941 }
2942 }
2943
2944 *CRT2Index = tempbx;
2945 *ResIndex = tempal;
2946
2947 } else { /* LVDS, 301B-DH (if running on LCD) */
2948
2949 tempbx = 0;
2950 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
2951
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002952 tempbx = 90;
2953 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2954 tempbx = 92;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 if(SiS_Pr->SiS_ModeType > ModeVGA) {
2956 if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
2957 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002958 if(SiS_Pr->SiS_TVMode & TVSetPALM) tempbx = 94;
2959 else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
2960 }
2961 if(tempbx != 99) {
2962 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
2963 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964
2965 } else {
2966
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002967 switch(SiS_Pr->SiS_LCDResInfo) {
2968 case Panel_640x480: tempbx = 12; break;
2969 case Panel_320x240_1: tempbx = 10; break;
2970 case Panel_320x240_2:
2971 case Panel_320x240_3: tempbx = 14; break;
2972 case Panel_800x600: tempbx = 16; break;
2973 case Panel_1024x600: tempbx = 18; break;
2974 case Panel_1152x768:
2975 case Panel_1024x768: tempbx = 20; break;
2976 case Panel_1280x768: tempbx = 22; break;
2977 case Panel_1280x1024: tempbx = 24; break;
2978 case Panel_1400x1050: tempbx = 26; break;
2979 case Panel_1600x1200: tempbx = 28; break;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002980#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 case Panel_Barco1366: tempbx = 80; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002982#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 }
2984
2985 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002986 case Panel_320x240_1:
2987 case Panel_320x240_2:
2988 case Panel_320x240_3:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 case Panel_640x480:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990 break;
2991 default:
2992 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
2993 }
2994
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002995 if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002997#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
2999 tempbx = 82;
3000 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003001 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 tempbx = 84;
3003 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3004 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003005#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006
3007 }
3008
3009 (*CRT2Index) = tempbx;
3010 (*ResIndex) = tempal & 0x1F;
3011 }
3012}
3013
3014static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003015SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3016 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003018 unsigned short tempax=0, tempbx=0, index, dotclock;
3019 unsigned short temp1=0, modeflag=0, tempcx=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020
3021 SiS_Pr->SiS_RVBHCMAX = 1;
3022 SiS_Pr->SiS_RVBHCFACT = 1;
3023
3024 if(ModeNo <= 0x13) {
3025
3026 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3027 index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
3028
3029 tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
3030 tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
3031 temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
3032
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003033 dotclock = (modeflag & Charx8Dot) ? 8 : 9;
3034
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 } else {
3036
3037 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003038 index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039
3040 tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
3041 tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
3042 tempax &= 0x03FF;
3043 tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
3044 tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
3045 tempcx &= 0x0100;
3046 tempcx <<= 2;
3047 tempbx |= tempcx;
3048 temp1 = SiS_Pr->SiS_CRT1Table[index].CR[7];
3049
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003050 dotclock = 8;
3051
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 }
3053
3054 if(temp1 & 0x01) tempbx |= 0x0100;
3055 if(temp1 & 0x20) tempbx |= 0x0200;
3056
3057 tempax += 5;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003058 tempax *= dotclock;
3059 if(modeflag & HalfDCLK) tempax <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060
3061 tempbx++;
3062
3063 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3064 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
3065}
3066
3067static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003068SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3069 unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003071 unsigned short ResIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003073 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3074 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3075 if(SiS_Pr->UseCustomMode) {
3076 ResIndex = SiS_Pr->CHTotal;
3077 if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
3078 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
3079 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3080 } else {
3081 if(ModeNo < 0x13) {
3082 ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3083 } else {
3084 ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3085 }
3086 if(ResIndex == 0x09) {
3087 if(SiS_Pr->Alternate1600x1200) ResIndex = 0x20; /* 1600x1200 LCDA */
3088 else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
3089 }
3090 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
3091 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
3092 SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
3093 SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
3094 }
3095 } else {
3096 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3097 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3098 }
3099 } else {
3100 /* This handles custom modes and custom panels */
3101 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3102 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3103 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3104 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3105 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
3106 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
3107 }
3108}
3109
3110static void
3111SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3112 unsigned short RefreshRateTableIndex)
3113{
3114 unsigned short CRT2Index, ResIndex, backup;
3115 const struct SiS_LVDSData *LVDSData = NULL;
3116
3117 SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118
3119 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3120 SiS_Pr->SiS_RVBHCMAX = 1;
3121 SiS_Pr->SiS_RVBHCFACT = 1;
3122 SiS_Pr->SiS_NewFlickerMode = 0;
3123 SiS_Pr->SiS_RVBHRS = 50;
3124 SiS_Pr->SiS_RY1COE = 0;
3125 SiS_Pr->SiS_RY2COE = 0;
3126 SiS_Pr->SiS_RY3COE = 0;
3127 SiS_Pr->SiS_RY4COE = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003128 SiS_Pr->SiS_RVBHRS2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 }
3130
3131 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3132
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003133#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003134 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3135 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136#endif
3137
3138 } else {
3139
3140 /* 301BDH needs LVDS Data */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003141 backup = SiS_Pr->SiS_IF_DEF_LVDS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3143 SiS_Pr->SiS_IF_DEF_LVDS = 1;
3144 }
3145
3146 SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003147 &CRT2Index, &ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003149 SiS_Pr->SiS_IF_DEF_LVDS = backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003151 switch(CRT2Index) {
3152 case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1; break;
3153 case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2; break;
3154 case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break;
3155 case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
3156 case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
3157 case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003158#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break;
3160 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break;
3161 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1; break;
3163 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003164#endif
3165 case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break;
3166 case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break;
3167 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData; break;
3168 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData; break;
3169 case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
3170 case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
3171 case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
3172 case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
3173 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 }
3175
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003176 if(LVDSData) {
3177 SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
3178 SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
3179 SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT;
3180 SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT;
3181 } else {
3182 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3183 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003185 if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
3186 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
3187 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
3188 if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
3189 (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
3190 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3191 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003192#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003193 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3194 if(ResIndex < 0x08) {
3195 SiS_Pr->SiS_HDE = 1280;
3196 SiS_Pr->SiS_VDE = 1024;
3197 }
3198 }
3199#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 }
3201 }
3202 }
3203}
3204
3205static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003206SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3207 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003209 unsigned char *ROMAddr = NULL;
3210 unsigned short tempax, tempbx, modeflag, romptr=0;
3211 unsigned short resinfo, CRT2Index, ResIndex;
3212 const struct SiS_LCDData *LCDPtr = NULL;
3213 const struct SiS_TVData *TVPtr = NULL;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003214#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003215 short resinfo661;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216#endif
3217
3218 if(ModeNo <= 0x13) {
3219 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3220 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
3221 } else if(SiS_Pr->UseCustomMode) {
3222 modeflag = SiS_Pr->CModeFlag;
3223 resinfo = 0;
3224 } else {
3225 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3226 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003227#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3229 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003230 (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
3231 (resinfo661 >= 0) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 (SiS_Pr->SiS_NeedRomModeData) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003233 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 if((romptr = (SISGETROMW(21)))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003235 romptr += (resinfo661 * 10);
3236 ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237 }
3238 }
3239 }
3240#endif
3241 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003242
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243 SiS_Pr->SiS_NewFlickerMode = 0;
3244 SiS_Pr->SiS_RVBHRS = 50;
3245 SiS_Pr->SiS_RY1COE = 0;
3246 SiS_Pr->SiS_RY2COE = 0;
3247 SiS_Pr->SiS_RY3COE = 0;
3248 SiS_Pr->SiS_RY4COE = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003249 SiS_Pr->SiS_RVBHRS2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003251 SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003253 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254
3255 if(SiS_Pr->UseCustomMode) {
3256
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003257 SiS_Pr->SiS_RVBHCMAX = 1;
3258 SiS_Pr->SiS_RVBHCFACT = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003260 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3261
3262 tempax = SiS_Pr->CHTotal;
3263 if(modeflag & HalfDCLK) tempax <<= 1;
3264 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3265 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266
3267 } else {
3268
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003269 SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270
3271 }
3272
3273 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3274
3275 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003276 &CRT2Index,&ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277
3278 switch(CRT2Index) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003279 case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break;
3280 case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break;
3281 case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
3282 case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break;
3283 case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break;
3284 case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break;
3285 case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
3286 case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
3287 case 10: TVPtr = SiS_Pr->SiS_St525iData; break;
3288 case 11: TVPtr = SiS_Pr->SiS_St525pData; break;
3289 case 12: TVPtr = SiS_Pr->SiS_St750pData; break;
3290 case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break;
3291 case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break;
3292 default: TVPtr = SiS_Pr->SiS_StPALData; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293 }
3294
3295 SiS_Pr->SiS_RVBHCMAX = (TVPtr+ResIndex)->RVBHCMAX;
3296 SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
3297 SiS_Pr->SiS_VGAHT = (TVPtr+ResIndex)->VGAHT;
3298 SiS_Pr->SiS_VGAVT = (TVPtr+ResIndex)->VGAVT;
3299 SiS_Pr->SiS_HDE = (TVPtr+ResIndex)->TVHDE;
3300 SiS_Pr->SiS_VDE = (TVPtr+ResIndex)->TVVDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003301 SiS_Pr->SiS_RVBHRS2 = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302 if(modeflag & HalfDCLK) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003303 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
3304 if(SiS_Pr->SiS_RVBHRS2) {
3305 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3306 tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
3307 if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
3308 else SiS_Pr->SiS_RVBHRS2 += tempax;
3309 }
3310 } else {
3311 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003313 SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
3315 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3316
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003317 if((resinfo == SIS_RI_960x600) ||
3318 (resinfo == SIS_RI_1024x768) ||
3319 (resinfo == SIS_RI_1280x1024) ||
3320 (resinfo == SIS_RI_1280x720)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321 SiS_Pr->SiS_NewFlickerMode = 0x40;
3322 }
3323
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003324 if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003326 SiS_Pr->SiS_HT = ExtHiTVHT;
3327 SiS_Pr->SiS_VT = ExtHiTVVT;
3328 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3329 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
3330 SiS_Pr->SiS_HT = StHiTVHT;
3331 SiS_Pr->SiS_VT = StHiTVVT;
3332 }
3333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334
3335 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3336
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003337 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3338 SiS_Pr->SiS_HT = 1650;
3339 SiS_Pr->SiS_VT = 750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3341 SiS_Pr->SiS_HT = NTSCHT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003342 if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343 SiS_Pr->SiS_VT = NTSCVT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003344 } else {
3345 SiS_Pr->SiS_HT = NTSCHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003347 SiS_Pr->SiS_VT = NTSCVT;
3348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349
3350 } else {
3351
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003352 SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
3353 SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
3354 SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
3355 SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003357 if(modeflag & HalfDCLK) {
3358 SiS_Pr->SiS_RY1COE = 0x00;
3359 SiS_Pr->SiS_RY2COE = 0xf4;
3360 SiS_Pr->SiS_RY3COE = 0x10;
3361 SiS_Pr->SiS_RY4COE = 0x38;
3362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003364 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
3365 SiS_Pr->SiS_HT = NTSCHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003367 SiS_Pr->SiS_VT = NTSCVT;
3368 } else {
3369 SiS_Pr->SiS_HT = PALHT;
3370 SiS_Pr->SiS_VT = PALVT;
3371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372
3373 }
3374
3375 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3376
3377 SiS_Pr->SiS_RVBHCMAX = 1;
3378 SiS_Pr->SiS_RVBHCFACT = 1;
3379
3380 if(SiS_Pr->UseCustomMode) {
3381
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003383 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3384
3385 tempax = SiS_Pr->CHTotal;
3386 if(modeflag & HalfDCLK) tempax <<= 1;
3387 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3388 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389
3390 } else {
3391
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003392 bool gotit = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003394 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003396 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
3397 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3398 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3399 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003400 gotit = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401
3402 } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3403
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003404#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003406 SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3407 SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
3408 SiS_Pr->SiS_VGAVT = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
3409 SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
3410 SiS_Pr->SiS_VT = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
3411 SiS_Pr->SiS_RVBHRS2 = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
3412 if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
3413 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3414 tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
3415 if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
3416 else SiS_Pr->SiS_RVBHRS2 += tempax;
3417 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003418 if(SiS_Pr->SiS_VGAHT) gotit = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 else {
3420 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
3421 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003422 SiS_Pr->SiS_RVBHCMAX = 1;
3423 SiS_Pr->SiS_RVBHCFACT = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003425 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3426 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3427 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3428 SiS_Pr->SiS_RVBHRS2 = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003429 gotit = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 }
3431#endif
3432
3433 }
3434
3435 if(!gotit) {
3436
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003437 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3438 &CRT2Index,&ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003440 switch(CRT2Index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 case Panel_1024x768 : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3442 case Panel_1024x768 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break;
3443 case Panel_1280x720 :
3444 case Panel_1280x720 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data; break;
3445 case Panel_1280x768_2 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003446 case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447 case Panel_1280x800 :
3448 case Panel_1280x800 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data; break;
3449 case Panel_1280x800_2 :
3450 case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003451 case Panel_1280x854 :
3452 case Panel_1280x854 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 case Panel_1280x960 :
3454 case Panel_1280x960 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003455 case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break;
3456 case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3457 case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break;
3458 case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break;
3459 case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break;
3460 case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 case Panel_1680x1050 :
3462 case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break;
3463 case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003464#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465 case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break;
3466 case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3467#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003468 default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3469 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003471 SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
3472 SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3473 SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
3474 SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
3475 SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
3476 SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477
3478 }
3479
3480 tempax = SiS_Pr->PanelXRes;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003481 tempbx = SiS_Pr->PanelYRes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003483 switch(SiS_Pr->SiS_LCDResInfo) {
3484 case Panel_1024x768:
3485 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3486 if(SiS_Pr->ChipType < SIS_315H) {
3487 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3488 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3489 }
3490 } else {
3491 if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
3492 else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
3493 else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
3494 else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
3495 else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3496 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3497 }
3498 break;
3499 case Panel_1280x960:
3500 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
3501 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
3502 else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
3503 break;
3504 case Panel_1280x1024:
3505 if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
3506 else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
3507 else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
3508 break;
3509 case Panel_1600x1200:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003511 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
3512 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
3513 }
3514 break;
3515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003517 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3518 tempax = SiS_Pr->SiS_VGAHDE;
3519 tempbx = SiS_Pr->SiS_VGAVDE;
3520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003522 SiS_Pr->SiS_HDE = tempax;
3523 SiS_Pr->SiS_VDE = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 }
3525 }
3526}
3527
3528static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003529SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3530 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531{
3532
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003533 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003535 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3536 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3537 } else {
3538 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3539 /* Need LVDS Data for LCD on 301B-DH */
3540 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3541 } else {
3542 SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3543 }
3544 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003546 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003548 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551}
3552
3553/*********************************************/
3554/* GET LVDS DES (SKEW) DATA */
3555/*********************************************/
3556
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003557static const struct SiS_LVDSDes *
3558SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003560 const struct SiS_LVDSDes *PanelDesPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003562#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003563 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003565 if(SiS_Pr->ChipType < SIS_315H) {
3566 if(SiS_Pr->SiS_LCDTypeInfo == 4) {
3567 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3568 PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
3569 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3570 PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
3571 }
3572 } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3573 PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
3574 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3575 PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
3576 }
3577 }
3578 }
3579 }
3580 }
3581#endif
3582 return PanelDesPtr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583}
3584
3585static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003586SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3587 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003589 unsigned short modeflag, ResIndex;
3590 const struct SiS_LVDSDes *PanelDesPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591
3592 SiS_Pr->SiS_LCDHDES = 0;
3593 SiS_Pr->SiS_LCDVDES = 0;
3594
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003595 /* Some special cases */
3596 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3597
3598 /* Trumpion */
3599 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
3600 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3601 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3602 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3603 }
3604 }
3605 return;
3606 }
3607
3608 /* 640x480 on LVDS */
3609 if(SiS_Pr->ChipType < SIS_315H) {
3610 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
3611 SiS_Pr->SiS_LCDHDES = 8;
3612 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3613 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3614 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3615 return;
3616 }
3617 }
3618
3619 } /* LCD */
3620
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 if( (SiS_Pr->UseCustomMode) ||
3622 (SiS_Pr->SiS_LCDResInfo == Panel_Custom) ||
3623 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003624 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ||
3625 (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 return;
3627 }
3628
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003629 if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3630 else ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3631
3632 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003634#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003636 /* non-pass 1:1 only, see above */
3637 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3638 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 }
3640 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3641 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3642 }
3643 }
3644 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003645 switch(SiS_Pr->SiS_CustomT) {
3646 case CUT_UNIWILL1024:
3647 case CUT_UNIWILL10242:
3648 case CUT_CLEVO1400:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3650 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3651 }
3652 break;
3653 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003654 switch(SiS_Pr->SiS_LCDResInfo) {
3655 case Panel_1280x1024:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
3657 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3658 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003659 break;
3660 case Panel_1280x800: /* Verified for Averatec 6240 */
3661 case Panel_1280x800_2: /* Verified for Asus A4L */
3662 case Panel_1280x854: /* Not verified yet FIXME */
3663 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3664 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 }
3666 }
3667#endif
3668
3669 } else {
3670
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003671 if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003673 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
3674 if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
3675 }
3676
3677 } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
3678
3679 SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
3680 SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
3681
3682 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3683
3684 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3685 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3686 }
3687 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3688 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3689 } else {
3690 if(SiS_Pr->ChipType < SIS_315H) {
3691 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3692 } else {
3693 switch(SiS_Pr->SiS_LCDResInfo) {
3694 case Panel_800x600:
3695 case Panel_1024x768:
3696 case Panel_1280x1024:
3697 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3698 break;
3699 case Panel_1400x1050:
3700 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3701 break;
3702 }
3703 }
3704 }
3705
3706 } else {
3707
3708 if(SiS_Pr->ChipType < SIS_315H) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003709#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003710 switch(SiS_Pr->SiS_LCDResInfo) {
3711 case Panel_800x600:
3712 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3713 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3714 } else {
3715 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
3716 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3717 if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
3718 else SiS_Pr->SiS_LCDVDES -= 4;
3719 }
3720 break;
3721 case Panel_1024x768:
3722 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3723 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3724 } else {
3725 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3726 if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
3727 if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
3728 }
3729 break;
3730 case Panel_1024x600:
3731 default:
3732 if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
3733 (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
3734 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3735 } else {
3736 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3737 }
3738 break;
3739 }
3740
3741 switch(SiS_Pr->SiS_LCDTypeInfo) {
3742 case 1:
3743 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
3744 break;
3745 case 3: /* 640x480 only? */
3746 SiS_Pr->SiS_LCDHDES = 8;
3747 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3748 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3749 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3750 break;
3751 }
3752#endif
3753 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003754#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003755 switch(SiS_Pr->SiS_LCDResInfo) {
3756 case Panel_1024x768:
3757 case Panel_1280x1024:
3758 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3759 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3760 }
3761 break;
3762 case Panel_320x240_1:
3763 case Panel_320x240_2:
3764 case Panel_320x240_3:
3765 SiS_Pr->SiS_LCDVDES = 524;
3766 break;
3767 }
3768#endif
3769 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 }
3771
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003773 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3774 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003776 } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3777 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
3778 if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
3779 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
3781 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003782#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003783 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
3784 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003786 if(!(modeflag & HalfDCLK)) {
3787 SiS_Pr->SiS_LCDHDES = 320;
3788 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003790 }
3791#endif
3792 }
3793 }
3794 }
3795 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 }
3797 }
3798}
3799
3800/*********************************************/
3801/* DISABLE VIDEO BRIDGE */
3802/*********************************************/
3803
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003804#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003805static int
3806SiS_HandlePWD(struct SiS_Private *SiS_Pr)
3807{
3808 int ret = 0;
3809#ifdef SET_PWD
3810 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3811 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
3812 unsigned char drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
3813 unsigned short temp;
3814
3815 if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
3816 (romptr) &&
3817 (SiS_Pr->SiS_PWDOffset) ) {
3818 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
3819 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
3820 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
3821 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
3822 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
3823 temp = 0x00;
3824 if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
3825 temp = 0x80;
3826 ret = 1;
3827 }
3828 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003829 }
3830#endif
3831 return ret;
3832}
3833#endif
3834
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835/* NEVER use any variables (VBInfo), this will be called
3836 * from outside the context of modeswitch!
3837 * MUST call getVBType before calling this
3838 */
3839void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003840SiS_DisableBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841{
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003842#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003843 unsigned short tempah, pushax=0, modenum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003845 unsigned short temp=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
3847 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3848
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003849 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ===== For 30xB/C/LV ===== */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003851 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003853#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003855 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
3856 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3857 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003859 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003861 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 }
3863 if(SiS_Is301B(SiS_Pr)) {
3864 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
3865 SiS_ShortDelay(SiS_Pr,1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003866 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
3868 SiS_DisplayOff(SiS_Pr);
3869 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3870 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003871 SiS_UnLockCRT2(SiS_Pr);
3872 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
3874 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
3875 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003876 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
3877 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
3878 SiS_PanelDelay(SiS_Pr, 2);
3879 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3880 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003882 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 }
3884 }
3885
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003886#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887
3888 } else {
3889
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003890#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003892 int didpwd = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003893 bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
3894 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
3896 modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
3897
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003898 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899
3900#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003901 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003903 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 }
3905 }
3906#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003907
3908 didpwd = SiS_HandlePWD(SiS_Pr);
3909
3910 if( (modenum <= 0x13) ||
3911 (SiS_IsVAMode(SiS_Pr)) ||
3912 (!(SiS_IsDualEdge(SiS_Pr))) ) {
3913 if(!didpwd) {
3914 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
3915 if(custom1) SiS_PanelDelay(SiS_Pr, 3);
3916 } else {
3917 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
3918 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 }
3920
3921 if(!custom1) {
3922 SiS_DDC2Delay(SiS_Pr,0xff00);
3923 SiS_DDC2Delay(SiS_Pr,0xe000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003924 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
3925 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 if(IS_SIS740) {
3927 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
3928 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003929 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 }
3931
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 }
3933
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003934 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
3935 /* if(SiS_Pr->ChipType < SIS_340) {*/
3936 tempah = 0xef;
3937 if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
3938 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
3939 /*}*/
3940 }
3941
3942 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
3944 }
3945
3946 tempah = 0x3f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003947 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 tempah = 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003949 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950 }
3951 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
3952
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003953 if((SiS_IsVAMode(SiS_Pr)) ||
3954 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955
3956 SiS_DisplayOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003957 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3958 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 }
3960 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3961 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
3962
3963 }
3964
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003965 if((!(SiS_IsVAMode(SiS_Pr))) ||
3966 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003968 if(!(SiS_IsDualEdge(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
3970 SiS_DisplayOff(SiS_Pr);
3971 }
3972 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
3973
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003974 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3975 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 }
3977
3978 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3979 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003980 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
3982 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
3983
3984 }
3985
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003986 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
3988 }
3989
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003990 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3991
3992 if( (!(SiS_IsVAMode(SiS_Pr))) &&
3993 (!(SiS_CRT2IsLCD(SiS_Pr))) &&
3994 (!(SiS_IsDualEdge(SiS_Pr))) ) {
3995
3996 if(custom1) SiS_PanelDelay(SiS_Pr, 2);
3997 if(!didpwd) {
3998 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
3999 }
4000 if(custom1) SiS_PanelDelay(SiS_Pr, 4);
4001 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002
4003 if(!custom1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004004 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4005 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4006 if(SiS_IsVAorLCD(SiS_Pr)) {
4007 SiS_PanelDelayLoop(SiS_Pr, 3, 20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008 }
4009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004011
4012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004014#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015
4016 }
4017
4018 } else { /* ============ For 301 ================ */
4019
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004020 if(SiS_Pr->ChipType < SIS_315H) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004021#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004022 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4023 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4024 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025 }
4026#endif
4027 }
4028
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004029 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
4030 SiS_DisplayOff(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004032 if(SiS_Pr->ChipType >= SIS_315H) {
4033 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 }
4035
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004036 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004038 if(SiS_Pr->ChipType >= SIS_315H) {
4039 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4040 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4042 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4043 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004044#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004045 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
4046 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4047 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4048 SiS_PanelDelay(SiS_Pr, 2);
4049 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050 }
4051#endif
4052 }
4053
4054 }
4055
4056 } else { /* ============ For LVDS =============*/
4057
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004058 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004060#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061
4062 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004063 SiS_SetCH700x(SiS_Pr,0x0E,0x09);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 }
4065
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004066 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004068 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004070 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4071 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4072 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073 }
4074 } else {
4075 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4076 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004077 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4078 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
4080 SiS_DisplayOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004081 }
4082 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4083 SiS_PanelDelay(SiS_Pr, 3);
4084 }
4085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086 }
4087 }
4088
4089 SiS_DisplayOff(SiS_Pr);
4090
4091 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4092
4093 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004094 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4096 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4097
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004098 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4099 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4100 SiS_PanelDelay(SiS_Pr, 2);
4101 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102 }
4103
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004104#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
4106 } else {
4107
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004108#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004110 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4111 /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
4112 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
4113 /* } */
4114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115
4116 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4117
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004118 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 temp = SiS_GetCH701x(SiS_Pr,0x61);
4120 if(temp < 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004121 SiS_SetCH701x(SiS_Pr,0x76,0xac);
4122 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 }
4124
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004125 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4126 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4127 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 }
4129 }
4130
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004131 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4132 (SiS_IsVAMode(SiS_Pr)) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 SiS_Chrontel701xBLOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004134 SiS_Chrontel701xOff(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135 }
4136
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004137 if(SiS_Pr->ChipType != SIS_740) {
4138 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4139 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4140 SiS_SetCH701x(SiS_Pr,0x49,0x01);
4141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 }
4143
4144 }
4145
4146 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004147 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4148 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 }
4150
4151 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004152 (!(SiS_IsDualEdge(SiS_Pr))) ||
4153 (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 SiS_DisplayOff(SiS_Pr);
4155 }
4156
4157 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004158 (!(SiS_IsDualEdge(SiS_Pr))) ||
4159 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4161 }
4162
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004163 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4165 }
4166
4167 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4168
4169 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004170 (!(SiS_IsDualEdge(SiS_Pr))) ||
4171 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4173 }
4174
4175 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004176 if(SiS_CRT2IsLCD(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004178 if(SiS_Pr->ChipType == SIS_550) {
4179 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
4180 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 }
4182 }
4183 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004184 if(SiS_Pr->ChipType == SIS_740) {
4185 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4186 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004188 } else if(SiS_IsVAMode(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4190 }
4191 }
4192
4193 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004194 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195 /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
4196 } else {
4197 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
4198 }
4199 }
4200
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004201 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004203 if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
4205 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
4206 } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004207 (!(SiS_IsDualEdge(SiS_Pr))) ||
4208 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4210 }
4211
4212 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004213 if(SiS_CRT2IsLCD(SiS_Pr)) {
4214 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4215 SiS_PanelDelay(SiS_Pr, 2);
4216 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217 }
4218 }
4219 }
4220
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004221#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222
4223 } /* 315 series */
4224
4225 } /* LVDS */
4226
4227}
4228
4229/*********************************************/
4230/* ENABLE VIDEO BRIDGE */
4231/*********************************************/
4232
4233/* NEVER use any variables (VBInfo), this will be called
4234 * from outside the context of a mode switch!
4235 * MUST call getVBType before calling this
4236 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004237static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004238void
4239SiS_EnableBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004241 unsigned short temp=0, tempah;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004242#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004243 unsigned short temp1, pushax=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004244 bool delaylong = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245#endif
4246
4247 if(SiS_Pr->SiS_VBType & VB_SISVB) {
4248
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004249 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ====== For 301B et al ====== */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004251 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004253#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004255 if(SiS_CRT2IsLCD(SiS_Pr)) {
4256 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4258 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004259 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004261 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
4262 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4263 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264 }
4265 }
4266 }
4267
4268 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004269 (SiS_CRT2IsLCD(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
4271 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* Enable CRT2 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004272 SiS_DisplayOn(SiS_Pr);
4273 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4275 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004276 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4277 } else {
4278 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4281 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004282 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4283 SiS_PanelDelay(SiS_Pr, 1);
4284 }
4285 SiS_WaitVBRetrace(SiS_Pr);
4286 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 }
4289
4290 } else {
4291
4292 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004293 if(SiS_BridgeInSlavemode(SiS_Pr)) {
4294 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4295 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4296 }
4297 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4299 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4300 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
4301 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004302 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4303 if(SiS_CRT2IsLCD(SiS_Pr)) {
4304 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4305 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4306 SiS_PanelDelay(SiS_Pr, 1);
4307 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 }
4311 }
4312
4313 }
4314
4315
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004316#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
4318 } else {
4319
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004320#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321
4322#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004323 unsigned char r30=0, r31=0, r32=0, r33=0, cr36=0;
4324 int didpwd = 0;
4325 /* unsigned short emidelay=0; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326#endif
4327
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004328 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
4330#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004331 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4333 }
4334#endif
4335 }
4336
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004337 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4338 /*if(SiS_Pr->ChipType < SIS_340) { */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 tempah = 0x10;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004340 if(SiS_LCDAEnabled(SiS_Pr)) {
4341 if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
4342 else tempah = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 }
4344 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004345 /*}*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346 }
4347
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004348 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349
4350 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4351 SiS_DisplayOff(SiS_Pr);
4352 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4353 if(IS_SIS740) {
4354 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4355 }
4356
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004357 didpwd = SiS_HandlePWD(SiS_Pr);
4358
4359 if(SiS_IsVAorLCD(SiS_Pr)) {
4360 if(!didpwd) {
4361 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
4362 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4363 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4364 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4365 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4366 SiS_GenericDelay(SiS_Pr, 17664);
4367 }
4368 }
4369 } else {
4370 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4371 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4372 SiS_GenericDelay(SiS_Pr, 17664);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373 }
4374 }
4375 }
4376
4377 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004378 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004379 delaylong = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380 }
4381
4382 }
4383
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004384 if(!(SiS_IsVAMode(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004386 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004388 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4389 if(!(tempah & SetCRT2ToRAMDAC)) {
4390 if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004392 }
4393 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394
4395 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4396
4397 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4398 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4399
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004400 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4401 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402 }
4403
4404 } else {
4405
4406 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
4407
4408 }
4409
4410 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
4411 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4412
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004413 if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
4414 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4415 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4416 /* Enable "LVDS PLL power on" (even on 301C) */
4417 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
4418 /* Enable "LVDS Driver Power on" (even on 301C) */
4419 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
4420 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004423 tempah = 0xc0;
4424 if(SiS_IsDualEdge(SiS_Pr)) {
4425 tempah = 0x80;
4426 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
4427 }
4428 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004430 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4431
4432 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433
4434 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
4435 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4436
4437 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4438#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004439 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4440 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4441 SiS_GenericDelay(SiS_Pr, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 }
4443#endif
4444 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
4445
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004446 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447#ifdef SET_EMI
4448 cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
4449
4450 if(SiS_Pr->SiS_ROMNew) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004451 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
4452 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 if(romptr) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004454 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455 SiS_Pr->EMI_30 = 0;
4456 SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
4457 SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
4458 SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
4459 if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
4460 /* emidelay = SISGETROMW((romptr + 0x22)); */
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004461 SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462 }
4463 }
4464
4465 /* (P4_30|0x40) */
4466 /* Compal 1400x1050: 0x05, 0x60, 0x00 YES (1.10.7w; CR36=69) */
4467 /* Compal 1400x1050: 0x0d, 0x70, 0x40 YES (1.10.7x; CR36=69) */
4468 /* Acer 1280x1024: 0x12, 0xd0, 0x6b NO (1.10.9k; CR36=73) */
4469 /* Compaq 1280x1024: 0x0d, 0x70, 0x6b YES (1.12.04b; CR36=03) */
4470 /* Clevo 1024x768: 0x05, 0x60, 0x33 NO (1.10.8e; CR36=12, DL!) */
4471 /* Clevo 1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES (1.10.8y; CR36=?2) */
4472 /* Clevo 1024x768: 0x05, 0x60, 0x33 (if type != 3) YES (1.10.8y; CR36=?2) */
4473 /* Asus 1024x768: ? ? (1.10.8o; CR36=?2) */
4474 /* Asus 1024x768: 0x08, 0x10, 0x3c (problematic) YES (1.10.8q; CR36=22) */
4475
4476 if(SiS_Pr->HaveEMI) {
4477 r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
4478 r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
4479 } else {
4480 r30 = 0;
4481 }
4482
4483 /* EMI_30 is read at driver start; however, the BIOS sets this
4484 * (if it is used) only if the LCD is in use. In case we caught
4485 * the machine while on TV output, this bit is not set and we
4486 * don't know if it should be set - hence our detection is wrong.
4487 * Work-around this here:
4488 */
4489
4490 if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
4491 switch((cr36 & 0x0f)) {
4492 case 2:
4493 r30 |= 0x40;
4494 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
4495 if(!SiS_Pr->HaveEMI) {
4496 r31 = 0x05; r32 = 0x60; r33 = 0x33;
4497 if((cr36 & 0xf0) == 0x30) {
4498 r31 = 0x0d; r32 = 0x70; r33 = 0x40;
4499 }
4500 }
4501 break;
4502 case 3: /* 1280x1024 */
4503 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
4504 if(!SiS_Pr->HaveEMI) {
4505 r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4506 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4507 r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
4508 }
4509 }
4510 break;
4511 case 9: /* 1400x1050 */
4512 r30 |= 0x40;
4513 if(!SiS_Pr->HaveEMI) {
4514 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4515 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4516 r31 = 0x0d; r32 = 0x70; r33 = 0x40; /* BIOS values */
4517 }
4518 }
4519 break;
4520 case 11: /* 1600x1200 - unknown */
4521 r30 |= 0x40;
4522 if(!SiS_Pr->HaveEMI) {
4523 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4524 }
4525 }
4526 }
4527
4528 /* BIOS values don't work so well sometimes */
4529 if(!SiS_Pr->OverruleEMI) {
4530#ifdef COMPAL_HACK
4531 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004532 if((cr36 & 0x0f) == 0x09) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533 r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
4534 }
4535 }
4536#endif
4537#ifdef COMPAQ_HACK
4538 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004539 if((cr36 & 0x0f) == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540 r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4541 }
4542 }
4543#endif
4544#ifdef ASUS_HACK
4545 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004546 if((cr36 & 0x0f) == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547 /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 2 */
4548 /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 3 */
4549 /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 4 */
4550 /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 5 */
4551 }
4552 }
4553#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004554 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555
4556 if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
4557 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004558 SiS_GenericDelay(SiS_Pr, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559 }
4560 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
4561 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
4562 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
4563#endif /* SET_EMI */
4564
4565 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
4566
4567#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004568 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4569 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4570 if(r30 & 0x40) {
4571 /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
4572 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 if(delaylong) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004574 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004575 delaylong = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004577 SiS_WaitVBRetrace(SiS_Pr);
4578 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004580 SiS_GenericDelay(SiS_Pr, 1280);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004582 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */
4583 /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
4584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585 }
4586#endif
4587 }
4588 }
4589
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004590 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4591 if(SiS_IsVAorLCD(SiS_Pr)) {
4592 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004593 if(delaylong) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004594 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004596 SiS_WaitVBRetrace(SiS_Pr);
4597 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4598 SiS_GenericDelay(SiS_Pr, 2048);
4599 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004601 if(!didpwd) {
4602 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4603 } else {
4604 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
4605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606 }
4607 }
4608
4609 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4610 SiS_DisplayOn(SiS_Pr);
4611 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
4612
4613 }
4614
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004615 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4617 }
4618
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004619#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004620
4621 }
4622
4623 } else { /* ============ For 301 ================ */
4624
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004625 if(SiS_Pr->ChipType < SIS_315H) {
4626 if(SiS_CRT2IsLCD(SiS_Pr)) {
4627 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4628 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 }
4630 }
4631
4632 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
4633 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004634 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4635 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636 }
4637 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4638
4639 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4640
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004641 if(SiS_Pr->ChipType >= SIS_315H) {
4642 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4643 if(!(temp & 0x80)) {
4644 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645 }
4646 }
4647
4648 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4649
4650 SiS_VBLongWait(SiS_Pr);
4651 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004652 if(SiS_Pr->ChipType >= SIS_315H) {
4653 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004654 }
4655 SiS_VBLongWait(SiS_Pr);
4656
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004657 if(SiS_Pr->ChipType < SIS_315H) {
4658 if(SiS_CRT2IsLCD(SiS_Pr)) {
4659 SiS_PanelDelay(SiS_Pr, 1);
4660 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004661 }
4662 }
4663
4664 }
4665
4666 } else { /* =================== For LVDS ================== */
4667
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004668 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004670#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004671
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004672 if(SiS_CRT2IsLCD(SiS_Pr)) {
4673 if(SiS_Pr->ChipType == SIS_730) {
4674 SiS_PanelDelay(SiS_Pr, 1);
4675 SiS_PanelDelay(SiS_Pr, 1);
4676 SiS_PanelDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004678 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4679 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4680 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681 }
4682 }
4683
4684 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4685 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004686 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004687 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4688 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004689 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004690 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004691 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004692 }
4693
4694 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004695 if(!(SiS_CRT2IsLCD(SiS_Pr))) {
4696 SiS_WaitVBRetrace(SiS_Pr);
4697 SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
4698 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699 }
4700
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004701 if(SiS_CRT2IsLCD(SiS_Pr)) {
4702 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4703 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4704 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4705 SiS_PanelDelay(SiS_Pr, 1);
4706 SiS_PanelDelay(SiS_Pr, 1);
4707 }
4708 SiS_WaitVBRetrace(SiS_Pr);
4709 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4710 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711 }
4712 }
4713
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004714#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004715
4716 } else {
4717
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004718#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004720 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4721 /*if(SiS_Pr->ChipType < SIS_340) {*/ /* XGI needs this */
4722 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
4723 /*}*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724 }
4725
4726 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004727 if(SiS_CRT2IsLCD(SiS_Pr)) {
4728 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4729 SiS_PanelDelay(SiS_Pr, 0);
4730 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731 }
4732
4733 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004734 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735
4736 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4737
4738 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004739 temp = SiS_GetCH701x(SiS_Pr,0x66);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740 temp &= 0x20;
4741 SiS_Chrontel701xBLOff(SiS_Pr);
4742 }
4743
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004744 if(SiS_Pr->ChipType != SIS_550) {
4745 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746 }
4747
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004748 if(SiS_Pr->ChipType == SIS_740) {
4749 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4750 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4751 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752 }
4753 }
4754 }
4755
4756 temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4757 if(!(temp1 & 0x80)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004758 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759 }
4760
4761 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004762 if(temp) {
4763 SiS_Chrontel701xBLOn(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764 }
4765 }
4766
4767 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004768 if(SiS_CRT2IsLCD(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004769 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004770 if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
4772 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
4773 }
4774 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004775 } else if(SiS_IsVAMode(SiS_Pr)) {
4776 if(SiS_Pr->ChipType != SIS_740) {
4777 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778 }
4779 }
4780
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004781 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4782 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783 }
4784
4785 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004786 if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
4787 SiS_Chrontel701xOn(SiS_Pr);
4788 }
4789 if( (SiS_IsVAMode(SiS_Pr)) ||
4790 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4791 SiS_ChrontelDoSomething1(SiS_Pr);
4792 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793 }
4794
4795 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004796 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4797 if( (SiS_IsVAMode(SiS_Pr)) ||
4798 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4799 SiS_Chrontel701xBLOn(SiS_Pr);
4800 SiS_ChrontelInitTVVSync(SiS_Pr);
4801 }
4802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803 } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004804 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4805 if(SiS_CRT2IsLCD(SiS_Pr)) {
4806 SiS_PanelDelay(SiS_Pr, 1);
4807 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004808 }
4809 }
4810 }
4811
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004812#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004813
4814 } /* 310 series */
4815
4816 } /* LVDS */
4817
4818}
4819
4820/*********************************************/
4821/* SET PART 1 REGISTER GROUP */
4822/*********************************************/
4823
4824/* Set CRT2 OFFSET / PITCH */
4825static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004826SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
4827 unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004829 unsigned short offset;
4830 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004831
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004832 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004833
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004834 offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004835
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004836 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
4837 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004839 temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
4840 if(offset & 0x07) temp++;
4841 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004842}
4843
4844/* Set CRT2 sync and PanelLink mode */
4845static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004846SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004848 unsigned short tempah=0, tempbl, infoflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004849
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004850 tempbl = 0xC0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004852 if(SiS_Pr->UseCustomMode) {
4853 infoflag = SiS_Pr->CInfoFlag;
4854 } else {
4855 infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
4856 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004857
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004858 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004859
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004860 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4861 tempah = 0;
4862 } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
4863 tempah = SiS_Pr->SiS_LCDInfo;
4864 } else tempah = infoflag >> 8;
4865 tempah &= 0xC0;
4866 tempah |= 0x20;
4867 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4868 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4869 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
4870 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
4871 tempah |= 0xf0;
4872 }
4873 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4874 (SiS_Pr->SiS_IF_DEF_DSTN) ||
4875 (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
4876 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
4877 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
4878 tempah |= 0x30;
4879 }
4880 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4881 (SiS_Pr->SiS_IF_DEF_DSTN) ) {
4882 tempah &= ~0xc0;
4883 }
4884 }
4885 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4886 if(SiS_Pr->ChipType >= SIS_315H) {
4887 tempah >>= 3;
4888 tempah &= 0x18;
4889 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
4890 /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
4891 } else {
4892 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
4893 }
4894 } else {
4895 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004897
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004898 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004899
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004900 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004902#ifdef CONFIG_FB_SIS_300 /* ---- 300 series --- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004904 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* 630 - 301B(-DH) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004905
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004906 tempah = infoflag >> 8;
4907 tempbl = 0;
4908 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4909 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4910 tempah = SiS_Pr->SiS_LCDInfo;
4911 tempbl = (tempah >> 6) & 0x03;
4912 }
4913 }
4914 tempah &= 0xC0;
4915 tempah |= 0x20;
4916 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4917 tempah |= 0xc0;
4918 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4919 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
4920 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4921 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004923 } else { /* 630 - 301 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004925 tempah = ((infoflag >> 8) & 0xc0) | 0x20;
4926 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4927 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004929 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004930
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004931#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004932
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004933 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004935#ifdef CONFIG_FB_SIS_315 /* ------- 315 series ------ */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004937 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* 315 - LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004938
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004939 tempbl = 0;
4940 if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
4941 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
4942 tempah = infoflag >> 8;
4943 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4944 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
4945 }
4946 } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
4947 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
4948 tempah = infoflag >> 8;
4949 tempbl = 0x03;
4950 } else {
4951 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
4952 tempbl = (tempah >> 6) & 0x03;
4953 tempbl |= 0x08;
4954 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
4955 }
4956 tempah &= 0xC0;
4957 tempah |= 0x20;
4958 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4959 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0;
4960 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4961 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
4962 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4963 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4964 }
4965 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004966
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004967 } else { /* 315 - TMDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004969 tempah = tempbl = infoflag >> 8;
4970 if(!SiS_Pr->UseCustomMode) {
4971 tempbl = 0;
4972 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4973 if(ModeNo <= 0x13) {
4974 tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
4975 }
4976 }
4977 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
4978 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
4979 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4980 tempah = SiS_Pr->SiS_LCDInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004981 tempbl = (tempah >> 6) & 0x03;
4982 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004983 }
4984 }
4985 }
4986 tempah &= 0xC0;
4987 tempah |= 0x20;
4988 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4989 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4990 /* Imitate BIOS bug */
4991 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0;
4992 }
4993 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4994 tempah >>= 3;
4995 tempah &= 0x18;
4996 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
4997 } else {
4998 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4999 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
5000 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5001 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
5002 }
5003 }
5004 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005005
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005006 }
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005007#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005008 }
5009 }
5010}
5011
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005012/* Set CRT2 FIFO on 300/540/630/730 */
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005013#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07005014static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005015SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005016{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005017 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5018 unsigned short temp, index, modeidindex, refreshratetableindex;
5019 unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
5020 unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
5021 unsigned int data, pci50, pciA0;
5022 static const unsigned char colortharray[] = {
5023 1, 1, 2, 2, 3, 4
Linus Torvalds1da177e2005-04-16 15:20:36 -07005024 };
5025
5026 SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
5027
5028 if(!SiS_Pr->CRT1UsesCustomMode) {
5029
5030 CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */
5031 SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
5032 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
5033 SiS_Pr->SiS_SelectCRT2Rate = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005034 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035
5036 if(CRT1ModeNo >= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005037 /* Get VCLK */
5038 index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
5039 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005041 /* Get colordepth */
5042 colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
5043 if(!colorth) colorth++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044 }
5045
5046 } else {
5047
5048 CRT1ModeNo = 0xfe;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005049
5050 /* Get VCLK */
5051 VCLK = SiS_Pr->CSRClock_CRT1;
5052
5053 /* Get color depth */
5054 colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055
5056 }
5057
5058 if(CRT1ModeNo >= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005059 /* Get MCLK */
5060 if(SiS_Pr->ChipType == SIS_300) {
5061 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
5062 } else {
5063 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
5064 }
5065 index &= 0x07;
5066 MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005068 temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
5069 if(!temp) temp++;
5070 temp <<= 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005072 data2 = temp - ((colorth * VCLK) / MCLK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005074 temp = (28 * 16) % data2;
5075 data2 = (28 * 16) / data2;
5076 if(temp) data2++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005077
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005078 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005079
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005080 SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
5081 data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005083 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005085 pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
5086 pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005088 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005089
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005090 index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
5091 index += (unsigned short)(((pci50 >> 9)) & 0x03);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005093 /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
5094 index = 0; /* -- do it like the BIOS anyway... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005096 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005098 pci50 >>= 24;
5099 pciA0 >>= 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005101 index = (pci50 >> 1) & 0x07;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005103 if(pci50 & 0x01) index += 6;
5104 if(!(pciA0 & 0x01)) index += 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005106 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005110 data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
5111 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005113 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005115 data += data2; /* CRT1 Request Period */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005117 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5118 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005120 if(!SiS_Pr->UseCustomMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005121
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005122 CRT2ModeNo = ModeNo;
5123 SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005124
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005125 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005127 /* Get VCLK */
5128 index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
5129 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005131 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5132 if(SiS_Pr->SiS_UseROM) {
5133 if(ROMAddr[0x220] & 0x01) {
5134 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
5135 }
5136 }
5137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005138
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005139 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005141 /* Get VCLK */
5142 CRT2ModeNo = 0xfe;
5143 VCLK = SiS_Pr->CSRClock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005145 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005146
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005147 /* Get colordepth */
5148 colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
5149 if(!colorth) colorth++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005150
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005151 data = data * VCLK * colorth;
5152 temp = data % (MCLK << 4);
5153 data = data / (MCLK << 4);
5154 if(temp) data++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005155
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005156 if(data < 6) data = 6;
5157 else if(data > 0x14) data = 0x14;
5158
5159 if(SiS_Pr->ChipType == SIS_300) {
5160 temp = 0x16;
5161 if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
5162 temp = 0x13;
5163 } else {
5164 temp = 0x16;
5165 if(( (SiS_Pr->ChipType == SIS_630) ||
5166 (SiS_Pr->ChipType == SIS_730) ) &&
5167 (SiS_Pr->ChipRevision >= 0x30))
5168 temp = 0x1b;
5169 }
5170 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
5171
5172 if((SiS_Pr->ChipType == SIS_630) &&
5173 (SiS_Pr->ChipRevision >= 0x30)) {
5174 if(data > 0x13) data = 0x13;
5175 }
5176 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177
5178 } else { /* If mode <= 0x13, we just restore everything */
5179
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005180 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5181 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182
5183 }
5184}
5185#endif
5186
5187/* Set CRT2 FIFO on 315/330 series */
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005188#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005190SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191{
5192 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005193 if( (SiS_Pr->ChipType == SIS_760) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07005194 (SiS_Pr->SiS_SysFlags & SF_760LFB) &&
5195 (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
5196 (SiS_Pr->SiS_VGAHDE >= 1280) &&
5197 (SiS_Pr->SiS_VGAVDE >= 1024) ) {
5198 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
5199 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
5200 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5201 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
5202 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5203 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
5204 } else {
5205 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
5206 }
5207
5208}
5209#endif
5210
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005211static unsigned short
5212SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005213{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005214 unsigned int tempax,tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215
5216 tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
5217 tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
5218 tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005219 return (unsigned short)tempax;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005220}
5221
5222/* Set Part 1 / SiS bridge slave mode */
5223static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005224SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
5225 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005227 unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
5228 static const unsigned short CRTranslation[] = {
5229 /* CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 */
5230 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
5231 /* CR8 CR9 SR0A SR0B SR0C SR0D SR0E CR0F */
5232 0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
5233 /* CR10 CR11 CR12 CR13 CR14 CR15 CR16 CR17 */
5234 0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
5235 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07005236
5237 if(ModeNo <= 0x13) {
5238 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239 } else if(SiS_Pr->UseCustomMode) {
5240 modeflag = SiS_Pr->CModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241 xres = SiS_Pr->CHDisplay;
5242 } else {
5243 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244 xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
5245 }
5246
5247 /* The following is only done if bridge is in slave mode: */
5248
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005249 if(SiS_Pr->ChipType >= SIS_315H) {
5250 if(xres >= 1600) { /* BIOS: == 1600 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
5252 }
5253 }
5254
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005255 SiS_Pr->CHTotal = 8224; /* Max HT, 0x2020, results in 0x3ff in registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005257 SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
5258 if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005260 SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005261 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005262 SiS_Pr->CHBlankStart += 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005263 }
5264
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005265 SiS_Pr->CHBlankEnd = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005267 if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005270 temp = SiS_Pr->SiS_VGAHT - 96;
5271 if(!(modeflag & HalfDCLK)) temp -= 32;
5272 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
5273 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
5274 temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
5275 temp -= 3;
5276 temp <<= 3;
5277 } else {
5278 if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005280 SiS_Pr->CHSyncStart = temp;
5281
5282 SiS_Pr->CHSyncEnd = 0xffe8; /* results in 0x2000 in registers */
5283
5284 SiS_Pr->CVTotal = 2049; /* Max VT, 0x0801, results in 0x7ff in registers */
5285
5286 VGAVDE = SiS_Pr->SiS_VGAVDE;
5287 if (VGAVDE == 357) VGAVDE = 350;
5288 else if(VGAVDE == 360) VGAVDE = 350;
5289 else if(VGAVDE == 375) VGAVDE = 350;
5290 else if(VGAVDE == 405) VGAVDE = 400;
5291 else if(VGAVDE == 420) VGAVDE = 400;
5292 else if(VGAVDE == 525) VGAVDE = 480;
5293 else if(VGAVDE == 1056) VGAVDE = 1024;
5294 SiS_Pr->CVDisplay = VGAVDE;
5295
5296 SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
5297
5298 SiS_Pr->CVBlankEnd = 1;
5299 if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
5300
5301 temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
5302 SiS_Pr->CVSyncStart = VGAVDE + temp;
5303
5304 temp >>= 3;
5305 SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
5306
5307 SiS_CalcCRRegisters(SiS_Pr, 0);
5308 SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
5309
5310 for(i = 0; i <= 7; i++) {
5311 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
5312 }
5313 for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
5314 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5315 }
5316 for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
5317 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5318 }
5319 for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
5320 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5321 }
5322
5323 temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
5324 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
5325
5326 temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
5327 if(modeflag & DoubleScanMode) temp |= 0x80;
5328 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005329
5330 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005331 temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
5332 if(modeflag & HalfDCLK) temp |= 0x08;
5333 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005334
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005335 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* CR14: (text mode: underline location) */
5336 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* CR17: n/a */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005337
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005338 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005339 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005340 temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005342 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* SR0E, dither[7] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343
5344 temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005345 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); /* ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346}
5347
5348/* Setup panel link
5349 * This is used for LVDS, LCDA and Chrontel TV output
5350 * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
5351 */
5352static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005353SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5354 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005356 unsigned short modeflag, resinfo = 0;
5357 unsigned short push2, tempax, tempbx, tempcx, temp;
5358 unsigned int tempeax = 0, tempebx, tempecx, tempvcfact = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005359 bool islvds = false, issis = false, chkdclkfirst = false;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005360#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005361 unsigned short crt2crtc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005362#endif
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005363#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005364 unsigned short pushcx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365#endif
5366
5367 if(ModeNo <= 0x13) {
5368 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5369 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005370#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07005371 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5372#endif
5373 } else if(SiS_Pr->UseCustomMode) {
5374 modeflag = SiS_Pr->CModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375 } else {
5376 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5377 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005378#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005379 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005380#endif
5381 }
5382
5383 /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
5384 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005385 islvds = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386 }
5387
5388 /* is really sis if sis bridge, but not 301B-DH */
5389 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005390 issis = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005391 }
5392
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005393 if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005394 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005395 chkdclkfirst = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396 }
5397 }
5398
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005399#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005400 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401 if(IS_SIS330) {
5402 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5403 } else if(IS_SIS740) {
5404 if(islvds) {
5405 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5406 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
5407 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5408 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5409 }
5410 } else {
5411 if(islvds) {
5412 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5413 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
5414 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5415 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005416 if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417 if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
5418 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5419 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
5420 }
5421 }
5422 }
5423 }
5424 }
5425#endif
5426
5427 /* Horizontal */
5428
5429 tempax = SiS_Pr->SiS_LCDHDES;
5430 if(islvds) {
5431 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005432 if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
5433 if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
5434 (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
5435 tempax -= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436 }
5437 }
5438 }
5439 }
5440
5441 temp = (tempax & 0x0007);
5442 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* BPLHDESKEW[2:0] */
5443 temp = (tempax >> 3) & 0x00FF;
5444 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* BPLHDESKEW[10:3] */
5445
5446 tempbx = SiS_Pr->SiS_HDE;
5447 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5449 tempbx = SiS_Pr->PanelXRes;
5450 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005451 if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
5452 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
5453 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
5454 tempbx >>= 1;
5455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005456 }
5457
5458 tempax += tempbx;
5459 if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
5460
5461 temp = tempax;
5462 if(temp & 0x07) temp += 8;
5463 temp >>= 3;
5464 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp); /* BPLHDEE */
5465
5466 tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
5467
5468 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5469 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5470 if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
5471 }
5472 }
5473
5474 tempcx += tempax;
5475 if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
5476
5477 temp = (tempcx >> 3) & 0x00FF;
5478 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5479 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005480 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5481 switch(ModeNo) {
5482 case 0x04:
5483 case 0x05:
5484 case 0x0d: temp = 0x56; break;
5485 case 0x10: temp = 0x60; break;
5486 case 0x13: temp = 0x5f; break;
5487 case 0x40:
5488 case 0x41:
5489 case 0x4f:
5490 case 0x43:
5491 case 0x44:
5492 case 0x62:
5493 case 0x56:
5494 case 0x53:
5495 case 0x5d:
5496 case 0x5e: temp = 0x54; break;
5497 }
5498 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499 }
5500 }
5501 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp); /* BPLHRS */
5502
5503 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5504 temp += 2;
5505 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005506 temp += 8;
5507 if(SiS_Pr->PanelHRE != 999) {
5508 temp = tempcx + SiS_Pr->PanelHRE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509 if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
5510 temp >>= 3;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005511 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005512 }
5513 } else {
5514 temp += 10;
5515 }
5516
5517 temp &= 0x1F;
5518 temp |= ((tempcx & 0x07) << 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005519 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp); /* BPLHRE */
5520
5521 /* Vertical */
5522
5523 tempax = SiS_Pr->SiS_VGAVDE;
5524 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5525 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5526 tempax = SiS_Pr->PanelYRes;
5527 }
5528 }
5529
5530 tempbx = SiS_Pr->SiS_LCDVDES + tempax;
5531 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5532
5533 push2 = tempbx;
5534
5535 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005536 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005537 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005538 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005539 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
5540 }
5541 }
5542 }
5543 if(islvds) tempcx >>= 1;
5544 else tempcx >>= 2;
5545
5546 if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
5547 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
5548 (SiS_Pr->PanelVRS != 999) ) {
5549 tempcx = SiS_Pr->PanelVRS;
5550 tempbx += tempcx;
5551 if(issis) tempbx++;
5552 } else {
5553 tempbx += tempcx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005554 if(SiS_Pr->ChipType < SIS_315H) tempbx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005555 else if(issis) tempbx++;
5556 }
5557
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005558 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005559
5560 temp = tempbx & 0x00FF;
5561 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5562 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005563 if(ModeNo == 0x10) temp = 0xa9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564 }
5565 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005566 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp); /* BPLVRS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567
5568 tempcx >>= 3;
5569 tempcx++;
5570
5571 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5572 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5573 if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
5574 }
5575 }
5576
5577 tempcx += tempbx;
5578 temp = tempcx & 0x000F;
5579 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); /* BPLVRE */
5580
5581 temp = ((tempbx >> 8) & 0x07) << 3;
5582 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5583 if(SiS_Pr->SiS_HDE != 640) {
5584 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5585 }
5586 } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5587 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40;
5588 tempbx = 0x87;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005589 if((SiS_Pr->ChipType >= SIS_315H) ||
5590 (SiS_Pr->ChipRevision >= 0x30)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005591 tempbx = 0x07;
5592 if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
5593 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03) temp |= 0x80;
5594 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005595 /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005596 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5597 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5598 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
5599 } else {
5600 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
5601 }
5602 }
5603 }
5604 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
5605
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005606 tempbx = push2; /* BPLVDEE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005607
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005608 tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609
5610 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5611 switch(SiS_Pr->SiS_LCDResInfo) {
5612 case Panel_640x480:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005613 tempbx = SiS_Pr->SiS_VGAVDE - 1;
5614 tempcx = SiS_Pr->SiS_VGAVDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615 break;
5616 case Panel_800x600:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005617 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5618 if(resinfo == SIS_RI_800x600) tempcx++;
5619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005620 break;
5621 case Panel_1024x600:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005622 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5623 if(resinfo == SIS_RI_1024x600) tempcx++;
5624 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625 if(resinfo == SIS_RI_800x600) tempcx++;
5626 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005627 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005628 break;
5629 case Panel_1024x768:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005630 if(SiS_Pr->ChipType < SIS_315H) {
5631 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5632 if(resinfo == SIS_RI_1024x768) tempcx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005633 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005634 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635 break;
5636 }
5637 }
5638
5639 temp = ((tempbx >> 8) & 0x07) << 3;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005640 temp |= ((tempcx >> 8) & 0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005641 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
5643 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
5644
5645 /* Vertical scaling */
5646
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005647 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005648
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005649#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005650 tempeax = SiS_Pr->SiS_VGAVDE << 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005651 temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
5652 tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005653 if(temp) tempeax++;
5654
5655 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
5656
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005657 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005658 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */
5659 tempvcfact = temp;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005660#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661
5662 } else {
5663
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005664#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005665 tempeax = SiS_Pr->SiS_VGAVDE << 18;
5666 tempebx = SiS_Pr->SiS_VDE;
5667 temp = (tempeax % tempebx);
5668 tempeax = tempeax / tempebx;
5669 if(temp) tempeax++;
5670 tempvcfact = tempeax;
5671
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005672 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005673 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005674 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005675 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005676 temp = (unsigned short)((tempeax & 0x00030000) >> 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005677 if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
5678 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
5679
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005680 if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
5681 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005682 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005683 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005684 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005685 temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005686 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
5687 temp = 0;
5688 if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
5689 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
5690 }
5691#endif
5692
5693 }
5694
5695 /* Horizontal scaling */
5696
5697 tempeax = SiS_Pr->SiS_VGAHDE; /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
5698 if(chkdclkfirst) {
5699 if(modeflag & HalfDCLK) tempeax >>= 1;
5700 }
5701 tempebx = tempeax << 16;
5702 if(SiS_Pr->SiS_HDE == tempeax) {
5703 tempecx = 0xFFFF;
5704 } else {
5705 tempecx = tempebx / SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005706 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005707 if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
5708 }
5709 }
5710
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005711 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005712 tempeax = (tempebx / tempecx) - 1;
5713 } else {
5714 tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
5715 }
5716 tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005717 temp = (unsigned short)(tempecx & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
5719
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005720 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721 tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005722 tempbx = (unsigned short)(tempeax & 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005723 } else {
5724 tempeax = SiS_Pr->SiS_VGAVDE << 6;
5725 tempbx = tempvcfact & 0x3f;
5726 if(tempbx == 0) tempbx = 64;
5727 tempeax /= tempbx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005728 tempbx = (unsigned short)(tempeax & 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729 }
5730 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
5731 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
5732 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
5733 else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) tempbx = 1;
5734 }
5735
5736 temp = ((tempbx >> 8) & 0x07) << 3;
5737 temp = temp | ((tempecx >> 8) & 0x07);
5738 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
5739 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
5740
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005741 tempecx >>= 16; /* BPLHCFACT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742 if(!chkdclkfirst) {
5743 if(modeflag & HalfDCLK) tempecx >>= 1;
5744 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005745 temp = (unsigned short)((tempecx & 0xFF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005746 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005747 temp = (unsigned short)(tempecx & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005748 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
5749
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005750#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005751 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005752 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005753 if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005754 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
5755 }
5756 } else {
5757 if(islvds) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005758 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005759 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
5760 } else {
5761 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
5762 }
5763 }
5764 }
5765 }
5766#endif
5767
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005768#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07005769 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005770 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5771 unsigned char *trumpdata;
5772 int i, j = crt2crtc;
5773 unsigned char TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 };
5774 unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
5775 unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
5776
5777 if(SiS_Pr->SiS_UseROM) {
5778 trumpdata = &ROMAddr[0x8001 + (j * 80)];
5779 } else {
5780 if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
5781 trumpdata = &SiS300_TrumpionData[j][0];
5782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783
5784 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
5785 for(i=0; i<5; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005786 SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005787 }
5788 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005789 if(ModeNo == 0x13) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005790 for(i=0; i<4; i++) {
5791 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
5792 }
5793 } else if(ModeNo == 0x10) {
5794 for(i=0; i<4; i++) {
5795 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
5796 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
5797 }
5798 }
5799 }
5800 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
5801 }
5802#endif
5803
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005804#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5806 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
5807 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
5808 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
5809 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
5810 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
5811 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
5812 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005813 tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
5814 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5815 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5816 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005817 tempax += 64;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005818 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
5819 temp = (tempax >> 8) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005821 tempax += 32; /* Blpe = lBlps+32 */
5822 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
5823 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml = 0 */
5824 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005825
5826 tempax = SiS_Pr->SiS_VDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005827 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5828 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5829 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005830 tempax >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005831 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
5832 temp = (tempax >> 8) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005833 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
5834
5835 tempeax = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005836 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5837 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5838 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
5839 tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
5840 temp = tempeax & 0x7f;
5841 tempeax >>= 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842 if(temp) tempeax++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005843 temp = tempeax & 0x3f;
5844 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
5845 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
5847 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005848 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849
5850 tempax = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005851 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5852 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5853 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5854 tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005855 pushcx = tempax;
5856 temp = tempax & 0x00FF;
5857 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
5858 temp = ((tempax & 0xFF00) >> 8) << 3;
5859 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
5860
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005861 tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
5862 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5863 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5864 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5865 tempeax = tempax * pushcx;
5866 temp = tempeax & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005868 temp = (tempeax & 0xFF00) >> 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005869 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005870 temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005872 temp = ((tempeax & 0x01000000) >> 24) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
5874
5875 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
5876 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
5877 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
5878 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
5879 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
5880
5881 if(SiS_Pr->SiS_IF_DEF_FSTN) {
5882 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
5883 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
5884 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
5885 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
5886 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
5887 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
5888 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
5889 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
5890 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
5891 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
5892 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
5893 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
5894 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
5895 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
5896 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
5897 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
5898 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
5899 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
5900 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
5901 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
5902 }
5903 }
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005904#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005905}
5906
5907/* Set Part 1 */
5908static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005909SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5910 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005911{
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005912#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005913 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005914#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005915 unsigned short temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
5916 unsigned short pushbx=0, CRT1Index=0, modeflag, resinfo=0;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005917#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005918 unsigned short tempbl=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919#endif
5920
5921 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005922 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005923 return;
5924 }
5925
5926 if(ModeNo <= 0x13) {
5927 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5928 } else if(SiS_Pr->UseCustomMode) {
5929 modeflag = SiS_Pr->CModeFlag;
5930 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005931 CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5933 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5934 }
5935
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005936 SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005938 if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939 (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
5940 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
5941
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005942 if(SiS_Pr->ChipType < SIS_315H ) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005943#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005944 SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945#endif
5946 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005947#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005948 SiS_SetCRT2FIFO_310(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005949#endif
5950 }
5951
5952 /* 1. Horizontal setup */
5953
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005954 if(SiS_Pr->ChipType < SIS_315H ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005956#ifdef CONFIG_FB_SIS_300 /* ------------- 300 series --------------*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005958 temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
5959 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005960
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005961 temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
5962 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005963
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005964 temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
5965 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966
5967 pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA2HRS 0x0B,0x0C */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005968 tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
5969 tempbx = pushbx + tempcx;
5970 tempcx <<= 1;
5971 tempcx += tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972
5973 bridgeadd = 12;
5974
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005975#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005976
5977 } else {
5978
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005979#ifdef CONFIG_FB_SIS_315 /* ------------------- 315/330 series --------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980
5981 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */
5982 if(modeflag & HalfDCLK) {
5983 if(SiS_Pr->SiS_VBType & VB_SISVB) {
5984 tempcx >>= 1;
5985 } else {
5986 tempax = SiS_Pr->SiS_VGAHDE >> 1;
5987 tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
5988 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
5989 tempcx = SiS_Pr->SiS_HT - tempax;
5990 }
5991 }
5992 }
5993 tempcx--;
5994 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx); /* CRT2 Horizontal Total */
5995 temp = (tempcx >> 4) & 0xF0;
5996 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp); /* CRT2 Horizontal Total Overflow [7:4] */
5997
5998 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HDEE 0x0A,0x0C */
5999 tempbx = SiS_Pr->SiS_VGAHDE;
6000 tempcx -= tempbx;
6001 tempcx >>= 2;
6002 if(modeflag & HalfDCLK) {
6003 tempbx >>= 1;
6004 tempcx >>= 1;
6005 }
6006 tempbx += 16;
6007
6008 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx); /* CRT2 Horizontal Display Enable End */
6009
6010 pushbx = tempbx;
6011 tempcx >>= 1;
6012 tempbx += tempcx;
6013 tempcx += tempbx;
6014
6015 bridgeadd = 16;
6016
6017 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006018 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006019 if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
6020 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
6021 if(resinfo == SIS_RI_1280x1024) {
6022 tempcx = (tempcx & 0xff00) | 0x30;
6023 } else if(resinfo == SIS_RI_1600x1200) {
6024 tempcx = (tempcx & 0xff00) | 0xff;
6025 }
6026 }
6027 }
6028 }
6029
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006030#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031
6032 } /* 315/330 series */
6033
6034 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6035
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006036 if(SiS_Pr->UseCustomMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037 tempbx = SiS_Pr->CHSyncStart + bridgeadd;
6038 tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
6039 tempax = SiS_Pr->SiS_VGAHT;
6040 if(modeflag & HalfDCLK) tempax >>= 1;
6041 tempax--;
6042 if(tempcx > tempax) tempcx = tempax;
6043 }
6044
6045 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6046 unsigned char cr4, cr14, cr5, cr15;
6047 if(SiS_Pr->UseCustomMode) {
6048 cr4 = SiS_Pr->CCRT1CRTC[4];
6049 cr14 = SiS_Pr->CCRT1CRTC[14];
6050 cr5 = SiS_Pr->CCRT1CRTC[5];
6051 cr15 = SiS_Pr->CCRT1CRTC[15];
6052 } else {
6053 cr4 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
6054 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
6055 cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
6056 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
6057 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006058 tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
6059 tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060 tempcx &= 0x00FF;
6061 tempcx |= (tempbx & 0xFF00);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006062 tempbx += bridgeadd;
6063 tempcx += bridgeadd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064 tempax = SiS_Pr->SiS_VGAHT;
6065 if(modeflag & HalfDCLK) tempax >>= 1;
6066 tempax--;
6067 if(tempcx > tempax) tempcx = tempax;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006070 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
6071 tempbx = 1040;
6072 tempcx = 1044; /* HWCursor bug! */
6073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006074
6075 }
6076
6077 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx); /* CRT2 Horizontal Retrace Start */
6078
6079 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx); /* CRT2 Horizontal Retrace End */
6080
6081 temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
6082 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp); /* Overflow */
6083
6084 /* 2. Vertical setup */
6085
6086 tempcx = SiS_Pr->SiS_VGAVT - 1;
6087 temp = tempcx & 0x00FF;
6088
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006089 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006091 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6093 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6094 temp--;
6095 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006097 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006098 temp--;
6099 }
6100 } else if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006101 temp--;
6102 }
6103 }
6104 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp); /* CRT2 Vertical Total */
6105
6106 tempbx = SiS_Pr->SiS_VGAVDE - 1;
6107 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx); /* CRT2 Vertical Display Enable End */
6108
6109 temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
6110 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp); /* Overflow */
6111
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006112 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
6113 tempbx++;
6114 tempax = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115 tempcx++;
6116 tempcx -= tempax;
6117 tempcx >>= 2;
6118 tempbx += tempcx;
6119 if(tempcx < 4) tempcx = 4;
6120 tempcx >>= 2;
6121 tempcx += tempbx;
6122 tempcx++;
6123 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006124 tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
6125 tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126 }
6127
6128 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6129 if(SiS_Pr->UseCustomMode) {
6130 tempbx = SiS_Pr->CVSyncStart;
6131 tempcx = SiS_Pr->CVSyncEnd;
6132 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006133 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134 unsigned char cr8, cr7, cr13;
6135 if(SiS_Pr->UseCustomMode) {
6136 cr8 = SiS_Pr->CCRT1CRTC[8];
6137 cr7 = SiS_Pr->CCRT1CRTC[7];
6138 cr13 = SiS_Pr->CCRT1CRTC[13];
6139 tempcx = SiS_Pr->CCRT1CRTC[9];
6140 } else {
6141 cr8 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
6142 cr7 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
6143 cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
6144 tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
6145 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006146 tempbx = cr8;
6147 if(cr7 & 0x04) tempbx |= 0x0100;
6148 if(cr7 & 0x80) tempbx |= 0x0200;
6149 if(cr13 & 0x08) tempbx |= 0x0400;
6150 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006151 }
6152 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx); /* CRT2 Vertical Retrace Start */
6153
6154 temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
6155 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp); /* CRT2 Vert. Retrace End; Overflow */
6156
6157 /* 3. Panel delay compensation */
6158
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006159 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006161#ifdef CONFIG_FB_SIS_300 /* ---------- 300 series -------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162
6163 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6164 temp = 0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006165 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006166 temp = 0x10;
6167 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) temp = 0x2c;
6168 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6169 }
6170 if(SiS_Pr->SiS_VBType & VB_SIS301) {
6171 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6172 }
6173 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) temp = 0x24;
6174 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) temp = 0x2c;
6175 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08;
6176 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006177 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
6178 else temp = 0x20;
6179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006180 if(SiS_Pr->SiS_UseROM) {
6181 if(ROMAddr[0x220] & 0x80) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006182 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
6183 temp = ROMAddr[0x221];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006184 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
6185 temp = ROMAddr[0x222];
6186 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
6187 temp = ROMAddr[0x223];
6188 else
6189 temp = ROMAddr[0x224];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006190 }
6191 }
6192 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006193 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006194 }
6195
6196 } else {
6197 temp = 0x20;
6198 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6199 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
6200 }
6201 if(SiS_Pr->SiS_UseROM) {
6202 if(ROMAddr[0x220] & 0x80) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006203 temp = ROMAddr[0x220];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006204 }
6205 }
6206 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006207 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006208 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006211 temp &= 0x3c;
6212
6213 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 -07006214
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006215#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006216
6217 } else {
6218
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006219#ifdef CONFIG_FB_SIS_315 /* --------------- 315/330 series ---------------*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006221 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006222
6223 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6224
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006225 if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
6226 else temp = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006227
6228 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
6229 tempbl = 0xF0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006230 if(SiS_Pr->ChipType == SIS_650) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006231 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6232 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
6233 }
6234 }
6235
6236 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
6237 temp = 0x08;
6238 tempbl = 0;
6239 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
6240 if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
6241 }
6242 }
6243
6244 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp); /* Panel Link Delay Compensation */
6245 }
6246
6247 } /* < 661 */
6248
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006249 tempax = 0;
6250 if(modeflag & DoubleScanMode) tempax |= 0x80;
6251 if(modeflag & HalfDCLK) tempax |= 0x40;
6252 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006254#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006255
6256 }
6257
6258 } /* Slavemode */
6259
6260 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6261 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006262 /* For 301BDH with LCD, we set up the Panel Link */
6263 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006265 SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006266 }
6267 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006268 if(SiS_Pr->ChipType < SIS_315H) {
6269 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270 } else {
6271 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006272 if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6273 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
6274 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006275 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006276 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277 }
6278 }
6279 }
6280}
6281
6282/*********************************************/
6283/* SET PART 2 REGISTER GROUP */
6284/*********************************************/
6285
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006286#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006287static unsigned char *
6288SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006289{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006290 const unsigned char *tableptr = NULL;
6291 unsigned short a, b, p = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006292
6293 a = SiS_Pr->SiS_VGAHDE;
6294 b = SiS_Pr->SiS_HDE;
6295 if(tabletype) {
6296 a = SiS_Pr->SiS_VGAVDE;
6297 b = SiS_Pr->SiS_VDE;
6298 }
6299
6300 if(a < b) {
6301 tableptr = SiS_Part2CLVX_1;
6302 } else if(a == b) {
6303 tableptr = SiS_Part2CLVX_2;
6304 } else {
6305 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6306 tableptr = SiS_Part2CLVX_4;
6307 } else {
6308 tableptr = SiS_Part2CLVX_3;
6309 }
6310 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6311 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) tableptr = SiS_Part2CLVX_3;
6312 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tableptr = SiS_Part2CLVX_3;
6313 else tableptr = SiS_Part2CLVX_5;
6314 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6315 tableptr = SiS_Part2CLVX_6;
6316 }
6317 do {
6318 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
6319 p += 0x42;
6320 } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
6321 if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
6322 }
6323 p += 2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006324 return ((unsigned char *)&tableptr[p]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006325}
6326
6327static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006328SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6329 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006330{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006331 unsigned char *tableptr;
6332 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006333 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006334
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006335 if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006336
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006337 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006338 for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
6339 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6340 }
6341 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006342 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006343 for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
6344 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6345 }
6346 }
6347 temp = 0x10;
6348 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
6349 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
6350}
6351
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006352static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006353SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
6354 unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
6355 unsigned short *ResIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006356{
6357
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006358 if(SiS_Pr->ChipType < SIS_315H) return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006359
6360 if(ModeNo <= 0x13)
6361 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6362 else
6363 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6364
6365 (*ResIndex) &= 0x3f;
6366 (*CRT2Index) = 0;
6367
6368 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6369 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6370 (*CRT2Index) = 200;
6371 }
6372 }
6373
6374 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
6375 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6376 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
6377 }
6378 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006379 return (((*CRT2Index) != 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006380}
6381#endif
6382
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006383#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07006384static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006385SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006386{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006387 unsigned short tempcx;
6388 static const unsigned char atable[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006389 0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
6390 0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
6391 };
6392
6393 if(!SiS_Pr->UseCustomMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006394 if( ( ( (SiS_Pr->ChipType == SIS_630) ||
6395 (SiS_Pr->ChipType == SIS_730) ) &&
6396 (SiS_Pr->ChipRevision > 2) ) &&
6397 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
6398 (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
6399 (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
6400 if(ModeNo == 0x13) {
6401 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
6402 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
6403 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
6404 } else if((crt2crtc & 0x3F) == 4) {
6405 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
6406 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
6407 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
6408 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
6409 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
6410 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006411 }
6412
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006413 if(SiS_Pr->ChipType < SIS_315H) {
6414 if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
6415 crt2crtc &= 0x1f;
6416 tempcx = 0;
6417 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6418 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6419 tempcx += 7;
6420 }
6421 }
6422 tempcx += crt2crtc;
6423 if(crt2crtc >= 4) {
6424 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
6425 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006426
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006427 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6428 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6429 if(crt2crtc == 4) {
6430 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
6431 }
6432 }
6433 }
6434 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
6435 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
6436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006437 }
6438 }
6439}
6440
6441/* For ECS A907. Highly preliminary. */
6442static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006443SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
6444 unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006445{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006446 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6447 unsigned short crt2crtc, resindex;
6448 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006449
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006450 if(SiS_Pr->ChipType != SIS_300) return;
6451 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006452 if(SiS_Pr->UseCustomMode) return;
6453
6454 if(ModeNo <= 0x13) {
6455 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6456 } else {
6457 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6458 }
6459
6460 resindex = crt2crtc & 0x3F;
6461 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6462 else CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
6463
6464 /* The BIOS code (1.16.51,56) is obviously a fragment! */
6465 if(ModeNo > 0x13) {
6466 CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6467 resindex = 4;
6468 }
6469
6470 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6471 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6472 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006473 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006474 }
6475 for(j = 0x1c; j <= 0x1d; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006476 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006477 }
6478 for(j = 0x1f; j <= 0x21; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006479 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006480 }
6481 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6482 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6483}
6484#endif
6485
6486static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006487SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006488{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006489 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006490 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
6491 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
6492
6493 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6494 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006495 const unsigned char specialtv[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006496 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
6497 0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
6498 0x58,0xe4,0x73,0xda,0x13
6499 };
6500 int i, j;
6501 for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
6502 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
6503 }
6504 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
6505 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
6506 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6507 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
6508 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
6509 } else {
6510 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14); /* 15 */
6511 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a); /* 1b */
6512 }
6513 }
6514 }
6515 } else {
6516 if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
6517 (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
6518 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b); /* 21 */
6519 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54); /* 5a */
6520 } else {
6521 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a); /* 21 */
6522 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53); /* 5a */
6523 }
6524 }
6525}
6526
6527static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006528SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006529{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006530 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006531
6532 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6533 if(SiS_Pr->SiS_VGAVDE == 525) {
6534 temp = 0xc3;
6535 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6536 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006537 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006538 }
6539 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6540 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
6541 } else if(SiS_Pr->SiS_VGAVDE == 420) {
6542 temp = 0x4d;
6543 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6544 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006545 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006546 }
6547 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6548 }
6549 }
6550
6551 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6552 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006553 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006554 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
6555 /* Not always for LV, see SetGrp2 */
6556 }
6557 temp = 1;
6558 if(ModeNo <= 0x13) temp = 3;
6559 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
6560 }
6561#if 0
6562 /* 651+301C, for 1280x768 - do I really need that? */
6563 if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
6564 if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
6565 if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
6566 ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
6567 SiS_SetReg(SiS_Part2Port,0x01,0x2b);
6568 SiS_SetReg(SiS_Part2Port,0x02,0x13);
6569 SiS_SetReg(SiS_Part2Port,0x04,0xe5);
6570 SiS_SetReg(SiS_Part2Port,0x05,0x08);
6571 SiS_SetReg(SiS_Part2Port,0x06,0xe2);
6572 SiS_SetReg(SiS_Part2Port,0x1c,0x21);
6573 SiS_SetReg(SiS_Part2Port,0x1d,0x45);
6574 SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
6575 SiS_SetReg(SiS_Part2Port,0x20,0x00);
6576 SiS_SetReg(SiS_Part2Port,0x21,0xa9);
6577 SiS_SetReg(SiS_Part2Port,0x23,0x0b);
6578 SiS_SetReg(SiS_Part2Port,0x25,0x04);
6579 }
6580 }
6581 }
6582#endif
6583 }
6584}
6585
6586static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006587SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6588 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006589{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006590 unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
6591 unsigned short push2, modeflag, crt2crtc, bridgeoffset;
6592 unsigned int longtemp, PhaseIndex;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006593 bool newtvphase;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006594 const unsigned char *TimingPoint;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006595#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006596 unsigned short resindex, CRT2Index;
6597 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006598
6599 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
6600#endif
6601
6602 if(ModeNo <= 0x13) {
6603 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6604 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6605 } else if(SiS_Pr->UseCustomMode) {
6606 modeflag = SiS_Pr->CModeFlag;
6607 crt2crtc = 0;
6608 } else {
6609 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6610 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6611 }
6612
6613 temp = 0;
6614 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
6615 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
6616 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) temp |= 0x02;
6617 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp |= 0x01;
6618
6619 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) temp |= 0x10;
6620
6621 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
6622
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006623 PhaseIndex = 0x01; /* SiS_PALPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006624 TimingPoint = SiS_Pr->SiS_PALTiming;
6625
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006626 newtvphase = false;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006627 if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
6628 ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6629 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006630 newtvphase = true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006631 }
6632
Linus Torvalds1da177e2005-04-16 15:20:36 -07006633 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6634
6635 TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
6636 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6637 TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
6638 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6639 TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006640 }
6641 }
6642
6643 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6644
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006645 i = 0;
6646 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) i = 2;
6647 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006648
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006649 TimingPoint = &SiS_YPbPrTable[i][0];
6650
6651 PhaseIndex = 0x00; /* SiS_NTSCPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006652
6653 } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6654
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006655 if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006656
6657 } else {
6658
6659 TimingPoint = SiS_Pr->SiS_NTSCTiming;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006660 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00; /* SiS_PALPhase : SiS_NTSCPhase */
6661 if(newtvphase) PhaseIndex += 8; /* SiS_PALPhase2 : SiS_NTSCPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006662
6663 }
6664
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006665 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
6666 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03; /* SiS_PALMPhase : SiS_PALNPhase */
6667 if(newtvphase) PhaseIndex += 8; /* SiS_PALMPhase2 : SiS_PALNPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006668 }
6669
6670 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006671 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006672 PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006673 } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006674 PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
6675 } else {
6676 PhaseIndex = 0x10; /* SiS_SpecialPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006677 }
6678 }
6679
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006680 for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
6681 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006682 }
6683
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006684 for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006685 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6686 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006687 for(i = 0x39; i <= 0x45; i++, j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006688 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6689 }
6690
6691 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6692 if(SiS_Pr->SiS_ModeType != ModeText) {
6693 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
6694 }
6695 }
6696
6697 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
6698
6699 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
6700 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
6701 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
6702 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
6703
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006704 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950;
6705 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempax = 680;
6706 else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520;
6707 else tempax = 440; /* NTSC, YPbPr 525 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006708
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006709 if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07006710 ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
6711 ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
6712
6713 tempax -= SiS_Pr->SiS_VDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006714 tempax >>= 1;
6715 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
6716 tempax >>= 1;
6717 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006718 tempax &= 0x00ff;
6719
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006720 temp = tempax + (unsigned short)TimingPoint[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006721 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
6722
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006723 temp = tempax + (unsigned short)TimingPoint[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006724 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
6725
6726 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
6727 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006728 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
6729 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006730 } else {
6731 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
6732 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
6733 }
6734 }
6735
6736 }
6737
6738 tempcx = SiS_Pr->SiS_HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006739 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006740 tempcx--;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006741 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006742 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
6743 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
6744
6745 tempcx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006746 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006747 tempcx += 7;
6748 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6749 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
6750
6751 tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
6752 tempbx += tempcx;
6753 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
6754 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
6755
6756 tempbx += 8;
6757 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6758 tempbx -= 4;
6759 tempcx = tempbx;
6760 }
6761 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
6762
6763 j += 2;
6764 tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
6765 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
6766 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
6767
6768 tempcx += 8;
6769 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6770 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
6771
6772 tempcx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006773 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006774 j += 2;
6775 tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
6776 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
6777
6778 tempcx -= 11;
6779 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6780 tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
6781 }
6782 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
6783
6784 tempbx = SiS_Pr->SiS_VDE;
6785 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6786 if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
6787 if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
6788 if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
6789 } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6790 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
6791 tempbx >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006792 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006793 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6794 if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
6795 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6796 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6797 if(crt2crtc == 4) tempbx++;
6798 }
6799 }
6800 }
6801 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6802 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6803 if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
6804 }
6805 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6806 if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
6807 }
6808 }
6809 }
6810 tempbx -= 2;
6811 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
6812
6813 temp = (tempcx >> 8) & 0x0F;
6814 temp |= ((tempbx >> 2) & 0xC0);
6815 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6816 temp |= 0x10;
6817 if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
6818 }
6819 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
6820
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006821 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006822 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
6823 }
6824
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006825 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006826 tempbx = SiS_Pr->SiS_VDE;
6827 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6828 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
6829 tempbx >>= 1;
6830 }
6831 tempbx -= 3;
6832 temp = ((tempbx >> 3) & 0x60) | 0x18;
6833 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
6834 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
6835
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006836 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006837 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
6838 }
6839 }
6840
6841 tempbx = 0;
6842 if(!(modeflag & HalfDCLK)) {
6843 if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
6844 tempax = 0;
6845 tempbx |= 0x20;
6846 }
6847 }
6848
6849 tempch = tempcl = 0x01;
6850 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006851 if(SiS_Pr->SiS_VGAHDE >= 960) {
6852 if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006853 tempcl = 0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006854 if(SiS_Pr->SiS_VGAHDE >= 1280) {
6855 tempch = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006856 tempbx &= ~0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006857 } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
6858 tempch = 25;
6859 } else {
6860 tempch = 25; /* OK */
6861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006862 }
6863 }
6864 }
6865
6866 if(!(tempbx & 0x20)) {
6867 if(modeflag & HalfDCLK) tempcl <<= 1;
6868 longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006869 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006870 tempax = longtemp / SiS_Pr->SiS_HDE;
6871 if(longtemp % SiS_Pr->SiS_HDE) tempax++;
6872 tempbx |= ((tempax >> 8) & 0x1F);
6873 tempcx = tempax >> 13;
6874 }
6875
6876 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
6877 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
6878
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006879 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006880
6881 tempcx &= 0x07;
6882 if(tempbx & 0x20) tempcx = 0;
6883 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
6884
6885 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6886 tempbx = 0x0382;
6887 tempcx = 0x007e;
6888 } else {
6889 tempbx = 0x0369;
6890 tempcx = 0x0061;
6891 }
6892 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
6893 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
6894 temp = (tempcx & 0x0300) >> 6;
6895 temp |= ((tempbx >> 8) & 0x03);
6896 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6897 temp |= 0x10;
6898 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp |= 0x20;
6899 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
6900 }
6901 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
6902
6903 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
6904 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
6905
6906 SiS_SetTVSpecial(SiS_Pr, ModeNo);
6907
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006908 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006909 temp = 0;
6910 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
6911 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
6912 }
6913
6914 }
6915
6916 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6917 if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
6918 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
6919 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
6920 }
6921 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
6922 }
6923
6924 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6925 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6926 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
6927 }
6928 }
6929
6930 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
6931
6932 /* From here: Part2 LCD setup */
6933
6934 tempbx = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006935 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006936 tempbx--; /* RHACTE = HDE - 1 */
6937 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
6938 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
6939
6940 temp = 0x01;
6941 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
6942 if(SiS_Pr->SiS_ModeType == ModeEGA) {
6943 if(SiS_Pr->SiS_VGAHDE >= 1024) {
6944 temp = 0x02;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006945 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
6946 temp = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006947 }
6948 }
6949 }
6950 }
6951 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
6952
6953 tempbx = SiS_Pr->SiS_VDE - 1;
6954 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
6955 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
6956
6957 tempcx = SiS_Pr->SiS_VT - 1;
6958 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
6959 temp = (tempcx >> 3) & 0xE0;
6960 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
6961 /* Enable dithering; only do this for 32bpp mode */
6962 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
6963 temp |= 0x10;
6964 }
6965 }
6966 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
6967
6968 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
6969 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
6970
6971 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
6972 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
6973
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006974#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07006975 if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006976 &CRT2Index, &resindex)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006977 switch(CRT2Index) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006978 case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break;
6979 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006980 case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006981 }
6982
6983 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6984 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6985 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
6986 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6987 }
6988 for(j = 0x1c; j <= 0x1d; i++, j++ ) {
6989 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6990 }
6991 for(j = 0x1f; j <= 0x21; i++, j++ ) {
6992 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6993 }
6994 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6995 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6996
6997 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
6998
Linus Torvalds1da177e2005-04-16 15:20:36 -07006999 } else {
7000#endif
7001
7002 /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
7003 /* Clevo dual-link 1024x768 */
7004 /* Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct) */
7005 /* Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
7006
7007 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7008 if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7009 tempbx = SiS_Pr->SiS_VDE - 1;
7010 tempcx = SiS_Pr->SiS_VT - 1;
7011 } else {
7012 tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7013 tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7014 }
7015 } else {
7016 tempbx = SiS_Pr->PanelYRes;
7017 tempcx = SiS_Pr->SiS_VT;
7018 tempax = 1;
7019 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7020 tempax = SiS_Pr->PanelYRes;
7021 /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c; */ /* 651+301C */
7022 if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7023 tempax = tempcx = 0;
7024 } else {
7025 tempax -= SiS_Pr->SiS_VDE;
7026 }
7027 tempax >>= 1;
7028 }
7029 tempcx -= tempax; /* lcdvdes */
7030 tempbx -= tempax; /* lcdvdee */
7031 }
7032
7033 /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7034
Linus Torvalds1da177e2005-04-16 15:20:36 -07007035 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */
7036 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */
7037
7038 temp = (tempbx >> 5) & 0x38;
7039 temp |= ((tempcx >> 8) & 0x07);
7040 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7041
7042 tempax = SiS_Pr->SiS_VDE;
7043 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7044 tempax = SiS_Pr->PanelYRes;
7045 }
7046 tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7047 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7048 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7049 tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7050 }
7051 }
7052
7053 tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7054 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7055 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7056 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7057 tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7058 if(tempax % 4) { tempax >>= 2; tempax++; }
7059 else { tempax >>= 2; }
7060 tempbx -= (tempax - 1);
7061 } else {
7062 tempbx -= 10;
7063 if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7064 }
7065 }
7066 }
7067 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7068 tempbx++;
7069 if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7070 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7071 tempbx = 770;
7072 tempcx = 3;
7073 }
7074 }
7075 }
7076
7077 /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7078
7079 if(SiS_Pr->UseCustomMode) {
7080 tempbx = SiS_Pr->CVSyncStart;
7081 }
7082
Linus Torvalds1da177e2005-04-16 15:20:36 -07007083 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */
7084
7085 temp = (tempbx >> 4) & 0xF0;
7086 tempbx += (tempcx + 1);
7087 temp |= (tempbx & 0x0F);
7088
7089 if(SiS_Pr->UseCustomMode) {
7090 temp &= 0xf0;
7091 temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7092 }
7093
Linus Torvalds1da177e2005-04-16 15:20:36 -07007094 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7095
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007096#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007097 SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007098#endif
7099
7100 bridgeoffset = 7;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007101 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) bridgeoffset += 2;
7102 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
7103 if(SiS_IsDualLink(SiS_Pr)) bridgeoffset++;
7104 else if(SiS_Pr->SiS_VBType & VB_SIS302LV) bridgeoffset++; /* OK for Asus A4L 1280x800 */
7105 /* Higher bridgeoffset shifts to the LEFT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007106
7107 temp = 0;
7108 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7109 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007110 temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7111 if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007112 }
7113 }
7114 temp += bridgeoffset;
7115 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp); /* lcdhdes */
7116 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7117
7118 tempcx = SiS_Pr->SiS_HT;
7119 tempax = tempbx = SiS_Pr->SiS_HDE;
7120 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7121 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7122 tempax = SiS_Pr->PanelXRes;
7123 tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7124 }
7125 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007126 if(SiS_IsDualLink(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007127 tempcx >>= 1;
7128 tempbx >>= 1;
7129 tempax >>= 1;
7130 }
7131
Linus Torvalds1da177e2005-04-16 15:20:36 -07007132 tempbx += bridgeoffset;
7133
7134 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx); /* lcdhdee */
7135 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7136
7137 tempcx = (tempcx - tempax) >> 2;
7138
7139 tempbx += tempcx;
7140 push2 = tempbx;
7141
7142 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7143 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7144 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7145 if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7146 }
7147 }
7148 }
7149
7150 if(SiS_Pr->UseCustomMode) {
7151 tempbx = SiS_Pr->CHSyncStart;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007152 if(modeflag & HalfDCLK) tempbx <<= 1;
7153 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007154 tempbx += bridgeoffset;
7155 }
7156
Linus Torvalds1da177e2005-04-16 15:20:36 -07007157 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */
7158 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7159
7160 tempbx = push2;
7161
7162 tempcx <<= 1;
7163 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7164 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7165 }
7166 tempbx += tempcx;
7167
7168 if(SiS_Pr->UseCustomMode) {
7169 tempbx = SiS_Pr->CHSyncEnd;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007170 if(modeflag & HalfDCLK) tempbx <<= 1;
7171 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007172 tempbx += bridgeoffset;
7173 }
7174
Linus Torvalds1da177e2005-04-16 15:20:36 -07007175 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */
7176
7177 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7178
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007179#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007180 SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007181#endif
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007182#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07007183 } /* CRT2-LCD from table */
7184#endif
7185}
7186
7187/*********************************************/
7188/* SET PART 3 REGISTER GROUP */
7189/*********************************************/
7190
7191static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007192SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007193{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007194 unsigned short i;
7195 const unsigned char *tempdi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007196
7197 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7198
7199#ifndef SIS_CP
7200 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7201#else
7202 SIS_CP_INIT301_CP
7203#endif
7204
7205 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7206 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7207 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7208 } else {
7209 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7210 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7211 }
7212
7213 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7214 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7215 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7216 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7217 }
7218
7219 tempdi = NULL;
7220 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7221 tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7222 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7223 tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7224 }
7225 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7226 if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7227 tempdi = SiS_HiTVGroup3_1;
7228 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7229 }
7230 }
7231 if(tempdi) {
7232 for(i=0; i<=0x3E; i++) {
7233 SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7234 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007235 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007236 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7237 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7238 }
7239 }
7240 }
7241
7242#ifdef SIS_CP
7243 SIS_CP_INIT301_CP2
7244#endif
7245}
7246
7247/*********************************************/
7248/* SET PART 4 REGISTER GROUP */
7249/*********************************************/
7250
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007251#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007252#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07007253static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007254SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007255{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007256 unsigned short temp, temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007257
7258 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7259 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007260 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007261 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7262 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7263 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007264 temp = (unsigned short)((int)(temp) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007265 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7266 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7267 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007268 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007269 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7270 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7271}
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007272#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007273
7274static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007275SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007276{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007277 unsigned short temp, temp1, resinfo = 0;
7278 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007279
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007280 if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007281 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7282
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007283 if(SiS_Pr->ChipType >= XGI_20) return;
7284
7285 if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
7286 if(!(ROMAddr[0x61] & 0x04)) return;
7287 }
7288
Linus Torvalds1da177e2005-04-16 15:20:36 -07007289 if(ModeNo > 0x13) {
7290 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7291 }
7292
7293 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7294 temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7295 if(!(temp & 0x01)) {
7296 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7297 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007298 if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007299 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7300 }
7301 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7302 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp = 0x0000;
7303 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7304 else if(SiS_Pr->SiS_TVMode & TVSetHiVision) temp = 0x0400;
7305 else temp = 0x0402;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007306 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007307 temp1 = 0;
7308 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7309 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7310 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7311 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007312 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7313 if(ModeNo > 0x13) {
7314 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
7315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007316 } else {
7317 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7318 if(temp1 == 0x01) temp |= 0x01;
7319 if(temp1 == 0x03) temp |= 0x04; /* ? why not 0x10? */
7320 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007321 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7322 if(ModeNo > 0x13) {
7323 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7324 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007325 }
7326
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007327#if 0
7328 if(SiS_Pr->ChipType >= SIS_661) { /* ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007329 if(SiS_Pr->SiS_TVMode & TVAspect43) {
7330 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7331 if(resinfo == SIS_RI_1024x768) {
7332 SiS_ShiftXPos(SiS_Pr, 97);
7333 } else {
7334 SiS_ShiftXPos(SiS_Pr, 111);
7335 }
7336 } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7337 SiS_ShiftXPos(SiS_Pr, 136);
7338 }
7339 }
7340 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007341#endif
7342
Linus Torvalds1da177e2005-04-16 15:20:36 -07007343 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007344
Linus Torvalds1da177e2005-04-16 15:20:36 -07007345}
7346#endif
7347
7348static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007349SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7350 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007351{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007352 unsigned short vclkindex, temp, reg1, reg2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007353
7354 if(SiS_Pr->UseCustomMode) {
7355 reg1 = SiS_Pr->CSR2B;
7356 reg2 = SiS_Pr->CSR2C;
7357 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007358 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007359 reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7360 reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7361 }
7362
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007363 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7364 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007365 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7366 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7367 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7368 } else {
7369 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7370 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7371 }
7372 } else {
7373 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7374 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7375 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7376 }
7377 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7378 temp = 0x08;
7379 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7380 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7381}
7382
7383static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007384SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007385{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007386 if(SiS_Pr->ChipType >= SIS_315H) {
7387 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
7388 if((SiS_CRT2IsLCD(SiS_Pr)) ||
7389 (SiS_IsVAMode(SiS_Pr))) {
7390 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
7391 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7392 } else {
7393 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7394 }
7395 }
7396 }
7397 }
7398 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
7399 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7400#ifdef SET_EMI
7401 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7402#endif
7403 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7404 }
7405}
7406
7407static void
7408SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7409 unsigned short RefreshRateTableIndex)
7410{
7411 unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
7412 unsigned int tempebx, tempeax, templong;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007413
7414 if(ModeNo <= 0x13) {
7415 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7416 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7417 } else if(SiS_Pr->UseCustomMode) {
7418 modeflag = SiS_Pr->CModeFlag;
7419 resinfo = 0;
7420 } else {
7421 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7422 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7423 }
7424
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007425 if(SiS_Pr->ChipType >= SIS_315H) {
7426 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7427 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7428 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007429 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007430 }
7431 }
7432
7433 if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
7434 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7435 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
7436 }
7437 }
7438
7439 if(SiS_Pr->ChipType >= SIS_315H) {
7440 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7441 SiS_SetDualLinkEtc(SiS_Pr);
7442 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007443 }
7444 }
7445
7446 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7447
7448 tempbx = SiS_Pr->SiS_RVBHCMAX;
7449 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7450
7451 temp = (tempbx >> 1) & 0x80;
7452
7453 tempcx = SiS_Pr->SiS_VGAHT - 1;
7454 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7455
7456 temp |= ((tempcx >> 5) & 0x78);
7457
7458 tempcx = SiS_Pr->SiS_VGAVT - 1;
7459 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7460 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7461
7462 temp |= ((tempcx >> 8) & 0x07);
7463 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7464
7465 tempbx = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007466 if(modeflag & HalfDCLK) tempbx >>= 1;
7467 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007468
7469 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7470 temp = 0;
7471 if(tempbx > 800) temp = 0x60;
7472 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7473 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007474 if(tempbx > 1024) temp = 0xC0;
7475 else if(tempbx >= 960) temp = 0xA0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007476 } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7477 temp = 0;
7478 if(tempbx >= 1280) temp = 0x40;
7479 else if(tempbx >= 1024) temp = 0x20;
7480 } else {
7481 temp = 0x80;
7482 if(tempbx >= 1024) temp = 0xA0;
7483 }
7484
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007485 temp |= SiS_Pr->Init_P4_0E;
7486
Linus Torvalds1da177e2005-04-16 15:20:36 -07007487 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007488 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
7489 temp &= 0xf0;
7490 temp |= 0x0A;
7491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007492 }
7493
7494 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7495
7496 tempeax = SiS_Pr->SiS_VGAVDE;
7497 tempebx = SiS_Pr->SiS_VDE;
7498 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7499 if(!(temp & 0xE0)) tempebx >>=1;
7500 }
7501
7502 tempcx = SiS_Pr->SiS_RVBHRS;
7503 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7504 tempcx >>= 8;
7505 tempcx |= 0x40;
7506
7507 if(tempeax <= tempebx) {
7508 tempcx ^= 0x40;
7509 } else {
7510 tempeax -= tempebx;
7511 }
7512
7513 tempeax *= (256 * 1024);
7514 templong = tempeax % tempebx;
7515 tempeax /= tempebx;
7516 if(templong) tempeax++;
7517
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007518 temp = (unsigned short)(tempeax & 0x000000FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007519 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007520 temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007521 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007522 temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007523 temp |= (tempcx & 0x4F);
7524 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7525
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007526 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007527
7528 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7529
7530 /* Calc Linebuffer max address and set/clear decimode */
7531 tempbx = 0;
7532 if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7533 tempax = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007534 if(modeflag & HalfDCLK) tempax >>= 1;
7535 if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007536 if(tempax > 800) {
7537 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7538 tempax -= 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007539 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007540 tempbx = 0x08;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007541 if(tempax == 960) tempax *= 25; /* Correct */
7542 else if(tempax == 1024) tempax *= 25;
7543 else tempax *= 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007544 temp = tempax % 32;
7545 tempax /= 32;
7546 if(temp) tempax++;
7547 tempax++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007548 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7549 if(resinfo == SIS_RI_1024x768 ||
7550 resinfo == SIS_RI_1024x576 ||
7551 resinfo == SIS_RI_1280x1024 ||
7552 resinfo == SIS_RI_1280x720) {
7553 /* Otherwise white line or garbage at right edge */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007554 tempax = (tempax & 0xff00) | 0x20;
7555 }
7556 }
7557 }
7558 }
7559 tempax--;
7560 temp = ((tempax >> 4) & 0x30) | tempbx;
7561 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7562 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7563
7564 temp = 0x0036; tempbx = 0xD0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007565 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007566 temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7567 }
7568 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7569 if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7570 temp |= 0x01;
7571 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7572 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7573 temp &= ~0x01;
7574 }
7575 }
7576 }
7577 }
7578 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7579
7580 tempbx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007581 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007582 tempbx -= 2;
7583 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7584 temp = (tempbx >> 5) & 0x38;
7585 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7586
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007587 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007588 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7589 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7590 /* LCD-too-dark-error-source, see FinalizeLCD() */
7591 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007592 }
7593
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007594 SiS_SetDualLinkEtc(SiS_Pr);
7595
Linus Torvalds1da177e2005-04-16 15:20:36 -07007596 } /* 301B */
7597
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007598 SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007599}
7600
7601/*********************************************/
7602/* SET PART 5 REGISTER GROUP */
7603/*********************************************/
7604
7605static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007606SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007607{
7608
7609 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7610
7611 if(SiS_Pr->SiS_ModeType == ModeVGA) {
7612 if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7613 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007614 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007615 }
7616 }
7617}
7618
7619/*********************************************/
7620/* MODIFY CRT1 GROUP FOR SLAVE MODE */
7621/*********************************************/
7622
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007623static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007624SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7625 unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
7626 unsigned short *DisplayType)
7627 {
7628 unsigned short modeflag = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007629 bool checkhd = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007630
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007631 /* Pass 1:1 not supported here */
7632
7633 if(ModeNo <= 0x13) {
7634 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7635 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7636 } else {
7637 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7638 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7639 }
7640
7641 (*ResIndex) &= 0x3F;
7642
7643 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7644
7645 (*DisplayType) = 80;
7646 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
7647 (*DisplayType) = 82;
7648 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7649 if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
7650 }
7651 }
7652 if((*DisplayType) != 84) {
7653 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
7654 }
7655
7656 } else {
7657
7658 (*DisplayType = 0);
7659 switch(SiS_Pr->SiS_LCDResInfo) {
7660 case Panel_320x240_1: (*DisplayType) = 50;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007661 checkhd = false;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007662 break;
7663 case Panel_320x240_2: (*DisplayType) = 14;
7664 break;
7665 case Panel_320x240_3: (*DisplayType) = 18;
7666 break;
7667 case Panel_640x480: (*DisplayType) = 10;
7668 break;
7669 case Panel_1024x600: (*DisplayType) = 26;
7670 break;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007671 default: return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007672 }
7673
7674 if(checkhd) {
7675 if(modeflag & HalfDCLK) (*DisplayType)++;
7676 }
7677
7678 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
7679 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
7680 }
7681
7682 }
7683
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007684 return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007685}
7686
7687static void
7688SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7689 unsigned short RefreshRateTableIndex)
7690{
7691 unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
7692 const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
7693 static const unsigned short CRIdx[] = {
7694 0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
7695 0x07, 0x10, 0x11, 0x15, 0x16
7696 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07007697
7698 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
7699 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007700 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
7701 (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
Linus Torvalds1da177e2005-04-16 15:20:36 -07007702 return;
7703
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007704 if(SiS_Pr->SiS_IF_DEF_LVDS) {
7705 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7706 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7707 }
7708 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
7709 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7710 } else return;
7711
7712 if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
7713
7714 if(SiS_Pr->ChipType < SIS_315H) {
7715 if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
7716 }
7717
Linus Torvalds1da177e2005-04-16 15:20:36 -07007718 if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7719 &ResIndex, &DisplayType))) {
7720 return;
7721 }
7722
Linus Torvalds1da177e2005-04-16 15:20:36 -07007723 switch(DisplayType) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007724 case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1; break; /* xSTN */
7725 case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2; break; /* xSTN */
7726 case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H; break; /* xSTN */
7727 case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3; break; /* xSTN */
7728 case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H; break; /* xSTN */
7729 case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
7730 case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
7731#if 0 /* Works better with calculated numbers */
7732 case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break;
7733 case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break;
7734 case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break;
7735 case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break;
7736#endif
7737 case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break;
7738 case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break;
7739 case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break;
7740 case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
7741 case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007742 }
7743
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007744 if(LVDSCRT1Ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007745
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007746 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007747
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007748 for(i = 0; i <= 10; i++) {
7749 tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
7750 SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
7751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007752
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007753 for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
7754 tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
7755 SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
7756 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007757
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007758 tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
7759 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
7760
7761 if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7762 else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7763
7764 tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
7765 if(modeflag & DoubleScanMode) tempah |= 0x80;
7766 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
7767
7768 } else {
7769
7770 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
7771
7772 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007773}
7774
7775/*********************************************/
7776/* SET CRT2 ECLK */
7777/*********************************************/
7778
7779static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007780SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7781 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007782{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007783 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
7784 unsigned short clkbase, vclkindex = 0;
7785 unsigned char sr2b, sr2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007786
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007787 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7788 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
7789 if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
7790 RefreshRateTableIndex--;
7791 }
7792 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7793 RefreshRateTableIndex);
7794 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007795 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007796 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7797 RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007798 }
7799
7800 sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
7801 sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
7802
7803 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
7804 if(SiS_Pr->SiS_UseROM) {
7805 if(ROMAddr[0x220] & 0x01) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007806 sr2b = ROMAddr[0x227];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007807 sr2c = ROMAddr[0x228];
7808 }
7809 }
7810 }
7811
7812 clkbase = 0x02B;
7813 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7814 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007815 clkbase += 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007816 }
7817 }
7818
7819 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
7820 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7821 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7822 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
7823 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7824 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7825 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
7826 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7827 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7828}
7829
7830/*********************************************/
7831/* SET UP CHRONTEL CHIPS */
7832/*********************************************/
7833
7834static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007835SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7836 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007837{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007838 unsigned short TVType, resindex;
7839 const struct SiS_CHTVRegData *CHTVRegData = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007840
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007841 if(ModeNo <= 0x13)
7842 resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7843 else
7844 resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007845
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007846 resindex &= 0x3F;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007847
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007848 TVType = 0;
7849 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7850 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7851 TVType += 2;
7852 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7853 if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
7854 }
7855 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7856 TVType = 4;
7857 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7858 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
7859 TVType = 6;
7860 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7861 }
7862 }
7863
7864 switch(TVType) {
7865 case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
7866 case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
7867 case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break;
7868 case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
7869 case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
7870 case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
7871 case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
7872 case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
7873 case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
7874 default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
7875 }
7876
7877
7878 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007879
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007880#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07007881
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007882 /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007883
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007884 /* We don't support modes >800x600 */
7885 if (resindex > 5) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007886
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007887 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7888 SiS_SetCH700x(SiS_Pr,0x04,0x43); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
7889 SiS_SetCH700x(SiS_Pr,0x09,0x69); /* Black level for PAL (105)*/
7890 } else {
7891 SiS_SetCH700x(SiS_Pr,0x04,0x03); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
7892 SiS_SetCH700x(SiS_Pr,0x09,0x71); /* Black level for NTSC (113)*/
7893 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007894
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007895 SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]); /* Mode register */
7896 SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]); /* Start active video register */
7897 SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]); /* Position overflow register */
7898 SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]); /* Horiz Position register */
7899 SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]); /* Vertical Position register */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007900
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007901 /* Set minimum flicker filter for Luma channel (SR1-0=00),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007902 minimum text enhancement (S3-2=10),
7903 maximum flicker filter for Chroma channel (S5-4=10)
7904 =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007905 */
7906 SiS_SetCH700x(SiS_Pr,0x01,0x28);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007907
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007908 /* Set video bandwidth
Adrian Bunk9aaeded2006-06-30 18:19:55 +02007909 High bandwidth Luma composite video filter(S0=1)
7910 low bandwidth Luma S-video filter (S2-1=00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007911 disable peak filter in S-video channel (S3=0)
7912 high bandwidth Chroma Filter (S5-4=11)
7913 =00110001=0x31
Linus Torvalds1da177e2005-04-16 15:20:36 -07007914 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007915 SiS_SetCH700x(SiS_Pr,0x03,0xb1); /* old: 3103 */
7916
7917 /* Register 0x3D does not exist in non-macrovision register map
7918 (Maybe this is a macrovision register?)
7919 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007920#ifndef SIS_CP
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007921 SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007922#endif
7923
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007924 /* Register 0x10 only contains 1 writable bit (S0) for sensing,
7925 all other bits a read-only. Macrovision?
7926 */
7927 SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007928
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007929 /* Register 0x11 only contains 3 writable bits (S0-S2) for
7930 contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
7931 */
7932 SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007933
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007934 /* Clear DSEN
7935 */
7936 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007937
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007938 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */
7939 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
7940 if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */
7941 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7942 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on, no need to set FSCI */
7943 } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */
7944 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */
7945 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
7946 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
7947 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
7948 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
7949 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
7950 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
7951 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
7952 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF); /* Loop filter on for mode 23 */
7953 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); /* ACIV off, need to set FSCI */
7954 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007955 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007956 if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */
7957 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7958 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7959 } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */
7960#if 0
7961 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
7962 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0); /* FSCI for mode 24 is 428,554,851 */
7963 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0); /* 198b3a63 */
7964 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
7965 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
7966 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
7967 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
7968 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
7969 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off for mode 24 */
7970 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); * ACIV off, need to set FSCI */
7971#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */
7972 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7973 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7974 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007975 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007976 } else { /* ---- PAL ---- */
7977 /* We don't play around with FSCI in PAL mode */
7978 if(resindex == 0x04) {
7979 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7980 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
7981 } else {
7982 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7983 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
7984 }
7985 }
7986
Linus Torvalds1da177e2005-04-16 15:20:36 -07007987#endif /* 300 */
7988
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007989 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007990
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007991 /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007992
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007993#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07007994
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007995 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007996
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007997 /* We don't support modes >1024x768 */
7998 if (resindex > 6) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007999
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008000 temp = CHTVRegData[resindex].Reg[0];
8001 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
8002 SiS_SetCH701x(SiS_Pr,0x00,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008003
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008004 SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
8005 SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
8006 SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
8007 SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
8008 SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
8009 SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008010
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008011 temp = CHTVRegData[resindex].Reg[7];
8012 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
8013 SiS_SetCH701x(SiS_Pr,0x07,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008014
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008015 SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
8016 SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
8017 SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
8018 SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
8019 SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
8020 SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
8021 SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
8022 SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008023
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008024 temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8025 /* D1 should be set for PAL, PAL-N and NTSC-J,
8026 but I won't do that for PAL unless somebody
8027 tells me to do so. Since the BIOS uses
8028 non-default CIV values and blacklevels,
8029 this might be compensated anyway.
8030 */
8031 if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8032 SiS_SetCH701x(SiS_Pr,0x21,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008033
8034#endif /* 315 */
8035
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008036 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008037
8038#ifdef SIS_CP
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008039 SIS_CP_INIT301_CP3
Linus Torvalds1da177e2005-04-16 15:20:36 -07008040#endif
8041
8042}
8043
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008044#ifdef CONFIG_FB_SIS_315 /* ----------- 315 series only ---------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008045
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008046void
8047SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008048{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008049 unsigned short temp;
8050
8051 /* Enable Chrontel 7019 LCD panel backlight */
8052 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8053 if(SiS_Pr->ChipType == SIS_740) {
8054 SiS_SetCH701x(SiS_Pr,0x66,0x65);
8055 } else {
8056 temp = SiS_GetCH701x(SiS_Pr,0x66);
8057 temp |= 0x20;
8058 SiS_SetCH701x(SiS_Pr,0x66,temp);
8059 }
8060 }
8061}
8062
8063void
8064SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
8065{
8066 unsigned short temp;
8067
8068 /* Disable Chrontel 7019 LCD panel backlight */
8069 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8070 temp = SiS_GetCH701x(SiS_Pr,0x66);
8071 temp &= 0xDF;
8072 SiS_SetCH701x(SiS_Pr,0x66,temp);
8073 }
8074}
8075
8076static void
8077SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
8078{
8079 static const unsigned char regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8080 static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8081 static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8082 static const unsigned char asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8083 static const unsigned char asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8084 static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8085 static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8086 const unsigned char *tableptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008087 int i;
8088
8089 /* Set up Power up/down timing */
8090
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008091 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008092 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008093 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8094 else tableptr = table1024_740;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008095 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008096 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008097 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8098 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8099 else tableptr = table1400_740;
8100 } else return;
8101 } else {
8102 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008103 tableptr = table1024_650;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008104 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008105 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008106 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008107 tableptr = table1400_650;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008108 } else return;
8109 }
8110
8111 for(i=0; i<5; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008112 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008113 }
8114}
8115
8116static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008117SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008118{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008119 const unsigned char *tableptr = NULL;
8120 unsigned short tempbh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008121 int i;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008122 static const unsigned char regtable[] = {
8123 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8124 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
8125 };
8126 static const unsigned char table1024_740[] = {
8127 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8128 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
8129 };
8130 static const unsigned char table1280_740[] = {
8131 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8132 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8133 };
8134 static const unsigned char table1400_740[] = {
8135 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8136 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8137 };
8138 static const unsigned char table1600_740[] = {
8139 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8140 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
8141 };
8142 static const unsigned char table1024_650[] = {
8143 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8144 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
8145 };
8146 static const unsigned char table1280_650[] = {
8147 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8148 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
8149 };
8150 static const unsigned char table1400_650[] = {
8151 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8152 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
8153 };
8154 static const unsigned char table1600_650[] = {
8155 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8156 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
8157 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07008158
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008159 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008160 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_740;
8161 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8162 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8163 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8164 else return;
8165 } else {
8166 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_650;
8167 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8168 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8169 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8170 else return;
8171 }
8172
8173 tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8174 if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8175 tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8176 if(tempbh == 0xc8) {
8177 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8178 } else if(tempbh == 0xdb) {
8179 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8180 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8181 } else if(tempbh == 0xde) {
8182 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8183 }
8184 }
8185
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008186 if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
8187 else tempbh = 0x0c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008188
8189 for(i = 0; i < tempbh; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008190 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008191 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008192 SiS_ChrontelPowerSequencing(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008193 tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8194 tempbh |= 0xc0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008195 SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008196
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008197 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008198 tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8199 tempbh &= 0xfb;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008200 SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008201 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8202 tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8203 tempbh |= 0x40;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008204 SiS_SetCH701x(SiS_Pr,0x64,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008205 tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8206 tempbh &= 0x3f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008207 SiS_SetCH701x(SiS_Pr,0x03,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008208 }
8209}
8210
8211static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008212SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008213{
8214 unsigned char temp, temp1;
8215
8216 temp1 = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008217 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008218 temp = SiS_GetCH701x(SiS_Pr,0x47);
8219 temp &= 0x7f; /* Use external VSYNC */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008220 SiS_SetCH701x(SiS_Pr,0x47,temp);
8221 SiS_LongDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008222 temp = SiS_GetCH701x(SiS_Pr,0x47);
8223 temp |= 0x80; /* Use internal VSYNC */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008224 SiS_SetCH701x(SiS_Pr,0x47,temp);
8225 SiS_SetCH701x(SiS_Pr,0x49,temp1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008226}
8227
8228static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008229SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008230{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008231 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008232
8233 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008234 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008235 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8236 temp |= 0x04; /* Invert XCLK phase */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008237 SiS_SetCH701x(SiS_Pr,0x1c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008238 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008239 if(SiS_IsYPbPr(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008240 temp = SiS_GetCH701x(SiS_Pr,0x01);
8241 temp &= 0x3f;
8242 temp |= 0x80; /* Enable YPrPb (HDTV) */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008243 SiS_SetCH701x(SiS_Pr,0x01,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008244 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008245 if(SiS_IsChScart(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008246 temp = SiS_GetCH701x(SiS_Pr,0x01);
8247 temp &= 0x3f;
8248 temp |= 0xc0; /* Enable SCART + CVBS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008249 SiS_SetCH701x(SiS_Pr,0x01,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008250 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008251 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008252 SiS_ChrontelResetVSync(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008253 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008254 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008255 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008256 temp = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008257 if(SiS_IsYPbPr(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008258 temp = SiS_GetCH701x(SiS_Pr,0x73);
8259 temp |= 0x60;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008260 SiS_SetCH701x(SiS_Pr,0x73,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008261 }
8262 temp = SiS_GetCH701x(SiS_Pr,0x47);
8263 temp &= 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008264 SiS_SetCH701x(SiS_Pr,0x47,temp);
8265 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008266 temp = SiS_GetCH701x(SiS_Pr,0x47);
8267 temp |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008268 SiS_SetCH701x(SiS_Pr,0x47,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008269 }
8270 }
8271}
8272
8273static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008274SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008275{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008276 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008277
8278 /* Complete power down of LVDS */
8279 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008280 if(SiS_Pr->ChipType == SIS_740) {
8281 SiS_LongDelay(SiS_Pr, 1);
8282 SiS_GenericDelay(SiS_Pr, 5887);
8283 SiS_SetCH701x(SiS_Pr,0x76,0xac);
8284 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008285 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008286 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008287 temp = SiS_GetCH701x(SiS_Pr,0x76);
8288 temp &= 0xfc;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008289 SiS_SetCH701x(SiS_Pr,0x76,temp);
8290 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008291 }
8292 }
8293}
8294
8295static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008296SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008297{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008298 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008299
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008300 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008301
8302 temp = SiS_GetCH701x(SiS_Pr,0x4a); /* Version ID */
8303 temp &= 0x01;
8304 if(!temp) {
8305
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008306 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008307 temp = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008308 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008310
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008311 /* Reset Chrontel 7019 datapath */
8312 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8313 SiS_LongDelay(SiS_Pr, 1);
8314 SiS_SetCH701x(SiS_Pr,0x48,0x18);
8315
8316 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008317 SiS_ChrontelResetVSync(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008318 SiS_SetCH701x(SiS_Pr,0x49,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008319 }
8320
8321 } else {
8322
8323 /* Clear/set/clear GPIO */
8324 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8325 temp &= 0xef;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008326 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008327 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8328 temp |= 0x10;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008329 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008330 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8331 temp &= 0xef;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008332 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008333 temp = SiS_GetCH701x(SiS_Pr,0x61);
8334 if(!temp) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008335 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008336 }
8337 }
8338
8339 } else { /* 650 */
8340 /* Reset Chrontel 7019 datapath */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008341 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8342 SiS_LongDelay(SiS_Pr, 1);
8343 SiS_SetCH701x(SiS_Pr,0x48,0x18);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008344 }
8345}
8346
8347static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008348SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008349{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008350 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008351
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008352 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008353
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008354 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008355 SiS_ChrontelResetVSync(SiS_Pr);
8356 }
8357
8358 } else {
8359
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008360 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* Power up LVDS block */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008361 temp = SiS_GetCH701x(SiS_Pr,0x49);
8362 temp &= 1;
8363 if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */
8364 temp = SiS_GetCH701x(SiS_Pr,0x47);
8365 temp &= 0x70;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008366 SiS_SetCH701x(SiS_Pr,0x47,temp); /* enable VSYNC */
8367 SiS_LongDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008368 temp = SiS_GetCH701x(SiS_Pr,0x47);
8369 temp |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008370 SiS_SetCH701x(SiS_Pr,0x47,temp); /* disable VSYNC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008371 }
8372
8373 }
8374}
8375
8376static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008377SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008378{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008379 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008380
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008381 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008382
8383 temp = SiS_GetCH701x(SiS_Pr,0x61);
8384 if(temp < 1) {
8385 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008386 SiS_SetCH701x(SiS_Pr,0x61,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008387 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008388 SiS_SetCH701x(SiS_Pr,0x66,0x45); /* Panel power on */
8389 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on */
8390 SiS_LongDelay(SiS_Pr, 1);
8391 SiS_GenericDelay(SiS_Pr, 5887);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008392
8393 } else { /* 650 */
8394
8395 temp1 = 0;
8396 temp = SiS_GetCH701x(SiS_Pr,0x61);
8397 if(temp < 2) {
8398 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008399 SiS_SetCH701x(SiS_Pr,0x61,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008400 temp1 = 1;
8401 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008402 SiS_SetCH701x(SiS_Pr,0x76,0xac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008403 temp = SiS_GetCH701x(SiS_Pr,0x66);
8404 temp |= 0x5f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008405 SiS_SetCH701x(SiS_Pr,0x66,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008406 if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008407 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8408 SiS_GenericDelay(SiS_Pr, 1023);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008409 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008410 SiS_GenericDelay(SiS_Pr, 767);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008411 }
8412 } else {
8413 if(!temp1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008414 SiS_GenericDelay(SiS_Pr, 767);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008415 }
8416 temp = SiS_GetCH701x(SiS_Pr,0x76);
8417 temp |= 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008418 SiS_SetCH701x(SiS_Pr,0x76,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008419 temp = SiS_GetCH701x(SiS_Pr,0x66);
8420 temp &= 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008421 SiS_SetCH701x(SiS_Pr,0x66,temp);
8422 SiS_LongDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008423
8424 }
8425}
8426
8427static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008428SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008429{
Adrian Bunke4ccde32006-03-27 01:17:41 -08008430 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008431
8432 SiS_LongDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008433
8434 do {
8435 temp = SiS_GetCH701x(SiS_Pr,0x66);
8436 temp &= 0x04; /* PLL stable? -> bail out */
8437 if(temp == 0x04) break;
8438
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008439 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008440 /* Power down LVDS output, PLL normal operation */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008441 SiS_SetCH701x(SiS_Pr,0x76,0xac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008442 }
8443
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008444 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008445
Linus Torvalds1da177e2005-04-16 15:20:36 -07008446 temp = SiS_GetCH701x(SiS_Pr,0x76);
8447 temp &= 0xfb; /* Reset PLL */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008448 SiS_SetCH701x(SiS_Pr,0x76,temp);
8449 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008450 temp = SiS_GetCH701x(SiS_Pr,0x76);
8451 temp |= 0x04; /* PLL normal operation */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008452 SiS_SetCH701x(SiS_Pr,0x76,temp);
8453 if(SiS_Pr->ChipType == SIS_740) {
8454 SiS_SetCH701x(SiS_Pr,0x78,0xe0); /* PLL loop filter */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008455 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008456 SiS_SetCH701x(SiS_Pr,0x78,0x60);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008457 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008458 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008459 } while(0);
8460
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008461 SiS_SetCH701x(SiS_Pr,0x77,0x00); /* MV? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008462}
8463
8464static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008465SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008466{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008467 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008468
8469 temp = SiS_GetCH701x(SiS_Pr,0x03);
8470 temp |= 0x80; /* Set datapath 1 to TV */
8471 temp &= 0xbf; /* Set datapath 2 to LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008472 SiS_SetCH701x(SiS_Pr,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008473
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008474 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008475
8476 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8477 temp &= 0xfb; /* Normal XCLK phase */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008478 SiS_SetCH701x(SiS_Pr,0x1c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008479
8480 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8481
8482 temp = SiS_GetCH701x(SiS_Pr,0x64);
8483 temp |= 0x40; /* ? Bit not defined */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008484 SiS_SetCH701x(SiS_Pr,0x64,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008485
8486 temp = SiS_GetCH701x(SiS_Pr,0x03);
8487 temp &= 0x3f; /* D1 input to both LVDS and TV */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008488 SiS_SetCH701x(SiS_Pr,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008489
8490 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008491 SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008492 SiS_LongDelay(SiS_Pr, 1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008493 SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
8494 SiS_ChrontelResetDB(SiS_Pr);
8495 SiS_ChrontelDoSomething2(SiS_Pr);
8496 SiS_ChrontelDoSomething3(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008497 } else {
8498 temp = SiS_GetCH701x(SiS_Pr,0x66);
8499 if(temp != 0x45) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008500 SiS_ChrontelResetDB(SiS_Pr);
8501 SiS_ChrontelDoSomething2(SiS_Pr);
8502 SiS_ChrontelDoSomething3(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008503 }
8504 }
8505
8506 } else { /* 650 */
8507
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008508 SiS_ChrontelResetDB(SiS_Pr);
8509 SiS_ChrontelDoSomething2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008510 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008511 SiS_ChrontelDoSomething3(SiS_Pr,temp);
8512 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on, LVDS normal operation */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008513
8514 }
8515
8516}
8517#endif /* 315 series */
8518
8519/*********************************************/
8520/* MAIN: SET CRT2 REGISTER GROUP */
8521/*********************************************/
8522
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008523bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008524SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008525{
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008526#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008527 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008528#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008529 unsigned short ModeIdIndex, RefreshRateTableIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008530
8531 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8532
8533 if(!SiS_Pr->UseCustomMode) {
8534 SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8535 } else {
8536 ModeIdIndex = 0;
8537 }
8538
8539 /* Used for shifting CR33 */
8540 SiS_Pr->SiS_SelectCRT2Rate = 4;
8541
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008542 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008543
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008544 RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008545
8546 SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8547
8548 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008549 SiS_DisableBridge(SiS_Pr);
8550 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008551 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8552 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008553 SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008554 }
8555
8556 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008557 SiS_LockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008558 SiS_DisplayOn(SiS_Pr);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008559 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008560 }
8561
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008562 SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008563
8564 /* Set up Panel Link for LVDS and LCDA */
8565 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8566 if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8567 ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008568 ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
8569 SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008570 }
8571
Linus Torvalds1da177e2005-04-16 15:20:36 -07008572 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008573 SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008574 }
8575
8576 if(SiS_Pr->SiS_VBType & VB_SISVB) {
8577
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008578 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008579
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008580 SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008581#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008582 SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008583#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008584 SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
8585 SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008586#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008587 SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008588#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008589 SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008590
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008591 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008592
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008593 /* For 301BDH (Panel link initialization): */
8594 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8595
8596 if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8597 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8598 SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8599 }
8600 }
8601 SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8602 }
8603 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008604
8605 } else {
8606
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008607 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008608
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008609 SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008610
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008611 SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008612
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008613 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8614 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8615 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8616 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008617#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008618 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008619#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008620 }
8621 }
8622 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8623 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8624 }
8625 }
8626 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008627
8628 }
8629
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008630#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008631 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008632 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8633 if(SiS_Pr->SiS_UseOEM) {
8634 if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8635 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008636 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008637 }
8638 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008639 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008640 }
8641 }
8642 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008643 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008644 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008645 SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008646 }
8647 SiS_DisplayOn(SiS_Pr);
8648 }
8649 }
8650 }
8651#endif
8652
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008653#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008654 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008655 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008656 if(SiS_Pr->ChipType < SIS_661) {
8657 SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
8658 SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008659 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008660 SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008661 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008662 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008663 }
8664 }
8665#endif
8666
8667 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008668 SiS_EnableBridge(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008669 }
8670
8671 SiS_DisplayOn(SiS_Pr);
8672
8673 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8674 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8675 /* Disable LCD panel when using TV */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008676 SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008677 } else {
8678 /* Disable TV when using LCD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008679 SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008680 }
8681 }
8682
8683 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008684 SiS_LockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008685 }
8686
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008687 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008688}
8689
8690
8691/*********************************************/
8692/* ENABLE/DISABLE LCD BACKLIGHT (SIS) */
8693/*********************************************/
8694
8695void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008696SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008697{
8698 /* Switch on LCD backlight on SiS30xLV */
8699 SiS_DDC2Delay(SiS_Pr,0xff00);
8700 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
8701 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008702 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008703 }
8704 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
8705 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
8706 }
8707}
8708
8709void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008710SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008711{
8712 /* Switch off LCD backlight on SiS30xLV */
8713 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008714 SiS_DDC2Delay(SiS_Pr,0xff00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008715}
8716
8717/*********************************************/
8718/* DDC RELATED FUNCTIONS */
8719/*********************************************/
8720
8721static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008722SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008723{
8724 SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
8725 SiS_Pr->SiS_DDC_NClk = ~SiS_Pr->SiS_DDC_Clk;
8726 if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
8727 SiS_Pr->SiS_DDC_NData &= 0x0f;
8728 SiS_Pr->SiS_DDC_NClk &= 0x0f;
8729 }
8730}
8731
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008732#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008733static unsigned char *
8734SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008735{
8736 int i, j, num;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008737 unsigned short tempah,temp;
8738 unsigned char *mydataptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008739
8740 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8741 mydataptr = dataptr;
8742 num = *mydataptr++;
8743 if(!num) return mydataptr;
8744 if(i) {
8745 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008746 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008747 }
8748 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8749 tempah = SiS_Pr->SiS_DDC_DeviceAddr;
8750 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
8751 if(temp) continue; /* (ERROR: no ack) */
8752 tempah = *mydataptr++;
8753 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write register number */
8754 if(temp) continue; /* (ERROR: no ack) */
8755 for(j=0; j<num; j++) {
8756 tempah = *mydataptr++;
8757 temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
8758 if(temp) break;
8759 }
8760 if(temp) continue;
8761 if(SiS_SetStop(SiS_Pr)) continue;
8762 return mydataptr;
8763 }
8764 return NULL;
8765}
8766
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008767static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008768SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008769{
8770 SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */
8771 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008772 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8773 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008774 SiS_SetupDDCN(SiS_Pr);
8775
8776 SiS_SetSwitchDDC2(SiS_Pr);
8777
8778 while(*dataptr) {
8779 dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008780 if(!dataptr) return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008781 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008782 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008783}
8784#endif
8785
8786/* The Chrontel 700x is connected to the 630/730 via
8787 * the 630/730's DDC/I2C port.
8788 *
8789 * On 630(S)T chipset, the index changed from 0x11 to
8790 * 0x0a, possibly for working around the DDC problems
8791 */
8792
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008793static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008794SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008795{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008796 unsigned short temp, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008797
8798 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8799 if(i) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008800 SiS_SetStop(SiS_Pr);
8801 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008802 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008803 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8804 temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
8805 if(temp) continue; /* (ERROR: no ack) */
8806 temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor)); /* Write RAB (700x: set bit 7, see datasheet) */
8807 if(temp) continue; /* (ERROR: no ack) */
8808 temp = SiS_WriteDDC2Data(SiS_Pr, val); /* Write data */
8809 if(temp) continue; /* (ERROR: no ack) */
8810 if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008811 SiS_Pr->SiS_ChrontelInit = 1;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008812 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008813 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008814 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008815}
8816
Linus Torvalds1da177e2005-04-16 15:20:36 -07008817/* Write to Chrontel 700x */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008818void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008819SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008820{
8821 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
8822
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008823 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8824
Linus Torvalds1da177e2005-04-16 15:20:36 -07008825 if(!(SiS_Pr->SiS_ChrontelInit)) {
8826 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008827 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8828 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008829 SiS_SetupDDCN(SiS_Pr);
8830 }
8831
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008832 if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07008833 (!(SiS_Pr->SiS_ChrontelInit)) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008834 SiS_Pr->SiS_DDC_Index = 0x0a;
8835 SiS_Pr->SiS_DDC_Data = 0x80;
8836 SiS_Pr->SiS_DDC_Clk = 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008837 SiS_SetupDDCN(SiS_Pr);
8838
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008839 SiS_SetChReg(SiS_Pr, reg, val, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008840 }
8841}
8842
8843/* Write to Chrontel 701x */
8844/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
8845void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008846SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008847{
8848 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008849 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
8850 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008851 SiS_SetupDDCN(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008852 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
8853 SiS_SetChReg(SiS_Pr, reg, val, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008854}
8855
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008856static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008857void
8858SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008859{
8860 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008861 SiS_SetCH700x(SiS_Pr, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008862 else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008863 SiS_SetCH701x(SiS_Pr, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008864}
8865
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008866static unsigned short
8867SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008868{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008869 unsigned short tempah, temp, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008870
8871 for(i=0; i<20; i++) { /* Do 20 attempts to read */
8872 if(i) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008873 SiS_SetStop(SiS_Pr);
8874 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008875 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008876 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8877 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
8878 if(temp) continue; /* (ERROR: no ack) */
8879 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor); /* Write RAB (700x: | 0x80) */
8880 if(temp) continue; /* (ERROR: no ack) */
8881 if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
8882 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
8883 if(temp) continue; /* (ERROR: no ack) */
8884 tempah = SiS_ReadDDC2Data(SiS_Pr); /* Read byte */
8885 if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008886 SiS_Pr->SiS_ChrontelInit = 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008887 return tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008888 }
8889 return 0xFFFF;
8890}
8891
Linus Torvalds1da177e2005-04-16 15:20:36 -07008892/* Read from Chrontel 700x */
8893/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008894unsigned short
8895SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008896{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008897 unsigned short result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008898
8899 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
8900
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008901 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8902
Linus Torvalds1da177e2005-04-16 15:20:36 -07008903 if(!(SiS_Pr->SiS_ChrontelInit)) {
8904 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008905 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8906 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008907 SiS_SetupDDCN(SiS_Pr);
8908 }
8909
8910 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8911
8912 if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
8913 (!SiS_Pr->SiS_ChrontelInit) ) {
8914
8915 SiS_Pr->SiS_DDC_Index = 0x0a;
8916 SiS_Pr->SiS_DDC_Data = 0x80;
8917 SiS_Pr->SiS_DDC_Clk = 0x40;
8918 SiS_SetupDDCN(SiS_Pr);
8919
8920 result = SiS_GetChReg(SiS_Pr,0x80);
8921 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008922 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008923}
8924
8925/* Read from Chrontel 701x */
8926/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008927unsigned short
8928SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008929{
8930 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008931 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
8932 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008933 SiS_SetupDDCN(SiS_Pr);
8934 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
8935
8936 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8937
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008938 return SiS_GetChReg(SiS_Pr,0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008939}
8940
8941/* Read from Chrontel 70xx */
8942/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008943static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008944unsigned short
8945SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008946{
8947 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008948 return SiS_GetCH700x(SiS_Pr, tempbx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008949 else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008950 return SiS_GetCH701x(SiS_Pr, tempbx);
8951}
8952
8953void
8954SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
8955 unsigned char myor, unsigned short myand)
8956{
8957 unsigned short tempbl;
8958
8959 tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
8960 SiS_SetCH70xx(SiS_Pr, reg, tempbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008961}
8962
8963/* Our own DDC functions */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008964static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008965unsigned short
8966SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008967 unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008968 unsigned int VBFlags2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008969{
8970 unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
8971 unsigned char flag, cr32;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008972 unsigned short temp = 0, myadaptnum = adaptnum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008973
8974 if(adaptnum != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008975 if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
8976 if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
8977 }
8978
Linus Torvalds1da177e2005-04-16 15:20:36 -07008979 /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008980
Linus Torvalds1da177e2005-04-16 15:20:36 -07008981 SiS_Pr->SiS_ChrontelInit = 0; /* force re-detection! */
8982
8983 SiS_Pr->SiS_DDC_SecAddr = 0;
8984 SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
8985 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
8986 SiS_Pr->SiS_DDC_Index = 0x11;
8987 flag = 0xff;
8988
8989 cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
8990
8991#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008992 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008993 if(myadaptnum == 0) {
8994 if(!(cr32 & 0x20)) {
8995 myadaptnum = 2;
8996 if(!(cr32 & 0x10)) {
8997 myadaptnum = 1;
8998 if(!(cr32 & 0x08)) {
8999 myadaptnum = 0;
9000 }
9001 }
9002 }
9003 }
9004 }
9005#endif
9006
9007 if(VGAEngine == SIS_300_VGA) { /* 300 series */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009008
Linus Torvalds1da177e2005-04-16 15:20:36 -07009009 if(myadaptnum != 0) {
9010 flag = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009011 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009012 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9013 SiS_Pr->SiS_DDC_Index = 0x0f;
9014 }
9015 }
9016
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009017 if(!(VBFlags2 & VB2_301)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009018 if((cr32 & 0x80) && (checkcr32)) {
9019 if(myadaptnum >= 1) {
9020 if(!(cr32 & 0x08)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009021 myadaptnum = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009022 if(!(cr32 & 0x10)) return 0xFFFF;
9023 }
9024 }
9025 }
9026 }
9027
9028 temp = 4 - (myadaptnum * 2);
9029 if(flag) temp = 0;
9030
9031 } else { /* 315/330 series */
9032
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009033 /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009034
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009035 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009036 if(myadaptnum == 2) {
9037 myadaptnum = 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009038 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009039 }
9040
9041 if(myadaptnum == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009042 flag = 0;
9043 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009044 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9045 SiS_Pr->SiS_DDC_Index = 0x0f;
9046 }
9047 }
9048
9049 if((cr32 & 0x80) && (checkcr32)) {
9050 if(myadaptnum >= 1) {
9051 if(!(cr32 & 0x08)) {
9052 myadaptnum = 1;
9053 if(!(cr32 & 0x10)) return 0xFFFF;
9054 }
9055 }
9056 }
9057
9058 temp = myadaptnum;
9059 if(myadaptnum == 1) {
9060 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009061 if(VBFlags2 & VB2_LVDS) flag = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009062 }
9063
9064 if(flag) temp = 0;
9065 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009066
Linus Torvalds1da177e2005-04-16 15:20:36 -07009067 SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9068 SiS_Pr->SiS_DDC_Clk = 0x01 << temp;
9069
9070 SiS_SetupDDCN(SiS_Pr);
9071
Linus Torvalds1da177e2005-04-16 15:20:36 -07009072 return 0;
9073}
9074
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009075static unsigned short
9076SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009077{
9078 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9079 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009080 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009081 }
9082 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009083 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009084 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009085 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009086}
9087
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009088static unsigned short
9089SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009090{
9091 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9092 if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009093 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009094 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009095 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009096}
9097
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009098static unsigned short
9099SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009100{
9101 if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009102 if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
9103 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009104}
9105
9106static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009107SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009108{
9109 SiS_SetSCLKLow(SiS_Pr);
9110 if(yesno) {
9111 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009112 SiS_Pr->SiS_DDC_Index,
9113 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009114 SiS_Pr->SiS_DDC_Data);
9115 } else {
9116 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009117 SiS_Pr->SiS_DDC_Index,
9118 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009119 0);
9120 }
9121 SiS_SetSCLKHigh(SiS_Pr);
9122}
9123
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009124static unsigned short
9125SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009126{
9127 unsigned char mask, value;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009128 unsigned short temp, ret=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009129 bool failed = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009130
9131 SiS_SetSwitchDDC2(SiS_Pr);
9132 if(SiS_PrepareDDC(SiS_Pr)) {
9133 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009134 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009135 }
9136 mask = 0xf0;
9137 value = 0x20;
9138 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009139 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009140 SiS_SendACK(SiS_Pr, 0);
9141 if(temp == 0) {
9142 mask = 0xff;
9143 value = 0xff;
9144 } else {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009145 failed = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009146 ret = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009147 }
9148 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009149 if(!failed) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009150 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009151 SiS_SendACK(SiS_Pr, 1);
9152 temp &= mask;
9153 if(temp == value) ret = 0;
9154 else {
9155 ret = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009156 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9157 if(temp == 0x30) ret = 0;
9158 }
9159 }
9160 }
9161 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009162 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009163}
9164
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009165static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009166unsigned short
9167SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009168{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009169 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009170
9171 flag = 0x180;
9172 SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9173 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9174 SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9175 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9176 SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9177 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9178 if(!(flag & 0x1a)) flag = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009179 return flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009180}
9181
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009182static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009183unsigned short
9184SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009185{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009186 unsigned short flag, length, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009187 unsigned char chksum,gotcha;
9188
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009189 if(DDCdatatype > 4) return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009190
9191 flag = 0;
9192 SiS_SetSwitchDDC2(SiS_Pr);
9193 if(!(SiS_PrepareDDC(SiS_Pr))) {
9194 length = 127;
9195 if(DDCdatatype != 1) length = 255;
9196 chksum = 0;
9197 gotcha = 0;
9198 for(i=0; i<length; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009199 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009200 chksum += buffer[i];
9201 gotcha |= buffer[i];
9202 SiS_SendACK(SiS_Pr, 0);
9203 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009204 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009205 chksum += buffer[i];
9206 SiS_SendACK(SiS_Pr, 1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009207 if(gotcha) flag = (unsigned short)chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009208 else flag = 0xFFFF;
9209 } else {
9210 flag = 0xFFFF;
9211 }
9212 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009213 return flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009214}
9215
9216/* Our private DDC functions
9217
9218 It complies somewhat with the corresponding VESA function
9219 in arguments and return values.
9220
9221 Since this is probably called before the mode is changed,
9222 we use our pre-detected pSiS-values instead of SiS_Pr as
9223 regards chipset and video bridge type.
9224
9225 Arguments:
9226 adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9227 CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9228 LCDA is CRT1, but DDC is read from CRT2 port.
9229 DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9230 buffer: ptr to 256 data bytes which will be filled with read data.
9231
9232 Returns 0xFFFF if error, otherwise
9233 if DDCdatatype > 0: Returns 0 if reading OK (included a correct checksum)
9234 if DDCdatatype = 0: Returns supported DDC modes
9235
9236 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009237unsigned short
9238SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9239 unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
9240 unsigned int VBFlags2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009241{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009242 unsigned char sr1f, cr17=1;
9243 unsigned short result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009244
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009245 if(adaptnum > 2)
9246 return 0xFFFF;
9247
9248 if(DDCdatatype > 4)
9249 return 0xFFFF;
9250
9251 if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
9252 return 0xFFFF;
9253
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009254 if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009255 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009256
9257 sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9258 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9259 if(VGAEngine == SIS_300_VGA) {
9260 cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9261 if(!cr17) {
9262 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9263 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9264 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9265 }
9266 }
9267 if((sr1f) || (!cr17)) {
9268 SiS_WaitRetrace1(SiS_Pr);
9269 SiS_WaitRetrace1(SiS_Pr);
9270 SiS_WaitRetrace1(SiS_Pr);
9271 SiS_WaitRetrace1(SiS_Pr);
9272 }
9273
9274 if(DDCdatatype == 0) {
9275 result = SiS_ProbeDDC(SiS_Pr);
9276 } else {
9277 result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9278 if((!result) && (DDCdatatype == 1)) {
9279 if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9280 (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9281 (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9282 (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9283 (buffer[0x12] == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009284 if(!SiS_Pr->DDCPortMixup) {
9285 if(adaptnum == 1) {
9286 if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9287 } else {
9288 if(buffer[0x14] & 0x80) result = 0xFFFE;
9289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009290 }
9291 }
9292 }
9293 }
9294 SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9295 if(VGAEngine == SIS_300_VGA) {
9296 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9297 }
9298 return result;
9299}
9300
Linus Torvalds1da177e2005-04-16 15:20:36 -07009301/* Generic I2C functions for Chrontel & DDC --------- */
9302
9303static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009304SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009305{
9306 SiS_SetSCLKHigh(SiS_Pr);
9307 SiS_WaitRetrace1(SiS_Pr);
9308
9309 SiS_SetSCLKLow(SiS_Pr);
9310 SiS_WaitRetrace1(SiS_Pr);
9311}
9312
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009313unsigned short
9314SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009315{
9316 SiS_WaitRetrace1(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009317 return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009318}
9319
9320/* Set I2C start condition */
9321/* This is done by a SD high-to-low transition while SC is high */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009322static unsigned short
9323SiS_SetStart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009324{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009325 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009326 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009327 SiS_Pr->SiS_DDC_Index,
9328 SiS_Pr->SiS_DDC_NData,
9329 SiS_Pr->SiS_DDC_Data); /* SD->high */
9330 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009331 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009332 SiS_Pr->SiS_DDC_Index,
9333 SiS_Pr->SiS_DDC_NData,
9334 0x00); /* SD->low = start condition */
9335 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009336 return 0;
9337}
9338
9339/* Set I2C stop condition */
9340/* This is done by a SD low-to-high transition while SC is high */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009341static unsigned short
9342SiS_SetStop(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009343{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009344 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009345 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009346 SiS_Pr->SiS_DDC_Index,
9347 SiS_Pr->SiS_DDC_NData,
9348 0x00); /* SD->low */
9349 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009350 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009351 SiS_Pr->SiS_DDC_Index,
9352 SiS_Pr->SiS_DDC_NData,
9353 SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
9354 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009355 return 0;
9356}
9357
9358/* Write 8 bits of data */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009359static unsigned short
9360SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009361{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009362 unsigned short i,flag,temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009363
9364 flag = 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009365 for(i = 0; i < 8; i++) {
9366 SiS_SetSCLKLow(SiS_Pr); /* SC->low */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009367 if(tempax & flag) {
9368 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009369 SiS_Pr->SiS_DDC_Index,
9370 SiS_Pr->SiS_DDC_NData,
9371 SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009372 } else {
9373 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009374 SiS_Pr->SiS_DDC_Index,
9375 SiS_Pr->SiS_DDC_NData,
9376 0x00); /* Write bit (0) to SD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009377 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009378 SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009379 flag >>= 1;
9380 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009381 temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
9382 return temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009383}
9384
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009385static unsigned short
9386SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009387{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009388 unsigned short i, temp, getdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009389
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009390 getdata = 0;
9391 for(i = 0; i < 8; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009392 getdata <<= 1;
9393 SiS_SetSCLKLow(SiS_Pr);
9394 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009395 SiS_Pr->SiS_DDC_Index,
9396 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009397 SiS_Pr->SiS_DDC_Data);
9398 SiS_SetSCLKHigh(SiS_Pr);
9399 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9400 if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
9401 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009402 return getdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009403}
9404
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009405static unsigned short
9406SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009407{
9408 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009409 SiS_Pr->SiS_DDC_Index,
9410 SiS_Pr->SiS_DDC_NClk,
9411 0x00); /* SetSCLKLow() */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009412 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9413 return 0;
9414}
9415
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009416static unsigned short
9417SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009418{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009419 unsigned short temp, watchdog=1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009420
9421 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009422 SiS_Pr->SiS_DDC_Index,
9423 SiS_Pr->SiS_DDC_NClk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009424 SiS_Pr->SiS_DDC_Clk); /* SetSCLKHigh() */
9425 do {
9426 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9427 } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
9428 if (!watchdog) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009429 return 0xFFFF;
9430 }
9431 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9432 return 0;
9433}
9434
9435/* Check I2C acknowledge */
9436/* Returns 0 if ack ok, non-0 if ack not ok */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009437static unsigned short
9438SiS_CheckACK(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009439{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009440 unsigned short tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009441
9442 SiS_SetSCLKLow(SiS_Pr); /* (SC->low) */
9443 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009444 SiS_Pr->SiS_DDC_Index,
9445 SiS_Pr->SiS_DDC_NData,
9446 SiS_Pr->SiS_DDC_Data); /* (SD->high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009447 SiS_SetSCLKHigh(SiS_Pr); /* SC->high = clock impulse for ack */
9448 tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
9449 SiS_SetSCLKLow(SiS_Pr); /* SC->low = end of clock impulse */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009450 if(tempah & SiS_Pr->SiS_DDC_Data) return 1; /* Ack OK if bit = 0 */
9451 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009452}
9453
9454/* End of I2C functions ----------------------- */
9455
9456
9457/* =============== SiS 315/330 O.E.M. ================= */
9458
Aaro Koskinenf7854e52010-11-19 21:58:47 +00009459#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07009460
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009461static unsigned short
9462GetRAMDACromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009463{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009464 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9465 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009466
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009467 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009468 romptr = SISGETROMW(0x128);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009469 if(SiS_Pr->SiS_VBType & VB_SIS30xB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009470 romptr = SISGETROMW(0x12a);
9471 } else {
9472 romptr = SISGETROMW(0x1a8);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009473 if(SiS_Pr->SiS_VBType & VB_SIS30xB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009474 romptr = SISGETROMW(0x1aa);
9475 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009476 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009477}
9478
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009479static unsigned short
9480GetLCDromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009481{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009482 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9483 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009484
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009485 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009486 romptr = SISGETROMW(0x120);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009487 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009488 romptr = SISGETROMW(0x122);
9489 } else {
9490 romptr = SISGETROMW(0x1a0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009491 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009492 romptr = SISGETROMW(0x1a2);
9493 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009494 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009495}
9496
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009497static unsigned short
9498GetTVromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009499{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009500 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9501 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009502
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009503 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009504 romptr = SISGETROMW(0x114);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009505 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009506 romptr = SISGETROMW(0x11a);
9507 } else {
9508 romptr = SISGETROMW(0x194);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009509 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009510 romptr = SISGETROMW(0x19a);
9511 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009512 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009513}
9514
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009515static unsigned short
9516GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009517{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009518 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009519
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009520 if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9521 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009522 if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
9523 index >>= 4;
9524 index *= 3;
9525 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9526 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9527 return index;
9528 }
9529 }
9530 }
9531
9532 index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
9533 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) index -= 5;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009534 if(SiS_Pr->SiS_VBType & VB_SIS301C) { /* 1.15.20 and later (not VB specific) */
9535 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
9536 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
9537 } else {
9538 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
9539 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009540 index--;
9541 index *= 3;
9542 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9543 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9544 return index;
9545}
9546
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009547static unsigned short
9548GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009549{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009550 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009551
9552 index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
9553 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9554 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9555 return index;
9556}
9557
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009558static unsigned short
9559GetTVPtrIndex(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009560{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009561 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009562
9563 index = 0;
9564 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9565 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
9566
9567 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
9568
9569 index <<= 1;
9570
9571 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
9572 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9573 index++;
9574 }
9575
9576 return index;
9577}
9578
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009579static unsigned int
9580GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009581{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009582 unsigned short index = 0, temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009583
9584 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9585 if(SiS_Pr->SiS_TVMode & TVSetPALM) index = 2;
9586 if(SiS_Pr->SiS_TVMode & TVSetPALN) index = 3;
9587 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
9588 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
9589 index = 4;
9590 if(SiS_Pr->SiS_TVMode & TVSetPALM) index++;
9591 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
9592 }
9593
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009594 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009595 if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
9596 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9597 index += addme;
9598 temp++;
9599 }
9600 temp += 0x0100;
9601 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009602 return (unsigned int)(index | (temp << 16));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009603}
9604
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009605static unsigned int
9606GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009607{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009608 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009609}
9610
9611#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009612static unsigned int
9613GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009614{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009615 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009616}
9617#endif
9618
9619static int
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009620GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009621{
9622 int index = 0;
9623
9624 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 2;
9625 if(SiS_Pr->SiS_ROMNew) {
9626 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
9627 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
9628 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
9629 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 10;
9630 } else {
9631 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 4;
9632 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
9633 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
9634 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
9635 }
9636
9637 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
9638
9639 return index;
9640}
9641
9642static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009643SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009644{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009645 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9646 unsigned short delay=0,index,myindex,temp,romptr=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009647 bool dochiptest = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009648
9649 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9650 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
9651 } else {
9652 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
9653 }
9654
9655 /* Find delay (from ROM, internal tables, PCI subsystem) */
9656
9657 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { /* ------------ VGA */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009658
Linus Torvalds1da177e2005-04-16 15:20:36 -07009659 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009660 romptr = GetRAMDACromptr(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009661 }
9662 if(romptr) delay = ROMAddr[romptr];
9663 else {
9664 delay = 0x04;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009665 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009666 if(IS_SIS650) {
9667 delay = 0x0a;
9668 } else if(IS_SIS740) {
9669 delay = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009670 } else if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009671 delay = 0x0c;
9672 } else {
9673 delay = 0x0c;
9674 }
9675 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9676 delay = 0x00;
9677 }
9678 }
9679
9680 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) { /* ---------- LCD/LCDA */
9681
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009682 bool gotitfrompci = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009683
9684 /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
9685
9686 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
9687 if(SiS_Pr->PDC != -1) {
9688 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
9689 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
9690 return;
9691 }
9692 } else {
9693 if(SiS_Pr->PDCA != -1) {
9694 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
9695 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
9696 return;
9697 }
9698 }
9699
9700 /* Custom Panel? */
9701
9702 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
9703 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9704 delay = 0x00;
9705 if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
9706 delay = 0x20;
9707 }
9708 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
9709 } else {
9710 delay = 0x0c;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009711 if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9712 delay = 0x03;
9713 if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
9714 delay = 0x00;
9715 }
9716 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009717 if(IS_SIS740) delay = 0x01;
9718 else delay = 0x03;
9719 }
9720 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
9721 }
9722 return;
9723 }
9724
9725 /* This is a piece of typical SiS crap: They code the OEM LCD
9726 * delay into the code, at no defined place in the BIOS.
9727 * We now have to start doing a PCI subsystem check here.
9728 */
9729
9730 switch(SiS_Pr->SiS_CustomT) {
9731 case CUT_COMPAQ1280:
9732 case CUT_COMPAQ12802:
9733 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009734 gotitfrompci = true;
9735 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009736 delay = 0x03;
9737 }
9738 break;
9739 case CUT_CLEVO1400:
9740 case CUT_CLEVO14002:
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009741 gotitfrompci = true;
9742 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009743 delay = 0x02;
9744 break;
9745 case CUT_CLEVO1024:
9746 case CUT_CLEVO10242:
9747 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009748 gotitfrompci = true;
9749 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009750 delay = 0x33;
9751 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9752 delay &= 0x0f;
9753 }
9754 break;
9755 }
9756
9757 /* Could we find it through the PCI ID? If no, use ROM or table */
9758
9759 if(!gotitfrompci) {
9760
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009761 index = GetLCDPtrIndexBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009762 myindex = GetLCDPtrIndex(SiS_Pr);
9763
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009764 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009765
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009766 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009767
9768 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9769 /* Always use the second pointer on 650; some BIOSes */
9770 /* still carry old 301 data at the first location */
9771 /* romptr = SISGETROMW(0x120); */
9772 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
9773 romptr = SISGETROMW(0x122);
9774 if(!romptr) return;
9775 delay = ROMAddr[(romptr + index)];
9776 } else {
9777 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9778 }
9779
9780 } else {
9781
9782 delay = SiS310_LCDDelayCompensation_651301LV[myindex];
9783 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
9784 delay = SiS310_LCDDelayCompensation_651302LV[myindex];
9785
9786 }
9787
9788 } else if(SiS_Pr->SiS_UseROM &&
9789 (!(SiS_Pr->SiS_ROMNew)) &&
9790 (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
9791 (SiS_Pr->SiS_LCDResInfo != Panel_1280x768) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009792 (SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
9793 (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200) &&
9794 ((romptr = GetLCDromptr(SiS_Pr)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009795
9796 /* Data for 1280x1024 wrong in 301B BIOS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009797 /* Data for 1600x1200 wrong in 301C BIOS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009798 delay = ROMAddr[(romptr + index)];
9799
9800 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9801
9802 if(IS_SIS740) delay = 0x03;
9803 else delay = 0x00;
9804
9805 } else {
9806
9807 delay = SiS310_LCDDelayCompensation_301[myindex];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009808 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009809 if(IS_SIS740) delay = 0x01;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009810 else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07009811 else delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9812 } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9813 if(IS_SIS740) delay = 0x01; /* ? */
9814 else delay = 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009815 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
9816 } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009817 if(IS_SIS740) delay = 0x01;
9818 else delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
9819 }
9820
9821 }
9822
9823 } /* got it from PCI */
9824
9825 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9826 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009827 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009828 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009829
Linus Torvalds1da177e2005-04-16 15:20:36 -07009830 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* ------------ TV */
9831
9832 index = GetTVPtrIndex(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009833
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009834 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9835
9836 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009837
9838 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9839 /* Always use the second pointer on 650; some BIOSes */
9840 /* still carry old 301 data at the first location */
9841 /* romptr = SISGETROMW(0x114); */
9842 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
9843 romptr = SISGETROMW(0x11a);
9844 if(!romptr) return;
9845 delay = ROMAddr[romptr + index];
9846
9847 } else {
9848
9849 delay = SiS310_TVDelayCompensation_301B[index];
9850
9851 }
9852
9853 } else {
9854
9855 switch(SiS_Pr->SiS_CustomT) {
9856 case CUT_COMPAQ1280:
9857 case CUT_COMPAQ12802:
9858 case CUT_CLEVO1400:
9859 case CUT_CLEVO14002:
9860 delay = 0x02;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009861 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009862 break;
9863 case CUT_CLEVO1024:
9864 case CUT_CLEVO10242:
9865 delay = 0x03;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009866 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009867 break;
9868 default:
9869 delay = SiS310_TVDelayCompensation_651301LV[index];
9870 if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
9871 delay = SiS310_TVDelayCompensation_651302LV[index];
9872 }
9873 }
9874 }
9875
9876 } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9877
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009878 romptr = GetTVromptr(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009879 if(!romptr) return;
9880 delay = ROMAddr[romptr + index];
9881
9882 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9883
9884 delay = SiS310_TVDelayCompensation_LVDS[index];
9885
9886 } else {
9887
9888 delay = SiS310_TVDelayCompensation_301[index];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009889 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009890 if(IS_SIS740) {
9891 delay = SiS310_TVDelayCompensation_740301B[index];
9892 /* LV: use 301 data? BIOS bug? */
9893 } else {
9894 delay = SiS310_TVDelayCompensation_301B[index];
9895 if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
9896 }
9897 }
9898
9899 }
9900
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009901 if(SiS_LCDAEnabled(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009902 delay &= 0x0f;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009903 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009904 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009905
Linus Torvalds1da177e2005-04-16 15:20:36 -07009906 } else return;
9907
9908 /* Write delay */
9909
9910 if(SiS_Pr->SiS_VBType & VB_SISVB) {
9911
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009912 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009913
9914 temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
9915 if(temp == 8) { /* 1400x1050 BIOS (COMPAL) */
9916 delay &= 0x0f;
9917 delay |= 0xb0;
9918 } else if(temp == 6) {
9919 delay &= 0x0f;
9920 delay |= 0xc0;
9921 } else if(temp > 7) { /* 1280x1024 BIOS (which one?) */
9922 delay = 0x35;
9923 }
9924 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9925
9926 } else {
9927
9928 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9929
9930 }
9931
9932 } else { /* LVDS */
9933
9934 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
9935 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9936 } else {
9937 if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
9938 delay <<= 4;
9939 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
9940 } else {
9941 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9942 }
9943 }
9944
9945 }
9946
9947}
9948
9949static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009950SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009951{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009952 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9953 unsigned short index,temp,temp1,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009954
9955 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
9956
9957 if(ModeNo<=0x13)
9958 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
9959 else
9960 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
9961
9962 temp = GetTVPtrIndex(SiS_Pr);
9963 temp >>= 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9964 temp1 = temp;
9965
9966 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009967 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009968 temp1 = GetOEMTVPtr661(SiS_Pr);
9969 temp1 >>= 1;
9970 romptr = SISGETROMW(0x260);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009971 if(SiS_Pr->ChipType >= SIS_760) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009972 romptr = SISGETROMW(0x360);
9973 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009974 } else if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009975 romptr = SISGETROMW(0x192);
9976 } else {
9977 romptr = SISGETROMW(0x112);
9978 }
9979 }
9980
9981 if(romptr) {
9982 temp1 <<= 1;
9983 temp = ROMAddr[romptr + temp1 + index];
9984 } else {
9985 temp = SiS310_TVAntiFlick1[temp][index];
9986 }
9987 temp <<= 4;
9988
9989 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp); /* index 0A D[6:4] */
9990}
9991
9992static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009993SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009994{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009995 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9996 unsigned short index,temp,temp1,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009997
9998 temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9999
10000 if(ModeNo <= 0x13)
10001 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
10002 else
10003 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
10004
10005 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010006 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010007 romptr = SISGETROMW(0x26c);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010008 if(SiS_Pr->ChipType >= SIS_760) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010009 romptr = SISGETROMW(0x36c);
10010 }
10011 temp1 = GetOEMTVPtr661(SiS_Pr);
10012 temp1 >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010013 } else if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010014 romptr = SISGETROMW(0x1a4);
10015 } else {
10016 romptr = SISGETROMW(0x124);
10017 }
10018 }
10019
10020 if(romptr) {
10021 temp1 <<= 1;
10022 temp = ROMAddr[romptr + temp1 + index];
10023 } else {
10024 temp = SiS310_TVEdge1[temp][index];
10025 }
10026 temp <<= 5;
10027 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp); /* index 0A D[7:5] */
10028}
10029
10030static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010031SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010032{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010033 unsigned short index, temp, i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010034
10035 if(ModeNo <= 0x13) {
10036 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
10037 } else {
10038 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
10039 }
10040
10041 temp = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10042
10043 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 1; /* NTSC-J uses PAL */
10044 else if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 3; /* PAL-M */
10045 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 4; /* PAL-N */
10046 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1; /* HiVision uses PAL */
10047
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010048 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010049 for(i=0x35, j=0; i<=0x38; i++, j++) {
10050 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10051 }
10052 for(i=0x48; i<=0x4A; i++, j++) {
10053 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10054 }
10055 } else {
10056 for(i=0x35, j=0; i<=0x38; i++, j++) {
10057 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
10058 }
10059 }
10060}
10061
10062static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010063SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010064{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010065 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10066 unsigned short index,temp,i,j,resinfo,romptr=0;
10067 unsigned int lindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010068
10069 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
10070
10071 /* NTSC-J data not in BIOS, and already set in SetGroup2 */
10072 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
10073
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010074 if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010075 lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
10076 lindex <<= 2;
10077 for(j=0, i=0x31; i<=0x34; i++, j++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010078 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010079 }
10080 return;
10081 }
10082
10083 /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
10084 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
10085
10086 if(ModeNo<=0x13) {
10087 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10088 } else {
10089 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10090 }
10091
10092 temp = GetTVPtrIndex(SiS_Pr);
10093 /* 0: NTSC Graphics, 1: NTSC Text, 2: PAL Graphics,
10094 * 3: PAL Text, 4: HiTV Graphics 5: HiTV Text
10095 */
10096 if(SiS_Pr->SiS_UseROM) {
10097 romptr = SISGETROMW(0x116);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010098 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010099 romptr = SISGETROMW(0x196);
10100 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010101 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010102 romptr = SISGETROMW(0x11c);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010103 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010104 romptr = SISGETROMW(0x19c);
10105 }
10106 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
10107 romptr = SISGETROMW(0x116);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010108 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010109 romptr = SISGETROMW(0x196);
10110 }
10111 }
10112 }
10113 }
10114 if(romptr) {
10115 romptr += (temp << 2);
10116 for(j=0, i=0x31; i<=0x34; i++, j++) {
10117 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10118 }
10119 } else {
10120 index = temp % 2;
10121 temp >>= 1; /* 0:NTSC, 1:PAL, 2:HiTV */
10122 for(j=0, i=0x31; i<=0x34; i++, j++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010123 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
Linus Torvalds1da177e2005-04-16 15:20:36 -070010124 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10125 else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
10126 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
10127 else
10128 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10129 }
10130 }
10131
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010132 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010133 if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
10134 if((resinfo == SIS_RI_640x480) ||
10135 (resinfo == SIS_RI_800x600)) {
10136 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
10137 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
10138 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
10139 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
10140 } else if(resinfo == SIS_RI_1024x768) {
10141 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
10142 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
10143 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
10144 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
10145 }
10146 }
10147 }
10148}
10149
10150static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010151SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10152 unsigned short ModeIdIndex, unsigned short RTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010153{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010154 unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
10155 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010156
10157 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
10158 return;
10159
10160 /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
10161 /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
10162
10163 if(SiS_Pr->SiS_ROMNew) {
10164 if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) ||
10165 ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
10166 (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
10167 index = 25;
10168 if(SiS_Pr->UseCustomMode) {
10169 index = SiS_Pr->CSRClock;
10170 } else if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010171 index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010172 index = SiS_Pr->SiS_VCLKData[index].CLOCK;
10173 }
10174 if(index < 25) index = 25;
10175 index = ((index / 25) - 1) << 1;
10176 if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
10177 index++;
10178 }
10179 romptr = SISGETROMW(0x104);
10180 delay = ROMAddr[romptr + index];
10181 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
10182 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10183 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10184 } else {
10185 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10186 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10187 }
10188 return;
10189 }
10190 }
10191
10192 /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
10193
10194 if(SiS_Pr->UseCustomMode) delay = 0x04;
10195 else if(ModeNo <= 0x13) delay = 0x04;
10196 else delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
10197 delay |= (delay << 8);
10198
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010199 if(SiS_Pr->ChipType >= XGI_20) {
10200
10201 delay = 0x0606;
10202 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10203
10204 delay = 0x0404;
10205 if(SiS_Pr->SiS_XGIROM) {
10206 index = GetTVPtrIndex(SiS_Pr);
10207 if((romptr = SISGETROMW(0x35e))) {
10208 delay = (ROMAddr[romptr + index] & 0x0f) << 1;
10209 delay |= (delay << 8);
10210 }
10211 }
10212
10213 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
10214 if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
10215 delay -= 0x0404;
10216 }
10217 }
10218 }
10219
10220 } else if(SiS_Pr->ChipType >= SIS_340) {
10221
10222 delay = 0x0606;
10223 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10224 delay = 0x0404;
10225 }
10226 /* TODO (eventually) */
10227
10228 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010229
10230 /* 3. TV */
10231
10232 index = GetOEMTVPtr661(SiS_Pr);
10233 if(SiS_Pr->SiS_ROMNew) {
10234 romptr = SISGETROMW(0x106);
10235 if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
10236 delay = ROMAddr[romptr + index];
10237 } else {
10238 delay = 0x04;
10239 if(index > 3) delay = 0;
10240 }
10241
10242 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10243
10244 /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
10245
10246 if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010247 ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010248
10249 lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
10250
10251 /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
10252 delay = ROMAddr[romptr + lcdpdcindex + 1]; /* LCD */
10253 delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
10254
10255 } else {
10256
10257 /* TMDS: Set our own, since BIOS has no idea */
10258 /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
10259 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10260 switch(SiS_Pr->SiS_LCDResInfo) {
10261 case Panel_1024x768: delay = 0x0008; break;
10262 case Panel_1280x720: delay = 0x0004; break;
10263 case Panel_1280x768:
10264 case Panel_1280x768_2:delay = 0x0004; break;
10265 case Panel_1280x800:
10266 case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010267 case Panel_1280x854: delay = 0x0004; break; /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010268 case Panel_1280x1024: delay = 0x1e04; break;
10269 case Panel_1400x1050: delay = 0x0004; break;
10270 case Panel_1600x1200: delay = 0x0400; break;
10271 case Panel_1680x1050: delay = 0x0e04; break;
10272 default:
10273 if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
10274 delay = 0x0008;
10275 } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
10276 delay = 0x1e04;
10277 } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
10278 delay = 0x0004;
10279 } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
10280 delay = 0x0400;
10281 } else
10282 delay = 0x0e04;
10283 break;
10284 }
10285 }
10286
10287 /* Override by detected or user-set values */
10288 /* (but only if, for some reason, we can't read value from BIOS) */
10289 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
10290 delay = SiS_Pr->PDC & 0x1f;
10291 }
10292 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
10293 delay = (SiS_Pr->PDCA & 0x1f) << 8;
10294 }
10295
10296 }
10297
10298 }
10299
10300 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10301 delay >>= 8;
10302 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10303 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10304 } else {
10305 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10306 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10307 }
10308}
10309
10310static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010311SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010312{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010313 unsigned short infoflag;
10314 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010315
10316 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10317
10318 if(ModeNo <= 0x13) {
10319 infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
10320 } else if(SiS_Pr->UseCustomMode) {
10321 infoflag = SiS_Pr->CInfoFlag;
10322 } else {
10323 infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
10324 }
10325
10326 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10327 infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
10328 }
10329
10330 infoflag &= 0xc0;
10331
10332 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10333 temp = (infoflag >> 6) | 0x0c;
10334 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10335 temp ^= 0x04;
10336 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
10337 }
10338 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
10339 } else {
10340 temp = 0x30;
10341 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
10342 temp |= infoflag;
10343 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
10344 temp = 0;
10345 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10346 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
10347 }
10348 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
10349 }
10350
10351 }
10352}
10353
10354static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010355SetPanelParms661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010356{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010357 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10358 unsigned short romptr, temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010359
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010360 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
10361 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
10362 }
10363
10364 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010365 if(SiS_Pr->LVDSHL != -1) {
10366 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10367 }
10368 }
10369
10370 if(SiS_Pr->SiS_ROMNew) {
10371
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010372 if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
10373 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010374 temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
10375 temp2 = 0xfc;
10376 if(SiS_Pr->LVDSHL != -1) {
10377 temp1 &= 0xfc;
10378 temp2 = 0xf3;
10379 }
10380 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
10381 }
10382 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10383 temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
10384 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
10385 }
10386 }
10387
10388 }
10389}
10390
10391static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010392SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010393{
10394 if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010395 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010396 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010397 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10398 SetPanelParms661(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010399 }
10400 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010401 SetDelayComp(SiS_Pr,ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010402 }
10403
10404 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010405 SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
10406 SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
10407 SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010408 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010409 SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010410 }
10411 }
10412}
10413
10414static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010415SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10416 unsigned short ModeIdIndex, unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010417{
10418 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10419
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010420 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010421
10422 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010423 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10424 SetPanelParms661(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010425 }
10426
10427 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010428 SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
10429 SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
10430 SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010431 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010432 SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010433 }
10434 }
10435 }
10436}
10437
10438/* FinalizeLCD
10439 * This finalizes some CRT2 registers for the very panel used.
10440 * If we have a backup if these registers, we use it; otherwise
10441 * we set the register according to most BIOSes. However, this
10442 * function looks quite different in every BIOS, so you better
10443 * pray that we have a backup...
10444 */
10445static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010446SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010447{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010448 unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
10449 unsigned short resinfo,modeflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010450
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010451 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010452 if(SiS_Pr->SiS_ROMNew) return;
10453
10454 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10455 if(SiS_Pr->LVDSHL != -1) {
10456 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10457 }
10458 }
10459
10460 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10461 if(SiS_Pr->UseCustomMode) return;
10462
10463 switch(SiS_Pr->SiS_CustomT) {
10464 case CUT_COMPAQ1280:
10465 case CUT_COMPAQ12802:
10466 case CUT_CLEVO1400:
10467 case CUT_CLEVO14002:
10468 return;
10469 }
10470
10471 if(ModeNo <= 0x13) {
10472 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10473 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10474 } else {
10475 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10476 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10477 }
10478
10479 if(IS_SIS650) {
10480 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
10481 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10482 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
10483 } else {
10484 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
10485 }
10486 }
10487 }
10488
10489 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10490 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10491 /* Maybe all panels? */
10492 if(SiS_Pr->LVDSHL == -1) {
10493 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10494 }
10495 return;
10496 }
10497 }
10498
10499 if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
10500 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10501 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10502 if(SiS_Pr->LVDSHL == -1) {
10503 /* Maybe all panels? */
10504 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10505 }
10506 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10507 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10508 if(tempch == 3) {
10509 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10510 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10511 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10512 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10513 }
10514 }
10515 return;
10516 }
10517 }
10518 }
10519
10520 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10521 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010522 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010523 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
10524#ifdef SET_EMI
10525 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
10526#endif
10527 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
10528 }
10529 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10530 if(SiS_Pr->LVDSHL == -1) {
10531 /* Maybe ACER only? */
10532 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10533 }
10534 }
10535 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10536 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10537 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
10538 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
10539 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10540 if(tempch == 0x03) {
10541 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10542 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10543 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10544 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10545 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -080010546 if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010547 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
10548 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
10549 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
10550 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
10551 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
10552 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
10553 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
10554 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
10555 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
10556 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
10557 } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { /* 1.10.8w */
10558 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
10559 if(ModeNo <= 0x13) {
10560 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
10561 if((resinfo == 0) || (resinfo == 2)) return;
10562 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
10563 if((resinfo == 1) || (resinfo == 3)) return;
10564 }
10565 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10566 if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
10567 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02); /* 1.10.7u */
10568#if 0
10569 tempbx = 806; /* 0x326 */ /* other older BIOSes */
10570 tempbx--;
10571 temp = tempbx & 0xff;
10572 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
10573 temp = (tempbx >> 8) & 0x03;
10574 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
10575#endif
10576 }
10577 } else if(ModeNo <= 0x13) {
10578 if(ModeNo <= 1) {
10579 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
10580 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
10581 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10582 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10583 }
10584 if(!(modeflag & HalfDCLK)) {
10585 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
10586 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
10587 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
10588 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
10589 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
10590 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10591 if(ModeNo == 0x12) {
10592 switch(tempch) {
10593 case 0:
10594 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10595 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10596 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
10597 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10598 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
10599 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10600 break;
10601 case 2:
10602 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10603 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10604 break;
10605 case 3:
10606 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10607 break;
10608 }
10609 }
10610 }
10611 }
10612 }
10613 } else {
10614 tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
10615 tempcl &= 0x0f;
10616 tempbh &= 0x70;
10617 tempbh >>= 4;
10618 tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
10619 tempbx = (tempbh << 8) | tempbl;
10620 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10621 if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
10622 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
10623 tempbx = 770;
10624 } else {
10625 if(tempbx > 770) tempbx = 770;
10626 if(SiS_Pr->SiS_VGAVDE < 600) {
10627 tempax = 768 - SiS_Pr->SiS_VGAVDE;
10628 tempax >>= 4; /* 1.10.7w; 1.10.6s: 3; */
10629 if(SiS_Pr->SiS_VGAVDE <= 480) tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
10630 tempbx -= tempax;
10631 }
10632 }
10633 } else return;
10634 }
10635 temp = tempbx & 0xff;
10636 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
10637 temp = ((tempbx & 0xff00) >> 4) | tempcl;
10638 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
10639 }
10640 }
10641}
10642
10643#endif
10644
10645/* ================= SiS 300 O.E.M. ================== */
10646
Aaro Koskinenf7854e52010-11-19 21:58:47 +000010647#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -070010648
10649static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010650SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
10651 unsigned short RefTabIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010652{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010653 unsigned short crt2crtc=0, modeflag, myindex=0;
10654 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010655 int i;
10656
10657 if(ModeNo <= 0x13) {
10658 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10659 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
10660 } else {
10661 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10662 crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
10663 }
10664
10665 crt2crtc &= 0x3f;
10666
10667 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
10668 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
10669 }
10670
10671 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
10672 if(modeflag & HalfDCLK) myindex = 1;
10673
10674 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
10675 for(i=0; i<7; i++) {
10676 if(barco_p1[myindex][crt2crtc][i][0]) {
10677 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
10678 barco_p1[myindex][crt2crtc][i][0],
10679 barco_p1[myindex][crt2crtc][i][2],
10680 barco_p1[myindex][crt2crtc][i][1]);
10681 }
10682 }
10683 }
10684 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
10685 if(temp & 0x80) {
10686 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
10687 temp++;
10688 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
10689 }
10690 }
10691}
10692
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010693static unsigned short
10694GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010695{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010696 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10697 unsigned short tempbx=0,romptr=0;
10698 static const unsigned char customtable300[] = {
10699 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010700 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10701 };
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010702 static const unsigned char customtable630[] = {
10703 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010704 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10705 };
10706
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010707 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010708
10709 tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
10710 if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
10711 tempbx -= 2;
10712 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
10713 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10714 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
10715 }
10716 if(SiS_Pr->SiS_UseROM) {
10717 if(ROMAddr[0x235] & 0x80) {
10718 tempbx = SiS_Pr->SiS_LCDTypeInfo;
10719 if(Flag) {
10720 romptr = SISGETROMW(0x255);
10721 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10722 else tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
10723 if(tempbx == 0xFF) return 0xFFFF;
10724 }
10725 tempbx <<= 1;
10726 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
10727 }
10728 }
10729
10730 } else {
10731
10732 if(Flag) {
10733 if(SiS_Pr->SiS_UseROM) {
10734 romptr = SISGETROMW(0x255);
10735 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10736 else tempbx = 0xff;
10737 } else {
10738 tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
10739 }
10740 if(tempbx == 0xFF) return 0xFFFF;
10741 tempbx <<= 2;
10742 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10743 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10744 return tempbx;
10745 }
10746 tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
10747 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10748 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10749
10750 }
10751
10752 return tempbx;
10753}
10754
10755static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010756SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010757{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010758 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10759 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010760
10761 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10762
10763 if(SiS_Pr->SiS_UseROM) {
10764 if(!(ROMAddr[0x237] & 0x01)) return;
10765 if(!(ROMAddr[0x237] & 0x02)) return;
10766 romptr = SISGETROMW(0x24b);
10767 }
10768
10769 /* The Panel Compensation Delay should be set according to tables
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010770 * here. Unfortunately, various BIOS versions don't care about
Linus Torvalds1da177e2005-04-16 15:20:36 -070010771 * a uniform way using eg. ROM byte 0x220, but use different
10772 * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010773 * Thus we don't set this if the user selected a custom pdc or if
Linus Torvalds1da177e2005-04-16 15:20:36 -070010774 * we otherwise detected a valid pdc.
10775 */
10776 if(SiS_Pr->PDC != -1) return;
10777
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010778 temp = GetOEMLCDPtr(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010779
10780 if(SiS_Pr->UseCustomMode)
10781 index = 0;
10782 else
10783 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
10784
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010785 if(SiS_Pr->ChipType != SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010786 if(romptr) {
10787 romptr += (temp * 2);
10788 romptr = SISGETROMW(romptr);
10789 romptr += index;
10790 temp = ROMAddr[romptr];
10791 } else {
10792 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10793 temp = SiS300_OEMLCDDelay2[temp][index];
10794 } else {
10795 temp = SiS300_OEMLCDDelay3[temp][index];
10796 }
10797 }
10798 } else {
10799 if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
10800 if(romptr) {
10801 romptr += (temp * 2);
10802 romptr = SISGETROMW(romptr);
10803 romptr += index;
10804 temp = ROMAddr[romptr];
10805 } else {
10806 temp = SiS300_OEMLCDDelay5[temp][index];
10807 }
10808 } else {
10809 if(SiS_Pr->SiS_UseROM) {
10810 romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
10811 if(romptr) {
10812 romptr += (temp * 2);
10813 romptr = SISGETROMW(romptr);
10814 romptr += index;
10815 temp = ROMAddr[romptr];
10816 } else {
10817 temp = SiS300_OEMLCDDelay4[temp][index];
10818 }
10819 } else {
10820 temp = SiS300_OEMLCDDelay4[temp][index];
10821 }
10822 }
10823 }
10824 temp &= 0x3c;
10825 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* index 0A D[6:4] */
10826}
10827
10828static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010829SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010830{
10831#if 0 /* Unfinished; Data table missing */
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010832 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10833 unsigned short index,temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010834
10835 if((SiS_Pr->SiS_UseROM) {
10836 if(!(ROMAddr[0x237] & 0x01)) return;
10837 if(!(ROMAddr[0x237] & 0x04)) return;
10838 /* No rom pointer in BIOS header! */
10839 }
10840
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010841 temp = GetOEMLCDPtr(SiS_Pr, 1);
10842 if(temp == 0xFFFF) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010843
10844 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
10845 for(i=0x14, j=0; i<=0x17; i++, j++) {
10846 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
10847 }
10848 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
10849
10850 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
10851 SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
10852 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
10853 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
10854 for(i=0x1b, j=3; i<=0x1d; i++, j++) {
10855 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
10856 }
10857#endif
10858}
10859
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010860static unsigned short
10861GetOEMTVPtr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010862{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010863 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010864
10865 index = 0;
10866 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) index += 4;
10867 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10868 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) index += 2;
10869 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
10870 else if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
10871 } else {
10872 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
10873 if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
10874 }
10875 return index;
10876}
10877
10878static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010879SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
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 index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010883
10884 if(SiS_Pr->SiS_UseROM) {
10885 if(!(ROMAddr[0x238] & 0x01)) return;
10886 if(!(ROMAddr[0x238] & 0x02)) return;
10887 romptr = SISGETROMW(0x241);
10888 }
10889
10890 temp = GetOEMTVPtr(SiS_Pr);
10891
10892 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
10893
10894 if(romptr) {
10895 romptr += (temp * 2);
10896 romptr = SISGETROMW(romptr);
10897 romptr += index;
10898 temp = ROMAddr[romptr];
10899 } else {
10900 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10901 temp = SiS300_OEMTVDelay301[temp][index];
10902 } else {
10903 temp = SiS300_OEMTVDelayLVDS[temp][index];
10904 }
10905 }
10906 temp &= 0x3c;
10907 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
10908}
10909
10910static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010911SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010912{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010913 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10914 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010915
10916 if(SiS_Pr->SiS_UseROM) {
10917 if(!(ROMAddr[0x238] & 0x01)) return;
10918 if(!(ROMAddr[0x238] & 0x04)) return;
10919 romptr = SISGETROMW(0x243);
10920 }
10921
10922 temp = GetOEMTVPtr(SiS_Pr);
10923
10924 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
10925
10926 if(romptr) {
10927 romptr += (temp * 2);
10928 romptr = SISGETROMW(romptr);
10929 romptr += index;
10930 temp = ROMAddr[romptr];
10931 } else {
10932 temp = SiS300_OEMTVFlicker[temp][index];
10933 }
10934 temp &= 0x70;
10935 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
10936}
10937
10938static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010939SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010940{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010941 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10942 unsigned short index,i,j,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010943
10944 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
10945
10946 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
10947
10948 if(SiS_Pr->SiS_UseROM) {
10949 if(!(ROMAddr[0x238] & 0x01)) return;
10950 if(!(ROMAddr[0x238] & 0x08)) return;
10951 romptr = SISGETROMW(0x245);
10952 }
10953
10954 temp = GetOEMTVPtr(SiS_Pr);
10955
10956 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
10957
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010958 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010959 for(i=0x31, j=0; i<=0x34; i++, j++) {
10960 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
10961 }
10962 } else {
10963 if(romptr) {
10964 romptr += (temp * 2);
10965 romptr = SISGETROMW(romptr);
10966 romptr += (index * 4);
10967 for(i=0x31, j=0; i<=0x34; i++, j++) {
10968 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10969 }
10970 } else {
10971 for(i=0x31, j=0; i<=0x34; i++, j++) {
10972 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
10973 }
10974 }
10975 }
10976}
10977
10978static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010979SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010980{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010981 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10982 unsigned short index,temp,i,j,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010983
10984 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
10985
10986 if(SiS_Pr->SiS_UseROM) {
10987 if(!(ROMAddr[0x238] & 0x01)) return;
10988 if(!(ROMAddr[0x238] & 0x10)) return;
10989 romptr = SISGETROMW(0x247);
10990 }
10991
10992 temp = GetOEMTVPtr(SiS_Pr);
10993
10994 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
10995 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
10996 /* NTSCJ uses NTSC filters */
10997
10998 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
10999
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011000 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070011001 for(i=0x35, j=0; i<=0x38; i++, j++) {
11002 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11003 }
11004 for(i=0x48; i<=0x4A; i++, j++) {
11005 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11006 }
11007 } else {
11008 if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
11009 romptr += (temp * 2);
11010 romptr = SISGETROMW(romptr);
11011 romptr += (index * 4);
11012 for(i=0x35, j=0; i<=0x38; i++, j++) {
11013 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11014 }
11015 } else {
11016 for(i=0x35, j=0; i<=0x38; i++, j++) {
11017 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
11018 }
11019 }
11020 }
11021}
11022
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011023static unsigned short
11024SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011025{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011026 unsigned short ModeIdIndex;
11027 unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011028
11029 if(*ModeNo <= 5) *ModeNo |= 1;
11030
11031 for(ModeIdIndex=0; ; ModeIdIndex++) {
11032 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
11033 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF) return 0;
11034 }
11035
11036 if(*ModeNo != 0x07) {
11037 if(*ModeNo > 0x03) return ModeIdIndex;
11038 if(VGAINFO & 0x80) return ModeIdIndex;
11039 ModeIdIndex++;
11040 }
11041
11042 if(VGAINFO & 0x10) ModeIdIndex++; /* 400 lines */
11043 /* else 350 lines */
11044 return ModeIdIndex;
11045}
11046
11047static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011048SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
11049 unsigned short RefTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011050{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011051 unsigned short OEMModeIdIndex = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011052
11053 if(!SiS_Pr->UseCustomMode) {
11054 OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
11055 if(!(OEMModeIdIndex)) return;
11056 }
11057
11058 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011059 SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011060 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011061 SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011062 }
11063 }
11064 if(SiS_Pr->UseCustomMode) return;
11065 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011066 SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011067 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011068 SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
11069 SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
11070 SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011071 }
11072 }
11073}
11074#endif
11075