blob: a89e3cafd5adbfd6c2d8a1622b97c47a339aef81 [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
60#if 1
61#define SET_EMI /* 302LV/ELV: Set EMI values */
62#endif
63
Thomas Winischhofer544393f2005-09-09 13:04:45 -070064#if 1
65#define SET_PWD /* 301/302LV: Set PWD */
66#endif
67
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#define COMPAL_HACK /* Needed for Compal 1400x1050 (EMI) */
69#define COMPAQ_HACK /* Needed for Inventec/Compaq 1280x1024 (EMI) */
70#define ASUS_HACK /* Needed for Asus A2H 1024x768 (EMI) */
71
72#include "init301.h"
73
Aaro Koskinenf7854e52010-11-19 21:58:47 +000074#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -070075#include "oem300.h"
76#endif
77
Aaro Koskinenf7854e52010-11-19 21:58:47 +000078#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -070079#include "oem310.h"
80#endif
81
82#define SiS_I2CDELAY 1000
83#define SiS_I2CDELAYSHORT 150
84
Thomas Winischhofer544393f2005-09-09 13:04:45 -070085static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070086static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88/*********************************************/
89/* HELPER: Lock/Unlock CRT2 */
90/*********************************************/
91
92void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070093SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070095 if(SiS_Pr->ChipType == XGI_20)
96 return;
97 else if(SiS_Pr->ChipType >= SIS_315H)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
99 else
100 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
101}
102
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700103static
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700104void
105SiS_LockCRT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700107 if(SiS_Pr->ChipType == XGI_20)
108 return;
109 else if(SiS_Pr->ChipType >= SIS_315H)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
111 else
112 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
113}
114
115/*********************************************/
116/* HELPER: Write SR11 */
117/*********************************************/
118
119static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700120SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700122 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 DataAND &= 0x0f;
124 DataOR &= 0x0f;
125 }
126 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
127}
128
129/*********************************************/
130/* HELPER: Get Pointer to LCD structure */
131/*********************************************/
132
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000133#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700134static unsigned char *
135GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700137 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
138 unsigned char *myptr = NULL;
139 unsigned short romindex = 0, reg = 0, idx = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141 /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
142 * due to the variaty of panels the BIOS doesn't know about.
143 * Exception: If the BIOS has better knowledge (such as in case
144 * of machines with a 301C and a panel that does not support DDC)
145 * use the BIOS data as well.
146 */
147
148 if((SiS_Pr->SiS_ROMNew) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700149 ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700151 if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
152 else reg = 0x7d;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
154 idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
155
156 if(idx < (8*26)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700157 myptr = (unsigned char *)&SiS_LCDStruct661[idx];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 }
159 romindex = SISGETROMW(0x100);
160 if(romindex) {
161 romindex += idx;
162 myptr = &ROMAddr[romindex];
163 }
164 }
165 return myptr;
166}
167
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700168static unsigned short
169GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700171 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
172 unsigned short romptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
174 /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
175 * due to the variaty of panels the BIOS doesn't know about.
176 * Exception: If the BIOS has better knowledge (such as in case
177 * of machines with a 301C and a panel that does not support DDC)
178 * use the BIOS data as well.
179 */
180
181 if((SiS_Pr->SiS_ROMNew) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700182 ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 romptr = SISGETROMW(0x102);
184 romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
185 }
186
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700187 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188}
189#endif
190
191/*********************************************/
192/* Adjust Rate for CRT2 */
193/*********************************************/
194
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800195static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700196SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
197 unsigned short RRTI, unsigned short *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700199 unsigned short checkmask=0, modeid, infoflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700201 modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700203 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700205 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700207 checkmask |= SupportRAMDAC2;
208 if(SiS_Pr->ChipType >= SIS_315H) {
209 checkmask |= SupportRAMDAC2_135;
210 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
211 checkmask |= SupportRAMDAC2_162;
212 if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
213 checkmask |= SupportRAMDAC2_202;
214 }
215 }
216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700218 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700220 checkmask |= SupportLCD;
221 if(SiS_Pr->ChipType >= SIS_315H) {
222 if(SiS_Pr->SiS_VBType & VB_SISVB) {
223 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
224 if(modeid == 0x2e) checkmask |= Support64048060Hz;
225 }
226 }
227 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700229 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700231 checkmask |= SupportHiVision;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700233 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700235 checkmask |= SupportTV;
236 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
237 checkmask |= SupportTV1024;
238 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
239 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
240 checkmask |= SupportYPbPr750p;
241 }
242 }
243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700245 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700247 } else { /* LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700249 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
250 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
251 checkmask |= SupportCHTV;
252 }
253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700255 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
256 checkmask |= SupportLCD;
257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700259 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700261 /* Look backwards in table for matching CRT2 mode */
262 for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
263 infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800264 if(infoflag & checkmask) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700265 if((*i) == 0) break;
266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700268 /* Look through the whole mode-section of the table from the beginning
269 * for a matching CRT2 mode if no mode was found yet.
270 */
271 for((*i) = 0; ; (*i)++) {
272 if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
273 infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800274 if(infoflag & checkmask) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700275 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800276 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277}
278
279/*********************************************/
280/* Get rate index */
281/*********************************************/
282
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700283unsigned short
284SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700286 unsigned short RRTI,i,backup_i;
287 unsigned short modeflag,index,temp,backupindex;
288 static const unsigned short LCDRefreshIndex[] = {
289 0x00, 0x00, 0x01, 0x01,
290 0x01, 0x01, 0x01, 0x01,
291 0x01, 0x01, 0x01, 0x01,
292 0x01, 0x01, 0x01, 0x01,
293 0x00, 0x00, 0x00, 0x00
294 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700296 /* Do NOT check for UseCustomMode here, will skrew up FIFO */
297 if(ModeNo == 0xfe) return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700299 if(ModeNo <= 0x13) {
300 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
301 } else {
302 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700305 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
306 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
307 if(modeflag & HalfDCLK) return 0;
308 }
309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700311 if(ModeNo < 0x14) return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700313 index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
314 backupindex = index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700316 if(index > 0) index--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700318 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
319 if(SiS_Pr->SiS_VBType & VB_SISVB) {
320 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
321 if(SiS_Pr->SiS_VBType & VB_NoLCD) index = 0;
322 else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
323 }
324 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
325 if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
326 temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
327 if(index > temp) index = temp;
328 }
329 }
330 } else {
331 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
332 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
333 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
334 }
335 }
336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700338 RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
339 ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700341 if(SiS_Pr->ChipType >= SIS_315H) {
342 if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
343 if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
344 (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
345 if(backupindex <= 1) RRTI++;
346 }
347 }
348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700350 i = 0;
351 do {
352 if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
353 temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
354 temp &= ModeTypeMask;
355 if(temp < SiS_Pr->SiS_ModeType) break;
356 i++;
357 index--;
358 } while(index != 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700360 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
361 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
362 temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
363 if(temp & InterlaceMode) i++;
364 }
365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700367 i--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700369 if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
370 backup_i = i;
371 if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
372 i = backup_i;
373 }
374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700376 return (RRTI + i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377}
378
379/*********************************************/
380/* STORE CRT2 INFO in CR34 */
381/*********************************************/
382
383static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700384SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700386 unsigned short temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700388 /* Store CRT1 ModeNo in CR34 */
389 SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
390 temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
391 temp2 = ~(SetInSlaveMode >> 8);
392 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393}
394
395/*********************************************/
396/* HELPER: GET SOME DATA FROM BIOS ROM */
397/*********************************************/
398
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000399#ifdef CONFIG_FB_SIS_300
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800400static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700401SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700403 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
404 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700406 if(SiS_Pr->SiS_UseROM) {
407 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
408 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
409 temp1 = SISGETROMW(0x23b);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800410 if(temp1 & temp) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700411 }
412 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800413 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414}
415
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800416static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700417SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700419 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
420 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700422 if(SiS_Pr->SiS_UseROM) {
423 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
424 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
425 temp1 = SISGETROMW(0x23d);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800426 if(temp1 & temp) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700427 }
428 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800429 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430}
431#endif
432
433/*********************************************/
434/* HELPER: DELAY FUNCTIONS */
435/*********************************************/
436
437void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700438SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
David Rientjesb860e732006-12-08 02:40:19 -0800440 while (delaytime-- > 0)
441 SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442}
443
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000444#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700446SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700448 SiS_DDC2Delay(SiS_Pr, delay * 36);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449}
450#endif
451
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000452#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700454SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700456 while(delay--) {
457 SiS_GenericDelay(SiS_Pr, 6623);
458 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459}
460#endif
461
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000462#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700464SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700466 while(delay--) {
467 SiS_GenericDelay(SiS_Pr, 66);
468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469}
470#endif
471
472static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700473SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000475#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700476 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
477 unsigned short PanelID, DelayIndex, Delay=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478#endif
479
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700480 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000482#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
485 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700486 if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
487 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 }
489 DelayIndex = PanelID >> 4;
490 if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700491 Delay = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700493 if(DelayTime >= 2) DelayTime -= 2;
494 if(!(DelayTime & 0x01)) {
495 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
496 } else {
497 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
498 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 if(SiS_Pr->SiS_UseROM) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700500 if(ROMAddr[0x220] & 0x40) {
501 if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
502 else Delay = (unsigned short)ROMAddr[0x226];
503 }
504 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 }
506 SiS_ShortDelay(SiS_Pr, Delay);
507
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000508#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
510 } else {
511
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000512#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700514 if((SiS_Pr->ChipType >= SIS_661) ||
515 (SiS_Pr->ChipType <= SIS_315PRO) ||
516 (SiS_Pr->ChipType == SIS_330) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 (SiS_Pr->SiS_ROMNew)) {
518
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700519 if(!(DelayTime & 0x01)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 SiS_DDC2Delay(SiS_Pr, 0x1000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700521 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 SiS_DDC2Delay(SiS_Pr, 0x4000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
525 } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700526 (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */
528
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700529 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
530 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
532 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
533 }
534 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
535 DelayIndex = PanelID & 0x0f;
536 } else {
537 DelayIndex = PanelID >> 4;
538 }
539 if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700540 Delay = 3;
541 } else {
542 if(DelayTime >= 2) DelayTime -= 2;
543 if(!(DelayTime & 0x01)) {
544 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
545 } else {
546 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700549 if(ROMAddr[0x13c] & 0x40) {
550 if(!(DelayTime & 0x01)) {
551 Delay = (unsigned short)ROMAddr[0x17e];
552 } else {
553 Delay = (unsigned short)ROMAddr[0x17f];
554 }
555 }
556 }
557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 SiS_ShortDelay(SiS_Pr, Delay);
559 }
560
561 } else if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 315 series, all bridges */
562
563 DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700564 if(!(DelayTime & 0x01)) {
565 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
566 } else {
567 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 Delay <<= 8;
570 SiS_DDC2Delay(SiS_Pr, Delay);
571
572 }
573
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000574#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
576 }
577}
578
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000579#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700581SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
583 int i;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700584 for(i = 0; i < DelayLoop; i++) {
585 SiS_PanelDelay(SiS_Pr, DelayTime);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 }
587}
588#endif
589
590/*********************************************/
591/* HELPER: WAIT-FOR-RETRACE FUNCTIONS */
592/*********************************************/
593
594void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700595SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700597 unsigned short watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700599 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
600 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700602 watchdog = 65535;
603 while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
604 watchdog = 65535;
605 while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606}
607
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000608#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700610SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700612 unsigned short watchdog;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700614 watchdog = 65535;
615 while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
616 watchdog = 65535;
617 while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618}
619#endif
620
621static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700622SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700624 if(SiS_Pr->ChipType < SIS_315H) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000625#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700626 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
627 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
628 }
629 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
630 SiS_WaitRetrace1(SiS_Pr);
631 } else {
632 SiS_WaitRetrace2(SiS_Pr, 0x25);
633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700635 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000636#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700637 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
638 SiS_WaitRetrace1(SiS_Pr);
639 } else {
640 SiS_WaitRetrace2(SiS_Pr, 0x30);
641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700643 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644}
645
646static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700647SiS_VBWait(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700649 unsigned short tempal,temp,i,j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700651 temp = 0;
652 for(i = 0; i < 3; i++) {
653 for(j = 0; j < 100; j++) {
654 tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
655 if(temp & 0x01) {
656 if((tempal & 0x08)) continue;
657 else break;
658 } else {
659 if(!(tempal & 0x08)) continue;
660 else break;
661 }
662 }
663 temp ^= 0x01;
664 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665}
666
667static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700668SiS_VBLongWait(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700670 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
671 SiS_VBWait(SiS_Pr);
672 } else {
673 SiS_WaitRetrace1(SiS_Pr);
674 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675}
676
677/*********************************************/
678/* HELPER: MISC */
679/*********************************************/
680
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000681#ifdef CONFIG_FB_SIS_300
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800682static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700683SiS_Is301B(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800685 if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
686 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687}
688#endif
689
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800690static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700691SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700693 if(SiS_Pr->ChipType == SIS_730) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800694 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700695 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800696 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
697 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800700bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700701SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702{
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000703#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700704 if(SiS_Pr->ChipType >= SIS_315H) {
705 if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800706 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700707 }
708 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800710 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711}
712
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800713bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700714SiS_IsVAMode(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000716#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700717 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700719 if(SiS_Pr->ChipType >= SIS_315H) {
720 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800721 if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700722 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800724 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725}
726
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000727#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800728static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700729SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800731 if(SiS_IsVAMode(SiS_Pr)) return true;
732 if(SiS_CRT2IsLCD(SiS_Pr)) return true;
733 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734}
735#endif
736
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800737static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700738SiS_IsDualLink(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739{
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000740#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700741 if(SiS_Pr->ChipType >= SIS_315H) {
742 if((SiS_CRT2IsLCD(SiS_Pr)) ||
743 (SiS_IsVAMode(SiS_Pr))) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800744 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700745 }
746 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747#endif
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800748 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749}
750
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000751#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800752static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700753SiS_TVEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800755 if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700756 if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800757 if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700758 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800759 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760}
761#endif
762
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000763#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800764static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700765SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766{
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800767 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
768 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769}
770#endif
771
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000772#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800773static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700774SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700776 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800777 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700778 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800779 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780}
781#endif
782
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000783#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800784static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700785SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700787 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700789 if(SiS_Pr->ChipType == SIS_650) {
790 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
791 /* Check for revision != A0 only */
792 if((flag == 0xe0) || (flag == 0xc0) ||
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800793 (flag == 0xb0) || (flag == 0x90)) return false;
794 } else if(SiS_Pr->ChipType >= SIS_661) return false;
795 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796}
797#endif
798
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000799#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800800static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700801SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700803 if(SiS_Pr->ChipType >= SIS_315H) {
804 /* YPrPb = 0x08 */
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800805 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700806 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800807 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808}
809#endif
810
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000811#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800812static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700813SiS_IsChScart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700815 if(SiS_Pr->ChipType >= SIS_315H) {
816 /* Scart = 0x04 */
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800817 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700818 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800819 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820}
821#endif
822
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000823#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800824static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700825SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700827 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700829 if(SiS_Pr->ChipType >= SIS_315H) {
830 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800831 if(flag & SetCRT2ToTV) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700832 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800833 if(flag & EnableCHYPbPr) return true; /* = YPrPb = 0x08 */
834 if(flag & EnableCHScart) return true; /* = Scart = 0x04 - TW */
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700835 } else {
836 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800837 if(flag & SetCRT2ToTV) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700838 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800839 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840}
841#endif
842
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000843#ifdef CONFIG_FB_SIS_315
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800844static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700845SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700847 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700849 if(SiS_Pr->ChipType >= SIS_315H) {
850 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800851 if(flag & SetCRT2ToLCD) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700852 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800853 if(flag & SetToLCDA) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700854 } else {
855 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800856 if(flag & SetCRT2ToLCD) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700857 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800858 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859}
860#endif
861
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800862static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700863SiS_HaveBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700865 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700867 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800868 return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700869 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
870 flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800871 if((flag == 1) || (flag == 2)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700872 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800873 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874}
875
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800876static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700877SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700879 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700881 if(SiS_HaveBridge(SiS_Pr)) {
882 flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
883 if(SiS_Pr->ChipType < SIS_315H) {
884 flag &= 0xa0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800885 if((flag == 0x80) || (flag == 0x20)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700886 } else {
887 flag &= 0x50;
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800888 if((flag == 0x40) || (flag == 0x10)) return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700889 }
890 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800891 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892}
893
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800894static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700895SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700897 unsigned short flag1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700899 flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
Richard Knutssonc30660ea2007-02-12 00:55:06 -0800900 if(flag1 & (SetInSlaveMode >> 8)) return true;
901 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902}
903
904/*********************************************/
905/* GET VIDEO BRIDGE CONFIG INFO */
906/*********************************************/
907
908/* Setup general purpose IO for Chrontel communication */
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000909#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700911SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700913 unsigned int acpibase;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 unsigned short temp;
915
916 if(!(SiS_Pr->SiS_ChSW)) return;
917
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700918 acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 acpibase &= 0xFFFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700920 if(!acpibase) return;
921 temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 temp &= 0xFEFF;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700923 SiS_SetRegShort((acpibase + 0x3c), temp);
924 temp = SiS_GetRegShort((acpibase + 0x3c));
925 temp = SiS_GetRegShort((acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 temp &= 0xFEFF;
927 if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700928 SiS_SetRegShort((acpibase + 0x3a), temp);
929 temp = SiS_GetRegShort((acpibase + 0x3a));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930}
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700931#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932
933void
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700934SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
935 unsigned short ModeIdIndex, int checkcrt2mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936{
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700937 unsigned short tempax, tempbx, temp;
938 unsigned short modeflag, resinfo = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700940 SiS_Pr->SiS_SetFlag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700942 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700944 SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700946 if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
947 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
948 }
949
950 tempbx = 0;
951
952 if(SiS_HaveBridge(SiS_Pr)) {
953
954 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
955 tempbx |= temp;
956 tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
957 tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
958 tempbx |= tempax;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
Aaro Koskinenf7854e52010-11-19 21:58:47 +0000960#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700961 if(SiS_Pr->ChipType >= SIS_315H) {
962 if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 if(ModeNo == 0x03) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700964 /* Mode 0x03 is never in driver mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
966 }
967 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700968 /* Reset LCDA setting if not driver mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
970 }
971 if(IS_SIS650) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700972 if(SiS_Pr->SiS_UseLCDA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
974 if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700975 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 }
977 }
978 }
979 }
980 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700981 if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
982 tempbx |= SetCRT2ToLCDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 }
984 }
985
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700986 if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700988 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
989 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
990 if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
991 else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
992 tempbx |= SetCRT2ToYPbPr525750;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 }
994 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -0700995 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
998 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
999 if(temp & SetToLCDA) {
1000 tempbx |= SetCRT2ToLCDA;
1001 }
1002 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001003 if(temp & EnableCHYPbPr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 tempbx |= SetCRT2ToCHYPbPr;
1005 }
1006 }
1007 }
1008 }
1009
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001010#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001012 if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
1013 tempbx &= ~(SetCRT2ToRAMDAC);
1014 }
1015
1016 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 temp = SetCRT2ToSVIDEO |
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001018 SetCRT2ToAVIDEO |
1019 SetCRT2ToSCART |
1020 SetCRT2ToLCDA |
1021 SetCRT2ToLCD |
1022 SetCRT2ToRAMDAC |
1023 SetCRT2ToHiVision |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 SetCRT2ToYPbPr525750;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001025 } else {
1026 if(SiS_Pr->ChipType >= SIS_315H) {
1027 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1028 temp = SetCRT2ToAVIDEO |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 SetCRT2ToSVIDEO |
1030 SetCRT2ToSCART |
1031 SetCRT2ToLCDA |
1032 SetCRT2ToLCD |
1033 SetCRT2ToCHYPbPr;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001034 } else {
1035 temp = SetCRT2ToLCDA |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 SetCRT2ToLCD;
1037 }
1038 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001039 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1040 temp = SetCRT2ToTV | SetCRT2ToLCD;
1041 } else {
1042 temp = SetCRT2ToLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 }
1044 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001045 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001047 if(!(tempbx & temp)) {
1048 tempax = DisableCRT2Display;
1049 tempbx = 0;
1050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001052 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1053
1054 unsigned short clearmask = ( DriverMode |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 DisableCRT2Display |
1056 LoadDACFlag |
1057 SetNotSimuMode |
1058 SetInSlaveMode |
1059 SetPALTV |
1060 SwitchCRT2 |
1061 SetSimuScanMode );
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001062
1063 if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 if(tempbx & SetCRT2ToRAMDAC) tempbx &= (clearmask | SetCRT2ToRAMDAC);
1065 if(tempbx & SetCRT2ToLCD) tempbx &= (clearmask | SetCRT2ToLCD);
1066 if(tempbx & SetCRT2ToSCART) tempbx &= (clearmask | SetCRT2ToSCART);
1067 if(tempbx & SetCRT2ToHiVision) tempbx &= (clearmask | SetCRT2ToHiVision);
1068 if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001069
1070 } else {
1071
1072 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 if(tempbx & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001074 tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 }
1076 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001077 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1078 if(tempbx & SetCRT2ToTV) {
1079 tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001082 if(tempbx & SetCRT2ToLCD) {
1083 tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
1084 }
1085 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 if(tempbx & SetCRT2ToLCDA) {
1087 tempbx |= SetCRT2ToLCD;
1088 }
1089 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001090
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 }
1092
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001093 if(tempax & DisableCRT2Display) {
1094 if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1095 tempbx = SetSimuScanMode | DisableCRT2Display;
1096 }
1097 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001099 if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101 /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
1102 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
1103 if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
1104 ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001105 modeflag &= (~CRT2Mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 }
1107 }
1108
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001109 if(!(tempbx & SetSimuScanMode)) {
1110 if(tempbx & SwitchCRT2) {
1111 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1112 if(resinfo != SIS_RI_1600x1200) {
1113 tempbx |= SetSimuScanMode;
1114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001116 } else {
1117 if(SiS_BridgeIsEnabled(SiS_Pr)) {
1118 if(!(tempbx & DriverMode)) {
1119 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 tempbx |= SetSimuScanMode;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001121 }
1122 }
1123 }
1124 }
1125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001127 if(!(tempbx & DisableCRT2Display)) {
1128 if(tempbx & DriverMode) {
1129 if(tempbx & SetSimuScanMode) {
1130 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1131 if(resinfo != SIS_RI_1600x1200) {
1132 tempbx |= SetInSlaveMode;
1133 }
1134 }
1135 }
1136 } else {
1137 tempbx |= SetInSlaveMode;
1138 }
1139 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001143 SiS_Pr->SiS_VBInfo = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001145#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001146 if(SiS_Pr->ChipType == SIS_630) {
1147 SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1148 }
1149#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001151#if 0
1152 printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1154#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155}
1156
1157/*********************************************/
1158/* DETERMINE YPbPr MODE */
1159/*********************************************/
1160
1161void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001162SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163{
1164
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001165 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001167 /* Note: This variable is only used on 30xLV systems.
1168 * CR38 has a different meaning on LVDS/CH7019 systems.
1169 * On 661 and later, these bits moved to CR35.
1170 *
1171 * On 301, 301B, only HiVision 1080i is supported.
1172 * On 30xLV, 301C, only YPbPr 1080i is supported.
1173 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001175 SiS_Pr->SiS_YPbPr = 0;
1176 if(SiS_Pr->ChipType >= SIS_661) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001178 if(SiS_Pr->SiS_VBType) {
1179 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1180 SiS_Pr->SiS_YPbPr = YPbPrHiVision;
1181 }
1182 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001184 if(SiS_Pr->ChipType >= SIS_315H) {
1185 if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1186 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1187 if(temp & 0x08) {
1188 switch((temp >> 4)) {
1189 case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i; break;
1190 case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p; break;
1191 case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p; break;
1192 case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
1193 }
1194 }
1195 }
1196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
1198}
1199
1200/*********************************************/
1201/* DETERMINE TVMode flag */
1202/*********************************************/
1203
1204void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001205SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001207 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1208 unsigned short temp, temp1, resinfo = 0, romindex = 0;
1209 unsigned char OutputSelect = *SiS_Pr->pSiS_OutputSelect;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001211 SiS_Pr->SiS_TVMode = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001213 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
1214 if(SiS_Pr->UseCustomMode) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001216 if(ModeNo > 0x13) {
1217 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001220 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001222 if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001224 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1225 temp = 0;
1226 if((SiS_Pr->ChipType == SIS_630) ||
1227 (SiS_Pr->ChipType == SIS_730)) {
1228 temp = 0x35;
1229 romindex = 0xfe;
1230 } else if(SiS_Pr->ChipType >= SIS_315H) {
1231 temp = 0x38;
1232 if(SiS_Pr->ChipType < XGI_20) {
1233 romindex = 0xf3;
1234 if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
1235 }
1236 }
1237 if(temp) {
1238 if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
1239 OutputSelect = ROMAddr[romindex];
1240 if(!(OutputSelect & EnablePALMN)) {
1241 SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
1242 }
1243 }
1244 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
1245 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1246 if(temp1 & EnablePALM) { /* 0x40 */
1247 SiS_Pr->SiS_TVMode |= TVSetPALM;
1248 SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1249 } else if(temp1 & EnablePALN) { /* 0x80 */
1250 SiS_Pr->SiS_TVMode |= TVSetPALN;
1251 }
1252 } else {
1253 if(temp1 & EnableNTSCJ) { /* 0x40 */
1254 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1255 }
1256 }
1257 }
1258 /* Translate HiVision/YPbPr to our new flags */
1259 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1260 if(SiS_Pr->SiS_YPbPr == YPbPr750p) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1261 else if(SiS_Pr->SiS_YPbPr == YPbPr525p) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1262 else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
1263 else SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1264 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
1265 SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
1266 SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
1267 } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
1268 SiS_Pr->SiS_TVMode |= TVSetPAL;
1269 }
1270 }
1271 } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1272 if(SiS_Pr->SiS_CHOverScan) {
1273 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
1274 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1275 if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
1276 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1277 }
1278 } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1279 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
1280 if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
1281 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1282 }
1283 }
1284 if(SiS_Pr->SiS_CHSOverScan) {
1285 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1286 }
1287 }
1288 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1289 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1290 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1291 if(temp & EnablePALM) SiS_Pr->SiS_TVMode |= TVSetPALM;
1292 else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
1293 } else {
1294 if(temp & EnableNTSCJ) {
1295 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1296 }
1297 }
1298 }
1299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001301 } else { /* 661 and later */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001303 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1304 if(temp1 & 0x01) {
1305 SiS_Pr->SiS_TVMode |= TVSetPAL;
1306 if(temp1 & 0x08) {
1307 SiS_Pr->SiS_TVMode |= TVSetPALN;
1308 } else if(temp1 & 0x04) {
1309 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1310 SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1311 }
1312 SiS_Pr->SiS_TVMode |= TVSetPALM;
1313 }
1314 } else {
1315 if(temp1 & 0x02) {
1316 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1317 }
1318 }
1319 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1320 if(SiS_Pr->SiS_CHOverScan) {
1321 if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
1322 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1323 }
1324 }
1325 }
1326 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1327 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1328 temp1 &= 0xe0;
1329 if(temp1 == 0x00) SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1330 else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1331 else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1332 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1333 SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
1334 }
1335 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
1336 if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
1337 SiS_Pr->SiS_TVMode |= TVAspect169;
1338 } else {
1339 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
1340 if(temp1 & 0x02) {
1341 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
1342 SiS_Pr->SiS_TVMode |= TVAspect169;
1343 } else {
1344 SiS_Pr->SiS_TVMode |= TVAspect43LB;
1345 }
1346 } else {
1347 SiS_Pr->SiS_TVMode |= TVAspect43;
1348 }
1349 }
1350 }
1351 }
1352 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001354 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001356 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001358 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1359 SiS_Pr->SiS_TVMode |= TVSetPAL;
1360 SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
1361 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1362 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
1363 SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
1364 }
1365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001367 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1368 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
1369 SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1370 }
1371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001373 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
1374 if(resinfo == SIS_RI_1024x768) {
1375 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
1376 SiS_Pr->SiS_TVMode |= TVSet525p1024;
1377 } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
1378 SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
1379 }
1380 }
1381 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001383 SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
1384 if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
1385 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
1386 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1387 } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
1388 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1389 } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
1390 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
1391 SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1392 }
1393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001397 SiS_Pr->SiS_VBInfo &= ~SetPALTV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398}
1399
1400/*********************************************/
1401/* GET LCD INFO */
1402/*********************************************/
1403
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001404static unsigned short
1405SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001407 unsigned short temp = SiS_Pr->SiS_LCDResInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 /* Translate my LCDResInfo to BIOS value */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001409 switch(temp) {
1410 case Panel_1280x768_2: temp = Panel_1280x768; break;
1411 case Panel_1280x800_2: temp = Panel_1280x800; break;
1412 case Panel_1280x854: temp = Panel661_1280x854; break;
1413 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 return temp;
1415}
1416
1417static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001418SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419{
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001420#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001421 unsigned char *ROMAddr;
1422 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001424 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001426 SiS_Pr->SiS_NeedRomModeData = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 SiS_Pr->PanelHT = temp;
1428 }
1429 if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001430 SiS_Pr->SiS_NeedRomModeData = true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001431 SiS_Pr->PanelVT = temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 }
1433 SiS_Pr->PanelHRS = SISGETROMW(10);
1434 SiS_Pr->PanelHRE = SISGETROMW(12);
1435 SiS_Pr->PanelVRS = SISGETROMW(14);
1436 SiS_Pr->PanelVRE = SISGETROMW(16);
1437 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1438 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001439 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
1441 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
1442 SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
1443 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
1444
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 }
1446#endif
1447}
1448
1449static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001450SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
1451 const unsigned char *nonscalingmodes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001453 int i = 0;
1454 while(nonscalingmodes[i] != 0xff) {
1455 if(nonscalingmodes[i++] == resinfo) {
1456 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
1457 (SiS_Pr->UsePanelScaler == -1)) {
1458 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1459 }
1460 break;
1461 }
1462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463}
1464
1465void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001466SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001468 unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001469 bool panelcanscale = false;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001470#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001471 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1472 static const unsigned char SiS300SeriesLCDRes[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 { 0, 1, 2, 3, 7, 4, 5, 8,
1474 0, 0, 10, 0, 0, 0, 0, 15 };
1475#endif
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001476#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001477 unsigned char *myptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
1480 SiS_Pr->SiS_LCDResInfo = 0;
1481 SiS_Pr->SiS_LCDTypeInfo = 0;
1482 SiS_Pr->SiS_LCDInfo = 0;
1483 SiS_Pr->PanelHRS = 999; /* HSync start */
1484 SiS_Pr->PanelHRE = 999; /* HSync end */
1485 SiS_Pr->PanelVRS = 999; /* VSync start */
1486 SiS_Pr->PanelVRE = 999; /* VSync end */
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001487 SiS_Pr->SiS_NeedRomModeData = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001489 /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001490 SiS_Pr->Alternate1600x1200 = false;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001491
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
1493
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001494 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1495
1496 if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1498 modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
1499 modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
1500 }
1501
1502 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
1503
1504 /* For broken BIOSes: Assume 1024x768 */
1505 if(temp == 0) temp = 0x02;
1506
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001507 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001509 } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
1511 } else {
1512 SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1513 }
1514 temp &= 0x0f;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001515#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001516 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
1518 if(SiS_Pr->SiS_VBType & VB_SIS301) {
1519 if(temp < 0x0f) temp &= 0x07;
1520 }
1521 /* Translate 300 series LCDRes to 315 series for unified usage */
1522 temp = SiS300SeriesLCDRes[temp];
1523 }
1524#endif
1525
1526 /* Translate to our internal types */
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001527#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001528 if(SiS_Pr->ChipType == SIS_550) {
1529 if (temp == Panel310_1152x768) temp = Panel_320x240_2; /* Verified working */
1530 else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
1531 else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
1532 } else if(SiS_Pr->ChipType >= SIS_661) {
1533 if(temp == Panel661_1280x854) temp = Panel_1280x854;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001535#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001537 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 if(temp == Panel310_1280x768) {
1539 temp = Panel_1280x768_2;
1540 }
1541 if(SiS_Pr->SiS_ROMNew) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001542 if(temp == Panel661_1280x800) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 temp = Panel_1280x800_2;
1544 }
1545 }
1546 }
1547
1548 SiS_Pr->SiS_LCDResInfo = temp;
1549
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001550#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1552 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001553 SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001555 SiS_Pr->SiS_LCDResInfo = Panel_848x480;
1556 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
1557 SiS_Pr->SiS_LCDResInfo = Panel_856x480;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 }
1559 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001560#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
1562 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1563 if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
1564 SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
1565 } else {
1566 if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
1567 SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
1568 }
1569
1570 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
1571 SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
1572 /* Need temp below! */
1573
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001574 /* These must/can't scale no matter what */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001576 case Panel_320x240_1:
1577 case Panel_320x240_2:
1578 case Panel_320x240_3:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 case Panel_1280x960:
1580 SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001581 break;
1582 case Panel_640x480:
1583 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 }
1585
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001586 panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
1588 if(!SiS_Pr->UsePanelScaler) SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1589 else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1590
1591 /* Dual link, Pass 1:1 BIOS default, etc. */
Aaro Koskinenf7854e52010-11-19 21:58:47 +00001592#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001593 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001595 if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001597 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1598 if(SiS_Pr->SiS_ROMNew) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001600 } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
1601 if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 }
1603 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001604 } else if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001606 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 }
1608 if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001609 SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001611 if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
1612 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1614 }
1615 } else if(!(SiS_Pr->SiS_ROMNew)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001616 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1617 if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
1619 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1620 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001621 if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001623 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
1625 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1626 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001627 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 }
1629 }
1630#endif
1631
1632 /* Pass 1:1 */
1633 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
1634 /* Always center screen on LVDS (if scaling is disabled) */
1635 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1636 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1637 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001638 /* Always center screen on SiS LVDS (if scaling is disabled) */
1639 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001641 /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
1642 if(panelcanscale) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1643 if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 }
1645 }
1646
1647 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1648 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1649
1650 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001651 case Panel_320x240_1:
1652 case Panel_320x240_2:
1653 case Panel_320x240_3: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
1654 SiS_Pr->PanelVRS = 24; SiS_Pr->PanelVRE = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 SiS_Pr->PanelVCLKIdx300 = VCLK28;
1656 SiS_Pr->PanelVCLKIdx315 = VCLK28;
1657 break;
1658 case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001659 SiS_Pr->PanelVRE = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 SiS_Pr->PanelVCLKIdx300 = VCLK28;
1661 SiS_Pr->PanelVCLKIdx315 = VCLK28;
1662 break;
1663 case Panel_800x600: SiS_Pr->PanelXRes = 800; SiS_Pr->PanelYRes = 600;
1664 SiS_Pr->PanelHT = 1056; SiS_Pr->PanelVT = 628;
1665 SiS_Pr->PanelHRS = 40; SiS_Pr->PanelHRE = 128;
1666 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 4;
1667 SiS_Pr->PanelVCLKIdx300 = VCLK40;
1668 SiS_Pr->PanelVCLKIdx315 = VCLK40;
1669 break;
1670 case Panel_1024x600: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 600;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001671 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1673 SiS_Pr->PanelVRS = 2 /* 88 */ ; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001674 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001676 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001678 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1680 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001681 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 SiS_Pr->PanelHRS = 23;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001683 SiS_Pr->PanelVRE = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 }
1685 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1686 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001687 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 break;
1689 case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001690 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
1691 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001693 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 SiS_Pr->PanelHRS = 23;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001695 SiS_Pr->PanelVRE = 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001697 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001699 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001701 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 case Panel_1280x720: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 720;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001703 SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 SiS_Pr->PanelHRS = 110; SiS_Pr->PanelHRE = 40;
1705 SiS_Pr->PanelVRS = 5; SiS_Pr->PanelVRE = 5;
1706 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
1707 /* Data above for TMDS (projector); get from BIOS for LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001708 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 break;
1710 case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001711 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 806;
1713 SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
1714 SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
1715 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001716 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRS = 112;
1718 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1719 SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
1720 SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
1721 }
1722 break;
1723 case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001724 SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1726 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1727 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001728 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 break;
1730 case Panel_1280x800: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001731 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 SiS_Pr->PanelHRS = 21; SiS_Pr->PanelHRE = 24;
1733 SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
1734 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001735 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 break;
1737 case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001738 SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1740 SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
1741 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001742 SiS_GetLCDInfoBIOS(SiS_Pr);
1743 break;
1744 case Panel_1280x854: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 854;
1745 SiS_Pr->PanelHT = 1664; SiS_Pr->PanelVT = 861;
1746 SiS_Pr->PanelHRS = 16; SiS_Pr->PanelHRE = 112;
1747 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1748 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
1749 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 break;
1751 case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001752 SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1754 SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001755 if(resinfo == SIS_RI_1280x1024) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
1757 SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
1758 }
1759 break;
1760 case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001761 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1763 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1764 SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1765 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001766 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 break;
1768 case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001769 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1770 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1772 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001773 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 break;
1775 case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001776 SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 SiS_Pr->PanelHRS = 64; SiS_Pr->PanelHRE = 192;
1778 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1779 SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001780 if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
1781 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1782 SiS_Pr->PanelHT = 1760; SiS_Pr->PanelVT = 1235;
1783 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 32;
1784 SiS_Pr->PanelVRS = 2; SiS_Pr->PanelVRE = 4;
1785 SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08001786 SiS_Pr->Alternate1600x1200 = true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001787 }
1788 } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
1789 SiS_Pr->PanelHT = 2048; SiS_Pr->PanelVT = 1320;
1790 SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
1791 SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
1792 }
1793 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 break;
1795 case Panel_1680x1050: SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001796 SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 SiS_Pr->PanelHRS = 26; SiS_Pr->PanelHRE = 76;
1798 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1799 SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001800 SiS_GetLCDInfoBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 break;
1802 case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001803 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1804 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001806 SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
1807 break;
1808 case Panel_856x480: SiS_Pr->PanelXRes = 856; SiS_Pr->PanelYRes = 480;
1809 SiS_Pr->PanelHT = 1088; SiS_Pr->PanelVT = 525;
1810 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001812 SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 SiS_Pr->PanelHT = SiS_Pr->CHTotal;
1814 SiS_Pr->PanelVT = SiS_Pr->CVTotal;
1815 if(SiS_Pr->CP_PreferredIndex != -1) {
1816 SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001817 SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 SiS_Pr->PanelHT = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
1819 SiS_Pr->PanelVT = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
1820 SiS_Pr->PanelHRS = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
1821 SiS_Pr->PanelHRE = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
1822 SiS_Pr->PanelVRS = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
1823 SiS_Pr->PanelVRE = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
1824 SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
1825 SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
1826 SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
1827 SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
1828 if(SiS_Pr->CP_PrefClock) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001829 int idx;
1830 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001832 if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 else idx = VCLK_CUSTOM_315;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001834 SiS_Pr->SiS_VCLKData[idx].CLOCK =
1835 SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
1836 SiS_Pr->SiS_VCLKData[idx].SR2B =
1837 SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
1838 SiS_Pr->SiS_VCLKData[idx].SR2C =
1839 SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 }
1841 }
1842 break;
1843 default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001844 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 break;
1846 }
1847
1848 /* Special cases */
1849 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
1850 (SiS_Pr->SiS_IF_DEF_DSTN) ||
1851 (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1852 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001853 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1854 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 SiS_Pr->PanelHRS = 999;
1856 SiS_Pr->PanelHRE = 999;
1857 }
1858
1859 if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1860 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001861 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1862 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 SiS_Pr->PanelVRS = 999;
1864 SiS_Pr->PanelVRE = 999;
1865 }
1866
1867 /* DontExpand overrule */
1868 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
1869
1870 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
1871 /* No scaling for this mode on any panel (LCD=CRT2)*/
1872 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1873 }
1874
1875 switch(SiS_Pr->SiS_LCDResInfo) {
1876
1877 case Panel_Custom:
1878 case Panel_1152x864:
1879 case Panel_1280x768: /* TMDS only */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001880 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 break;
1882
1883 case Panel_800x600: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001884 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
1886 };
1887 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1888 break;
1889 }
1890 case Panel_1024x768: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001891 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1893 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1894 0xff
1895 };
1896 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1897 break;
1898 }
1899 case Panel_1280x720: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001900 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1902 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1903 0xff
1904 };
1905 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1906 if(SiS_Pr->PanelHT == 1650) {
1907 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1908 }
1909 break;
1910 }
1911 case Panel_1280x768_2: { /* LVDS only */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001912 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1914 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1915 SIS_RI_1152x768,0xff
1916 };
1917 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1918 switch(resinfo) {
1919 case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001920 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1921 }
1922 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001924 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 }
1926 case Panel_1280x800: { /* SiS TMDS special (Averatec 6200 series) */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001927 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1929 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1930 SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
1931 };
1932 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001933 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 }
1935 case Panel_1280x800_2: { /* SiS LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001936 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1938 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1939 SIS_RI_1152x768,0xff
1940 };
1941 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1942 switch(resinfo) {
1943 case SIS_RI_1280x720:
1944 case SIS_RI_1280x768: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001945 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1946 }
1947 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001949 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001951 case Panel_1280x854: { /* SiS LVDS */
1952 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1954 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001955 SIS_RI_1152x768,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 };
1957 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001958 switch(resinfo) {
1959 case SIS_RI_1280x720:
1960 case SIS_RI_1280x768:
1961 case SIS_RI_1280x800: if(SiS_Pr->UsePanelScaler == -1) {
1962 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1963 }
1964 break;
1965 }
1966 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001968 case Panel_1280x960: {
1969 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1971 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1972 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001973 SIS_RI_1280x854,0xff
1974 };
1975 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1976 break;
1977 }
1978 case Panel_1280x1024: {
1979 static const unsigned char nonscalingmodes[] = {
1980 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1981 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1982 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
1983 SIS_RI_1280x854,SIS_RI_1280x960,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 };
1985 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1986 break;
1987 }
1988 case Panel_1400x1050: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001989 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1991 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001992 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
1993 SIS_RI_1280x960,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 };
1995 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001996 switch(resinfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07001998 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1999 }
2000 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002002 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 }
2004 break;
2005 }
2006 case Panel_1600x1200: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002007 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2009 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2010 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002011 SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 };
2013 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002014 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 }
2016 case Panel_1680x1050: {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002017 static const unsigned char nonscalingmodes[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2019 SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002020 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
2021 SIS_RI_1360x1024,0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 };
2023 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2024 break;
2025 }
2026 }
2027 }
2028
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002029#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002031 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2032 SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg h/v sync, RGB24(D0 = 0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 }
2034 }
2035
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002036 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002038 if(SiS_Pr->SiS_UseROM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002040 if(!(ROMAddr[0x235] & 0x02)) {
2041 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002044 }
2045 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002047 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 }
2049 }
2050 }
2051#endif
2052
2053 /* Special cases */
2054
2055 if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
2056 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2057 }
2058
2059 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
2060 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2061 }
2062
2063 switch(SiS_Pr->SiS_LCDResInfo) {
2064 case Panel_640x480:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002065 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 break;
2067 case Panel_1280x800:
2068 /* Don't pass 1:1 by default (TMDS special) */
2069 if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2070 break;
2071 case Panel_1280x960:
2072 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2073 break;
2074 case Panel_Custom:
2075 if((!SiS_Pr->CP_PrefClock) ||
2076 (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
2077 SiS_Pr->SiS_LCDInfo |= LCDPass11;
2078 }
2079 break;
2080 }
2081
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002082 if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2084 }
2085
2086 /* (In)validate LCDPass11 flag */
2087 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2088 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2089 }
2090
2091 /* LVDS DDA */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002092 if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
2094 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
2095 if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
2096 if(ModeNo == 0x12) {
2097 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002098 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 }
2100 } else if(ModeNo > 0x13) {
2101 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002102 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2103 if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
2104 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 }
2106 }
2107 }
2108 }
2109 }
2110 }
2111
2112 if(modeflag & HalfDCLK) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002113 if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002115 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2117 } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
2118 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2119 } else if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002120 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
2121 if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2122 } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
2123 if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
2126 }
2127
2128 }
2129
2130 /* VESA timing */
2131 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2132 if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002133 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 }
2135 } else {
2136 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2137 }
2138
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002139#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
2141 SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
2142#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143}
2144
2145/*********************************************/
2146/* GET VCLK */
2147/*********************************************/
2148
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002149unsigned short
2150SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2151 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002153 unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
2154 unsigned short modeflag, resinfo, tempbx;
2155 const unsigned char *CHTVVCLKPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156
2157 if(ModeNo <= 0x13) {
2158 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2159 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
2160 CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2161 VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002162 VCLKIndexGENCRT = VCLKIndexGEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 } else {
2164 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2165 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2166 CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2167 VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002168 VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
2169 (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 }
2171
2172 if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 30x/B/LV */
2173
2174 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2175
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002176 CRT2Index >>= 6;
2177 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002179 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2181 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002182 VCLKIndex = VCLKIndexGEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 }
2184 } else {
2185 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2186 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2187 switch(resinfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002188 /* Correct those whose IndexGEN doesn't match VBVCLK array */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 case SIS_RI_720x480: VCLKIndex = VCLK_720x480; break;
2190 case SIS_RI_720x576: VCLKIndex = VCLK_720x576; break;
2191 case SIS_RI_768x576: VCLKIndex = VCLK_768x576; break;
2192 case SIS_RI_848x480: VCLKIndex = VCLK_848x480; break;
2193 case SIS_RI_856x480: VCLKIndex = VCLK_856x480; break;
2194 case SIS_RI_800x480: VCLKIndex = VCLK_800x480; break;
2195 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
2196 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002197 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
2199 default: VCLKIndex = VCLKIndexGEN;
2200 }
2201
2202 if(ModeNo <= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002203 if(SiS_Pr->ChipType <= SIS_315PRO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002205 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
2207 }
2208 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002209 if(SiS_Pr->ChipType <= SIS_315PRO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 if(VCLKIndex == 0) VCLKIndex = 0x41;
2211 if(VCLKIndex == 1) VCLKIndex = 0x43;
2212 if(VCLKIndex == 4) VCLKIndex = 0x44;
2213 }
2214 }
2215 }
2216
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002217 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
2219 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002220 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
2221 else VCLKIndex = HiTVVCLK;
2222 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) VCLKIndex = HiTVSimuVCLK;
2223 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK;
2224 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2;
2225 else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
2226 else VCLKIndex = TVVCLK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002228 if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
2229 else VCLKIndex += TVCLKBASE_315;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002231 } else { /* VGA2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002233 VCLKIndex = VCLKIndexGENCRT;
2234 if(SiS_Pr->ChipType < SIS_315H) {
2235 if(ModeNo > 0x13) {
2236 if( (SiS_Pr->ChipType == SIS_630) &&
2237 (SiS_Pr->ChipRevision >= 0x30)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 if(VCLKIndex == 0x14) VCLKIndex = 0x34;
2239 }
2240 /* Better VGA2 clock for 1280x1024@75 */
2241 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
2242 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002243 }
2244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
2246 } else { /* If not programming CRT2 */
2247
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002248 VCLKIndex = VCLKIndexGENCRT;
2249 if(SiS_Pr->ChipType < SIS_315H) {
2250 if(ModeNo > 0x13) {
2251 if( (SiS_Pr->ChipType != SIS_630) &&
2252 (SiS_Pr->ChipType != SIS_300) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2254 }
2255 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 }
2258
2259 } else { /* LVDS */
2260
2261 VCLKIndex = CRT2Index;
2262
2263 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2264
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002265 if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266
2267 VCLKIndex &= 0x1f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002268 tempbx = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002270 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 tempbx += 2;
2272 if(SiS_Pr->SiS_ModeType > ModeVGA) {
2273 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
2274 }
2275 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2276 tempbx = 4;
2277 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2278 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2279 tempbx = 6;
2280 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2281 }
2282 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002283 switch(tempbx) {
2284 case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break;
2285 case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break;
2286 case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break;
2287 case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 case 4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002289 case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break;
2290 case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break;
2291 case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 case 8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL; break;
2293 default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002294 }
2295 VCLKIndex = CHTVVCLKPtr[VCLKIndex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002297 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002299 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2301 } else {
2302 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2303 }
2304
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002305#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 /* Special Timing: Barco iQ Pro R series */
2307 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2308
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002309 /* Special Timing: 848x480 and 856x480 parallel lvds panels */
2310 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2311 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 VCLKIndex = VCLK34_300;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002313 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 } else {
2315 VCLKIndex = VCLK34_315;
2316 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2317 }
2318 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002319#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002321 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002323 VCLKIndex = VCLKIndexGENCRT;
2324 if(SiS_Pr->ChipType < SIS_315H) {
2325 if(ModeNo > 0x13) {
2326 if( (SiS_Pr->ChipType == SIS_630) &&
2327 (SiS_Pr->ChipRevision >= 0x30) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002329 }
2330 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
2334 } else { /* if not programming CRT2 */
2335
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002336 VCLKIndex = VCLKIndexGENCRT;
2337 if(SiS_Pr->ChipType < SIS_315H) {
2338 if(ModeNo > 0x13) {
2339 if( (SiS_Pr->ChipType != SIS_630) &&
2340 (SiS_Pr->ChipType != SIS_300) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2342 }
2343#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002344 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 if(VCLKIndex == 0x0b) VCLKIndex = 0x40; /* 1024x768-70 */
2346 if(VCLKIndex == 0x0d) VCLKIndex = 0x41; /* 1024x768-75 */
2347 }
2348#endif
2349 }
2350 }
2351
2352 }
2353
2354 }
2355
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002356 return VCLKIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357}
2358
2359/*********************************************/
2360/* SET CRT2 MODE TYPE REGISTERS */
2361/*********************************************/
2362
2363static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002364SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002366 unsigned short i, j, modeflag, tempah=0;
2367 short tempcl;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002368#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002369 unsigned short tempbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370#endif
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002371#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002372 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
2373 unsigned short tempah2, tempbl2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374#endif
2375
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002376 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
2378 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2379
2380 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
2381 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
2382
2383 } else {
2384
2385 for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002386 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
2388 }
2389
2390 tempcl = SiS_Pr->SiS_ModeType;
2391
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002392 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002394#ifdef CONFIG_FB_SIS_300 /* ---- 300 series ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002396 /* For 301BDH: (with LCD via LVDS) */
2397 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
2399 tempbl &= 0xef;
2400 tempbl |= 0x02;
2401 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2402 tempbl |= 0x10;
2403 tempbl &= 0xfd;
2404 }
2405 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002408 if(ModeNo > 0x13) {
2409 tempcl -= ModeVGA;
2410 if(tempcl >= 0) {
2411 tempah = ((0x10 >> tempcl) | 0x80);
2412 }
2413 } else tempah = 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002415 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002417#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
2419 } else {
2420
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002421#ifdef CONFIG_FB_SIS_315 /* ------- 315/330 series ------ */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002423 if(ModeNo > 0x13) {
2424 tempcl -= ModeVGA;
2425 if(tempcl >= 0) {
2426 tempah = (0x08 >> tempcl);
2427 if (tempah == 0) tempah = 1;
2428 tempah |= 0x40;
2429 }
2430 } else tempah = 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002432 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002434#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
2436 }
2437
2438 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2439
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002440 if(SiS_Pr->ChipType < SIS_315H) {
2441 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002443#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002444 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2445 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2446 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2447 if(IS_SIS740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2449 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002450 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002452 }
2453#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 }
2455
2456 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2457
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002458 tempah = 0x01;
2459 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2460 tempah |= 0x02;
2461 }
2462 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2463 tempah ^= 0x05;
2464 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
2465 tempah ^= 0x01;
2466 }
2467 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002469 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002471 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002473 tempah = (tempah << 5) & 0xFF;
2474 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2475 tempah = (tempah >> 5) & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002477 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002479 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x08;
2480 else if(!(SiS_IsDualEdge(SiS_Pr))) tempah |= 0x08;
2481 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
2482 tempah &= ~0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002484 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002486 if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
2487 tempah |= 0x10;
2488 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489
2490 tempah |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002491 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002493 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002495 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002497 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2498 tempah |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002500 }
2501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002503 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504
2505 tempah = 0x80;
2506 if(SiS_Pr->SiS_VBType & VB_SIS301) {
2507 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
2508 }
2509
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002510 if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002512 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002514 tempah |= 0x40;
2515 }
2516 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002518 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
2520 } else { /* LVDS */
2521
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002522 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002524#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 /* LVDS can only be slave in 8bpp modes */
2526 tempah = 0x80;
2527 if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
2528 if(SiS_Pr->SiS_VBInfo & DriverMode) {
2529 tempah |= 0x02;
2530 }
2531 }
2532
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002533 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) tempah |= 0x02;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002535 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah ^= 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002537 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002539 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540#endif
2541
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002542 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002544#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 tempah = 0;
2546 if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002547 tempah |= 0x02;
2548 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 tempah <<= 5;
2550
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002551 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552
2553 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2554#endif
2555
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
2558 }
2559
2560 } /* LCDA */
2561
2562 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2563
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002564 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002566#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002567 /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
2569 /* The following is nearly unpreditable and varies from machine
2570 * to machine. Especially the 301DH seems to be a real trouble
2571 * maker. Some BIOSes simply set the registers (like in the
2572 * NoLCD-if-statements here), some set them according to the
2573 * LCDA stuff. It is very likely that some machines are not
2574 * treated correctly in the following, very case-orientated
2575 * code. What do I do then...?
2576 */
2577
2578 /* 740 variants match for 30xB, 301B-DH, 30xLV */
2579
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002580 if(!(IS_SIS740)) {
2581 tempah = 0x04; /* For all bridges */
2582 tempbl = 0xfb;
2583 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2584 tempah = 0x00;
2585 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 tempbl = 0xff;
2587 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002588 }
2589 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 }
2591
2592 /* The following two are responsible for eventually wrong colors
2593 * in TV output. The DH (VB_NoLCD) conditions are unknown; the
2594 * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
2595 * in a 650 box (Jake). What is the criteria?
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002596 * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
2597 * treatment like the 651+301B-DH(b0) case. Seems more to be the
2598 * chipset than the bridge revision.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 */
2600
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002601 if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 tempah = 0x30;
2603 tempbl = 0xc0;
2604 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2605 ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
2606 tempah = 0x00;
2607 tempbl = 0x00;
2608 }
2609 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
2610 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
2611 } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
2612 /* Fixes "TV-blue-bug" on 315+301 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002613 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002615 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
2616 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002618 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* For 301B-DH */
2619 tempah = 0x30; tempah2 = 0xc0;
2620 tempbl = 0xcf; tempbl2 = 0x3f;
2621 if(SiS_Pr->SiS_TVBlue == 0) {
2622 tempah = tempah2 = 0x00;
2623 } else if(SiS_Pr->SiS_TVBlue == -1) {
2624 /* Set on 651/M650, clear on 315/650 */
2625 if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
2626 tempah = tempah2 = 0x00;
2627 }
2628 }
2629 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2630 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002632 tempah = 0x30; tempah2 = 0xc0; /* For 30xB, 301C */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 tempbl = 0xcf; tempbl2 = 0x3f;
2634 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2635 tempah = tempah2 = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002636 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 tempbl = tempbl2 = 0xff;
2638 }
2639 }
2640 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2641 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2642 }
2643
2644 if(IS_SIS740) {
2645 tempah = 0x80;
2646 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
2647 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
2648 } else {
2649 tempah = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002650 tempbl = 0x7f;
2651 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2652 tempbl = 0xff;
2653 if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
2654 }
2655 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 }
2657
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002658#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002660 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002662#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002663 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002665 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2666 ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
2668 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
2669 } else {
2670 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
2671 }
2672#endif
2673
2674 }
2675
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002676 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2677 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
2678 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
2680 }
2681 }
2682
2683 } else { /* LVDS */
2684
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002685#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002686 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002688 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002690 tempah = 0x04;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 tempbl = 0xfb;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002692 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2693 tempah = 0x00;
2694 if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
2695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2697
2698 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2699 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2700 }
2701
2702 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2703
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002704 } else if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705
2706 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2707 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2708
2709 }
2710
2711 }
2712#endif
2713
2714 }
2715
2716}
2717
2718/*********************************************/
2719/* GET RESOLUTION DATA */
2720/*********************************************/
2721
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002722unsigned short
2723SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002725 if(ModeNo <= 0x13)
2726 return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
2727 else
2728 return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729}
2730
2731static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002732SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002734 unsigned short xres, yres, modeflag=0, resindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002736 if(SiS_Pr->UseCustomMode) {
2737 xres = SiS_Pr->CHDisplay;
2738 if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
2739 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2740 /* DoubleScanMode-check done in CheckCalcCustomMode()! */
2741 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
2742 return;
2743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002745 resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002747 if(ModeNo <= 0x13) {
2748 xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
2749 yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
2750 } else {
2751 xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
2752 yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
2753 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002756 if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002758 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
2759 if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
2760 if(yres == 350) yres = 400;
2761 }
2762 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
2763 if(ModeNo == 0x12) yres = 400;
2764 }
2765 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002767 if(modeflag & HalfDCLK) xres <<= 1;
2768 if(modeflag & DoubleScanMode) yres <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002772 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002774 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2775 switch(SiS_Pr->SiS_LCDResInfo) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 case Panel_1024x768:
2777 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002778 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2779 if(yres == 350) yres = 357;
2780 if(yres == 400) yres = 420;
2781 if(yres == 480) yres = 525;
2782 }
2783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 break;
2785 case Panel_1280x1024:
2786 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2787 /* BIOS bug - does this regardless of scaling */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002788 if(yres == 400) yres = 405;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002790 if(yres == 350) yres = 360;
2791 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
2792 if(yres == 360) yres = 375;
2793 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 break;
2795 case Panel_1600x1200:
2796 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002797 if(yres == 1024) yres = 1056;
2798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002800 }
2801 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002803 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002805 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2806 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
2807 if(xres == 720) xres = 640;
2808 }
2809 } else if(xres == 720) xres = 640;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002811 if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
2812 yres = 400;
2813 if(SiS_Pr->ChipType >= SIS_315H) {
2814 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
2815 } else {
2816 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
2817 }
2818 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
2819 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002821 }
2822 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2823 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824}
2825
2826/*********************************************/
2827/* GET CRT2 TIMING DATA */
2828/*********************************************/
2829
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002831SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2832 unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
2833 unsigned short *ResIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002835 unsigned short tempbx=0, tempal=0, resinfo=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836
2837 if(ModeNo <= 0x13) {
2838 tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2839 } else {
2840 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2841 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2842 }
2843
2844 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
2845
2846 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
2847
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002848 tempbx = SiS_Pr->SiS_LCDResInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
2850
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002851 /* patch index */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
2853 if (resinfo == SIS_RI_1280x800) tempal = 9;
2854 else if(resinfo == SIS_RI_1400x1050) tempal = 11;
2855 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002856 (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
2857 (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858 if (resinfo == SIS_RI_1280x768) tempal = 9;
2859 }
2860
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002861 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 /* Pass 1:1 only (center-screen handled outside) */
2863 /* This is never called for the panel's native resolution */
2864 /* since Pass1:1 will not be set in this case */
2865 tempbx = 100;
2866 if(ModeNo >= 0x13) {
2867 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
2868 }
2869 }
2870
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002871#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
2873 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
2874 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002875 tempbx = 200;
2876 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877 }
2878 }
2879 }
2880#endif
2881
2882 } else { /* TV */
2883
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002884 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2885 /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
2886 tempbx = 2;
2887 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 tempbx = 13;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002889 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
2890 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002892 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7;
2893 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
2894 else tempbx = 5;
2895 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2896 } else {
2897 if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3;
2898 else tempbx = 4;
2899 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2900 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901
2902 }
2903
2904 tempal &= 0x3F;
2905
2906 if(ModeNo > 0x13) {
2907 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002908 switch(resinfo) {
2909 case SIS_RI_720x480:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910 tempal = 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002911 if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) tempal = 9;
2912 break;
2913 case SIS_RI_720x576:
2914 case SIS_RI_768x576:
2915 case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
2916 tempal = 6;
2917 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2918 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002920 break;
2921 case SIS_RI_800x480:
2922 tempal = 4;
2923 break;
2924 case SIS_RI_512x384:
2925 case SIS_RI_1024x768:
2926 tempal = 7;
2927 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2928 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempal = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002930 break;
2931 case SIS_RI_1280x720:
2932 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2933 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002935 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 }
2937 }
2938 }
2939
2940 *CRT2Index = tempbx;
2941 *ResIndex = tempal;
2942
2943 } else { /* LVDS, 301B-DH (if running on LCD) */
2944
2945 tempbx = 0;
2946 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
2947
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002948 tempbx = 90;
2949 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2950 tempbx = 92;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 if(SiS_Pr->SiS_ModeType > ModeVGA) {
2952 if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
2953 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002954 if(SiS_Pr->SiS_TVMode & TVSetPALM) tempbx = 94;
2955 else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
2956 }
2957 if(tempbx != 99) {
2958 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
2959 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960
2961 } else {
2962
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002963 switch(SiS_Pr->SiS_LCDResInfo) {
2964 case Panel_640x480: tempbx = 12; break;
2965 case Panel_320x240_1: tempbx = 10; break;
2966 case Panel_320x240_2:
2967 case Panel_320x240_3: tempbx = 14; break;
2968 case Panel_800x600: tempbx = 16; break;
2969 case Panel_1024x600: tempbx = 18; break;
2970 case Panel_1152x768:
2971 case Panel_1024x768: tempbx = 20; break;
2972 case Panel_1280x768: tempbx = 22; break;
2973 case Panel_1280x1024: tempbx = 24; break;
2974 case Panel_1400x1050: tempbx = 26; break;
2975 case Panel_1600x1200: tempbx = 28; break;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002976#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 case Panel_Barco1366: tempbx = 80; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002978#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 }
2980
2981 switch(SiS_Pr->SiS_LCDResInfo) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002982 case Panel_320x240_1:
2983 case Panel_320x240_2:
2984 case Panel_320x240_3:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 case Panel_640x480:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 break;
2987 default:
2988 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
2989 }
2990
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002991 if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992
Aaro Koskinenf7854e52010-11-19 21:58:47 +00002993#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
2995 tempbx = 82;
2996 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07002997 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 tempbx = 84;
2999 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3000 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003001#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
3003 }
3004
3005 (*CRT2Index) = tempbx;
3006 (*ResIndex) = tempal & 0x1F;
3007 }
3008}
3009
3010static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003011SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3012 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003014 unsigned short tempax=0, tempbx=0, index, dotclock;
3015 unsigned short temp1=0, modeflag=0, tempcx=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016
3017 SiS_Pr->SiS_RVBHCMAX = 1;
3018 SiS_Pr->SiS_RVBHCFACT = 1;
3019
3020 if(ModeNo <= 0x13) {
3021
3022 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3023 index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
3024
3025 tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
3026 tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
3027 temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
3028
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003029 dotclock = (modeflag & Charx8Dot) ? 8 : 9;
3030
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 } else {
3032
3033 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003034 index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035
3036 tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
3037 tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
3038 tempax &= 0x03FF;
3039 tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
3040 tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
3041 tempcx &= 0x0100;
3042 tempcx <<= 2;
3043 tempbx |= tempcx;
3044 temp1 = SiS_Pr->SiS_CRT1Table[index].CR[7];
3045
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003046 dotclock = 8;
3047
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 }
3049
3050 if(temp1 & 0x01) tempbx |= 0x0100;
3051 if(temp1 & 0x20) tempbx |= 0x0200;
3052
3053 tempax += 5;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003054 tempax *= dotclock;
3055 if(modeflag & HalfDCLK) tempax <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
3057 tempbx++;
3058
3059 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3060 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
3061}
3062
3063static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003064SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3065 unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003067 unsigned short ResIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003069 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3070 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3071 if(SiS_Pr->UseCustomMode) {
3072 ResIndex = SiS_Pr->CHTotal;
3073 if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
3074 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
3075 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3076 } else {
3077 if(ModeNo < 0x13) {
3078 ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3079 } else {
3080 ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3081 }
3082 if(ResIndex == 0x09) {
3083 if(SiS_Pr->Alternate1600x1200) ResIndex = 0x20; /* 1600x1200 LCDA */
3084 else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
3085 }
3086 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
3087 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
3088 SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
3089 SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
3090 }
3091 } else {
3092 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3093 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3094 }
3095 } else {
3096 /* This handles custom modes and custom panels */
3097 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3098 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3099 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3100 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3101 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
3102 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
3103 }
3104}
3105
3106static void
3107SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3108 unsigned short RefreshRateTableIndex)
3109{
3110 unsigned short CRT2Index, ResIndex, backup;
3111 const struct SiS_LVDSData *LVDSData = NULL;
3112
3113 SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114
3115 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3116 SiS_Pr->SiS_RVBHCMAX = 1;
3117 SiS_Pr->SiS_RVBHCFACT = 1;
3118 SiS_Pr->SiS_NewFlickerMode = 0;
3119 SiS_Pr->SiS_RVBHRS = 50;
3120 SiS_Pr->SiS_RY1COE = 0;
3121 SiS_Pr->SiS_RY2COE = 0;
3122 SiS_Pr->SiS_RY3COE = 0;
3123 SiS_Pr->SiS_RY4COE = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003124 SiS_Pr->SiS_RVBHRS2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 }
3126
3127 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3128
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003129#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003130 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3131 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132#endif
3133
3134 } else {
3135
3136 /* 301BDH needs LVDS Data */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003137 backup = SiS_Pr->SiS_IF_DEF_LVDS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3139 SiS_Pr->SiS_IF_DEF_LVDS = 1;
3140 }
3141
3142 SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003143 &CRT2Index, &ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003145 SiS_Pr->SiS_IF_DEF_LVDS = backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003147 switch(CRT2Index) {
3148 case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1; break;
3149 case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2; break;
3150 case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break;
3151 case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
3152 case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
3153 case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003154#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break;
3156 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break;
3157 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1; break;
3159 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003160#endif
3161 case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break;
3162 case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break;
3163 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData; break;
3164 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData; break;
3165 case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
3166 case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
3167 case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
3168 case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
3169 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 }
3171
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003172 if(LVDSData) {
3173 SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
3174 SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
3175 SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT;
3176 SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT;
3177 } else {
3178 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003181 if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
3182 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
3183 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
3184 if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
3185 (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
3186 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3187 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003188#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003189 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3190 if(ResIndex < 0x08) {
3191 SiS_Pr->SiS_HDE = 1280;
3192 SiS_Pr->SiS_VDE = 1024;
3193 }
3194 }
3195#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 }
3197 }
3198 }
3199}
3200
3201static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003202SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3203 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003205 unsigned char *ROMAddr = NULL;
3206 unsigned short tempax, tempbx, modeflag, romptr=0;
3207 unsigned short resinfo, CRT2Index, ResIndex;
3208 const struct SiS_LCDData *LCDPtr = NULL;
3209 const struct SiS_TVData *TVPtr = NULL;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003210#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003211 short resinfo661;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212#endif
3213
3214 if(ModeNo <= 0x13) {
3215 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3216 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
3217 } else if(SiS_Pr->UseCustomMode) {
3218 modeflag = SiS_Pr->CModeFlag;
3219 resinfo = 0;
3220 } else {
3221 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3222 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003223#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224 resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3225 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003226 (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
3227 (resinfo661 >= 0) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 (SiS_Pr->SiS_NeedRomModeData) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003229 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230 if((romptr = (SISGETROMW(21)))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003231 romptr += (resinfo661 * 10);
3232 ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233 }
3234 }
3235 }
3236#endif
3237 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003238
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239 SiS_Pr->SiS_NewFlickerMode = 0;
3240 SiS_Pr->SiS_RVBHRS = 50;
3241 SiS_Pr->SiS_RY1COE = 0;
3242 SiS_Pr->SiS_RY2COE = 0;
3243 SiS_Pr->SiS_RY3COE = 0;
3244 SiS_Pr->SiS_RY4COE = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003245 SiS_Pr->SiS_RVBHRS2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003247 SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003249 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250
3251 if(SiS_Pr->UseCustomMode) {
3252
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003253 SiS_Pr->SiS_RVBHCMAX = 1;
3254 SiS_Pr->SiS_RVBHCFACT = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003256 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3257
3258 tempax = SiS_Pr->CHTotal;
3259 if(modeflag & HalfDCLK) tempax <<= 1;
3260 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3261 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262
3263 } else {
3264
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003265 SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266
3267 }
3268
3269 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3270
3271 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003272 &CRT2Index,&ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
3274 switch(CRT2Index) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003275 case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break;
3276 case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break;
3277 case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
3278 case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break;
3279 case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break;
3280 case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break;
3281 case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
3282 case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
3283 case 10: TVPtr = SiS_Pr->SiS_St525iData; break;
3284 case 11: TVPtr = SiS_Pr->SiS_St525pData; break;
3285 case 12: TVPtr = SiS_Pr->SiS_St750pData; break;
3286 case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break;
3287 case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break;
3288 default: TVPtr = SiS_Pr->SiS_StPALData; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289 }
3290
3291 SiS_Pr->SiS_RVBHCMAX = (TVPtr+ResIndex)->RVBHCMAX;
3292 SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
3293 SiS_Pr->SiS_VGAHT = (TVPtr+ResIndex)->VGAHT;
3294 SiS_Pr->SiS_VGAVT = (TVPtr+ResIndex)->VGAVT;
3295 SiS_Pr->SiS_HDE = (TVPtr+ResIndex)->TVHDE;
3296 SiS_Pr->SiS_VDE = (TVPtr+ResIndex)->TVVDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003297 SiS_Pr->SiS_RVBHRS2 = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 if(modeflag & HalfDCLK) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003299 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
3300 if(SiS_Pr->SiS_RVBHRS2) {
3301 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3302 tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
3303 if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
3304 else SiS_Pr->SiS_RVBHRS2 += tempax;
3305 }
3306 } else {
3307 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003309 SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310
3311 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3312
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003313 if((resinfo == SIS_RI_960x600) ||
3314 (resinfo == SIS_RI_1024x768) ||
3315 (resinfo == SIS_RI_1280x1024) ||
3316 (resinfo == SIS_RI_1280x720)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317 SiS_Pr->SiS_NewFlickerMode = 0x40;
3318 }
3319
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003320 if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003322 SiS_Pr->SiS_HT = ExtHiTVHT;
3323 SiS_Pr->SiS_VT = ExtHiTVVT;
3324 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3325 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
3326 SiS_Pr->SiS_HT = StHiTVHT;
3327 SiS_Pr->SiS_VT = StHiTVVT;
3328 }
3329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330
3331 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3332
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003333 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3334 SiS_Pr->SiS_HT = 1650;
3335 SiS_Pr->SiS_VT = 750;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3337 SiS_Pr->SiS_HT = NTSCHT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003338 if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 SiS_Pr->SiS_VT = NTSCVT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003340 } else {
3341 SiS_Pr->SiS_HT = NTSCHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003343 SiS_Pr->SiS_VT = NTSCVT;
3344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345
3346 } else {
3347
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003348 SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
3349 SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
3350 SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
3351 SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003353 if(modeflag & HalfDCLK) {
3354 SiS_Pr->SiS_RY1COE = 0x00;
3355 SiS_Pr->SiS_RY2COE = 0xf4;
3356 SiS_Pr->SiS_RY3COE = 0x10;
3357 SiS_Pr->SiS_RY4COE = 0x38;
3358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003360 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
3361 SiS_Pr->SiS_HT = NTSCHT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003363 SiS_Pr->SiS_VT = NTSCVT;
3364 } else {
3365 SiS_Pr->SiS_HT = PALHT;
3366 SiS_Pr->SiS_VT = PALVT;
3367 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368
3369 }
3370
3371 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3372
3373 SiS_Pr->SiS_RVBHCMAX = 1;
3374 SiS_Pr->SiS_RVBHCFACT = 1;
3375
3376 if(SiS_Pr->UseCustomMode) {
3377
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003379 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3380
3381 tempax = SiS_Pr->CHTotal;
3382 if(modeflag & HalfDCLK) tempax <<= 1;
3383 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3384 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385
3386 } else {
3387
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003388 bool gotit = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003390 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003392 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
3393 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3394 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3395 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003396 gotit = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397
3398 } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3399
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003400#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003402 SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3403 SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
3404 SiS_Pr->SiS_VGAVT = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
3405 SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
3406 SiS_Pr->SiS_VT = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
3407 SiS_Pr->SiS_RVBHRS2 = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
3408 if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
3409 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3410 tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
3411 if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
3412 else SiS_Pr->SiS_RVBHRS2 += tempax;
3413 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003414 if(SiS_Pr->SiS_VGAHT) gotit = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 else {
3416 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
3417 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003418 SiS_Pr->SiS_RVBHCMAX = 1;
3419 SiS_Pr->SiS_RVBHCFACT = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003421 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3422 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3423 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3424 SiS_Pr->SiS_RVBHRS2 = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003425 gotit = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426 }
3427#endif
3428
3429 }
3430
3431 if(!gotit) {
3432
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003433 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3434 &CRT2Index,&ResIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003436 switch(CRT2Index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437 case Panel_1024x768 : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3438 case Panel_1024x768 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break;
3439 case Panel_1280x720 :
3440 case Panel_1280x720 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data; break;
3441 case Panel_1280x768_2 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003442 case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 case Panel_1280x800 :
3444 case Panel_1280x800 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data; break;
3445 case Panel_1280x800_2 :
3446 case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003447 case Panel_1280x854 :
3448 case Panel_1280x854 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 case Panel_1280x960 :
3450 case Panel_1280x960 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003451 case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break;
3452 case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3453 case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break;
3454 case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break;
3455 case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break;
3456 case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 case Panel_1680x1050 :
3458 case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break;
3459 case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003460#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break;
3462 case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3463#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003464 default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3465 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003467 SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
3468 SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3469 SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
3470 SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
3471 SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
3472 SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473
3474 }
3475
3476 tempax = SiS_Pr->PanelXRes;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003477 tempbx = SiS_Pr->PanelYRes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003479 switch(SiS_Pr->SiS_LCDResInfo) {
3480 case Panel_1024x768:
3481 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3482 if(SiS_Pr->ChipType < SIS_315H) {
3483 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3484 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3485 }
3486 } else {
3487 if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
3488 else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
3489 else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
3490 else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
3491 else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3492 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3493 }
3494 break;
3495 case Panel_1280x960:
3496 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
3497 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
3498 else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
3499 break;
3500 case Panel_1280x1024:
3501 if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
3502 else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
3503 else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
3504 break;
3505 case Panel_1600x1200:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003507 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
3508 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
3509 }
3510 break;
3511 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003513 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3514 tempax = SiS_Pr->SiS_VGAHDE;
3515 tempbx = SiS_Pr->SiS_VGAVDE;
3516 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003518 SiS_Pr->SiS_HDE = tempax;
3519 SiS_Pr->SiS_VDE = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 }
3521 }
3522}
3523
3524static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003525SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3526 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527{
3528
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003529 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003531 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3532 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3533 } else {
3534 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3535 /* Need LVDS Data for LCD on 301B-DH */
3536 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3537 } else {
3538 SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3539 }
3540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003542 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003544 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003546 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547}
3548
3549/*********************************************/
3550/* GET LVDS DES (SKEW) DATA */
3551/*********************************************/
3552
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003553static const struct SiS_LVDSDes *
3554SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003556 const struct SiS_LVDSDes *PanelDesPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003558#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003559 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003561 if(SiS_Pr->ChipType < SIS_315H) {
3562 if(SiS_Pr->SiS_LCDTypeInfo == 4) {
3563 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3564 PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
3565 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3566 PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
3567 }
3568 } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3569 PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
3570 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3571 PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
3572 }
3573 }
3574 }
3575 }
3576 }
3577#endif
3578 return PanelDesPtr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579}
3580
3581static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003582SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3583 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003585 unsigned short modeflag, ResIndex;
3586 const struct SiS_LVDSDes *PanelDesPtr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
3588 SiS_Pr->SiS_LCDHDES = 0;
3589 SiS_Pr->SiS_LCDVDES = 0;
3590
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003591 /* Some special cases */
3592 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3593
3594 /* Trumpion */
3595 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
3596 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3597 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3598 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3599 }
3600 }
3601 return;
3602 }
3603
3604 /* 640x480 on LVDS */
3605 if(SiS_Pr->ChipType < SIS_315H) {
3606 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
3607 SiS_Pr->SiS_LCDHDES = 8;
3608 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3609 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3610 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3611 return;
3612 }
3613 }
3614
3615 } /* LCD */
3616
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 if( (SiS_Pr->UseCustomMode) ||
3618 (SiS_Pr->SiS_LCDResInfo == Panel_Custom) ||
3619 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003620 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ||
3621 (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 return;
3623 }
3624
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003625 if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3626 else ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3627
3628 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003630#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003632 /* non-pass 1:1 only, see above */
3633 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3634 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 }
3636 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3637 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3638 }
3639 }
3640 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003641 switch(SiS_Pr->SiS_CustomT) {
3642 case CUT_UNIWILL1024:
3643 case CUT_UNIWILL10242:
3644 case CUT_CLEVO1400:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3646 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3647 }
3648 break;
3649 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003650 switch(SiS_Pr->SiS_LCDResInfo) {
3651 case Panel_1280x1024:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652 if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
3653 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3654 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003655 break;
3656 case Panel_1280x800: /* Verified for Averatec 6240 */
3657 case Panel_1280x800_2: /* Verified for Asus A4L */
3658 case Panel_1280x854: /* Not verified yet FIXME */
3659 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3660 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 }
3662 }
3663#endif
3664
3665 } else {
3666
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003667 if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003669 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
3670 if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
3671 }
3672
3673 } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
3674
3675 SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
3676 SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
3677
3678 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3679
3680 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3681 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3682 }
3683 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3684 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3685 } else {
3686 if(SiS_Pr->ChipType < SIS_315H) {
3687 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3688 } else {
3689 switch(SiS_Pr->SiS_LCDResInfo) {
3690 case Panel_800x600:
3691 case Panel_1024x768:
3692 case Panel_1280x1024:
3693 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3694 break;
3695 case Panel_1400x1050:
3696 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3697 break;
3698 }
3699 }
3700 }
3701
3702 } else {
3703
3704 if(SiS_Pr->ChipType < SIS_315H) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003705#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003706 switch(SiS_Pr->SiS_LCDResInfo) {
3707 case Panel_800x600:
3708 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3709 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3710 } else {
3711 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
3712 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3713 if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
3714 else SiS_Pr->SiS_LCDVDES -= 4;
3715 }
3716 break;
3717 case Panel_1024x768:
3718 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3719 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3720 } else {
3721 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3722 if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
3723 if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
3724 }
3725 break;
3726 case Panel_1024x600:
3727 default:
3728 if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
3729 (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
3730 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3731 } else {
3732 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3733 }
3734 break;
3735 }
3736
3737 switch(SiS_Pr->SiS_LCDTypeInfo) {
3738 case 1:
3739 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
3740 break;
3741 case 3: /* 640x480 only? */
3742 SiS_Pr->SiS_LCDHDES = 8;
3743 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3744 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3745 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3746 break;
3747 }
3748#endif
3749 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003750#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003751 switch(SiS_Pr->SiS_LCDResInfo) {
3752 case Panel_1024x768:
3753 case Panel_1280x1024:
3754 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3755 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3756 }
3757 break;
3758 case Panel_320x240_1:
3759 case Panel_320x240_2:
3760 case Panel_320x240_3:
3761 SiS_Pr->SiS_LCDVDES = 524;
3762 break;
3763 }
3764#endif
3765 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766 }
3767
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003769 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3770 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003772 } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3773 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
3774 if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
3775 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
3777 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003778#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003779 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
3780 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003782 if(!(modeflag & HalfDCLK)) {
3783 SiS_Pr->SiS_LCDHDES = 320;
3784 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003786 }
3787#endif
3788 }
3789 }
3790 }
3791 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792 }
3793 }
3794}
3795
3796/*********************************************/
3797/* DISABLE VIDEO BRIDGE */
3798/*********************************************/
3799
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003800#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003801static int
3802SiS_HandlePWD(struct SiS_Private *SiS_Pr)
3803{
3804 int ret = 0;
3805#ifdef SET_PWD
3806 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3807 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
3808 unsigned char drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
3809 unsigned short temp;
3810
3811 if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
3812 (romptr) &&
3813 (SiS_Pr->SiS_PWDOffset) ) {
3814 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
3815 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
3816 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
3817 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
3818 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
3819 temp = 0x00;
3820 if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
3821 temp = 0x80;
3822 ret = 1;
3823 }
3824 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003825 }
3826#endif
3827 return ret;
3828}
3829#endif
3830
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831/* NEVER use any variables (VBInfo), this will be called
3832 * from outside the context of modeswitch!
3833 * MUST call getVBType before calling this
3834 */
3835void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003836SiS_DisableBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837{
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003838#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003839 unsigned short tempah, pushax=0, modenum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003841 unsigned short temp=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
3843 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3844
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003845 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ===== For 30xB/C/LV ===== */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003847 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003849#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003851 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
3852 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3853 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003855 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003857 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 }
3859 if(SiS_Is301B(SiS_Pr)) {
3860 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
3861 SiS_ShortDelay(SiS_Pr,1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003862 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
3864 SiS_DisplayOff(SiS_Pr);
3865 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3866 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003867 SiS_UnLockCRT2(SiS_Pr);
3868 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
3870 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
3871 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003872 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
3873 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
3874 SiS_PanelDelay(SiS_Pr, 2);
3875 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3876 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003878 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 }
3880 }
3881
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003882#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
3884 } else {
3885
Aaro Koskinenf7854e52010-11-19 21:58:47 +00003886#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003888 int didpwd = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08003889 bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
3890 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891
3892 modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
3893
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003894 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
3896#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003897 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003899 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 }
3901 }
3902#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003903
3904 didpwd = SiS_HandlePWD(SiS_Pr);
3905
3906 if( (modenum <= 0x13) ||
3907 (SiS_IsVAMode(SiS_Pr)) ||
3908 (!(SiS_IsDualEdge(SiS_Pr))) ) {
3909 if(!didpwd) {
3910 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
3911 if(custom1) SiS_PanelDelay(SiS_Pr, 3);
3912 } else {
3913 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
3914 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 }
3916
3917 if(!custom1) {
3918 SiS_DDC2Delay(SiS_Pr,0xff00);
3919 SiS_DDC2Delay(SiS_Pr,0xe000);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003920 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
3921 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 if(IS_SIS740) {
3923 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
3924 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003925 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 }
3927
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 }
3929
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003930 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
3931 /* if(SiS_Pr->ChipType < SIS_340) {*/
3932 tempah = 0xef;
3933 if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
3934 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
3935 /*}*/
3936 }
3937
3938 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
3940 }
3941
3942 tempah = 0x3f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003943 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 tempah = 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003945 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 }
3947 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
3948
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003949 if((SiS_IsVAMode(SiS_Pr)) ||
3950 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951
3952 SiS_DisplayOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003953 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3954 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955 }
3956 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3957 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
3958
3959 }
3960
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003961 if((!(SiS_IsVAMode(SiS_Pr))) ||
3962 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003964 if(!(SiS_IsDualEdge(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
3966 SiS_DisplayOff(SiS_Pr);
3967 }
3968 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
3969
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003970 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3971 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 }
3973
3974 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3975 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003976 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
3978 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
3979
3980 }
3981
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003982 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
3984 }
3985
Thomas Winischhofer544393f2005-09-09 13:04:45 -07003986 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3987
3988 if( (!(SiS_IsVAMode(SiS_Pr))) &&
3989 (!(SiS_CRT2IsLCD(SiS_Pr))) &&
3990 (!(SiS_IsDualEdge(SiS_Pr))) ) {
3991
3992 if(custom1) SiS_PanelDelay(SiS_Pr, 2);
3993 if(!didpwd) {
3994 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
3995 }
3996 if(custom1) SiS_PanelDelay(SiS_Pr, 4);
3997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998
3999 if(!custom1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004000 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4001 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4002 if(SiS_IsVAorLCD(SiS_Pr)) {
4003 SiS_PanelDelayLoop(SiS_Pr, 3, 20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004 }
4005 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004007
4008 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004010#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011
4012 }
4013
4014 } else { /* ============ For 301 ================ */
4015
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004016 if(SiS_Pr->ChipType < SIS_315H) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004017#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004018 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4019 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4020 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 }
4022#endif
4023 }
4024
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004025 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
4026 SiS_DisplayOff(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004028 if(SiS_Pr->ChipType >= SIS_315H) {
4029 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 }
4031
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004032 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004034 if(SiS_Pr->ChipType >= SIS_315H) {
4035 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4036 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4038 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4039 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004040#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004041 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
4042 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4043 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4044 SiS_PanelDelay(SiS_Pr, 2);
4045 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 }
4047#endif
4048 }
4049
4050 }
4051
4052 } else { /* ============ For LVDS =============*/
4053
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004054 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004056#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057
4058 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004059 SiS_SetCH700x(SiS_Pr,0x0E,0x09);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 }
4061
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004062 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004064 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004066 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4067 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4068 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 }
4070 } else {
4071 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4072 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004073 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4074 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
4076 SiS_DisplayOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004077 }
4078 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4079 SiS_PanelDelay(SiS_Pr, 3);
4080 }
4081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 }
4083 }
4084
4085 SiS_DisplayOff(SiS_Pr);
4086
4087 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4088
4089 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004090 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4092 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4093
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004094 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4095 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4096 SiS_PanelDelay(SiS_Pr, 2);
4097 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 }
4099
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004100#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
4102 } else {
4103
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004104#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004106 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4107 /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
4108 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
4109 /* } */
4110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111
4112 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4113
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004114 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 temp = SiS_GetCH701x(SiS_Pr,0x61);
4116 if(temp < 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004117 SiS_SetCH701x(SiS_Pr,0x76,0xac);
4118 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 }
4120
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004121 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4122 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4123 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 }
4125 }
4126
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004127 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4128 (SiS_IsVAMode(SiS_Pr)) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 SiS_Chrontel701xBLOff(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004130 SiS_Chrontel701xOff(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 }
4132
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004133 if(SiS_Pr->ChipType != SIS_740) {
4134 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4135 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4136 SiS_SetCH701x(SiS_Pr,0x49,0x01);
4137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 }
4139
4140 }
4141
4142 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004143 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4144 SiS_PanelDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145 }
4146
4147 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004148 (!(SiS_IsDualEdge(SiS_Pr))) ||
4149 (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 SiS_DisplayOff(SiS_Pr);
4151 }
4152
4153 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004154 (!(SiS_IsDualEdge(SiS_Pr))) ||
4155 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4157 }
4158
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004159 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4161 }
4162
4163 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4164
4165 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004166 (!(SiS_IsDualEdge(SiS_Pr))) ||
4167 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4169 }
4170
4171 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004172 if(SiS_CRT2IsLCD(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004174 if(SiS_Pr->ChipType == SIS_550) {
4175 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
4176 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 }
4178 }
4179 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004180 if(SiS_Pr->ChipType == SIS_740) {
4181 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4182 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004184 } else if(SiS_IsVAMode(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4186 }
4187 }
4188
4189 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004190 if(SiS_IsDualEdge(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
4192 } else {
4193 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
4194 }
4195 }
4196
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004197 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004199 if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
4201 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
4202 } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004203 (!(SiS_IsDualEdge(SiS_Pr))) ||
4204 (!(SiS_IsVAMode(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4206 }
4207
4208 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004209 if(SiS_CRT2IsLCD(SiS_Pr)) {
4210 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4211 SiS_PanelDelay(SiS_Pr, 2);
4212 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 }
4214 }
4215 }
4216
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004217#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218
4219 } /* 315 series */
4220
4221 } /* LVDS */
4222
4223}
4224
4225/*********************************************/
4226/* ENABLE VIDEO BRIDGE */
4227/*********************************************/
4228
4229/* NEVER use any variables (VBInfo), this will be called
4230 * from outside the context of a mode switch!
4231 * MUST call getVBType before calling this
4232 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004233static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004234void
4235SiS_EnableBridge(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004237 unsigned short temp=0, tempah;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004238#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004239 unsigned short temp1, pushax=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004240 bool delaylong = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241#endif
4242
4243 if(SiS_Pr->SiS_VBType & VB_SISVB) {
4244
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004245 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ====== For 301B et al ====== */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004247 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004249#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004251 if(SiS_CRT2IsLCD(SiS_Pr)) {
4252 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4254 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004255 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004257 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
4258 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4259 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260 }
4261 }
4262 }
4263
4264 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004265 (SiS_CRT2IsLCD(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266
4267 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* Enable CRT2 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004268 SiS_DisplayOn(SiS_Pr);
4269 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4271 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004272 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4273 } else {
4274 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4275 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4277 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004278 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4279 SiS_PanelDelay(SiS_Pr, 1);
4280 }
4281 SiS_WaitVBRetrace(SiS_Pr);
4282 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284 }
4285
4286 } else {
4287
4288 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004289 if(SiS_BridgeInSlavemode(SiS_Pr)) {
4290 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4291 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4292 }
4293 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4295 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4296 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
4297 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004298 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4299 if(SiS_CRT2IsLCD(SiS_Pr)) {
4300 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4301 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4302 SiS_PanelDelay(SiS_Pr, 1);
4303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306 }
4307 }
4308
4309 }
4310
4311
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004312#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313
4314 } else {
4315
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004316#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
4318#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004319 unsigned char r30=0, r31=0, r32=0, r33=0, cr36=0;
4320 int didpwd = 0;
4321 /* unsigned short emidelay=0; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322#endif
4323
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004324 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
4326#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004327 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4329 }
4330#endif
4331 }
4332
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004333 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4334 /*if(SiS_Pr->ChipType < SIS_340) { */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335 tempah = 0x10;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004336 if(SiS_LCDAEnabled(SiS_Pr)) {
4337 if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
4338 else tempah = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 }
4340 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004341 /*}*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342 }
4343
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004344 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
4346 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4347 SiS_DisplayOff(SiS_Pr);
4348 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4349 if(IS_SIS740) {
4350 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4351 }
4352
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004353 didpwd = SiS_HandlePWD(SiS_Pr);
4354
4355 if(SiS_IsVAorLCD(SiS_Pr)) {
4356 if(!didpwd) {
4357 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
4358 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4359 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4360 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4361 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4362 SiS_GenericDelay(SiS_Pr, 17664);
4363 }
4364 }
4365 } else {
4366 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4367 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4368 SiS_GenericDelay(SiS_Pr, 17664);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369 }
4370 }
4371 }
4372
4373 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004374 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004375 delaylong = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376 }
4377
4378 }
4379
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004380 if(!(SiS_IsVAMode(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004382 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004384 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4385 if(!(tempah & SetCRT2ToRAMDAC)) {
4386 if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004388 }
4389 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390
4391 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4392
4393 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4394 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4395
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004396 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4397 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 }
4399
4400 } else {
4401
4402 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
4403
4404 }
4405
4406 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
4407 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4408
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004409 if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
4410 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4411 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4412 /* Enable "LVDS PLL power on" (even on 301C) */
4413 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
4414 /* Enable "LVDS Driver Power on" (even on 301C) */
4415 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
4416 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004419 tempah = 0xc0;
4420 if(SiS_IsDualEdge(SiS_Pr)) {
4421 tempah = 0x80;
4422 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
4423 }
4424 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004426 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4427
4428 SiS_PanelDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429
4430 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
4431 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4432
4433 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4434#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004435 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4436 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4437 SiS_GenericDelay(SiS_Pr, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 }
4439#endif
4440 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
4441
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004442 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443#ifdef SET_EMI
4444 cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
4445
4446 if(SiS_Pr->SiS_ROMNew) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004447 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
4448 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449 if(romptr) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004450 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451 SiS_Pr->EMI_30 = 0;
4452 SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
4453 SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
4454 SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
4455 if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
4456 /* emidelay = SISGETROMW((romptr + 0x22)); */
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004457 SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 }
4459 }
4460
4461 /* (P4_30|0x40) */
4462 /* Compal 1400x1050: 0x05, 0x60, 0x00 YES (1.10.7w; CR36=69) */
4463 /* Compal 1400x1050: 0x0d, 0x70, 0x40 YES (1.10.7x; CR36=69) */
4464 /* Acer 1280x1024: 0x12, 0xd0, 0x6b NO (1.10.9k; CR36=73) */
4465 /* Compaq 1280x1024: 0x0d, 0x70, 0x6b YES (1.12.04b; CR36=03) */
4466 /* Clevo 1024x768: 0x05, 0x60, 0x33 NO (1.10.8e; CR36=12, DL!) */
4467 /* Clevo 1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES (1.10.8y; CR36=?2) */
4468 /* Clevo 1024x768: 0x05, 0x60, 0x33 (if type != 3) YES (1.10.8y; CR36=?2) */
4469 /* Asus 1024x768: ? ? (1.10.8o; CR36=?2) */
4470 /* Asus 1024x768: 0x08, 0x10, 0x3c (problematic) YES (1.10.8q; CR36=22) */
4471
4472 if(SiS_Pr->HaveEMI) {
4473 r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
4474 r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
4475 } else {
4476 r30 = 0;
4477 }
4478
4479 /* EMI_30 is read at driver start; however, the BIOS sets this
4480 * (if it is used) only if the LCD is in use. In case we caught
4481 * the machine while on TV output, this bit is not set and we
4482 * don't know if it should be set - hence our detection is wrong.
4483 * Work-around this here:
4484 */
4485
4486 if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
4487 switch((cr36 & 0x0f)) {
4488 case 2:
4489 r30 |= 0x40;
4490 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
4491 if(!SiS_Pr->HaveEMI) {
4492 r31 = 0x05; r32 = 0x60; r33 = 0x33;
4493 if((cr36 & 0xf0) == 0x30) {
4494 r31 = 0x0d; r32 = 0x70; r33 = 0x40;
4495 }
4496 }
4497 break;
4498 case 3: /* 1280x1024 */
4499 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
4500 if(!SiS_Pr->HaveEMI) {
4501 r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4502 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4503 r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
4504 }
4505 }
4506 break;
4507 case 9: /* 1400x1050 */
4508 r30 |= 0x40;
4509 if(!SiS_Pr->HaveEMI) {
4510 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4511 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4512 r31 = 0x0d; r32 = 0x70; r33 = 0x40; /* BIOS values */
4513 }
4514 }
4515 break;
4516 case 11: /* 1600x1200 - unknown */
4517 r30 |= 0x40;
4518 if(!SiS_Pr->HaveEMI) {
4519 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4520 }
4521 }
4522 }
4523
4524 /* BIOS values don't work so well sometimes */
4525 if(!SiS_Pr->OverruleEMI) {
4526#ifdef COMPAL_HACK
4527 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004528 if((cr36 & 0x0f) == 0x09) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529 r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
4530 }
4531 }
4532#endif
4533#ifdef COMPAQ_HACK
4534 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004535 if((cr36 & 0x0f) == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536 r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4537 }
4538 }
4539#endif
4540#ifdef ASUS_HACK
4541 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004542 if((cr36 & 0x0f) == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543 /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 2 */
4544 /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 3 */
4545 /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 4 */
4546 /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 5 */
4547 }
4548 }
4549#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551
4552 if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
4553 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004554 SiS_GenericDelay(SiS_Pr, 2048);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555 }
4556 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
4557 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
4558 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
4559#endif /* SET_EMI */
4560
4561 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
4562
4563#ifdef SET_EMI
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004564 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4565 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4566 if(r30 & 0x40) {
4567 /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
4568 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569 if(delaylong) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004570 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08004571 delaylong = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004573 SiS_WaitVBRetrace(SiS_Pr);
4574 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004576 SiS_GenericDelay(SiS_Pr, 1280);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004578 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */
4579 /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
4580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581 }
4582#endif
4583 }
4584 }
4585
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004586 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4587 if(SiS_IsVAorLCD(SiS_Pr)) {
4588 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589 if(delaylong) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004590 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004592 SiS_WaitVBRetrace(SiS_Pr);
4593 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4594 SiS_GenericDelay(SiS_Pr, 2048);
4595 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004597 if(!didpwd) {
4598 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4599 } else {
4600 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
4601 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602 }
4603 }
4604
4605 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4606 SiS_DisplayOn(SiS_Pr);
4607 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
4608
4609 }
4610
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004611 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004612 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4613 }
4614
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004615#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616
4617 }
4618
4619 } else { /* ============ For 301 ================ */
4620
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004621 if(SiS_Pr->ChipType < SIS_315H) {
4622 if(SiS_CRT2IsLCD(SiS_Pr)) {
4623 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4624 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625 }
4626 }
4627
4628 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
4629 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004630 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4631 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632 }
4633 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4634
4635 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4636
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004637 if(SiS_Pr->ChipType >= SIS_315H) {
4638 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4639 if(!(temp & 0x80)) {
4640 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641 }
4642 }
4643
4644 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4645
4646 SiS_VBLongWait(SiS_Pr);
4647 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004648 if(SiS_Pr->ChipType >= SIS_315H) {
4649 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650 }
4651 SiS_VBLongWait(SiS_Pr);
4652
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004653 if(SiS_Pr->ChipType < SIS_315H) {
4654 if(SiS_CRT2IsLCD(SiS_Pr)) {
4655 SiS_PanelDelay(SiS_Pr, 1);
4656 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657 }
4658 }
4659
4660 }
4661
4662 } else { /* =================== For LVDS ================== */
4663
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004664 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004666#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004667
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004668 if(SiS_CRT2IsLCD(SiS_Pr)) {
4669 if(SiS_Pr->ChipType == SIS_730) {
4670 SiS_PanelDelay(SiS_Pr, 1);
4671 SiS_PanelDelay(SiS_Pr, 1);
4672 SiS_PanelDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004674 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4675 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4676 SiS_PanelDelay(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677 }
4678 }
4679
4680 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4681 SiS_DisplayOn(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004682 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4684 if(SiS_BridgeInSlavemode(SiS_Pr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004685 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004686 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004687 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688 }
4689
4690 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004691 if(!(SiS_CRT2IsLCD(SiS_Pr))) {
4692 SiS_WaitVBRetrace(SiS_Pr);
4693 SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
4694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004695 }
4696
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004697 if(SiS_CRT2IsLCD(SiS_Pr)) {
4698 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4699 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4700 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4701 SiS_PanelDelay(SiS_Pr, 1);
4702 SiS_PanelDelay(SiS_Pr, 1);
4703 }
4704 SiS_WaitVBRetrace(SiS_Pr);
4705 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004707 }
4708 }
4709
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004710#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711
4712 } else {
4713
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004714#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004715
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004716 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4717 /*if(SiS_Pr->ChipType < SIS_340) {*/ /* XGI needs this */
4718 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
4719 /*}*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720 }
4721
4722 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004723 if(SiS_CRT2IsLCD(SiS_Pr)) {
4724 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4725 SiS_PanelDelay(SiS_Pr, 0);
4726 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727 }
4728
4729 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004730 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731
4732 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4733
4734 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004735 temp = SiS_GetCH701x(SiS_Pr,0x66);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736 temp &= 0x20;
4737 SiS_Chrontel701xBLOff(SiS_Pr);
4738 }
4739
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004740 if(SiS_Pr->ChipType != SIS_550) {
4741 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 }
4743
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004744 if(SiS_Pr->ChipType == SIS_740) {
4745 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4746 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4747 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748 }
4749 }
4750 }
4751
4752 temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4753 if(!(temp1 & 0x80)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004754 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004755 }
4756
4757 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004758 if(temp) {
4759 SiS_Chrontel701xBLOn(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760 }
4761 }
4762
4763 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004764 if(SiS_CRT2IsLCD(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004765 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004766 if(SiS_Pr->ChipType == SIS_550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
4768 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
4769 }
4770 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004771 } else if(SiS_IsVAMode(SiS_Pr)) {
4772 if(SiS_Pr->ChipType != SIS_740) {
4773 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774 }
4775 }
4776
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004777 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4778 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004779 }
4780
4781 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004782 if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
4783 SiS_Chrontel701xOn(SiS_Pr);
4784 }
4785 if( (SiS_IsVAMode(SiS_Pr)) ||
4786 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4787 SiS_ChrontelDoSomething1(SiS_Pr);
4788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004789 }
4790
4791 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004792 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4793 if( (SiS_IsVAMode(SiS_Pr)) ||
4794 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4795 SiS_Chrontel701xBLOn(SiS_Pr);
4796 SiS_ChrontelInitTVVSync(SiS_Pr);
4797 }
4798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004799 } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004800 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4801 if(SiS_CRT2IsLCD(SiS_Pr)) {
4802 SiS_PanelDelay(SiS_Pr, 1);
4803 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804 }
4805 }
4806 }
4807
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004808#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809
4810 } /* 310 series */
4811
4812 } /* LVDS */
4813
4814}
4815
4816/*********************************************/
4817/* SET PART 1 REGISTER GROUP */
4818/*********************************************/
4819
4820/* Set CRT2 OFFSET / PITCH */
4821static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004822SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
4823 unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004825 unsigned short offset;
4826 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004827
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004828 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004830 offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004831
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004832 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
4833 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004835 temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
4836 if(offset & 0x07) temp++;
4837 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838}
4839
4840/* Set CRT2 sync and PanelLink mode */
4841static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004842SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004843{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004844 unsigned short tempah=0, tempbl, infoflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004846 tempbl = 0xC0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004848 if(SiS_Pr->UseCustomMode) {
4849 infoflag = SiS_Pr->CInfoFlag;
4850 } else {
4851 infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
4852 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004854 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004855
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004856 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4857 tempah = 0;
4858 } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
4859 tempah = SiS_Pr->SiS_LCDInfo;
4860 } else tempah = infoflag >> 8;
4861 tempah &= 0xC0;
4862 tempah |= 0x20;
4863 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4864 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4865 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
4866 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
4867 tempah |= 0xf0;
4868 }
4869 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4870 (SiS_Pr->SiS_IF_DEF_DSTN) ||
4871 (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
4872 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
4873 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
4874 tempah |= 0x30;
4875 }
4876 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4877 (SiS_Pr->SiS_IF_DEF_DSTN) ) {
4878 tempah &= ~0xc0;
4879 }
4880 }
4881 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4882 if(SiS_Pr->ChipType >= SIS_315H) {
4883 tempah >>= 3;
4884 tempah &= 0x18;
4885 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
4886 /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
4887 } else {
4888 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
4889 }
4890 } else {
4891 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4892 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004894 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004895
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004896 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004897
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004898#ifdef CONFIG_FB_SIS_300 /* ---- 300 series --- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004899
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004900 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* 630 - 301B(-DH) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004902 tempah = infoflag >> 8;
4903 tempbl = 0;
4904 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4905 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4906 tempah = SiS_Pr->SiS_LCDInfo;
4907 tempbl = (tempah >> 6) & 0x03;
4908 }
4909 }
4910 tempah &= 0xC0;
4911 tempah |= 0x20;
4912 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4913 tempah |= 0xc0;
4914 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4915 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
4916 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4917 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004919 } else { /* 630 - 301 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004921 tempah = ((infoflag >> 8) & 0xc0) | 0x20;
4922 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4923 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004927#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004929 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004930
Aaro Koskinenf7854e52010-11-19 21:58:47 +00004931#ifdef CONFIG_FB_SIS_315 /* ------- 315 series ------ */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004932
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004933 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* 315 - LVDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004935 tempbl = 0;
4936 if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
4937 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
4938 tempah = infoflag >> 8;
4939 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4940 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
4941 }
4942 } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
4943 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
4944 tempah = infoflag >> 8;
4945 tempbl = 0x03;
4946 } else {
4947 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
4948 tempbl = (tempah >> 6) & 0x03;
4949 tempbl |= 0x08;
4950 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
4951 }
4952 tempah &= 0xC0;
4953 tempah |= 0x20;
4954 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4955 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0;
4956 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4957 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
4958 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4959 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4960 }
4961 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004963 } else { /* 315 - TMDS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004965 tempah = tempbl = infoflag >> 8;
4966 if(!SiS_Pr->UseCustomMode) {
4967 tempbl = 0;
4968 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4969 if(ModeNo <= 0x13) {
4970 tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
4971 }
4972 }
4973 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
4974 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
4975 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4976 tempah = SiS_Pr->SiS_LCDInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977 tempbl = (tempah >> 6) & 0x03;
4978 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07004979 }
4980 }
4981 }
4982 tempah &= 0xC0;
4983 tempah |= 0x20;
4984 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4985 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4986 /* Imitate BIOS bug */
4987 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0;
4988 }
4989 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4990 tempah >>= 3;
4991 tempah &= 0x18;
4992 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
4993 } else {
4994 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4995 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
4996 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4997 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4998 }
4999 }
5000 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005001
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005002 }
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005003#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004 }
5005 }
5006}
5007
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005008/* Set CRT2 FIFO on 300/540/630/730 */
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005009#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005011SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005013 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5014 unsigned short temp, index, modeidindex, refreshratetableindex;
5015 unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
5016 unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
5017 unsigned int data, pci50, pciA0;
5018 static const unsigned char colortharray[] = {
5019 1, 1, 2, 2, 3, 4
Linus Torvalds1da177e2005-04-16 15:20:36 -07005020 };
5021
5022 SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
5023
5024 if(!SiS_Pr->CRT1UsesCustomMode) {
5025
5026 CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */
5027 SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
5028 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
5029 SiS_Pr->SiS_SelectCRT2Rate = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005030 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031
5032 if(CRT1ModeNo >= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005033 /* Get VCLK */
5034 index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
5035 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005037 /* Get colordepth */
5038 colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
5039 if(!colorth) colorth++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 }
5041
5042 } else {
5043
5044 CRT1ModeNo = 0xfe;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005045
5046 /* Get VCLK */
5047 VCLK = SiS_Pr->CSRClock_CRT1;
5048
5049 /* Get color depth */
5050 colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051
5052 }
5053
5054 if(CRT1ModeNo >= 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005055 /* Get MCLK */
5056 if(SiS_Pr->ChipType == SIS_300) {
5057 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
5058 } else {
5059 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
5060 }
5061 index &= 0x07;
5062 MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005064 temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
5065 if(!temp) temp++;
5066 temp <<= 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005068 data2 = temp - ((colorth * VCLK) / MCLK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005070 temp = (28 * 16) % data2;
5071 data2 = (28 * 16) / data2;
5072 if(temp) data2++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005074 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005076 SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
5077 data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005079 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005081 pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
5082 pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005083
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005084 if(SiS_Pr->ChipType == SIS_730) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005086 index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
5087 index += (unsigned short)(((pci50 >> 9)) & 0x03);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005088
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005089 /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
5090 index = 0; /* -- do it like the BIOS anyway... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005092 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005093
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005094 pci50 >>= 24;
5095 pciA0 >>= 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005096
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005097 index = (pci50 >> 1) & 0x07;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005099 if(pci50 & 0x01) index += 6;
5100 if(!(pciA0 & 0x01)) index += 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005101
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005102 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005103
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005106 data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
5107 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005108
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005110
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005111 data += data2; /* CRT1 Request Period */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005113 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5114 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005116 if(!SiS_Pr->UseCustomMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005118 CRT2ModeNo = ModeNo;
5119 SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005121 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005123 /* Get VCLK */
5124 index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
5125 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005127 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5128 if(SiS_Pr->SiS_UseROM) {
5129 if(ROMAddr[0x220] & 0x01) {
5130 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
5131 }
5132 }
5133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005134
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005135 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005137 /* Get VCLK */
5138 CRT2ModeNo = 0xfe;
5139 VCLK = SiS_Pr->CSRClock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005143 /* Get colordepth */
5144 colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
5145 if(!colorth) colorth++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005146
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005147 data = data * VCLK * colorth;
5148 temp = data % (MCLK << 4);
5149 data = data / (MCLK << 4);
5150 if(temp) data++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005151
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005152 if(data < 6) data = 6;
5153 else if(data > 0x14) data = 0x14;
5154
5155 if(SiS_Pr->ChipType == SIS_300) {
5156 temp = 0x16;
5157 if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
5158 temp = 0x13;
5159 } else {
5160 temp = 0x16;
5161 if(( (SiS_Pr->ChipType == SIS_630) ||
5162 (SiS_Pr->ChipType == SIS_730) ) &&
5163 (SiS_Pr->ChipRevision >= 0x30))
5164 temp = 0x1b;
5165 }
5166 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
5167
5168 if((SiS_Pr->ChipType == SIS_630) &&
5169 (SiS_Pr->ChipRevision >= 0x30)) {
5170 if(data > 0x13) data = 0x13;
5171 }
5172 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173
5174 } else { /* If mode <= 0x13, we just restore everything */
5175
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005176 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5177 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178
5179 }
5180}
5181#endif
5182
5183/* Set CRT2 FIFO on 315/330 series */
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005184#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07005185static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005186SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187{
5188 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005189 if( (SiS_Pr->ChipType == SIS_760) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07005190 (SiS_Pr->SiS_SysFlags & SF_760LFB) &&
5191 (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
5192 (SiS_Pr->SiS_VGAHDE >= 1280) &&
5193 (SiS_Pr->SiS_VGAVDE >= 1024) ) {
5194 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
5195 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
5196 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5197 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
5198 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5199 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
5200 } else {
5201 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
5202 }
5203
5204}
5205#endif
5206
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005207static unsigned short
5208SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005210 unsigned int tempax,tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211
5212 tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
5213 tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
5214 tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005215 return (unsigned short)tempax;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216}
5217
5218/* Set Part 1 / SiS bridge slave mode */
5219static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005220SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
5221 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005222{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005223 unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
5224 static const unsigned short CRTranslation[] = {
5225 /* CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 */
5226 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
5227 /* CR8 CR9 SR0A SR0B SR0C SR0D SR0E CR0F */
5228 0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
5229 /* CR10 CR11 CR12 CR13 CR14 CR15 CR16 CR17 */
5230 0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
5231 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232
5233 if(ModeNo <= 0x13) {
5234 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235 } else if(SiS_Pr->UseCustomMode) {
5236 modeflag = SiS_Pr->CModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237 xres = SiS_Pr->CHDisplay;
5238 } else {
5239 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005240 xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
5241 }
5242
5243 /* The following is only done if bridge is in slave mode: */
5244
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005245 if(SiS_Pr->ChipType >= SIS_315H) {
5246 if(xres >= 1600) { /* BIOS: == 1600 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
5248 }
5249 }
5250
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005251 SiS_Pr->CHTotal = 8224; /* Max HT, 0x2020, results in 0x3ff in registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005253 SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
5254 if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005255
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005256 SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005257 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005258 SiS_Pr->CHBlankStart += 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259 }
5260
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005261 SiS_Pr->CHBlankEnd = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005263 if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005265
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005266 temp = SiS_Pr->SiS_VGAHT - 96;
5267 if(!(modeflag & HalfDCLK)) temp -= 32;
5268 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
5269 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
5270 temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
5271 temp -= 3;
5272 temp <<= 3;
5273 } else {
5274 if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005275 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005276 SiS_Pr->CHSyncStart = temp;
5277
5278 SiS_Pr->CHSyncEnd = 0xffe8; /* results in 0x2000 in registers */
5279
5280 SiS_Pr->CVTotal = 2049; /* Max VT, 0x0801, results in 0x7ff in registers */
5281
5282 VGAVDE = SiS_Pr->SiS_VGAVDE;
5283 if (VGAVDE == 357) VGAVDE = 350;
5284 else if(VGAVDE == 360) VGAVDE = 350;
5285 else if(VGAVDE == 375) VGAVDE = 350;
5286 else if(VGAVDE == 405) VGAVDE = 400;
5287 else if(VGAVDE == 420) VGAVDE = 400;
5288 else if(VGAVDE == 525) VGAVDE = 480;
5289 else if(VGAVDE == 1056) VGAVDE = 1024;
5290 SiS_Pr->CVDisplay = VGAVDE;
5291
5292 SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
5293
5294 SiS_Pr->CVBlankEnd = 1;
5295 if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
5296
5297 temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
5298 SiS_Pr->CVSyncStart = VGAVDE + temp;
5299
5300 temp >>= 3;
5301 SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
5302
5303 SiS_CalcCRRegisters(SiS_Pr, 0);
5304 SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
5305
5306 for(i = 0; i <= 7; i++) {
5307 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
5308 }
5309 for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
5310 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5311 }
5312 for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
5313 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5314 }
5315 for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
5316 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
5317 }
5318
5319 temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
5320 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
5321
5322 temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
5323 if(modeflag & DoubleScanMode) temp |= 0x80;
5324 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005325
5326 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005327 temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
5328 if(modeflag & HalfDCLK) temp |= 0x08;
5329 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005330
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005331 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* CR14: (text mode: underline location) */
5332 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* CR17: n/a */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005334 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005336 temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005337 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005338 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* SR0E, dither[7] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005339
5340 temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005341 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); /* ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342}
5343
5344/* Setup panel link
5345 * This is used for LVDS, LCDA and Chrontel TV output
5346 * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
5347 */
5348static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005349SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5350 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005351{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005352 unsigned short modeflag, resinfo = 0;
5353 unsigned short push2, tempax, tempbx, tempcx, temp;
5354 unsigned int tempeax = 0, tempebx, tempecx, tempvcfact = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005355 bool islvds = false, issis = false, chkdclkfirst = false;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005356#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005357 unsigned short crt2crtc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358#endif
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005359#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005360 unsigned short pushcx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361#endif
5362
5363 if(ModeNo <= 0x13) {
5364 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5365 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005366#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5368#endif
5369 } else if(SiS_Pr->UseCustomMode) {
5370 modeflag = SiS_Pr->CModeFlag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005371 } else {
5372 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5373 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005374#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005375 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376#endif
5377 }
5378
5379 /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
5380 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005381 islvds = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382 }
5383
5384 /* is really sis if sis bridge, but not 301B-DH */
5385 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005386 issis = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005387 }
5388
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005389 if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08005391 chkdclkfirst = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005392 }
5393 }
5394
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005395#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005396 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397 if(IS_SIS330) {
5398 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5399 } else if(IS_SIS740) {
5400 if(islvds) {
5401 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5402 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
5403 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5404 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5405 }
5406 } else {
5407 if(islvds) {
5408 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5409 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
5410 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5411 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005412 if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413 if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
5414 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5415 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
5416 }
5417 }
5418 }
5419 }
5420 }
5421#endif
5422
5423 /* Horizontal */
5424
5425 tempax = SiS_Pr->SiS_LCDHDES;
5426 if(islvds) {
5427 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005428 if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
5429 if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
5430 (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
5431 tempax -= 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005432 }
5433 }
5434 }
5435 }
5436
5437 temp = (tempax & 0x0007);
5438 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* BPLHDESKEW[2:0] */
5439 temp = (tempax >> 3) & 0x00FF;
5440 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* BPLHDESKEW[10:3] */
5441
5442 tempbx = SiS_Pr->SiS_HDE;
5443 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005444 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5445 tempbx = SiS_Pr->PanelXRes;
5446 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005447 if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
5448 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
5449 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
5450 tempbx >>= 1;
5451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005452 }
5453
5454 tempax += tempbx;
5455 if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
5456
5457 temp = tempax;
5458 if(temp & 0x07) temp += 8;
5459 temp >>= 3;
5460 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp); /* BPLHDEE */
5461
5462 tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
5463
5464 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5465 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5466 if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
5467 }
5468 }
5469
5470 tempcx += tempax;
5471 if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
5472
5473 temp = (tempcx >> 3) & 0x00FF;
5474 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5475 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005476 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5477 switch(ModeNo) {
5478 case 0x04:
5479 case 0x05:
5480 case 0x0d: temp = 0x56; break;
5481 case 0x10: temp = 0x60; break;
5482 case 0x13: temp = 0x5f; break;
5483 case 0x40:
5484 case 0x41:
5485 case 0x4f:
5486 case 0x43:
5487 case 0x44:
5488 case 0x62:
5489 case 0x56:
5490 case 0x53:
5491 case 0x5d:
5492 case 0x5e: temp = 0x54; break;
5493 }
5494 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005495 }
5496 }
5497 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp); /* BPLHRS */
5498
5499 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5500 temp += 2;
5501 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005502 temp += 8;
5503 if(SiS_Pr->PanelHRE != 999) {
5504 temp = tempcx + SiS_Pr->PanelHRE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005505 if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
5506 temp >>= 3;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005507 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005508 }
5509 } else {
5510 temp += 10;
5511 }
5512
5513 temp &= 0x1F;
5514 temp |= ((tempcx & 0x07) << 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp); /* BPLHRE */
5516
5517 /* Vertical */
5518
5519 tempax = SiS_Pr->SiS_VGAVDE;
5520 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5521 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5522 tempax = SiS_Pr->PanelYRes;
5523 }
5524 }
5525
5526 tempbx = SiS_Pr->SiS_LCDVDES + tempax;
5527 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5528
5529 push2 = tempbx;
5530
5531 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005532 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005533 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005534 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005535 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
5536 }
5537 }
5538 }
5539 if(islvds) tempcx >>= 1;
5540 else tempcx >>= 2;
5541
5542 if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
5543 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
5544 (SiS_Pr->PanelVRS != 999) ) {
5545 tempcx = SiS_Pr->PanelVRS;
5546 tempbx += tempcx;
5547 if(issis) tempbx++;
5548 } else {
5549 tempbx += tempcx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005550 if(SiS_Pr->ChipType < SIS_315H) tempbx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005551 else if(issis) tempbx++;
5552 }
5553
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005554 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005555
5556 temp = tempbx & 0x00FF;
5557 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5558 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005559 if(ModeNo == 0x10) temp = 0xa9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560 }
5561 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005562 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp); /* BPLVRS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005563
5564 tempcx >>= 3;
5565 tempcx++;
5566
5567 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5568 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5569 if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
5570 }
5571 }
5572
5573 tempcx += tempbx;
5574 temp = tempcx & 0x000F;
5575 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); /* BPLVRE */
5576
5577 temp = ((tempbx >> 8) & 0x07) << 3;
5578 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5579 if(SiS_Pr->SiS_HDE != 640) {
5580 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5581 }
5582 } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5583 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40;
5584 tempbx = 0x87;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005585 if((SiS_Pr->ChipType >= SIS_315H) ||
5586 (SiS_Pr->ChipRevision >= 0x30)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587 tempbx = 0x07;
5588 if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
5589 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03) temp |= 0x80;
5590 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005591 /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5593 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5594 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
5595 } else {
5596 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
5597 }
5598 }
5599 }
5600 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
5601
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005602 tempbx = push2; /* BPLVDEE */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005603
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005604 tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005605
5606 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5607 switch(SiS_Pr->SiS_LCDResInfo) {
5608 case Panel_640x480:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005609 tempbx = SiS_Pr->SiS_VGAVDE - 1;
5610 tempcx = SiS_Pr->SiS_VGAVDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005611 break;
5612 case Panel_800x600:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005613 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5614 if(resinfo == SIS_RI_800x600) tempcx++;
5615 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005616 break;
5617 case Panel_1024x600:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005618 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5619 if(resinfo == SIS_RI_1024x600) tempcx++;
5620 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005621 if(resinfo == SIS_RI_800x600) tempcx++;
5622 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624 break;
5625 case Panel_1024x768:
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005626 if(SiS_Pr->ChipType < SIS_315H) {
5627 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5628 if(resinfo == SIS_RI_1024x768) tempcx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005629 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005630 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631 break;
5632 }
5633 }
5634
5635 temp = ((tempbx >> 8) & 0x07) << 3;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005636 temp |= ((tempcx >> 8) & 0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
5639 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
5640
5641 /* Vertical scaling */
5642
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005643 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005644
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005645#ifdef CONFIG_FB_SIS_300 /* 300 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005646 tempeax = SiS_Pr->SiS_VGAVDE << 6;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005647 temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
5648 tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005649 if(temp) tempeax++;
5650
5651 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
5652
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005653 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005654 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */
5655 tempvcfact = temp;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005656#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005657
5658 } else {
5659
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005660#ifdef CONFIG_FB_SIS_315 /* 315 series */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661 tempeax = SiS_Pr->SiS_VGAVDE << 18;
5662 tempebx = SiS_Pr->SiS_VDE;
5663 temp = (tempeax % tempebx);
5664 tempeax = tempeax / tempebx;
5665 if(temp) tempeax++;
5666 tempvcfact = tempeax;
5667
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005668 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005669 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005670 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005671 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005672 temp = (unsigned short)((tempeax & 0x00030000) >> 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005673 if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
5674 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
5675
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005676 if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
5677 temp = (unsigned short)(tempeax & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005678 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005679 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005681 temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005682 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
5683 temp = 0;
5684 if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
5685 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
5686 }
5687#endif
5688
5689 }
5690
5691 /* Horizontal scaling */
5692
5693 tempeax = SiS_Pr->SiS_VGAHDE; /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
5694 if(chkdclkfirst) {
5695 if(modeflag & HalfDCLK) tempeax >>= 1;
5696 }
5697 tempebx = tempeax << 16;
5698 if(SiS_Pr->SiS_HDE == tempeax) {
5699 tempecx = 0xFFFF;
5700 } else {
5701 tempecx = tempebx / SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005702 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005703 if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
5704 }
5705 }
5706
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005707 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708 tempeax = (tempebx / tempecx) - 1;
5709 } else {
5710 tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
5711 }
5712 tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005713 temp = (unsigned short)(tempecx & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005714 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
5715
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005716 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005717 tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005718 tempbx = (unsigned short)(tempeax & 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005719 } else {
5720 tempeax = SiS_Pr->SiS_VGAVDE << 6;
5721 tempbx = tempvcfact & 0x3f;
5722 if(tempbx == 0) tempbx = 64;
5723 tempeax /= tempbx;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005724 tempbx = (unsigned short)(tempeax & 0xFFFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005725 }
5726 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
5727 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
5728 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
5729 else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) tempbx = 1;
5730 }
5731
5732 temp = ((tempbx >> 8) & 0x07) << 3;
5733 temp = temp | ((tempecx >> 8) & 0x07);
5734 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
5735 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
5736
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005737 tempecx >>= 16; /* BPLHCFACT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005738 if(!chkdclkfirst) {
5739 if(modeflag & HalfDCLK) tempecx >>= 1;
5740 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005741 temp = (unsigned short)((tempecx & 0xFF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005743 temp = (unsigned short)(tempecx & 0x00FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005744 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
5745
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005746#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005747 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005748 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005749 if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005750 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
5751 }
5752 } else {
5753 if(islvds) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005754 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005755 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
5756 } else {
5757 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
5758 }
5759 }
5760 }
5761 }
5762#endif
5763
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005764#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07005765 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005766 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5767 unsigned char *trumpdata;
5768 int i, j = crt2crtc;
5769 unsigned char TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 };
5770 unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
5771 unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
5772
5773 if(SiS_Pr->SiS_UseROM) {
5774 trumpdata = &ROMAddr[0x8001 + (j * 80)];
5775 } else {
5776 if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
5777 trumpdata = &SiS300_TrumpionData[j][0];
5778 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005779
5780 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
5781 for(i=0; i<5; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005782 SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783 }
5784 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005785 if(ModeNo == 0x13) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005786 for(i=0; i<4; i++) {
5787 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
5788 }
5789 } else if(ModeNo == 0x10) {
5790 for(i=0; i<4; i++) {
5791 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
5792 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
5793 }
5794 }
5795 }
5796 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
5797 }
5798#endif
5799
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005800#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5802 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
5803 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
5804 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
5805 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
5806 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
5807 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
5808 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005809 tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
5810 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5811 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5812 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813 tempax += 64;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005814 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
5815 temp = (tempax >> 8) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005816 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005817 tempax += 32; /* Blpe = lBlps+32 */
5818 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
5819 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml = 0 */
5820 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821
5822 tempax = SiS_Pr->SiS_VDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005823 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5824 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5825 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826 tempax >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005827 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
5828 temp = (tempax >> 8) << 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005829 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
5830
5831 tempeax = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005832 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5833 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5834 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
5835 tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
5836 temp = tempeax & 0x7f;
5837 tempeax >>= 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838 if(temp) tempeax++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005839 temp = tempeax & 0x3f;
5840 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
5841 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
5843 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005844 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005845
5846 tempax = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005847 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5848 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5849 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5850 tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005851 pushcx = tempax;
5852 temp = tempax & 0x00FF;
5853 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
5854 temp = ((tempax & 0xFF00) >> 8) << 3;
Aaro Koskinen17d6ce12010-12-20 23:50:22 +02005855 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x44, 0x07, temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005856
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005857 tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
5858 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5859 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5860 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5861 tempeax = tempax * pushcx;
5862 temp = tempeax & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005864 temp = (tempeax & 0xFF00) >> 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005865 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005866 temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005868 temp = ((tempeax & 0x01000000) >> 24) << 7;
Aaro Koskinen17d6ce12010-12-20 23:50:22 +02005869 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x3C, 0x7F, temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870
5871 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
5872 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
5873 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
5874 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
5875 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
5876
5877 if(SiS_Pr->SiS_IF_DEF_FSTN) {
5878 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
5879 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
5880 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
5881 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
5882 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
5883 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
5884 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
5885 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
5886 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
5887 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
5888 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
5889 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
5890 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
5891 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
5892 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
5893 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
5894 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
5895 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
5896 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
5897 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
5898 }
5899 }
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005900#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005901}
5902
5903/* Set Part 1 */
5904static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005905SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5906 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907{
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005908#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005909 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005911 unsigned short temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
5912 unsigned short pushbx=0, CRT1Index=0, modeflag, resinfo=0;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005913#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005914 unsigned short tempbl=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915#endif
5916
5917 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005918 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919 return;
5920 }
5921
5922 if(ModeNo <= 0x13) {
5923 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5924 } else if(SiS_Pr->UseCustomMode) {
5925 modeflag = SiS_Pr->CModeFlag;
5926 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005927 CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5929 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5930 }
5931
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005932 SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005934 if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935 (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
5936 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
5937
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005938 if(SiS_Pr->ChipType < SIS_315H ) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005939#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005940 SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941#endif
5942 } else {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005943#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005944 SiS_SetCRT2FIFO_310(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945#endif
5946 }
5947
5948 /* 1. Horizontal setup */
5949
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005950 if(SiS_Pr->ChipType < SIS_315H ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005951
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005952#ifdef CONFIG_FB_SIS_300 /* ------------- 300 series --------------*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07005953
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005954 temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
5955 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005957 temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
5958 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005959
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005960 temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
5961 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005962
5963 pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA2HRS 0x0B,0x0C */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07005964 tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
5965 tempbx = pushbx + tempcx;
5966 tempcx <<= 1;
5967 tempcx += tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005968
5969 bridgeadd = 12;
5970
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005971#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972
5973 } else {
5974
Aaro Koskinenf7854e52010-11-19 21:58:47 +00005975#ifdef CONFIG_FB_SIS_315 /* ------------------- 315/330 series --------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005976
5977 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */
5978 if(modeflag & HalfDCLK) {
5979 if(SiS_Pr->SiS_VBType & VB_SISVB) {
5980 tempcx >>= 1;
5981 } else {
5982 tempax = SiS_Pr->SiS_VGAHDE >> 1;
5983 tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
5984 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
5985 tempcx = SiS_Pr->SiS_HT - tempax;
5986 }
5987 }
5988 }
5989 tempcx--;
5990 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx); /* CRT2 Horizontal Total */
5991 temp = (tempcx >> 4) & 0xF0;
5992 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp); /* CRT2 Horizontal Total Overflow [7:4] */
5993
5994 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HDEE 0x0A,0x0C */
5995 tempbx = SiS_Pr->SiS_VGAHDE;
5996 tempcx -= tempbx;
5997 tempcx >>= 2;
5998 if(modeflag & HalfDCLK) {
5999 tempbx >>= 1;
6000 tempcx >>= 1;
6001 }
6002 tempbx += 16;
6003
6004 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx); /* CRT2 Horizontal Display Enable End */
6005
6006 pushbx = tempbx;
6007 tempcx >>= 1;
6008 tempbx += tempcx;
6009 tempcx += tempbx;
6010
6011 bridgeadd = 16;
6012
6013 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006014 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015 if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
6016 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
6017 if(resinfo == SIS_RI_1280x1024) {
6018 tempcx = (tempcx & 0xff00) | 0x30;
6019 } else if(resinfo == SIS_RI_1600x1200) {
6020 tempcx = (tempcx & 0xff00) | 0xff;
6021 }
6022 }
6023 }
6024 }
6025
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006026#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027
6028 } /* 315/330 series */
6029
6030 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6031
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006032 if(SiS_Pr->UseCustomMode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033 tempbx = SiS_Pr->CHSyncStart + bridgeadd;
6034 tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
6035 tempax = SiS_Pr->SiS_VGAHT;
6036 if(modeflag & HalfDCLK) tempax >>= 1;
6037 tempax--;
6038 if(tempcx > tempax) tempcx = tempax;
6039 }
6040
6041 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6042 unsigned char cr4, cr14, cr5, cr15;
6043 if(SiS_Pr->UseCustomMode) {
6044 cr4 = SiS_Pr->CCRT1CRTC[4];
6045 cr14 = SiS_Pr->CCRT1CRTC[14];
6046 cr5 = SiS_Pr->CCRT1CRTC[5];
6047 cr15 = SiS_Pr->CCRT1CRTC[15];
6048 } else {
6049 cr4 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
6050 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
6051 cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
6052 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
6053 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006054 tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
6055 tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006056 tempcx &= 0x00FF;
6057 tempcx |= (tempbx & 0xFF00);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006058 tempbx += bridgeadd;
6059 tempcx += bridgeadd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060 tempax = SiS_Pr->SiS_VGAHT;
6061 if(modeflag & HalfDCLK) tempax >>= 1;
6062 tempax--;
6063 if(tempcx > tempax) tempcx = tempax;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006066 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
6067 tempbx = 1040;
6068 tempcx = 1044; /* HWCursor bug! */
6069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006070
6071 }
6072
6073 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx); /* CRT2 Horizontal Retrace Start */
6074
6075 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx); /* CRT2 Horizontal Retrace End */
6076
6077 temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
6078 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp); /* Overflow */
6079
6080 /* 2. Vertical setup */
6081
6082 tempcx = SiS_Pr->SiS_VGAVT - 1;
6083 temp = tempcx & 0x00FF;
6084
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006085 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006086 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006087 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006088 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6089 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6090 temp--;
6091 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006093 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006094 temp--;
6095 }
6096 } else if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006097 temp--;
6098 }
6099 }
6100 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp); /* CRT2 Vertical Total */
6101
6102 tempbx = SiS_Pr->SiS_VGAVDE - 1;
6103 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx); /* CRT2 Vertical Display Enable End */
6104
6105 temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
6106 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp); /* Overflow */
6107
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006108 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
6109 tempbx++;
6110 tempax = tempbx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006111 tempcx++;
6112 tempcx -= tempax;
6113 tempcx >>= 2;
6114 tempbx += tempcx;
6115 if(tempcx < 4) tempcx = 4;
6116 tempcx >>= 2;
6117 tempcx += tempbx;
6118 tempcx++;
6119 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006120 tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
6121 tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006122 }
6123
6124 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6125 if(SiS_Pr->UseCustomMode) {
6126 tempbx = SiS_Pr->CVSyncStart;
6127 tempcx = SiS_Pr->CVSyncEnd;
6128 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006129 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130 unsigned char cr8, cr7, cr13;
6131 if(SiS_Pr->UseCustomMode) {
6132 cr8 = SiS_Pr->CCRT1CRTC[8];
6133 cr7 = SiS_Pr->CCRT1CRTC[7];
6134 cr13 = SiS_Pr->CCRT1CRTC[13];
6135 tempcx = SiS_Pr->CCRT1CRTC[9];
6136 } else {
6137 cr8 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
6138 cr7 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
6139 cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
6140 tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
6141 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006142 tempbx = cr8;
6143 if(cr7 & 0x04) tempbx |= 0x0100;
6144 if(cr7 & 0x80) tempbx |= 0x0200;
6145 if(cr13 & 0x08) tempbx |= 0x0400;
6146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147 }
6148 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx); /* CRT2 Vertical Retrace Start */
6149
6150 temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
6151 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp); /* CRT2 Vert. Retrace End; Overflow */
6152
6153 /* 3. Panel delay compensation */
6154
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006155 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006156
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006157#ifdef CONFIG_FB_SIS_300 /* ---------- 300 series -------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006158
6159 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6160 temp = 0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006161 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162 temp = 0x10;
6163 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) temp = 0x2c;
6164 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6165 }
6166 if(SiS_Pr->SiS_VBType & VB_SIS301) {
6167 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6168 }
6169 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) temp = 0x24;
6170 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) temp = 0x2c;
6171 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08;
6172 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006173 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
6174 else temp = 0x20;
6175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006176 if(SiS_Pr->SiS_UseROM) {
6177 if(ROMAddr[0x220] & 0x80) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006178 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
6179 temp = ROMAddr[0x221];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006180 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
6181 temp = ROMAddr[0x222];
6182 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
6183 temp = ROMAddr[0x223];
6184 else
6185 temp = ROMAddr[0x224];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006186 }
6187 }
6188 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006189 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006190 }
6191
6192 } else {
6193 temp = 0x20;
6194 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6195 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
6196 }
6197 if(SiS_Pr->SiS_UseROM) {
6198 if(ROMAddr[0x220] & 0x80) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006199 temp = ROMAddr[0x220];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200 }
6201 }
6202 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006203 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006204 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006206
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006207 temp &= 0x3c;
6208
6209 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 -07006210
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006211#endif /* CONFIG_FB_SIS_300 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212
6213 } else {
6214
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006215#ifdef CONFIG_FB_SIS_315 /* --------------- 315/330 series ---------------*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07006216
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006217 if(SiS_Pr->ChipType < SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006218
6219 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6220
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006221 if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
6222 else temp = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006223
6224 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
6225 tempbl = 0xF0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006226 if(SiS_Pr->ChipType == SIS_650) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006227 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6228 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
6229 }
6230 }
6231
6232 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
6233 temp = 0x08;
6234 tempbl = 0;
6235 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
6236 if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
6237 }
6238 }
6239
6240 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp); /* Panel Link Delay Compensation */
6241 }
6242
6243 } /* < 661 */
6244
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006245 tempax = 0;
6246 if(modeflag & DoubleScanMode) tempax |= 0x80;
6247 if(modeflag & HalfDCLK) tempax |= 0x40;
6248 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006250#endif /* CONFIG_FB_SIS_315 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006251
6252 }
6253
6254 } /* Slavemode */
6255
6256 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6257 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006258 /* For 301BDH with LCD, we set up the Panel Link */
6259 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006260 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006261 SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006262 }
6263 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006264 if(SiS_Pr->ChipType < SIS_315H) {
6265 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006266 } else {
6267 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006268 if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6269 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
6270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006271 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006272 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006273 }
6274 }
6275 }
6276}
6277
6278/*********************************************/
6279/* SET PART 2 REGISTER GROUP */
6280/*********************************************/
6281
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006282#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006283static unsigned char *
6284SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006285{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006286 const unsigned char *tableptr = NULL;
6287 unsigned short a, b, p = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006288
6289 a = SiS_Pr->SiS_VGAHDE;
6290 b = SiS_Pr->SiS_HDE;
6291 if(tabletype) {
6292 a = SiS_Pr->SiS_VGAVDE;
6293 b = SiS_Pr->SiS_VDE;
6294 }
6295
6296 if(a < b) {
6297 tableptr = SiS_Part2CLVX_1;
6298 } else if(a == b) {
6299 tableptr = SiS_Part2CLVX_2;
6300 } else {
6301 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6302 tableptr = SiS_Part2CLVX_4;
6303 } else {
6304 tableptr = SiS_Part2CLVX_3;
6305 }
6306 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6307 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) tableptr = SiS_Part2CLVX_3;
6308 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tableptr = SiS_Part2CLVX_3;
6309 else tableptr = SiS_Part2CLVX_5;
6310 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6311 tableptr = SiS_Part2CLVX_6;
6312 }
6313 do {
6314 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
6315 p += 0x42;
6316 } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
6317 if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
6318 }
6319 p += 2;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006320 return ((unsigned char *)&tableptr[p]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006321}
6322
6323static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006324SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6325 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006326{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006327 unsigned char *tableptr;
6328 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006329 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006330
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006331 if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006332
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006333 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006334 for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
6335 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6336 }
6337 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006338 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006339 for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
6340 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6341 }
6342 }
6343 temp = 0x10;
6344 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
6345 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
6346}
6347
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006348static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006349SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
6350 unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
6351 unsigned short *ResIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006352{
6353
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006354 if(SiS_Pr->ChipType < SIS_315H) return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006355
6356 if(ModeNo <= 0x13)
6357 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6358 else
6359 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6360
6361 (*ResIndex) &= 0x3f;
6362 (*CRT2Index) = 0;
6363
6364 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6365 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6366 (*CRT2Index) = 200;
6367 }
6368 }
6369
6370 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
6371 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6372 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
6373 }
6374 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006375 return (((*CRT2Index) != 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006376}
6377#endif
6378
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006379#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07006380static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006381SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006382{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006383 unsigned short tempcx;
6384 static const unsigned char atable[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006385 0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
6386 0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
6387 };
6388
6389 if(!SiS_Pr->UseCustomMode) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006390 if( ( ( (SiS_Pr->ChipType == SIS_630) ||
6391 (SiS_Pr->ChipType == SIS_730) ) &&
6392 (SiS_Pr->ChipRevision > 2) ) &&
6393 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
6394 (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
6395 (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
6396 if(ModeNo == 0x13) {
6397 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
6398 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
6399 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
6400 } else if((crt2crtc & 0x3F) == 4) {
6401 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
6402 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
6403 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
6404 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
6405 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
6406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006407 }
6408
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006409 if(SiS_Pr->ChipType < SIS_315H) {
6410 if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
6411 crt2crtc &= 0x1f;
6412 tempcx = 0;
6413 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6414 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6415 tempcx += 7;
6416 }
6417 }
6418 tempcx += crt2crtc;
6419 if(crt2crtc >= 4) {
6420 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
6421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006422
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006423 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6424 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6425 if(crt2crtc == 4) {
6426 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
6427 }
6428 }
6429 }
6430 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
6431 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
6432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006433 }
6434 }
6435}
6436
6437/* For ECS A907. Highly preliminary. */
6438static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006439SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
6440 unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006441{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006442 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6443 unsigned short crt2crtc, resindex;
6444 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006445
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006446 if(SiS_Pr->ChipType != SIS_300) return;
6447 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006448 if(SiS_Pr->UseCustomMode) return;
6449
6450 if(ModeNo <= 0x13) {
6451 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6452 } else {
6453 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6454 }
6455
6456 resindex = crt2crtc & 0x3F;
6457 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6458 else CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
6459
6460 /* The BIOS code (1.16.51,56) is obviously a fragment! */
6461 if(ModeNo > 0x13) {
6462 CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6463 resindex = 4;
6464 }
6465
6466 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6467 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6468 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006469 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006470 }
6471 for(j = 0x1c; j <= 0x1d; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006472 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006473 }
6474 for(j = 0x1f; j <= 0x21; i++, j++ ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006475 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006476 }
6477 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6478 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6479}
6480#endif
6481
6482static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006483SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006484{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006485 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006486 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
6487 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
6488
6489 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6490 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006491 const unsigned char specialtv[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006492 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
6493 0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
6494 0x58,0xe4,0x73,0xda,0x13
6495 };
6496 int i, j;
6497 for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
6498 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
6499 }
6500 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
6501 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
6502 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6503 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
6504 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
6505 } else {
6506 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14); /* 15 */
6507 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a); /* 1b */
6508 }
6509 }
6510 }
6511 } else {
6512 if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
6513 (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
6514 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b); /* 21 */
6515 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54); /* 5a */
6516 } else {
6517 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a); /* 21 */
6518 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53); /* 5a */
6519 }
6520 }
6521}
6522
6523static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006524SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006525{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006526 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006527
6528 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6529 if(SiS_Pr->SiS_VGAVDE == 525) {
6530 temp = 0xc3;
6531 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6532 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006533 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006534 }
6535 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6536 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
6537 } else if(SiS_Pr->SiS_VGAVDE == 420) {
6538 temp = 0x4d;
6539 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6540 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006541 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006542 }
6543 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6544 }
6545 }
6546
6547 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6548 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006549 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006550 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
6551 /* Not always for LV, see SetGrp2 */
6552 }
6553 temp = 1;
6554 if(ModeNo <= 0x13) temp = 3;
6555 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
6556 }
6557#if 0
6558 /* 651+301C, for 1280x768 - do I really need that? */
6559 if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
6560 if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
6561 if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
6562 ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
6563 SiS_SetReg(SiS_Part2Port,0x01,0x2b);
6564 SiS_SetReg(SiS_Part2Port,0x02,0x13);
6565 SiS_SetReg(SiS_Part2Port,0x04,0xe5);
6566 SiS_SetReg(SiS_Part2Port,0x05,0x08);
6567 SiS_SetReg(SiS_Part2Port,0x06,0xe2);
6568 SiS_SetReg(SiS_Part2Port,0x1c,0x21);
6569 SiS_SetReg(SiS_Part2Port,0x1d,0x45);
6570 SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
6571 SiS_SetReg(SiS_Part2Port,0x20,0x00);
6572 SiS_SetReg(SiS_Part2Port,0x21,0xa9);
6573 SiS_SetReg(SiS_Part2Port,0x23,0x0b);
6574 SiS_SetReg(SiS_Part2Port,0x25,0x04);
6575 }
6576 }
6577 }
6578#endif
6579 }
6580}
6581
6582static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006583SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6584 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006585{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006586 unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
6587 unsigned short push2, modeflag, crt2crtc, bridgeoffset;
6588 unsigned int longtemp, PhaseIndex;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006589 bool newtvphase;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006590 const unsigned char *TimingPoint;
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006591#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006592 unsigned short resindex, CRT2Index;
6593 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006594
6595 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
6596#endif
6597
6598 if(ModeNo <= 0x13) {
6599 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6600 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6601 } else if(SiS_Pr->UseCustomMode) {
6602 modeflag = SiS_Pr->CModeFlag;
6603 crt2crtc = 0;
6604 } else {
6605 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6606 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6607 }
6608
6609 temp = 0;
6610 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
6611 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
6612 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) temp |= 0x02;
6613 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp |= 0x01;
6614
6615 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) temp |= 0x10;
6616
6617 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
6618
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006619 PhaseIndex = 0x01; /* SiS_PALPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006620 TimingPoint = SiS_Pr->SiS_PALTiming;
6621
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006622 newtvphase = false;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006623 if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
6624 ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6625 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08006626 newtvphase = true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006627 }
6628
Linus Torvalds1da177e2005-04-16 15:20:36 -07006629 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6630
6631 TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
6632 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6633 TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
6634 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6635 TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006636 }
6637 }
6638
6639 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6640
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006641 i = 0;
6642 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) i = 2;
6643 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006644
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006645 TimingPoint = &SiS_YPbPrTable[i][0];
6646
6647 PhaseIndex = 0x00; /* SiS_NTSCPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006648
6649 } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6650
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006651 if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006652
6653 } else {
6654
6655 TimingPoint = SiS_Pr->SiS_NTSCTiming;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006656 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00; /* SiS_PALPhase : SiS_NTSCPhase */
6657 if(newtvphase) PhaseIndex += 8; /* SiS_PALPhase2 : SiS_NTSCPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006658
6659 }
6660
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006661 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
6662 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03; /* SiS_PALMPhase : SiS_PALNPhase */
6663 if(newtvphase) PhaseIndex += 8; /* SiS_PALMPhase2 : SiS_PALNPhase2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006664 }
6665
6666 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006667 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006668 PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006669 } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006670 PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
6671 } else {
6672 PhaseIndex = 0x10; /* SiS_SpecialPhase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006673 }
6674 }
6675
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006676 for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
6677 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006678 }
6679
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006680 for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006681 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6682 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006683 for(i = 0x39; i <= 0x45; i++, j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006684 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6685 }
6686
6687 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6688 if(SiS_Pr->SiS_ModeType != ModeText) {
6689 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
6690 }
6691 }
6692
6693 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
6694
6695 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
6696 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
6697 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
6698 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
6699
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006700 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950;
6701 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempax = 680;
6702 else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520;
6703 else tempax = 440; /* NTSC, YPbPr 525 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006704
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006705 if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07006706 ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
6707 ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
6708
6709 tempax -= SiS_Pr->SiS_VDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006710 tempax >>= 1;
6711 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
6712 tempax >>= 1;
6713 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006714 tempax &= 0x00ff;
6715
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006716 temp = tempax + (unsigned short)TimingPoint[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006717 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
6718
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006719 temp = tempax + (unsigned short)TimingPoint[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006720 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
6721
6722 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
6723 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006724 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
6725 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006726 } else {
6727 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
6728 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
6729 }
6730 }
6731
6732 }
6733
6734 tempcx = SiS_Pr->SiS_HT;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006735 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006736 tempcx--;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006737 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006738 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
6739 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
6740
6741 tempcx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006742 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006743 tempcx += 7;
6744 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6745 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
6746
6747 tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
6748 tempbx += tempcx;
6749 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
6750 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
6751
6752 tempbx += 8;
6753 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6754 tempbx -= 4;
6755 tempcx = tempbx;
6756 }
6757 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
6758
6759 j += 2;
6760 tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
6761 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
6762 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
6763
6764 tempcx += 8;
6765 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6766 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
6767
6768 tempcx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006769 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006770 j += 2;
6771 tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
6772 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
6773
6774 tempcx -= 11;
6775 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6776 tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
6777 }
6778 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
6779
6780 tempbx = SiS_Pr->SiS_VDE;
6781 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6782 if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
6783 if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
6784 if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
6785 } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6786 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
6787 tempbx >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006788 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006789 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6790 if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
6791 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6792 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6793 if(crt2crtc == 4) tempbx++;
6794 }
6795 }
6796 }
6797 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6798 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6799 if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
6800 }
6801 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6802 if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
6803 }
6804 }
6805 }
6806 tempbx -= 2;
6807 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
6808
6809 temp = (tempcx >> 8) & 0x0F;
6810 temp |= ((tempbx >> 2) & 0xC0);
6811 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6812 temp |= 0x10;
6813 if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
6814 }
6815 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
6816
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006817 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006818 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
6819 }
6820
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006821 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006822 tempbx = SiS_Pr->SiS_VDE;
6823 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6824 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
6825 tempbx >>= 1;
6826 }
6827 tempbx -= 3;
6828 temp = ((tempbx >> 3) & 0x60) | 0x18;
6829 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
6830 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
6831
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006832 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006833 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
6834 }
6835 }
6836
6837 tempbx = 0;
6838 if(!(modeflag & HalfDCLK)) {
6839 if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
6840 tempax = 0;
6841 tempbx |= 0x20;
6842 }
6843 }
6844
6845 tempch = tempcl = 0x01;
6846 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006847 if(SiS_Pr->SiS_VGAHDE >= 960) {
6848 if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006849 tempcl = 0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006850 if(SiS_Pr->SiS_VGAHDE >= 1280) {
6851 tempch = 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006852 tempbx &= ~0x20;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006853 } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
6854 tempch = 25;
6855 } else {
6856 tempch = 25; /* OK */
6857 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006858 }
6859 }
6860 }
6861
6862 if(!(tempbx & 0x20)) {
6863 if(modeflag & HalfDCLK) tempcl <<= 1;
6864 longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006865 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006866 tempax = longtemp / SiS_Pr->SiS_HDE;
6867 if(longtemp % SiS_Pr->SiS_HDE) tempax++;
6868 tempbx |= ((tempax >> 8) & 0x1F);
6869 tempcx = tempax >> 13;
6870 }
6871
6872 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
6873 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
6874
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006875 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006876
6877 tempcx &= 0x07;
6878 if(tempbx & 0x20) tempcx = 0;
6879 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
6880
6881 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6882 tempbx = 0x0382;
6883 tempcx = 0x007e;
6884 } else {
6885 tempbx = 0x0369;
6886 tempcx = 0x0061;
6887 }
6888 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
6889 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
6890 temp = (tempcx & 0x0300) >> 6;
6891 temp |= ((tempbx >> 8) & 0x03);
6892 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6893 temp |= 0x10;
6894 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp |= 0x20;
6895 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
6896 }
6897 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
6898
6899 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
6900 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
6901
6902 SiS_SetTVSpecial(SiS_Pr, ModeNo);
6903
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006904 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006905 temp = 0;
6906 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
6907 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
6908 }
6909
6910 }
6911
6912 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6913 if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
6914 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
6915 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
6916 }
6917 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
6918 }
6919
6920 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6921 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6922 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
6923 }
6924 }
6925
6926 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
6927
6928 /* From here: Part2 LCD setup */
6929
6930 tempbx = SiS_Pr->SiS_HDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006931 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006932 tempbx--; /* RHACTE = HDE - 1 */
6933 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
6934 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
6935
6936 temp = 0x01;
6937 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
6938 if(SiS_Pr->SiS_ModeType == ModeEGA) {
6939 if(SiS_Pr->SiS_VGAHDE >= 1024) {
6940 temp = 0x02;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006941 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
6942 temp = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006943 }
6944 }
6945 }
6946 }
6947 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
6948
6949 tempbx = SiS_Pr->SiS_VDE - 1;
6950 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
6951 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
6952
6953 tempcx = SiS_Pr->SiS_VT - 1;
6954 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
6955 temp = (tempcx >> 3) & 0xE0;
6956 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
6957 /* Enable dithering; only do this for 32bpp mode */
6958 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
6959 temp |= 0x10;
6960 }
6961 }
6962 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
6963
6964 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
6965 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
6966
6967 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
6968 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
6969
Aaro Koskinenf7854e52010-11-19 21:58:47 +00006970#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07006971 if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006972 &CRT2Index, &resindex)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006973 switch(CRT2Index) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07006974 case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break;
6975 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006976 case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006977 }
6978
6979 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6980 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6981 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
6982 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6983 }
6984 for(j = 0x1c; j <= 0x1d; i++, j++ ) {
6985 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6986 }
6987 for(j = 0x1f; j <= 0x21; i++, j++ ) {
6988 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6989 }
6990 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6991 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6992
6993 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
6994
Linus Torvalds1da177e2005-04-16 15:20:36 -07006995 } else {
6996#endif
6997
6998 /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
6999 /* Clevo dual-link 1024x768 */
7000 /* Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct) */
7001 /* Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
7002
7003 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7004 if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7005 tempbx = SiS_Pr->SiS_VDE - 1;
7006 tempcx = SiS_Pr->SiS_VT - 1;
7007 } else {
7008 tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7009 tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7010 }
7011 } else {
7012 tempbx = SiS_Pr->PanelYRes;
7013 tempcx = SiS_Pr->SiS_VT;
7014 tempax = 1;
7015 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7016 tempax = SiS_Pr->PanelYRes;
7017 /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c; */ /* 651+301C */
7018 if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7019 tempax = tempcx = 0;
7020 } else {
7021 tempax -= SiS_Pr->SiS_VDE;
7022 }
7023 tempax >>= 1;
7024 }
7025 tempcx -= tempax; /* lcdvdes */
7026 tempbx -= tempax; /* lcdvdee */
7027 }
7028
7029 /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7030
Linus Torvalds1da177e2005-04-16 15:20:36 -07007031 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */
7032 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */
7033
7034 temp = (tempbx >> 5) & 0x38;
7035 temp |= ((tempcx >> 8) & 0x07);
7036 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7037
7038 tempax = SiS_Pr->SiS_VDE;
7039 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7040 tempax = SiS_Pr->PanelYRes;
7041 }
7042 tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7043 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7044 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7045 tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7046 }
7047 }
7048
7049 tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7050 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7051 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7052 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7053 tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7054 if(tempax % 4) { tempax >>= 2; tempax++; }
7055 else { tempax >>= 2; }
7056 tempbx -= (tempax - 1);
7057 } else {
7058 tempbx -= 10;
7059 if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7060 }
7061 }
7062 }
7063 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7064 tempbx++;
7065 if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7066 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7067 tempbx = 770;
7068 tempcx = 3;
7069 }
7070 }
7071 }
7072
7073 /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7074
7075 if(SiS_Pr->UseCustomMode) {
7076 tempbx = SiS_Pr->CVSyncStart;
7077 }
7078
Linus Torvalds1da177e2005-04-16 15:20:36 -07007079 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */
7080
7081 temp = (tempbx >> 4) & 0xF0;
7082 tempbx += (tempcx + 1);
7083 temp |= (tempbx & 0x0F);
7084
7085 if(SiS_Pr->UseCustomMode) {
7086 temp &= 0xf0;
7087 temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7088 }
7089
Linus Torvalds1da177e2005-04-16 15:20:36 -07007090 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7091
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007092#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007093 SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007094#endif
7095
7096 bridgeoffset = 7;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007097 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) bridgeoffset += 2;
7098 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
7099 if(SiS_IsDualLink(SiS_Pr)) bridgeoffset++;
7100 else if(SiS_Pr->SiS_VBType & VB_SIS302LV) bridgeoffset++; /* OK for Asus A4L 1280x800 */
7101 /* Higher bridgeoffset shifts to the LEFT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007102
7103 temp = 0;
7104 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7105 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007106 temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7107 if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108 }
7109 }
7110 temp += bridgeoffset;
7111 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp); /* lcdhdes */
7112 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7113
7114 tempcx = SiS_Pr->SiS_HT;
7115 tempax = tempbx = SiS_Pr->SiS_HDE;
7116 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7117 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7118 tempax = SiS_Pr->PanelXRes;
7119 tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7120 }
7121 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007122 if(SiS_IsDualLink(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007123 tempcx >>= 1;
7124 tempbx >>= 1;
7125 tempax >>= 1;
7126 }
7127
Linus Torvalds1da177e2005-04-16 15:20:36 -07007128 tempbx += bridgeoffset;
7129
7130 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx); /* lcdhdee */
7131 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7132
7133 tempcx = (tempcx - tempax) >> 2;
7134
7135 tempbx += tempcx;
7136 push2 = tempbx;
7137
7138 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7139 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7140 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7141 if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7142 }
7143 }
7144 }
7145
7146 if(SiS_Pr->UseCustomMode) {
7147 tempbx = SiS_Pr->CHSyncStart;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007148 if(modeflag & HalfDCLK) tempbx <<= 1;
7149 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007150 tempbx += bridgeoffset;
7151 }
7152
Linus Torvalds1da177e2005-04-16 15:20:36 -07007153 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */
7154 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7155
7156 tempbx = push2;
7157
7158 tempcx <<= 1;
7159 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7160 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7161 }
7162 tempbx += tempcx;
7163
7164 if(SiS_Pr->UseCustomMode) {
7165 tempbx = SiS_Pr->CHSyncEnd;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007166 if(modeflag & HalfDCLK) tempbx <<= 1;
7167 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007168 tempbx += bridgeoffset;
7169 }
7170
Linus Torvalds1da177e2005-04-16 15:20:36 -07007171 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */
7172
7173 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7174
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007175#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007176 SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007177#endif
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007178#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07007179 } /* CRT2-LCD from table */
7180#endif
7181}
7182
7183/*********************************************/
7184/* SET PART 3 REGISTER GROUP */
7185/*********************************************/
7186
7187static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007188SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007189{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007190 unsigned short i;
7191 const unsigned char *tempdi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007192
7193 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7194
7195#ifndef SIS_CP
7196 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7197#else
7198 SIS_CP_INIT301_CP
7199#endif
7200
7201 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7202 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7203 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7204 } else {
7205 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7206 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7207 }
7208
7209 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7210 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7211 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7212 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7213 }
7214
7215 tempdi = NULL;
7216 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7217 tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7218 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7219 tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7220 }
7221 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7222 if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7223 tempdi = SiS_HiTVGroup3_1;
7224 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7225 }
7226 }
7227 if(tempdi) {
7228 for(i=0; i<=0x3E; i++) {
7229 SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7230 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007231 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007232 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7233 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7234 }
7235 }
7236 }
7237
7238#ifdef SIS_CP
7239 SIS_CP_INIT301_CP2
7240#endif
7241}
7242
7243/*********************************************/
7244/* SET PART 4 REGISTER GROUP */
7245/*********************************************/
7246
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007247#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007248#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07007249static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007250SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007251{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007252 unsigned short temp, temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007253
7254 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7255 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007256 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007257 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7258 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7259 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007260 temp = (unsigned short)((int)(temp) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007261 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7262 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7263 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007264 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007265 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7266 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7267}
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007268#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07007269
7270static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007271SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007272{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007273 unsigned short temp, temp1, resinfo = 0;
7274 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007275
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007276 if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007277 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7278
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007279 if(SiS_Pr->ChipType >= XGI_20) return;
7280
7281 if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
7282 if(!(ROMAddr[0x61] & 0x04)) return;
7283 }
7284
Linus Torvalds1da177e2005-04-16 15:20:36 -07007285 if(ModeNo > 0x13) {
7286 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7287 }
7288
7289 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7290 temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7291 if(!(temp & 0x01)) {
7292 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7293 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007294 if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007295 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7296 }
7297 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7298 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp = 0x0000;
7299 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7300 else if(SiS_Pr->SiS_TVMode & TVSetHiVision) temp = 0x0400;
7301 else temp = 0x0402;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007302 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007303 temp1 = 0;
7304 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7305 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7306 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7307 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007308 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7309 if(ModeNo > 0x13) {
7310 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
7311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007312 } else {
7313 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7314 if(temp1 == 0x01) temp |= 0x01;
7315 if(temp1 == 0x03) temp |= 0x04; /* ? why not 0x10? */
7316 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007317 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7318 if(ModeNo > 0x13) {
7319 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007321 }
7322
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007323#if 0
7324 if(SiS_Pr->ChipType >= SIS_661) { /* ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007325 if(SiS_Pr->SiS_TVMode & TVAspect43) {
7326 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7327 if(resinfo == SIS_RI_1024x768) {
7328 SiS_ShiftXPos(SiS_Pr, 97);
7329 } else {
7330 SiS_ShiftXPos(SiS_Pr, 111);
7331 }
7332 } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7333 SiS_ShiftXPos(SiS_Pr, 136);
7334 }
7335 }
7336 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007337#endif
7338
Linus Torvalds1da177e2005-04-16 15:20:36 -07007339 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007340
Linus Torvalds1da177e2005-04-16 15:20:36 -07007341}
7342#endif
7343
7344static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007345SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7346 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007347{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007348 unsigned short vclkindex, temp, reg1, reg2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007349
7350 if(SiS_Pr->UseCustomMode) {
7351 reg1 = SiS_Pr->CSR2B;
7352 reg2 = SiS_Pr->CSR2C;
7353 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007354 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007355 reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7356 reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7357 }
7358
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007359 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7360 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007361 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7362 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7363 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7364 } else {
7365 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7366 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7367 }
7368 } else {
7369 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7370 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7371 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7372 }
7373 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7374 temp = 0x08;
7375 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7376 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7377}
7378
7379static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007380SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007381{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007382 if(SiS_Pr->ChipType >= SIS_315H) {
7383 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
7384 if((SiS_CRT2IsLCD(SiS_Pr)) ||
7385 (SiS_IsVAMode(SiS_Pr))) {
7386 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
7387 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7388 } else {
7389 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7390 }
7391 }
7392 }
7393 }
7394 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
7395 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7396#ifdef SET_EMI
7397 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7398#endif
7399 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7400 }
7401}
7402
7403static void
7404SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7405 unsigned short RefreshRateTableIndex)
7406{
7407 unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
7408 unsigned int tempebx, tempeax, templong;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007409
7410 if(ModeNo <= 0x13) {
7411 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7412 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7413 } else if(SiS_Pr->UseCustomMode) {
7414 modeflag = SiS_Pr->CModeFlag;
7415 resinfo = 0;
7416 } else {
7417 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7418 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7419 }
7420
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007421 if(SiS_Pr->ChipType >= SIS_315H) {
7422 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7423 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7424 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007425 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007426 }
7427 }
7428
7429 if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
7430 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7431 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
7432 }
7433 }
7434
7435 if(SiS_Pr->ChipType >= SIS_315H) {
7436 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7437 SiS_SetDualLinkEtc(SiS_Pr);
7438 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007439 }
7440 }
7441
7442 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7443
7444 tempbx = SiS_Pr->SiS_RVBHCMAX;
7445 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7446
7447 temp = (tempbx >> 1) & 0x80;
7448
7449 tempcx = SiS_Pr->SiS_VGAHT - 1;
7450 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7451
7452 temp |= ((tempcx >> 5) & 0x78);
7453
7454 tempcx = SiS_Pr->SiS_VGAVT - 1;
7455 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7456 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7457
7458 temp |= ((tempcx >> 8) & 0x07);
7459 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7460
7461 tempbx = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007462 if(modeflag & HalfDCLK) tempbx >>= 1;
7463 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007464
7465 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7466 temp = 0;
7467 if(tempbx > 800) temp = 0x60;
7468 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7469 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007470 if(tempbx > 1024) temp = 0xC0;
7471 else if(tempbx >= 960) temp = 0xA0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007472 } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7473 temp = 0;
7474 if(tempbx >= 1280) temp = 0x40;
7475 else if(tempbx >= 1024) temp = 0x20;
7476 } else {
7477 temp = 0x80;
7478 if(tempbx >= 1024) temp = 0xA0;
7479 }
7480
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007481 temp |= SiS_Pr->Init_P4_0E;
7482
Linus Torvalds1da177e2005-04-16 15:20:36 -07007483 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007484 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
7485 temp &= 0xf0;
7486 temp |= 0x0A;
7487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007488 }
7489
7490 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7491
7492 tempeax = SiS_Pr->SiS_VGAVDE;
7493 tempebx = SiS_Pr->SiS_VDE;
7494 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7495 if(!(temp & 0xE0)) tempebx >>=1;
7496 }
7497
7498 tempcx = SiS_Pr->SiS_RVBHRS;
7499 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7500 tempcx >>= 8;
7501 tempcx |= 0x40;
7502
7503 if(tempeax <= tempebx) {
7504 tempcx ^= 0x40;
7505 } else {
7506 tempeax -= tempebx;
7507 }
7508
7509 tempeax *= (256 * 1024);
7510 templong = tempeax % tempebx;
7511 tempeax /= tempebx;
7512 if(templong) tempeax++;
7513
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007514 temp = (unsigned short)(tempeax & 0x000000FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007515 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007516 temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007517 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007518 temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007519 temp |= (tempcx & 0x4F);
7520 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7521
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007522 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007523
7524 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7525
7526 /* Calc Linebuffer max address and set/clear decimode */
7527 tempbx = 0;
7528 if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7529 tempax = SiS_Pr->SiS_VGAHDE;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007530 if(modeflag & HalfDCLK) tempax >>= 1;
7531 if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007532 if(tempax > 800) {
7533 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7534 tempax -= 800;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007535 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007536 tempbx = 0x08;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007537 if(tempax == 960) tempax *= 25; /* Correct */
7538 else if(tempax == 1024) tempax *= 25;
7539 else tempax *= 20;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007540 temp = tempax % 32;
7541 tempax /= 32;
7542 if(temp) tempax++;
7543 tempax++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007544 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7545 if(resinfo == SIS_RI_1024x768 ||
7546 resinfo == SIS_RI_1024x576 ||
7547 resinfo == SIS_RI_1280x1024 ||
7548 resinfo == SIS_RI_1280x720) {
7549 /* Otherwise white line or garbage at right edge */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007550 tempax = (tempax & 0xff00) | 0x20;
7551 }
7552 }
7553 }
7554 }
7555 tempax--;
7556 temp = ((tempax >> 4) & 0x30) | tempbx;
7557 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7558 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7559
7560 temp = 0x0036; tempbx = 0xD0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007561 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007562 temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7563 }
7564 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7565 if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7566 temp |= 0x01;
7567 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7568 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7569 temp &= ~0x01;
7570 }
7571 }
7572 }
7573 }
7574 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7575
7576 tempbx = SiS_Pr->SiS_HT >> 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007577 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007578 tempbx -= 2;
7579 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7580 temp = (tempbx >> 5) & 0x38;
7581 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7582
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007583 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007584 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7585 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7586 /* LCD-too-dark-error-source, see FinalizeLCD() */
7587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007588 }
7589
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007590 SiS_SetDualLinkEtc(SiS_Pr);
7591
Linus Torvalds1da177e2005-04-16 15:20:36 -07007592 } /* 301B */
7593
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007594 SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007595}
7596
7597/*********************************************/
7598/* SET PART 5 REGISTER GROUP */
7599/*********************************************/
7600
7601static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007602SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007603{
7604
7605 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7606
7607 if(SiS_Pr->SiS_ModeType == ModeVGA) {
7608 if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7609 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007610 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007611 }
7612 }
7613}
7614
7615/*********************************************/
7616/* MODIFY CRT1 GROUP FOR SLAVE MODE */
7617/*********************************************/
7618
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007619static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007620SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7621 unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
7622 unsigned short *DisplayType)
7623 {
7624 unsigned short modeflag = 0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007625 bool checkhd = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007626
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007627 /* Pass 1:1 not supported here */
7628
7629 if(ModeNo <= 0x13) {
7630 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7631 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7632 } else {
7633 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7634 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7635 }
7636
7637 (*ResIndex) &= 0x3F;
7638
7639 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7640
7641 (*DisplayType) = 80;
7642 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
7643 (*DisplayType) = 82;
7644 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7645 if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
7646 }
7647 }
7648 if((*DisplayType) != 84) {
7649 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
7650 }
7651
7652 } else {
7653
7654 (*DisplayType = 0);
7655 switch(SiS_Pr->SiS_LCDResInfo) {
7656 case Panel_320x240_1: (*DisplayType) = 50;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007657 checkhd = false;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007658 break;
7659 case Panel_320x240_2: (*DisplayType) = 14;
7660 break;
7661 case Panel_320x240_3: (*DisplayType) = 18;
7662 break;
7663 case Panel_640x480: (*DisplayType) = 10;
7664 break;
7665 case Panel_1024x600: (*DisplayType) = 26;
7666 break;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007667 default: return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007668 }
7669
7670 if(checkhd) {
7671 if(modeflag & HalfDCLK) (*DisplayType)++;
7672 }
7673
7674 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
7675 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
7676 }
7677
7678 }
7679
Richard Knutssonc30660ea2007-02-12 00:55:06 -08007680 return true;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007681}
7682
7683static void
7684SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7685 unsigned short RefreshRateTableIndex)
7686{
7687 unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
7688 const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
7689 static const unsigned short CRIdx[] = {
7690 0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
7691 0x07, 0x10, 0x11, 0x15, 0x16
7692 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07007693
7694 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
7695 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007696 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
7697 (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
Linus Torvalds1da177e2005-04-16 15:20:36 -07007698 return;
7699
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007700 if(SiS_Pr->SiS_IF_DEF_LVDS) {
7701 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7702 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7703 }
7704 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
7705 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7706 } else return;
7707
7708 if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
7709
7710 if(SiS_Pr->ChipType < SIS_315H) {
7711 if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
7712 }
7713
Linus Torvalds1da177e2005-04-16 15:20:36 -07007714 if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7715 &ResIndex, &DisplayType))) {
7716 return;
7717 }
7718
Linus Torvalds1da177e2005-04-16 15:20:36 -07007719 switch(DisplayType) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007720 case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1; break; /* xSTN */
7721 case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2; break; /* xSTN */
7722 case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H; break; /* xSTN */
7723 case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3; break; /* xSTN */
7724 case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H; break; /* xSTN */
7725 case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
7726 case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
7727#if 0 /* Works better with calculated numbers */
7728 case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break;
7729 case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break;
7730 case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break;
7731 case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break;
7732#endif
7733 case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break;
7734 case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break;
7735 case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break;
7736 case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
7737 case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007738 }
7739
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007740 if(LVDSCRT1Ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007741
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007742 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007743
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007744 for(i = 0; i <= 10; i++) {
7745 tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
7746 SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
7747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007748
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007749 for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
7750 tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
7751 SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
7752 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007753
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007754 tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
7755 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
7756
7757 if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7758 else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7759
7760 tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
7761 if(modeflag & DoubleScanMode) tempah |= 0x80;
7762 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
7763
7764 } else {
7765
7766 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
7767
7768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007769}
7770
7771/*********************************************/
7772/* SET CRT2 ECLK */
7773/*********************************************/
7774
7775static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007776SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7777 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007778{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007779 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
7780 unsigned short clkbase, vclkindex = 0;
7781 unsigned char sr2b, sr2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007782
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007783 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7784 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
7785 if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
7786 RefreshRateTableIndex--;
7787 }
7788 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7789 RefreshRateTableIndex);
7790 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007791 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007792 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7793 RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007794 }
7795
7796 sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
7797 sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
7798
7799 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
7800 if(SiS_Pr->SiS_UseROM) {
7801 if(ROMAddr[0x220] & 0x01) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007802 sr2b = ROMAddr[0x227];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007803 sr2c = ROMAddr[0x228];
7804 }
7805 }
7806 }
7807
7808 clkbase = 0x02B;
7809 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7810 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007811 clkbase += 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007812 }
7813 }
7814
7815 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
7816 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7817 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7818 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
7819 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7820 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7821 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
7822 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7823 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7824}
7825
7826/*********************************************/
7827/* SET UP CHRONTEL CHIPS */
7828/*********************************************/
7829
7830static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007831SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7832 unsigned short RefreshRateTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007833{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007834 unsigned short TVType, resindex;
7835 const struct SiS_CHTVRegData *CHTVRegData = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007836
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007837 if(ModeNo <= 0x13)
7838 resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7839 else
7840 resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007841
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007842 resindex &= 0x3F;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007843
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007844 TVType = 0;
7845 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7846 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7847 TVType += 2;
7848 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7849 if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
7850 }
7851 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7852 TVType = 4;
7853 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7854 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
7855 TVType = 6;
7856 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7857 }
7858 }
7859
7860 switch(TVType) {
7861 case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
7862 case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
7863 case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break;
7864 case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
7865 case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
7866 case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
7867 case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
7868 case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
7869 case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
7870 default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
7871 }
7872
7873
7874 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007875
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007876#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -07007877
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007878 /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007879
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007880 /* We don't support modes >800x600 */
7881 if (resindex > 5) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007882
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007883 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7884 SiS_SetCH700x(SiS_Pr,0x04,0x43); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
7885 SiS_SetCH700x(SiS_Pr,0x09,0x69); /* Black level for PAL (105)*/
7886 } else {
7887 SiS_SetCH700x(SiS_Pr,0x04,0x03); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
7888 SiS_SetCH700x(SiS_Pr,0x09,0x71); /* Black level for NTSC (113)*/
7889 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007890
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007891 SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]); /* Mode register */
7892 SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]); /* Start active video register */
7893 SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]); /* Position overflow register */
7894 SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]); /* Horiz Position register */
7895 SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]); /* Vertical Position register */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007896
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007897 /* Set minimum flicker filter for Luma channel (SR1-0=00),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007898 minimum text enhancement (S3-2=10),
7899 maximum flicker filter for Chroma channel (S5-4=10)
7900 =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007901 */
7902 SiS_SetCH700x(SiS_Pr,0x01,0x28);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007903
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007904 /* Set video bandwidth
Adrian Bunk9aaeded2006-06-30 18:19:55 +02007905 High bandwidth Luma composite video filter(S0=1)
7906 low bandwidth Luma S-video filter (S2-1=00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007907 disable peak filter in S-video channel (S3=0)
7908 high bandwidth Chroma Filter (S5-4=11)
7909 =00110001=0x31
Linus Torvalds1da177e2005-04-16 15:20:36 -07007910 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007911 SiS_SetCH700x(SiS_Pr,0x03,0xb1); /* old: 3103 */
7912
7913 /* Register 0x3D does not exist in non-macrovision register map
7914 (Maybe this is a macrovision register?)
7915 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007916#ifndef SIS_CP
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007917 SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007918#endif
7919
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007920 /* Register 0x10 only contains 1 writable bit (S0) for sensing,
7921 all other bits a read-only. Macrovision?
7922 */
7923 SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007924
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007925 /* Register 0x11 only contains 3 writable bits (S0-S2) for
7926 contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
7927 */
7928 SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007929
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007930 /* Clear DSEN
7931 */
7932 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007933
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007934 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */
7935 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
7936 if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */
7937 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7938 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on, no need to set FSCI */
7939 } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */
7940 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */
7941 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
7942 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
7943 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
7944 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
7945 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
7946 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
7947 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
7948 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF); /* Loop filter on for mode 23 */
7949 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); /* ACIV off, need to set FSCI */
7950 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007951 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007952 if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */
7953 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7954 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7955 } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */
7956#if 0
7957 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
7958 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0); /* FSCI for mode 24 is 428,554,851 */
7959 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0); /* 198b3a63 */
7960 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
7961 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
7962 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
7963 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
7964 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
7965 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off for mode 24 */
7966 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); * ACIV off, need to set FSCI */
7967#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */
7968 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7969 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007971 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007972 } else { /* ---- PAL ---- */
7973 /* We don't play around with FSCI in PAL mode */
7974 if(resindex == 0x04) {
7975 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7976 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
7977 } else {
7978 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7979 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
7980 }
7981 }
7982
Linus Torvalds1da177e2005-04-16 15:20:36 -07007983#endif /* 300 */
7984
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007985 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007986
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007987 /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007988
Aaro Koskinenf7854e52010-11-19 21:58:47 +00007989#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07007990
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007991 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007992
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007993 /* We don't support modes >1024x768 */
7994 if (resindex > 6) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007995
Thomas Winischhofer544393f2005-09-09 13:04:45 -07007996 temp = CHTVRegData[resindex].Reg[0];
7997 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
7998 SiS_SetCH701x(SiS_Pr,0x00,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007999
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008000 SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
8001 SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
8002 SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
8003 SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
8004 SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
8005 SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008006
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008007 temp = CHTVRegData[resindex].Reg[7];
8008 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
8009 SiS_SetCH701x(SiS_Pr,0x07,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008010
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008011 SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
8012 SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
8013 SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
8014 SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
8015 SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
8016 SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
8017 SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
8018 SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008019
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008020 temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8021 /* D1 should be set for PAL, PAL-N and NTSC-J,
8022 but I won't do that for PAL unless somebody
8023 tells me to do so. Since the BIOS uses
8024 non-default CIV values and blacklevels,
8025 this might be compensated anyway.
8026 */
8027 if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8028 SiS_SetCH701x(SiS_Pr,0x21,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008029
8030#endif /* 315 */
8031
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008032 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008033
8034#ifdef SIS_CP
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008035 SIS_CP_INIT301_CP3
Linus Torvalds1da177e2005-04-16 15:20:36 -07008036#endif
8037
8038}
8039
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008040#ifdef CONFIG_FB_SIS_315 /* ----------- 315 series only ---------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008041
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008042void
8043SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008044{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008045 unsigned short temp;
8046
8047 /* Enable Chrontel 7019 LCD panel backlight */
8048 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8049 if(SiS_Pr->ChipType == SIS_740) {
8050 SiS_SetCH701x(SiS_Pr,0x66,0x65);
8051 } else {
8052 temp = SiS_GetCH701x(SiS_Pr,0x66);
8053 temp |= 0x20;
8054 SiS_SetCH701x(SiS_Pr,0x66,temp);
8055 }
8056 }
8057}
8058
8059void
8060SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
8061{
8062 unsigned short temp;
8063
8064 /* Disable Chrontel 7019 LCD panel backlight */
8065 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8066 temp = SiS_GetCH701x(SiS_Pr,0x66);
8067 temp &= 0xDF;
8068 SiS_SetCH701x(SiS_Pr,0x66,temp);
8069 }
8070}
8071
8072static void
8073SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
8074{
8075 static const unsigned char regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8076 static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8077 static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8078 static const unsigned char asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8079 static const unsigned char asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8080 static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8081 static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8082 const unsigned char *tableptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008083 int i;
8084
8085 /* Set up Power up/down timing */
8086
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008087 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008088 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008089 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8090 else tableptr = table1024_740;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008091 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008092 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008093 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8094 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8095 else tableptr = table1400_740;
8096 } else return;
8097 } else {
8098 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008099 tableptr = table1024_650;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008100 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008101 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008102 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008103 tableptr = table1400_650;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008104 } else return;
8105 }
8106
8107 for(i=0; i<5; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008108 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008109 }
8110}
8111
8112static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008113SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008114{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008115 const unsigned char *tableptr = NULL;
8116 unsigned short tempbh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008117 int i;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008118 static const unsigned char regtable[] = {
8119 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8120 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
8121 };
8122 static const unsigned char table1024_740[] = {
8123 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8124 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
8125 };
8126 static const unsigned char table1280_740[] = {
8127 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8128 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8129 };
8130 static const unsigned char table1400_740[] = {
8131 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8132 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8133 };
8134 static const unsigned char table1600_740[] = {
8135 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8136 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
8137 };
8138 static const unsigned char table1024_650[] = {
8139 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8140 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
8141 };
8142 static const unsigned char table1280_650[] = {
8143 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8144 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
8145 };
8146 static const unsigned char table1400_650[] = {
8147 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8148 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
8149 };
8150 static const unsigned char table1600_650[] = {
8151 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8152 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
8153 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07008154
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008155 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008156 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_740;
8157 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8158 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8159 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8160 else return;
8161 } else {
8162 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_650;
8163 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8164 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8165 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8166 else return;
8167 }
8168
8169 tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8170 if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8171 tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8172 if(tempbh == 0xc8) {
8173 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8174 } else if(tempbh == 0xdb) {
8175 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8176 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8177 } else if(tempbh == 0xde) {
8178 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8179 }
8180 }
8181
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008182 if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
8183 else tempbh = 0x0c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008184
8185 for(i = 0; i < tempbh; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008186 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008187 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008188 SiS_ChrontelPowerSequencing(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008189 tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8190 tempbh |= 0xc0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008191 SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008192
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008193 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008194 tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8195 tempbh &= 0xfb;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008196 SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008197 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8198 tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8199 tempbh |= 0x40;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008200 SiS_SetCH701x(SiS_Pr,0x64,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008201 tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8202 tempbh &= 0x3f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008203 SiS_SetCH701x(SiS_Pr,0x03,tempbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008204 }
8205}
8206
8207static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008208SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008209{
8210 unsigned char temp, temp1;
8211
8212 temp1 = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008213 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008214 temp = SiS_GetCH701x(SiS_Pr,0x47);
8215 temp &= 0x7f; /* Use external VSYNC */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008216 SiS_SetCH701x(SiS_Pr,0x47,temp);
8217 SiS_LongDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008218 temp = SiS_GetCH701x(SiS_Pr,0x47);
8219 temp |= 0x80; /* Use internal VSYNC */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008220 SiS_SetCH701x(SiS_Pr,0x47,temp);
8221 SiS_SetCH701x(SiS_Pr,0x49,temp1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008222}
8223
8224static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008225SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008226{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008227 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008228
8229 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008230 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008231 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8232 temp |= 0x04; /* Invert XCLK phase */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008233 SiS_SetCH701x(SiS_Pr,0x1c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008234 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008235 if(SiS_IsYPbPr(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008236 temp = SiS_GetCH701x(SiS_Pr,0x01);
8237 temp &= 0x3f;
8238 temp |= 0x80; /* Enable YPrPb (HDTV) */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008239 SiS_SetCH701x(SiS_Pr,0x01,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008240 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008241 if(SiS_IsChScart(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008242 temp = SiS_GetCH701x(SiS_Pr,0x01);
8243 temp &= 0x3f;
8244 temp |= 0xc0; /* Enable SCART + CVBS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008245 SiS_SetCH701x(SiS_Pr,0x01,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008246 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008247 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008248 SiS_ChrontelResetVSync(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008249 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008250 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008251 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008252 temp = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008253 if(SiS_IsYPbPr(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008254 temp = SiS_GetCH701x(SiS_Pr,0x73);
8255 temp |= 0x60;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008256 SiS_SetCH701x(SiS_Pr,0x73,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008257 }
8258 temp = SiS_GetCH701x(SiS_Pr,0x47);
8259 temp &= 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008260 SiS_SetCH701x(SiS_Pr,0x47,temp);
8261 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008262 temp = SiS_GetCH701x(SiS_Pr,0x47);
8263 temp |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008264 SiS_SetCH701x(SiS_Pr,0x47,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008265 }
8266 }
8267}
8268
8269static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008270SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008271{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008272 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008273
8274 /* Complete power down of LVDS */
8275 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008276 if(SiS_Pr->ChipType == SIS_740) {
8277 SiS_LongDelay(SiS_Pr, 1);
8278 SiS_GenericDelay(SiS_Pr, 5887);
8279 SiS_SetCH701x(SiS_Pr,0x76,0xac);
8280 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008281 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008282 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008283 temp = SiS_GetCH701x(SiS_Pr,0x76);
8284 temp &= 0xfc;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008285 SiS_SetCH701x(SiS_Pr,0x76,temp);
8286 SiS_SetCH701x(SiS_Pr,0x66,0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008287 }
8288 }
8289}
8290
8291static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008292SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008293{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008294 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008295
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008296 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008297
8298 temp = SiS_GetCH701x(SiS_Pr,0x4a); /* Version ID */
8299 temp &= 0x01;
8300 if(!temp) {
8301
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008302 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008303 temp = SiS_GetCH701x(SiS_Pr,0x49);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008304 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008306
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008307 /* Reset Chrontel 7019 datapath */
8308 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8309 SiS_LongDelay(SiS_Pr, 1);
8310 SiS_SetCH701x(SiS_Pr,0x48,0x18);
8311
8312 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008313 SiS_ChrontelResetVSync(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008314 SiS_SetCH701x(SiS_Pr,0x49,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008315 }
8316
8317 } else {
8318
8319 /* Clear/set/clear GPIO */
8320 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8321 temp &= 0xef;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008322 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008323 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8324 temp |= 0x10;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008325 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008326 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8327 temp &= 0xef;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008328 SiS_SetCH701x(SiS_Pr,0x5c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008329 temp = SiS_GetCH701x(SiS_Pr,0x61);
8330 if(!temp) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008331 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008332 }
8333 }
8334
8335 } else { /* 650 */
8336 /* Reset Chrontel 7019 datapath */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008337 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8338 SiS_LongDelay(SiS_Pr, 1);
8339 SiS_SetCH701x(SiS_Pr,0x48,0x18);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008340 }
8341}
8342
8343static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008344SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008345{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008346 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008347
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008348 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008349
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008350 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008351 SiS_ChrontelResetVSync(SiS_Pr);
8352 }
8353
8354 } else {
8355
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008356 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* Power up LVDS block */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008357 temp = SiS_GetCH701x(SiS_Pr,0x49);
8358 temp &= 1;
8359 if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */
8360 temp = SiS_GetCH701x(SiS_Pr,0x47);
8361 temp &= 0x70;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008362 SiS_SetCH701x(SiS_Pr,0x47,temp); /* enable VSYNC */
8363 SiS_LongDelay(SiS_Pr, 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008364 temp = SiS_GetCH701x(SiS_Pr,0x47);
8365 temp |= 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008366 SiS_SetCH701x(SiS_Pr,0x47,temp); /* disable VSYNC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008367 }
8368
8369 }
8370}
8371
8372static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008373SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008374{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008375 unsigned short temp,temp1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008376
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008377 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008378
8379 temp = SiS_GetCH701x(SiS_Pr,0x61);
8380 if(temp < 1) {
8381 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008382 SiS_SetCH701x(SiS_Pr,0x61,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008383 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008384 SiS_SetCH701x(SiS_Pr,0x66,0x45); /* Panel power on */
8385 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on */
8386 SiS_LongDelay(SiS_Pr, 1);
8387 SiS_GenericDelay(SiS_Pr, 5887);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008388
8389 } else { /* 650 */
8390
8391 temp1 = 0;
8392 temp = SiS_GetCH701x(SiS_Pr,0x61);
8393 if(temp < 2) {
8394 temp++;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008395 SiS_SetCH701x(SiS_Pr,0x61,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008396 temp1 = 1;
8397 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008398 SiS_SetCH701x(SiS_Pr,0x76,0xac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008399 temp = SiS_GetCH701x(SiS_Pr,0x66);
8400 temp |= 0x5f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008401 SiS_SetCH701x(SiS_Pr,0x66,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008402 if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008403 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8404 SiS_GenericDelay(SiS_Pr, 1023);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008405 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008406 SiS_GenericDelay(SiS_Pr, 767);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008407 }
8408 } else {
8409 if(!temp1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008410 SiS_GenericDelay(SiS_Pr, 767);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008411 }
8412 temp = SiS_GetCH701x(SiS_Pr,0x76);
8413 temp |= 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008414 SiS_SetCH701x(SiS_Pr,0x76,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008415 temp = SiS_GetCH701x(SiS_Pr,0x66);
8416 temp &= 0x7f;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008417 SiS_SetCH701x(SiS_Pr,0x66,temp);
8418 SiS_LongDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008419
8420 }
8421}
8422
8423static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008424SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008425{
Adrian Bunke4ccde32006-03-27 01:17:41 -08008426 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008427
8428 SiS_LongDelay(SiS_Pr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008429
8430 do {
8431 temp = SiS_GetCH701x(SiS_Pr,0x66);
8432 temp &= 0x04; /* PLL stable? -> bail out */
8433 if(temp == 0x04) break;
8434
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008435 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008436 /* Power down LVDS output, PLL normal operation */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008437 SiS_SetCH701x(SiS_Pr,0x76,0xac);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008438 }
8439
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008440 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008441
Linus Torvalds1da177e2005-04-16 15:20:36 -07008442 temp = SiS_GetCH701x(SiS_Pr,0x76);
8443 temp &= 0xfb; /* Reset PLL */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008444 SiS_SetCH701x(SiS_Pr,0x76,temp);
8445 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008446 temp = SiS_GetCH701x(SiS_Pr,0x76);
8447 temp |= 0x04; /* PLL normal operation */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008448 SiS_SetCH701x(SiS_Pr,0x76,temp);
8449 if(SiS_Pr->ChipType == SIS_740) {
8450 SiS_SetCH701x(SiS_Pr,0x78,0xe0); /* PLL loop filter */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008451 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008452 SiS_SetCH701x(SiS_Pr,0x78,0x60);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008453 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008454 SiS_LongDelay(SiS_Pr, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008455 } while(0);
8456
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008457 SiS_SetCH701x(SiS_Pr,0x77,0x00); /* MV? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008458}
8459
8460static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008461SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008462{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008463 unsigned short temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008464
8465 temp = SiS_GetCH701x(SiS_Pr,0x03);
8466 temp |= 0x80; /* Set datapath 1 to TV */
8467 temp &= 0xbf; /* Set datapath 2 to LVDS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008468 SiS_SetCH701x(SiS_Pr,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008469
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008470 if(SiS_Pr->ChipType == SIS_740) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008471
8472 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8473 temp &= 0xfb; /* Normal XCLK phase */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008474 SiS_SetCH701x(SiS_Pr,0x1c,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008475
8476 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8477
8478 temp = SiS_GetCH701x(SiS_Pr,0x64);
8479 temp |= 0x40; /* ? Bit not defined */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008480 SiS_SetCH701x(SiS_Pr,0x64,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008481
8482 temp = SiS_GetCH701x(SiS_Pr,0x03);
8483 temp &= 0x3f; /* D1 input to both LVDS and TV */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008484 SiS_SetCH701x(SiS_Pr,0x03,temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008485
8486 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008487 SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008488 SiS_LongDelay(SiS_Pr, 1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008489 SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
8490 SiS_ChrontelResetDB(SiS_Pr);
8491 SiS_ChrontelDoSomething2(SiS_Pr);
8492 SiS_ChrontelDoSomething3(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008493 } else {
8494 temp = SiS_GetCH701x(SiS_Pr,0x66);
8495 if(temp != 0x45) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008496 SiS_ChrontelResetDB(SiS_Pr);
8497 SiS_ChrontelDoSomething2(SiS_Pr);
8498 SiS_ChrontelDoSomething3(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008499 }
8500 }
8501
8502 } else { /* 650 */
8503
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008504 SiS_ChrontelResetDB(SiS_Pr);
8505 SiS_ChrontelDoSomething2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008506 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008507 SiS_ChrontelDoSomething3(SiS_Pr,temp);
8508 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on, LVDS normal operation */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008509
8510 }
8511
8512}
8513#endif /* 315 series */
8514
8515/*********************************************/
8516/* MAIN: SET CRT2 REGISTER GROUP */
8517/*********************************************/
8518
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008519bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008520SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008521{
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008522#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008523 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008524#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008525 unsigned short ModeIdIndex, RefreshRateTableIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008526
8527 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8528
8529 if(!SiS_Pr->UseCustomMode) {
8530 SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8531 } else {
8532 ModeIdIndex = 0;
8533 }
8534
8535 /* Used for shifting CR33 */
8536 SiS_Pr->SiS_SelectCRT2Rate = 4;
8537
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008538 SiS_UnLockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008539
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008540 RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008541
8542 SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8543
8544 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008545 SiS_DisableBridge(SiS_Pr);
8546 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008547 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8548 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008549 SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008550 }
8551
8552 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008553 SiS_LockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008554 SiS_DisplayOn(SiS_Pr);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008555 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008556 }
8557
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008558 SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008559
8560 /* Set up Panel Link for LVDS and LCDA */
8561 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8562 if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8563 ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008564 ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
8565 SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008566 }
8567
Linus Torvalds1da177e2005-04-16 15:20:36 -07008568 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008569 SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008570 }
8571
8572 if(SiS_Pr->SiS_VBType & VB_SISVB) {
8573
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008574 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008575
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008576 SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008577#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008578 SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008579#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008580 SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
8581 SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008582#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008583 SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008584#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008585 SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008586
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008587 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008588
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008589 /* For 301BDH (Panel link initialization): */
8590 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8591
8592 if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8593 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8594 SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8595 }
8596 }
8597 SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8598 }
8599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008600
8601 } else {
8602
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008603 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008604
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008605 SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008606
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008607 SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008608
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008609 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8610 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8611 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8612 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008613#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008614 SiS_SetCH701xForLCD(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008615#endif
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008616 }
8617 }
8618 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8619 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8620 }
8621 }
8622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008623
8624 }
8625
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008626#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008627 if(SiS_Pr->ChipType < SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008628 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8629 if(SiS_Pr->SiS_UseOEM) {
8630 if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8631 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008632 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008633 }
8634 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008635 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008636 }
8637 }
8638 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008639 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07008640 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008641 SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008642 }
8643 SiS_DisplayOn(SiS_Pr);
8644 }
8645 }
8646 }
8647#endif
8648
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008649#ifdef CONFIG_FB_SIS_315
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008650 if(SiS_Pr->ChipType >= SIS_315H) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008651 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008652 if(SiS_Pr->ChipType < SIS_661) {
8653 SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
8654 SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008655 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008656 SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008657 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008658 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008659 }
8660 }
8661#endif
8662
8663 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008664 SiS_EnableBridge(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008665 }
8666
8667 SiS_DisplayOn(SiS_Pr);
8668
8669 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8670 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8671 /* Disable LCD panel when using TV */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008672 SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008673 } else {
8674 /* Disable TV when using LCD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008675 SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008676 }
8677 }
8678
8679 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008680 SiS_LockCRT2(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008681 }
8682
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008683 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008684}
8685
8686
8687/*********************************************/
8688/* ENABLE/DISABLE LCD BACKLIGHT (SIS) */
8689/*********************************************/
8690
8691void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008692SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008693{
8694 /* Switch on LCD backlight on SiS30xLV */
8695 SiS_DDC2Delay(SiS_Pr,0xff00);
8696 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
8697 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008698 SiS_WaitVBRetrace(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008699 }
8700 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
8701 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
8702 }
8703}
8704
8705void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008706SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008707{
8708 /* Switch off LCD backlight on SiS30xLV */
8709 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008710 SiS_DDC2Delay(SiS_Pr,0xff00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008711}
8712
8713/*********************************************/
8714/* DDC RELATED FUNCTIONS */
8715/*********************************************/
8716
8717static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008718SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008719{
8720 SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
8721 SiS_Pr->SiS_DDC_NClk = ~SiS_Pr->SiS_DDC_Clk;
8722 if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
8723 SiS_Pr->SiS_DDC_NData &= 0x0f;
8724 SiS_Pr->SiS_DDC_NClk &= 0x0f;
8725 }
8726}
8727
Aaro Koskinenf7854e52010-11-19 21:58:47 +00008728#ifdef CONFIG_FB_SIS_300
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008729static unsigned char *
8730SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008731{
8732 int i, j, num;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008733 unsigned short tempah,temp;
8734 unsigned char *mydataptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008735
8736 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8737 mydataptr = dataptr;
8738 num = *mydataptr++;
8739 if(!num) return mydataptr;
8740 if(i) {
8741 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008742 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008743 }
8744 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8745 tempah = SiS_Pr->SiS_DDC_DeviceAddr;
8746 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
8747 if(temp) continue; /* (ERROR: no ack) */
8748 tempah = *mydataptr++;
8749 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write register number */
8750 if(temp) continue; /* (ERROR: no ack) */
8751 for(j=0; j<num; j++) {
8752 tempah = *mydataptr++;
8753 temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
8754 if(temp) break;
8755 }
8756 if(temp) continue;
8757 if(SiS_SetStop(SiS_Pr)) continue;
8758 return mydataptr;
8759 }
8760 return NULL;
8761}
8762
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008763static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008764SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008765{
8766 SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */
8767 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008768 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8769 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008770 SiS_SetupDDCN(SiS_Pr);
8771
8772 SiS_SetSwitchDDC2(SiS_Pr);
8773
8774 while(*dataptr) {
8775 dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008776 if(!dataptr) return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008777 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008778 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008779}
8780#endif
8781
8782/* The Chrontel 700x is connected to the 630/730 via
8783 * the 630/730's DDC/I2C port.
8784 *
8785 * On 630(S)T chipset, the index changed from 0x11 to
8786 * 0x0a, possibly for working around the DDC problems
8787 */
8788
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008789static bool
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008790SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008791{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008792 unsigned short temp, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008793
8794 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8795 if(i) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008796 SiS_SetStop(SiS_Pr);
8797 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008798 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008799 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8800 temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
8801 if(temp) continue; /* (ERROR: no ack) */
8802 temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor)); /* Write RAB (700x: set bit 7, see datasheet) */
8803 if(temp) continue; /* (ERROR: no ack) */
8804 temp = SiS_WriteDDC2Data(SiS_Pr, val); /* Write data */
8805 if(temp) continue; /* (ERROR: no ack) */
8806 if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008807 SiS_Pr->SiS_ChrontelInit = 1;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008808 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008809 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008810 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008811}
8812
Linus Torvalds1da177e2005-04-16 15:20:36 -07008813/* Write to Chrontel 700x */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008814void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008815SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008816{
8817 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
8818
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008819 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8820
Linus Torvalds1da177e2005-04-16 15:20:36 -07008821 if(!(SiS_Pr->SiS_ChrontelInit)) {
8822 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008823 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8824 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008825 SiS_SetupDDCN(SiS_Pr);
8826 }
8827
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008828 if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07008829 (!(SiS_Pr->SiS_ChrontelInit)) ) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008830 SiS_Pr->SiS_DDC_Index = 0x0a;
8831 SiS_Pr->SiS_DDC_Data = 0x80;
8832 SiS_Pr->SiS_DDC_Clk = 0x40;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008833 SiS_SetupDDCN(SiS_Pr);
8834
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008835 SiS_SetChReg(SiS_Pr, reg, val, 0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008836 }
8837}
8838
8839/* Write to Chrontel 701x */
8840/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
8841void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008842SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008843{
8844 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008845 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
8846 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008847 SiS_SetupDDCN(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008848 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
8849 SiS_SetChReg(SiS_Pr, reg, val, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008850}
8851
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008852static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008853void
8854SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008855{
8856 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008857 SiS_SetCH700x(SiS_Pr, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008858 else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008859 SiS_SetCH701x(SiS_Pr, reg, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008860}
8861
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008862static unsigned short
8863SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008864{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008865 unsigned short tempah, temp, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008866
8867 for(i=0; i<20; i++) { /* Do 20 attempts to read */
8868 if(i) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008869 SiS_SetStop(SiS_Pr);
8870 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008871 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008872 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8873 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
8874 if(temp) continue; /* (ERROR: no ack) */
8875 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor); /* Write RAB (700x: | 0x80) */
8876 if(temp) continue; /* (ERROR: no ack) */
8877 if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
8878 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
8879 if(temp) continue; /* (ERROR: no ack) */
8880 tempah = SiS_ReadDDC2Data(SiS_Pr); /* Read byte */
8881 if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008882 SiS_Pr->SiS_ChrontelInit = 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008883 return tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008884 }
8885 return 0xFFFF;
8886}
8887
Linus Torvalds1da177e2005-04-16 15:20:36 -07008888/* Read from Chrontel 700x */
8889/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008890unsigned short
8891SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008892{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008893 unsigned short result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008894
8895 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
8896
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008897 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8898
Linus Torvalds1da177e2005-04-16 15:20:36 -07008899 if(!(SiS_Pr->SiS_ChrontelInit)) {
8900 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008901 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8902 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008903 SiS_SetupDDCN(SiS_Pr);
8904 }
8905
8906 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8907
8908 if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
8909 (!SiS_Pr->SiS_ChrontelInit) ) {
8910
8911 SiS_Pr->SiS_DDC_Index = 0x0a;
8912 SiS_Pr->SiS_DDC_Data = 0x80;
8913 SiS_Pr->SiS_DDC_Clk = 0x40;
8914 SiS_SetupDDCN(SiS_Pr);
8915
8916 result = SiS_GetChReg(SiS_Pr,0x80);
8917 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008918 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008919}
8920
8921/* Read from Chrontel 701x */
8922/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008923unsigned short
8924SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008925{
8926 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008927 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
8928 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008929 SiS_SetupDDCN(SiS_Pr);
8930 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
8931
8932 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8933
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008934 return SiS_GetChReg(SiS_Pr,0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008935}
8936
8937/* Read from Chrontel 70xx */
8938/* Parameter is [Register no (S7-S0)] */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008939static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008940unsigned short
8941SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008942{
8943 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008944 return SiS_GetCH700x(SiS_Pr, tempbx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008945 else
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008946 return SiS_GetCH701x(SiS_Pr, tempbx);
8947}
8948
8949void
8950SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
8951 unsigned char myor, unsigned short myand)
8952{
8953 unsigned short tempbl;
8954
8955 tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
8956 SiS_SetCH70xx(SiS_Pr, reg, tempbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008957}
8958
8959/* Our own DDC functions */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008960static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008961unsigned short
8962SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
Richard Knutssonc30660ea2007-02-12 00:55:06 -08008963 unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008964 unsigned int VBFlags2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008965{
8966 unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
8967 unsigned char flag, cr32;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008968 unsigned short temp = 0, myadaptnum = adaptnum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008969
8970 if(adaptnum != 0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008971 if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
8972 if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
8973 }
8974
Linus Torvalds1da177e2005-04-16 15:20:36 -07008975 /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008976
Linus Torvalds1da177e2005-04-16 15:20:36 -07008977 SiS_Pr->SiS_ChrontelInit = 0; /* force re-detection! */
8978
8979 SiS_Pr->SiS_DDC_SecAddr = 0;
8980 SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
8981 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
8982 SiS_Pr->SiS_DDC_Index = 0x11;
8983 flag = 0xff;
8984
8985 cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
8986
8987#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07008988 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008989 if(myadaptnum == 0) {
8990 if(!(cr32 & 0x20)) {
8991 myadaptnum = 2;
8992 if(!(cr32 & 0x10)) {
8993 myadaptnum = 1;
8994 if(!(cr32 & 0x08)) {
8995 myadaptnum = 0;
8996 }
8997 }
8998 }
8999 }
9000 }
9001#endif
9002
9003 if(VGAEngine == SIS_300_VGA) { /* 300 series */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009004
Linus Torvalds1da177e2005-04-16 15:20:36 -07009005 if(myadaptnum != 0) {
9006 flag = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009007 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009008 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9009 SiS_Pr->SiS_DDC_Index = 0x0f;
9010 }
9011 }
9012
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009013 if(!(VBFlags2 & VB2_301)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009014 if((cr32 & 0x80) && (checkcr32)) {
9015 if(myadaptnum >= 1) {
9016 if(!(cr32 & 0x08)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009017 myadaptnum = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009018 if(!(cr32 & 0x10)) return 0xFFFF;
9019 }
9020 }
9021 }
9022 }
9023
9024 temp = 4 - (myadaptnum * 2);
9025 if(flag) temp = 0;
9026
9027 } else { /* 315/330 series */
9028
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009029 /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009030
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009031 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009032 if(myadaptnum == 2) {
9033 myadaptnum = 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009034 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009035 }
9036
9037 if(myadaptnum == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009038 flag = 0;
9039 if(VBFlags2 & VB2_SISBRIDGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009040 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9041 SiS_Pr->SiS_DDC_Index = 0x0f;
9042 }
9043 }
9044
9045 if((cr32 & 0x80) && (checkcr32)) {
9046 if(myadaptnum >= 1) {
9047 if(!(cr32 & 0x08)) {
9048 myadaptnum = 1;
9049 if(!(cr32 & 0x10)) return 0xFFFF;
9050 }
9051 }
9052 }
9053
9054 temp = myadaptnum;
9055 if(myadaptnum == 1) {
9056 temp = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009057 if(VBFlags2 & VB2_LVDS) flag = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009058 }
9059
9060 if(flag) temp = 0;
9061 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009062
Linus Torvalds1da177e2005-04-16 15:20:36 -07009063 SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9064 SiS_Pr->SiS_DDC_Clk = 0x01 << temp;
9065
9066 SiS_SetupDDCN(SiS_Pr);
9067
Linus Torvalds1da177e2005-04-16 15:20:36 -07009068 return 0;
9069}
9070
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009071static unsigned short
9072SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009073{
9074 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9075 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009076 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009077 }
9078 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009079 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009080 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009081 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009082}
9083
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009084static unsigned short
9085SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009086{
9087 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9088 if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009089 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009090 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009091 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009092}
9093
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009094static unsigned short
9095SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009096{
9097 if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009098 if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
9099 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009100}
9101
9102static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009103SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009104{
9105 SiS_SetSCLKLow(SiS_Pr);
9106 if(yesno) {
9107 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009108 SiS_Pr->SiS_DDC_Index,
9109 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009110 SiS_Pr->SiS_DDC_Data);
9111 } else {
9112 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009113 SiS_Pr->SiS_DDC_Index,
9114 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009115 0);
9116 }
9117 SiS_SetSCLKHigh(SiS_Pr);
9118}
9119
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009120static unsigned short
9121SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009122{
9123 unsigned char mask, value;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009124 unsigned short temp, ret=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009125 bool failed = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009126
9127 SiS_SetSwitchDDC2(SiS_Pr);
9128 if(SiS_PrepareDDC(SiS_Pr)) {
9129 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009130 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009131 }
9132 mask = 0xf0;
9133 value = 0x20;
9134 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009135 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009136 SiS_SendACK(SiS_Pr, 0);
9137 if(temp == 0) {
9138 mask = 0xff;
9139 value = 0xff;
9140 } else {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009141 failed = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009142 ret = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009143 }
9144 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009145 if(!failed) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009146 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009147 SiS_SendACK(SiS_Pr, 1);
9148 temp &= mask;
9149 if(temp == value) ret = 0;
9150 else {
9151 ret = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009152 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9153 if(temp == 0x30) ret = 0;
9154 }
9155 }
9156 }
9157 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009158 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009159}
9160
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009161static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009162unsigned short
9163SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009164{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009165 unsigned short flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009166
9167 flag = 0x180;
9168 SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9169 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9170 SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9171 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9172 SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9173 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9174 if(!(flag & 0x1a)) flag = 0;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009175 return flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009176}
9177
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009178static
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009179unsigned short
9180SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009181{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009182 unsigned short flag, length, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009183 unsigned char chksum,gotcha;
9184
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009185 if(DDCdatatype > 4) return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009186
9187 flag = 0;
9188 SiS_SetSwitchDDC2(SiS_Pr);
9189 if(!(SiS_PrepareDDC(SiS_Pr))) {
9190 length = 127;
9191 if(DDCdatatype != 1) length = 255;
9192 chksum = 0;
9193 gotcha = 0;
9194 for(i=0; i<length; i++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009195 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009196 chksum += buffer[i];
9197 gotcha |= buffer[i];
9198 SiS_SendACK(SiS_Pr, 0);
9199 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009200 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009201 chksum += buffer[i];
9202 SiS_SendACK(SiS_Pr, 1);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009203 if(gotcha) flag = (unsigned short)chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009204 else flag = 0xFFFF;
9205 } else {
9206 flag = 0xFFFF;
9207 }
9208 SiS_SetStop(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009209 return flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009210}
9211
9212/* Our private DDC functions
9213
9214 It complies somewhat with the corresponding VESA function
9215 in arguments and return values.
9216
9217 Since this is probably called before the mode is changed,
9218 we use our pre-detected pSiS-values instead of SiS_Pr as
9219 regards chipset and video bridge type.
9220
9221 Arguments:
9222 adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9223 CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9224 LCDA is CRT1, but DDC is read from CRT2 port.
9225 DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9226 buffer: ptr to 256 data bytes which will be filled with read data.
9227
9228 Returns 0xFFFF if error, otherwise
9229 if DDCdatatype > 0: Returns 0 if reading OK (included a correct checksum)
9230 if DDCdatatype = 0: Returns supported DDC modes
9231
9232 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009233unsigned short
9234SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9235 unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
9236 unsigned int VBFlags2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009237{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009238 unsigned char sr1f, cr17=1;
9239 unsigned short result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009240
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009241 if(adaptnum > 2)
9242 return 0xFFFF;
9243
9244 if(DDCdatatype > 4)
9245 return 0xFFFF;
9246
9247 if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
9248 return 0xFFFF;
9249
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009250 if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009251 return 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009252
9253 sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9254 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9255 if(VGAEngine == SIS_300_VGA) {
9256 cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9257 if(!cr17) {
9258 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9259 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9260 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9261 }
9262 }
9263 if((sr1f) || (!cr17)) {
9264 SiS_WaitRetrace1(SiS_Pr);
9265 SiS_WaitRetrace1(SiS_Pr);
9266 SiS_WaitRetrace1(SiS_Pr);
9267 SiS_WaitRetrace1(SiS_Pr);
9268 }
9269
9270 if(DDCdatatype == 0) {
9271 result = SiS_ProbeDDC(SiS_Pr);
9272 } else {
9273 result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9274 if((!result) && (DDCdatatype == 1)) {
9275 if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9276 (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9277 (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9278 (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9279 (buffer[0x12] == 1)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009280 if(!SiS_Pr->DDCPortMixup) {
9281 if(adaptnum == 1) {
9282 if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9283 } else {
9284 if(buffer[0x14] & 0x80) result = 0xFFFE;
9285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009286 }
9287 }
9288 }
9289 }
9290 SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9291 if(VGAEngine == SIS_300_VGA) {
9292 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9293 }
9294 return result;
9295}
9296
Linus Torvalds1da177e2005-04-16 15:20:36 -07009297/* Generic I2C functions for Chrontel & DDC --------- */
9298
9299static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009300SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009301{
9302 SiS_SetSCLKHigh(SiS_Pr);
9303 SiS_WaitRetrace1(SiS_Pr);
9304
9305 SiS_SetSCLKLow(SiS_Pr);
9306 SiS_WaitRetrace1(SiS_Pr);
9307}
9308
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009309unsigned short
9310SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009311{
9312 SiS_WaitRetrace1(SiS_Pr);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009313 return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009314}
9315
9316/* Set I2C start condition */
9317/* This is done by a SD high-to-low transition while SC is high */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009318static unsigned short
9319SiS_SetStart(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009320{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009321 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009322 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009323 SiS_Pr->SiS_DDC_Index,
9324 SiS_Pr->SiS_DDC_NData,
9325 SiS_Pr->SiS_DDC_Data); /* SD->high */
9326 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009327 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009328 SiS_Pr->SiS_DDC_Index,
9329 SiS_Pr->SiS_DDC_NData,
9330 0x00); /* SD->low = start condition */
9331 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009332 return 0;
9333}
9334
9335/* Set I2C stop condition */
9336/* This is done by a SD low-to-high transition while SC is high */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009337static unsigned short
9338SiS_SetStop(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009339{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009340 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009341 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009342 SiS_Pr->SiS_DDC_Index,
9343 SiS_Pr->SiS_DDC_NData,
9344 0x00); /* SD->low */
9345 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009346 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009347 SiS_Pr->SiS_DDC_Index,
9348 SiS_Pr->SiS_DDC_NData,
9349 SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
9350 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009351 return 0;
9352}
9353
9354/* Write 8 bits of data */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009355static unsigned short
9356SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009357{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009358 unsigned short i,flag,temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009359
9360 flag = 0x80;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009361 for(i = 0; i < 8; i++) {
9362 SiS_SetSCLKLow(SiS_Pr); /* SC->low */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009363 if(tempax & flag) {
9364 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009365 SiS_Pr->SiS_DDC_Index,
9366 SiS_Pr->SiS_DDC_NData,
9367 SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009368 } else {
9369 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009370 SiS_Pr->SiS_DDC_Index,
9371 SiS_Pr->SiS_DDC_NData,
9372 0x00); /* Write bit (0) to SD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009373 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009374 SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009375 flag >>= 1;
9376 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009377 temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
9378 return temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009379}
9380
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009381static unsigned short
9382SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009383{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009384 unsigned short i, temp, getdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009385
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009386 getdata = 0;
9387 for(i = 0; i < 8; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009388 getdata <<= 1;
9389 SiS_SetSCLKLow(SiS_Pr);
9390 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009391 SiS_Pr->SiS_DDC_Index,
9392 SiS_Pr->SiS_DDC_NData,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009393 SiS_Pr->SiS_DDC_Data);
9394 SiS_SetSCLKHigh(SiS_Pr);
9395 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9396 if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
9397 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009398 return getdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009399}
9400
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009401static unsigned short
9402SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009403{
9404 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009405 SiS_Pr->SiS_DDC_Index,
9406 SiS_Pr->SiS_DDC_NClk,
9407 0x00); /* SetSCLKLow() */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009408 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9409 return 0;
9410}
9411
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009412static unsigned short
9413SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009414{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009415 unsigned short temp, watchdog=1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009416
9417 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009418 SiS_Pr->SiS_DDC_Index,
9419 SiS_Pr->SiS_DDC_NClk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009420 SiS_Pr->SiS_DDC_Clk); /* SetSCLKHigh() */
9421 do {
9422 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9423 } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
9424 if (!watchdog) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009425 return 0xFFFF;
9426 }
9427 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9428 return 0;
9429}
9430
9431/* Check I2C acknowledge */
9432/* Returns 0 if ack ok, non-0 if ack not ok */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009433static unsigned short
9434SiS_CheckACK(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009435{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009436 unsigned short tempah;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009437
9438 SiS_SetSCLKLow(SiS_Pr); /* (SC->low) */
9439 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009440 SiS_Pr->SiS_DDC_Index,
9441 SiS_Pr->SiS_DDC_NData,
9442 SiS_Pr->SiS_DDC_Data); /* (SD->high) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009443 SiS_SetSCLKHigh(SiS_Pr); /* SC->high = clock impulse for ack */
9444 tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
9445 SiS_SetSCLKLow(SiS_Pr); /* SC->low = end of clock impulse */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009446 if(tempah & SiS_Pr->SiS_DDC_Data) return 1; /* Ack OK if bit = 0 */
9447 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009448}
9449
9450/* End of I2C functions ----------------------- */
9451
9452
9453/* =============== SiS 315/330 O.E.M. ================= */
9454
Aaro Koskinenf7854e52010-11-19 21:58:47 +00009455#ifdef CONFIG_FB_SIS_315
Linus Torvalds1da177e2005-04-16 15:20:36 -07009456
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009457static unsigned short
9458GetRAMDACromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009459{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009460 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9461 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009462
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009463 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009464 romptr = SISGETROMW(0x128);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009465 if(SiS_Pr->SiS_VBType & VB_SIS30xB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009466 romptr = SISGETROMW(0x12a);
9467 } else {
9468 romptr = SISGETROMW(0x1a8);
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(0x1aa);
9471 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009472 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009473}
9474
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009475static unsigned short
9476GetLCDromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009477{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009478 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9479 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009480
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009481 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009482 romptr = SISGETROMW(0x120);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009483 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009484 romptr = SISGETROMW(0x122);
9485 } else {
9486 romptr = SISGETROMW(0x1a0);
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(0x1a2);
9489 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009490 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009491}
9492
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009493static unsigned short
9494GetTVromptr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009495{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009496 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9497 unsigned short romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009498
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009499 if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009500 romptr = SISGETROMW(0x114);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009501 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009502 romptr = SISGETROMW(0x11a);
9503 } else {
9504 romptr = SISGETROMW(0x194);
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(0x19a);
9507 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009508 return romptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009509}
9510
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009511static unsigned short
9512GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009513{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009514 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009515
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009516 if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9517 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009518 if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
9519 index >>= 4;
9520 index *= 3;
9521 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9522 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9523 return index;
9524 }
9525 }
9526 }
9527
9528 index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
9529 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) index -= 5;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009530 if(SiS_Pr->SiS_VBType & VB_SIS301C) { /* 1.15.20 and later (not VB specific) */
9531 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
9532 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
9533 } else {
9534 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
9535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009536 index--;
9537 index *= 3;
9538 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9539 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9540 return index;
9541}
9542
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009543static unsigned short
9544GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009545{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009546 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009547
9548 index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
9549 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9550 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9551 return index;
9552}
9553
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009554static unsigned short
9555GetTVPtrIndex(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009556{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009557 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009558
9559 index = 0;
9560 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9561 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
9562
9563 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
9564
9565 index <<= 1;
9566
9567 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
9568 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9569 index++;
9570 }
9571
9572 return index;
9573}
9574
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009575static unsigned int
9576GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009577{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009578 unsigned short index = 0, temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009579
9580 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9581 if(SiS_Pr->SiS_TVMode & TVSetPALM) index = 2;
9582 if(SiS_Pr->SiS_TVMode & TVSetPALN) index = 3;
9583 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
9584 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
9585 index = 4;
9586 if(SiS_Pr->SiS_TVMode & TVSetPALM) index++;
9587 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
9588 }
9589
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009590 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009591 if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
9592 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9593 index += addme;
9594 temp++;
9595 }
9596 temp += 0x0100;
9597 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009598 return (unsigned int)(index | (temp << 16));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009599}
9600
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009601static unsigned int
9602GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009603{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009604 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009605}
9606
9607#if 0
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009608static unsigned int
9609GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009610{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009611 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07009612}
9613#endif
9614
9615static int
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009616GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009617{
9618 int index = 0;
9619
9620 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 2;
9621 if(SiS_Pr->SiS_ROMNew) {
9622 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
9623 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
9624 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
9625 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 10;
9626 } else {
9627 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 4;
9628 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
9629 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
9630 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
9631 }
9632
9633 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
9634
9635 return index;
9636}
9637
9638static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009639SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009640{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009641 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9642 unsigned short delay=0,index,myindex,temp,romptr=0;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009643 bool dochiptest = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009644
9645 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9646 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
9647 } else {
9648 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
9649 }
9650
9651 /* Find delay (from ROM, internal tables, PCI subsystem) */
9652
9653 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { /* ------------ VGA */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009654
Linus Torvalds1da177e2005-04-16 15:20:36 -07009655 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009656 romptr = GetRAMDACromptr(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009657 }
9658 if(romptr) delay = ROMAddr[romptr];
9659 else {
9660 delay = 0x04;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009661 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009662 if(IS_SIS650) {
9663 delay = 0x0a;
9664 } else if(IS_SIS740) {
9665 delay = 0x00;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009666 } else if(SiS_Pr->ChipType < SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009667 delay = 0x0c;
9668 } else {
9669 delay = 0x0c;
9670 }
9671 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9672 delay = 0x00;
9673 }
9674 }
9675
9676 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) { /* ---------- LCD/LCDA */
9677
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009678 bool gotitfrompci = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009679
9680 /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
9681
9682 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
9683 if(SiS_Pr->PDC != -1) {
9684 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
9685 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
9686 return;
9687 }
9688 } else {
9689 if(SiS_Pr->PDCA != -1) {
9690 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
9691 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
9692 return;
9693 }
9694 }
9695
9696 /* Custom Panel? */
9697
9698 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
9699 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9700 delay = 0x00;
9701 if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
9702 delay = 0x20;
9703 }
9704 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
9705 } else {
9706 delay = 0x0c;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009707 if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9708 delay = 0x03;
9709 if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
9710 delay = 0x00;
9711 }
9712 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009713 if(IS_SIS740) delay = 0x01;
9714 else delay = 0x03;
9715 }
9716 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
9717 }
9718 return;
9719 }
9720
9721 /* This is a piece of typical SiS crap: They code the OEM LCD
9722 * delay into the code, at no defined place in the BIOS.
9723 * We now have to start doing a PCI subsystem check here.
9724 */
9725
9726 switch(SiS_Pr->SiS_CustomT) {
9727 case CUT_COMPAQ1280:
9728 case CUT_COMPAQ12802:
9729 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009730 gotitfrompci = true;
9731 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009732 delay = 0x03;
9733 }
9734 break;
9735 case CUT_CLEVO1400:
9736 case CUT_CLEVO14002:
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009737 gotitfrompci = true;
9738 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009739 delay = 0x02;
9740 break;
9741 case CUT_CLEVO1024:
9742 case CUT_CLEVO10242:
9743 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009744 gotitfrompci = true;
9745 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009746 delay = 0x33;
9747 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9748 delay &= 0x0f;
9749 }
9750 break;
9751 }
9752
9753 /* Could we find it through the PCI ID? If no, use ROM or table */
9754
9755 if(!gotitfrompci) {
9756
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009757 index = GetLCDPtrIndexBIOS(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009758 myindex = GetLCDPtrIndex(SiS_Pr);
9759
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009760 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009761
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009762 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009763
9764 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9765 /* Always use the second pointer on 650; some BIOSes */
9766 /* still carry old 301 data at the first location */
9767 /* romptr = SISGETROMW(0x120); */
9768 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
9769 romptr = SISGETROMW(0x122);
9770 if(!romptr) return;
9771 delay = ROMAddr[(romptr + index)];
9772 } else {
9773 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9774 }
9775
9776 } else {
9777
9778 delay = SiS310_LCDDelayCompensation_651301LV[myindex];
9779 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
9780 delay = SiS310_LCDDelayCompensation_651302LV[myindex];
9781
9782 }
9783
9784 } else if(SiS_Pr->SiS_UseROM &&
9785 (!(SiS_Pr->SiS_ROMNew)) &&
9786 (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
9787 (SiS_Pr->SiS_LCDResInfo != Panel_1280x768) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009788 (SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
9789 (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200) &&
9790 ((romptr = GetLCDromptr(SiS_Pr)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009791
9792 /* Data for 1280x1024 wrong in 301B BIOS */
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009793 /* Data for 1600x1200 wrong in 301C BIOS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009794 delay = ROMAddr[(romptr + index)];
9795
9796 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9797
9798 if(IS_SIS740) delay = 0x03;
9799 else delay = 0x00;
9800
9801 } else {
9802
9803 delay = SiS310_LCDDelayCompensation_301[myindex];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009804 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009805 if(IS_SIS740) delay = 0x01;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009806 else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
Linus Torvalds1da177e2005-04-16 15:20:36 -07009807 else delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9808 } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9809 if(IS_SIS740) delay = 0x01; /* ? */
9810 else delay = 0x03;
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009811 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
9812 } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009813 if(IS_SIS740) delay = 0x01;
9814 else delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
9815 }
9816
9817 }
9818
9819 } /* got it from PCI */
9820
9821 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9822 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009823 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009824 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009825
Linus Torvalds1da177e2005-04-16 15:20:36 -07009826 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* ------------ TV */
9827
9828 index = GetTVPtrIndex(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009829
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009830 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9831
9832 if(SiS_IsNotM650orLater(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009833
9834 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9835 /* Always use the second pointer on 650; some BIOSes */
9836 /* still carry old 301 data at the first location */
9837 /* romptr = SISGETROMW(0x114); */
9838 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
9839 romptr = SISGETROMW(0x11a);
9840 if(!romptr) return;
9841 delay = ROMAddr[romptr + index];
9842
9843 } else {
9844
9845 delay = SiS310_TVDelayCompensation_301B[index];
9846
9847 }
9848
9849 } else {
9850
9851 switch(SiS_Pr->SiS_CustomT) {
9852 case CUT_COMPAQ1280:
9853 case CUT_COMPAQ12802:
9854 case CUT_CLEVO1400:
9855 case CUT_CLEVO14002:
9856 delay = 0x02;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009857 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009858 break;
9859 case CUT_CLEVO1024:
9860 case CUT_CLEVO10242:
9861 delay = 0x03;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009862 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009863 break;
9864 default:
9865 delay = SiS310_TVDelayCompensation_651301LV[index];
9866 if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
9867 delay = SiS310_TVDelayCompensation_651302LV[index];
9868 }
9869 }
9870 }
9871
9872 } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9873
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009874 romptr = GetTVromptr(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009875 if(!romptr) return;
9876 delay = ROMAddr[romptr + index];
9877
9878 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9879
9880 delay = SiS310_TVDelayCompensation_LVDS[index];
9881
9882 } else {
9883
9884 delay = SiS310_TVDelayCompensation_301[index];
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009885 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009886 if(IS_SIS740) {
9887 delay = SiS310_TVDelayCompensation_740301B[index];
9888 /* LV: use 301 data? BIOS bug? */
9889 } else {
9890 delay = SiS310_TVDelayCompensation_301B[index];
9891 if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
9892 }
9893 }
9894
9895 }
9896
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009897 if(SiS_LCDAEnabled(SiS_Pr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009898 delay &= 0x0f;
Richard Knutssonc30660ea2007-02-12 00:55:06 -08009899 dochiptest = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009900 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009901
Linus Torvalds1da177e2005-04-16 15:20:36 -07009902 } else return;
9903
9904 /* Write delay */
9905
9906 if(SiS_Pr->SiS_VBType & VB_SISVB) {
9907
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009908 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009909
9910 temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
9911 if(temp == 8) { /* 1400x1050 BIOS (COMPAL) */
9912 delay &= 0x0f;
9913 delay |= 0xb0;
9914 } else if(temp == 6) {
9915 delay &= 0x0f;
9916 delay |= 0xc0;
9917 } else if(temp > 7) { /* 1280x1024 BIOS (which one?) */
9918 delay = 0x35;
9919 }
9920 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9921
9922 } else {
9923
9924 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9925
9926 }
9927
9928 } else { /* LVDS */
9929
9930 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
9931 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9932 } else {
9933 if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
9934 delay <<= 4;
9935 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
9936 } else {
9937 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9938 }
9939 }
9940
9941 }
9942
9943}
9944
9945static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009946SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009947{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009948 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9949 unsigned short index,temp,temp1,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009950
9951 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
9952
9953 if(ModeNo<=0x13)
9954 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
9955 else
9956 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
9957
9958 temp = GetTVPtrIndex(SiS_Pr);
9959 temp >>= 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9960 temp1 = temp;
9961
9962 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009963 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009964 temp1 = GetOEMTVPtr661(SiS_Pr);
9965 temp1 >>= 1;
9966 romptr = SISGETROMW(0x260);
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009967 if(SiS_Pr->ChipType >= SIS_760) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009968 romptr = SISGETROMW(0x360);
9969 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009970 } else if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07009971 romptr = SISGETROMW(0x192);
9972 } else {
9973 romptr = SISGETROMW(0x112);
9974 }
9975 }
9976
9977 if(romptr) {
9978 temp1 <<= 1;
9979 temp = ROMAddr[romptr + temp1 + index];
9980 } else {
9981 temp = SiS310_TVAntiFlick1[temp][index];
9982 }
9983 temp <<= 4;
9984
9985 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp); /* index 0A D[6:4] */
9986}
9987
9988static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009989SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009990{
Thomas Winischhofer544393f2005-09-09 13:04:45 -07009991 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9992 unsigned short index,temp,temp1,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009993
9994 temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9995
9996 if(ModeNo <= 0x13)
9997 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
9998 else
9999 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
10000
10001 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010002 if(SiS_Pr->ChipType >= SIS_661) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010003 romptr = SISGETROMW(0x26c);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010004 if(SiS_Pr->ChipType >= SIS_760) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010005 romptr = SISGETROMW(0x36c);
10006 }
10007 temp1 = GetOEMTVPtr661(SiS_Pr);
10008 temp1 >>= 1;
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010009 } else if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010010 romptr = SISGETROMW(0x1a4);
10011 } else {
10012 romptr = SISGETROMW(0x124);
10013 }
10014 }
10015
10016 if(romptr) {
10017 temp1 <<= 1;
10018 temp = ROMAddr[romptr + temp1 + index];
10019 } else {
10020 temp = SiS310_TVEdge1[temp][index];
10021 }
10022 temp <<= 5;
10023 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp); /* index 0A D[7:5] */
10024}
10025
10026static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010027SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010028{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010029 unsigned short index, temp, i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010030
10031 if(ModeNo <= 0x13) {
10032 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
10033 } else {
10034 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
10035 }
10036
10037 temp = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10038
10039 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 1; /* NTSC-J uses PAL */
10040 else if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 3; /* PAL-M */
10041 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 4; /* PAL-N */
10042 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1; /* HiVision uses PAL */
10043
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010044 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010045 for(i=0x35, j=0; i<=0x38; i++, j++) {
10046 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10047 }
10048 for(i=0x48; i<=0x4A; i++, j++) {
10049 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10050 }
10051 } else {
10052 for(i=0x35, j=0; i<=0x38; i++, j++) {
10053 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
10054 }
10055 }
10056}
10057
10058static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010059SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010060{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010061 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10062 unsigned short index,temp,i,j,resinfo,romptr=0;
10063 unsigned int lindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010064
10065 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
10066
10067 /* NTSC-J data not in BIOS, and already set in SetGroup2 */
10068 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
10069
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010070 if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010071 lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
10072 lindex <<= 2;
10073 for(j=0, i=0x31; i<=0x34; i++, j++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010074 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010075 }
10076 return;
10077 }
10078
10079 /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
10080 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
10081
10082 if(ModeNo<=0x13) {
10083 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10084 } else {
10085 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10086 }
10087
10088 temp = GetTVPtrIndex(SiS_Pr);
10089 /* 0: NTSC Graphics, 1: NTSC Text, 2: PAL Graphics,
10090 * 3: PAL Text, 4: HiTV Graphics 5: HiTV Text
10091 */
10092 if(SiS_Pr->SiS_UseROM) {
10093 romptr = SISGETROMW(0x116);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010094 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010095 romptr = SISGETROMW(0x196);
10096 }
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010097 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010098 romptr = SISGETROMW(0x11c);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010099 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010100 romptr = SISGETROMW(0x19c);
10101 }
10102 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
10103 romptr = SISGETROMW(0x116);
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010104 if(SiS_Pr->ChipType >= SIS_330) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010105 romptr = SISGETROMW(0x196);
10106 }
10107 }
10108 }
10109 }
10110 if(romptr) {
10111 romptr += (temp << 2);
10112 for(j=0, i=0x31; i<=0x34; i++, j++) {
10113 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10114 }
10115 } else {
10116 index = temp % 2;
10117 temp >>= 1; /* 0:NTSC, 1:PAL, 2:HiTV */
10118 for(j=0, i=0x31; i<=0x34; i++, j++) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010119 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
Linus Torvalds1da177e2005-04-16 15:20:36 -070010120 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10121 else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
10122 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
10123 else
10124 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10125 }
10126 }
10127
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010128 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010129 if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
10130 if((resinfo == SIS_RI_640x480) ||
10131 (resinfo == SIS_RI_800x600)) {
10132 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
10133 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
10134 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
10135 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
10136 } else if(resinfo == SIS_RI_1024x768) {
10137 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
10138 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
10139 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
10140 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
10141 }
10142 }
10143 }
10144}
10145
10146static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010147SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10148 unsigned short ModeIdIndex, unsigned short RTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010149{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010150 unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
10151 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010152
10153 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
10154 return;
10155
10156 /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
10157 /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
10158
10159 if(SiS_Pr->SiS_ROMNew) {
10160 if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) ||
10161 ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
10162 (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
10163 index = 25;
10164 if(SiS_Pr->UseCustomMode) {
10165 index = SiS_Pr->CSRClock;
10166 } else if(ModeNo > 0x13) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010167 index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010168 index = SiS_Pr->SiS_VCLKData[index].CLOCK;
10169 }
10170 if(index < 25) index = 25;
10171 index = ((index / 25) - 1) << 1;
10172 if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
10173 index++;
10174 }
10175 romptr = SISGETROMW(0x104);
10176 delay = ROMAddr[romptr + index];
10177 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
10178 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10179 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10180 } else {
10181 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10182 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10183 }
10184 return;
10185 }
10186 }
10187
10188 /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
10189
10190 if(SiS_Pr->UseCustomMode) delay = 0x04;
10191 else if(ModeNo <= 0x13) delay = 0x04;
10192 else delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
10193 delay |= (delay << 8);
10194
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010195 if(SiS_Pr->ChipType >= XGI_20) {
10196
10197 delay = 0x0606;
10198 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10199
10200 delay = 0x0404;
10201 if(SiS_Pr->SiS_XGIROM) {
10202 index = GetTVPtrIndex(SiS_Pr);
10203 if((romptr = SISGETROMW(0x35e))) {
10204 delay = (ROMAddr[romptr + index] & 0x0f) << 1;
10205 delay |= (delay << 8);
10206 }
10207 }
10208
10209 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
10210 if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
10211 delay -= 0x0404;
10212 }
10213 }
10214 }
10215
10216 } else if(SiS_Pr->ChipType >= SIS_340) {
10217
10218 delay = 0x0606;
10219 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10220 delay = 0x0404;
10221 }
10222 /* TODO (eventually) */
10223
10224 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010225
10226 /* 3. TV */
10227
10228 index = GetOEMTVPtr661(SiS_Pr);
10229 if(SiS_Pr->SiS_ROMNew) {
10230 romptr = SISGETROMW(0x106);
10231 if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
10232 delay = ROMAddr[romptr + index];
10233 } else {
10234 delay = 0x04;
10235 if(index > 3) delay = 0;
10236 }
10237
10238 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10239
10240 /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
10241
10242 if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010243 ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010244
10245 lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
10246
10247 /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
10248 delay = ROMAddr[romptr + lcdpdcindex + 1]; /* LCD */
10249 delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
10250
10251 } else {
10252
10253 /* TMDS: Set our own, since BIOS has no idea */
10254 /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
10255 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10256 switch(SiS_Pr->SiS_LCDResInfo) {
10257 case Panel_1024x768: delay = 0x0008; break;
10258 case Panel_1280x720: delay = 0x0004; break;
10259 case Panel_1280x768:
10260 case Panel_1280x768_2:delay = 0x0004; break;
10261 case Panel_1280x800:
10262 case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010263 case Panel_1280x854: delay = 0x0004; break; /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010264 case Panel_1280x1024: delay = 0x1e04; break;
10265 case Panel_1400x1050: delay = 0x0004; break;
10266 case Panel_1600x1200: delay = 0x0400; break;
10267 case Panel_1680x1050: delay = 0x0e04; break;
10268 default:
10269 if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
10270 delay = 0x0008;
10271 } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
10272 delay = 0x1e04;
10273 } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
10274 delay = 0x0004;
10275 } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
10276 delay = 0x0400;
10277 } else
10278 delay = 0x0e04;
10279 break;
10280 }
10281 }
10282
10283 /* Override by detected or user-set values */
10284 /* (but only if, for some reason, we can't read value from BIOS) */
10285 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
10286 delay = SiS_Pr->PDC & 0x1f;
10287 }
10288 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
10289 delay = (SiS_Pr->PDCA & 0x1f) << 8;
10290 }
10291
10292 }
10293
10294 }
10295
10296 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10297 delay >>= 8;
10298 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10299 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10300 } else {
10301 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10302 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10303 }
10304}
10305
10306static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010307SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010308{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010309 unsigned short infoflag;
10310 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010311
10312 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10313
10314 if(ModeNo <= 0x13) {
10315 infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
10316 } else if(SiS_Pr->UseCustomMode) {
10317 infoflag = SiS_Pr->CInfoFlag;
10318 } else {
10319 infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
10320 }
10321
10322 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10323 infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
10324 }
10325
10326 infoflag &= 0xc0;
10327
10328 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10329 temp = (infoflag >> 6) | 0x0c;
10330 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10331 temp ^= 0x04;
10332 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
10333 }
10334 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
10335 } else {
10336 temp = 0x30;
10337 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
10338 temp |= infoflag;
10339 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
10340 temp = 0;
10341 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10342 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
10343 }
10344 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
10345 }
10346
10347 }
10348}
10349
10350static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010351SetPanelParms661(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010352{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010353 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10354 unsigned short romptr, temp1, temp2;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010355
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010356 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
10357 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
10358 }
10359
10360 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010361 if(SiS_Pr->LVDSHL != -1) {
10362 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10363 }
10364 }
10365
10366 if(SiS_Pr->SiS_ROMNew) {
10367
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010368 if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
10369 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010370 temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
10371 temp2 = 0xfc;
10372 if(SiS_Pr->LVDSHL != -1) {
10373 temp1 &= 0xfc;
10374 temp2 = 0xf3;
10375 }
10376 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
10377 }
10378 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10379 temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
10380 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
10381 }
10382 }
10383
10384 }
10385}
10386
10387static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010388SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010389{
10390 if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010391 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010392 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010393 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10394 SetPanelParms661(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010395 }
10396 } else {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010397 SetDelayComp(SiS_Pr,ModeNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010398 }
10399
10400 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010401 SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
10402 SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
10403 SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010404 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010405 SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010406 }
10407 }
10408}
10409
10410static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010411SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10412 unsigned short ModeIdIndex, unsigned short RRTI)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010413{
10414 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10415
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010416 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010417
10418 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010419 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10420 SetPanelParms661(SiS_Pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010421 }
10422
10423 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010424 SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
10425 SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
10426 SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010427 if(SiS_Pr->SiS_VBType & VB_SIS301) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010428 SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010429 }
10430 }
10431 }
10432}
10433
10434/* FinalizeLCD
10435 * This finalizes some CRT2 registers for the very panel used.
10436 * If we have a backup if these registers, we use it; otherwise
10437 * we set the register according to most BIOSes. However, this
10438 * function looks quite different in every BIOS, so you better
10439 * pray that we have a backup...
10440 */
10441static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010442SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010443{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010444 unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
10445 unsigned short resinfo,modeflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010446
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010447 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010448 if(SiS_Pr->SiS_ROMNew) return;
10449
10450 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10451 if(SiS_Pr->LVDSHL != -1) {
10452 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10453 }
10454 }
10455
10456 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10457 if(SiS_Pr->UseCustomMode) return;
10458
10459 switch(SiS_Pr->SiS_CustomT) {
10460 case CUT_COMPAQ1280:
10461 case CUT_COMPAQ12802:
10462 case CUT_CLEVO1400:
10463 case CUT_CLEVO14002:
10464 return;
10465 }
10466
10467 if(ModeNo <= 0x13) {
10468 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10469 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10470 } else {
10471 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10472 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10473 }
10474
10475 if(IS_SIS650) {
10476 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
10477 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10478 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
10479 } else {
10480 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
10481 }
10482 }
10483 }
10484
10485 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10486 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10487 /* Maybe all panels? */
10488 if(SiS_Pr->LVDSHL == -1) {
10489 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10490 }
10491 return;
10492 }
10493 }
10494
10495 if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
10496 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10497 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10498 if(SiS_Pr->LVDSHL == -1) {
10499 /* Maybe all panels? */
10500 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10501 }
10502 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10503 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10504 if(tempch == 3) {
10505 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10506 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10507 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10508 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10509 }
10510 }
10511 return;
10512 }
10513 }
10514 }
10515
10516 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10517 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010518 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010519 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
10520#ifdef SET_EMI
10521 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
10522#endif
10523 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
10524 }
10525 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10526 if(SiS_Pr->LVDSHL == -1) {
10527 /* Maybe ACER only? */
10528 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10529 }
10530 }
10531 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10532 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10533 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
10534 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
10535 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10536 if(tempch == 0x03) {
10537 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10538 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10539 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10540 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10541 }
Richard Knutssonc30660ea2007-02-12 00:55:06 -080010542 if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010543 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
10544 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
10545 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
10546 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
10547 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
10548 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
10549 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
10550 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
10551 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
10552 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
10553 } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { /* 1.10.8w */
10554 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
10555 if(ModeNo <= 0x13) {
10556 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
10557 if((resinfo == 0) || (resinfo == 2)) return;
10558 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
10559 if((resinfo == 1) || (resinfo == 3)) return;
10560 }
10561 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10562 if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
10563 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02); /* 1.10.7u */
10564#if 0
10565 tempbx = 806; /* 0x326 */ /* other older BIOSes */
10566 tempbx--;
10567 temp = tempbx & 0xff;
10568 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
10569 temp = (tempbx >> 8) & 0x03;
10570 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
10571#endif
10572 }
10573 } else if(ModeNo <= 0x13) {
10574 if(ModeNo <= 1) {
10575 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
10576 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
10577 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10578 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10579 }
10580 if(!(modeflag & HalfDCLK)) {
10581 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
10582 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
10583 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
10584 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
10585 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
10586 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10587 if(ModeNo == 0x12) {
10588 switch(tempch) {
10589 case 0:
10590 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10591 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10592 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
10593 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10594 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
10595 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10596 break;
10597 case 2:
10598 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10599 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10600 break;
10601 case 3:
10602 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10603 break;
10604 }
10605 }
10606 }
10607 }
10608 }
10609 } else {
10610 tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
10611 tempcl &= 0x0f;
10612 tempbh &= 0x70;
10613 tempbh >>= 4;
10614 tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
10615 tempbx = (tempbh << 8) | tempbl;
10616 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10617 if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
10618 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
10619 tempbx = 770;
10620 } else {
10621 if(tempbx > 770) tempbx = 770;
10622 if(SiS_Pr->SiS_VGAVDE < 600) {
10623 tempax = 768 - SiS_Pr->SiS_VGAVDE;
10624 tempax >>= 4; /* 1.10.7w; 1.10.6s: 3; */
10625 if(SiS_Pr->SiS_VGAVDE <= 480) tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
10626 tempbx -= tempax;
10627 }
10628 }
10629 } else return;
10630 }
10631 temp = tempbx & 0xff;
10632 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
10633 temp = ((tempbx & 0xff00) >> 4) | tempcl;
10634 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
10635 }
10636 }
10637}
10638
10639#endif
10640
10641/* ================= SiS 300 O.E.M. ================== */
10642
Aaro Koskinenf7854e52010-11-19 21:58:47 +000010643#ifdef CONFIG_FB_SIS_300
Linus Torvalds1da177e2005-04-16 15:20:36 -070010644
10645static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010646SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
10647 unsigned short RefTabIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010648{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010649 unsigned short crt2crtc=0, modeflag, myindex=0;
10650 unsigned char temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010651 int i;
10652
10653 if(ModeNo <= 0x13) {
10654 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10655 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
10656 } else {
10657 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10658 crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
10659 }
10660
10661 crt2crtc &= 0x3f;
10662
10663 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
10664 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
10665 }
10666
10667 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
10668 if(modeflag & HalfDCLK) myindex = 1;
10669
10670 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
10671 for(i=0; i<7; i++) {
10672 if(barco_p1[myindex][crt2crtc][i][0]) {
10673 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
10674 barco_p1[myindex][crt2crtc][i][0],
10675 barco_p1[myindex][crt2crtc][i][2],
10676 barco_p1[myindex][crt2crtc][i][1]);
10677 }
10678 }
10679 }
10680 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
10681 if(temp & 0x80) {
10682 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
10683 temp++;
10684 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
10685 }
10686 }
10687}
10688
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010689static unsigned short
10690GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010691{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010692 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10693 unsigned short tempbx=0,romptr=0;
10694 static const unsigned char customtable300[] = {
10695 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010696 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10697 };
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010698 static const unsigned char customtable630[] = {
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 };
10702
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010703 if(SiS_Pr->ChipType == SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010704
10705 tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
10706 if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
10707 tempbx -= 2;
10708 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
10709 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10710 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
10711 }
10712 if(SiS_Pr->SiS_UseROM) {
10713 if(ROMAddr[0x235] & 0x80) {
10714 tempbx = SiS_Pr->SiS_LCDTypeInfo;
10715 if(Flag) {
10716 romptr = SISGETROMW(0x255);
10717 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10718 else tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
10719 if(tempbx == 0xFF) return 0xFFFF;
10720 }
10721 tempbx <<= 1;
10722 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
10723 }
10724 }
10725
10726 } else {
10727
10728 if(Flag) {
10729 if(SiS_Pr->SiS_UseROM) {
10730 romptr = SISGETROMW(0x255);
10731 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10732 else tempbx = 0xff;
10733 } else {
10734 tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
10735 }
10736 if(tempbx == 0xFF) return 0xFFFF;
10737 tempbx <<= 2;
10738 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10739 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10740 return tempbx;
10741 }
10742 tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
10743 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10744 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10745
10746 }
10747
10748 return tempbx;
10749}
10750
10751static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010752SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010753{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010754 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10755 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010756
10757 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10758
10759 if(SiS_Pr->SiS_UseROM) {
10760 if(!(ROMAddr[0x237] & 0x01)) return;
10761 if(!(ROMAddr[0x237] & 0x02)) return;
10762 romptr = SISGETROMW(0x24b);
10763 }
10764
10765 /* The Panel Compensation Delay should be set according to tables
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010766 * here. Unfortunately, various BIOS versions don't care about
Linus Torvalds1da177e2005-04-16 15:20:36 -070010767 * a uniform way using eg. ROM byte 0x220, but use different
10768 * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010769 * Thus we don't set this if the user selected a custom pdc or if
Linus Torvalds1da177e2005-04-16 15:20:36 -070010770 * we otherwise detected a valid pdc.
10771 */
10772 if(SiS_Pr->PDC != -1) return;
10773
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010774 temp = GetOEMLCDPtr(SiS_Pr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070010775
10776 if(SiS_Pr->UseCustomMode)
10777 index = 0;
10778 else
10779 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
10780
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010781 if(SiS_Pr->ChipType != SIS_300) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010782 if(romptr) {
10783 romptr += (temp * 2);
10784 romptr = SISGETROMW(romptr);
10785 romptr += index;
10786 temp = ROMAddr[romptr];
10787 } else {
10788 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10789 temp = SiS300_OEMLCDDelay2[temp][index];
10790 } else {
10791 temp = SiS300_OEMLCDDelay3[temp][index];
10792 }
10793 }
10794 } else {
10795 if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
10796 if(romptr) {
10797 romptr += (temp * 2);
10798 romptr = SISGETROMW(romptr);
10799 romptr += index;
10800 temp = ROMAddr[romptr];
10801 } else {
10802 temp = SiS300_OEMLCDDelay5[temp][index];
10803 }
10804 } else {
10805 if(SiS_Pr->SiS_UseROM) {
10806 romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
10807 if(romptr) {
10808 romptr += (temp * 2);
10809 romptr = SISGETROMW(romptr);
10810 romptr += index;
10811 temp = ROMAddr[romptr];
10812 } else {
10813 temp = SiS300_OEMLCDDelay4[temp][index];
10814 }
10815 } else {
10816 temp = SiS300_OEMLCDDelay4[temp][index];
10817 }
10818 }
10819 }
10820 temp &= 0x3c;
10821 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* index 0A D[6:4] */
10822}
10823
10824static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010825SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010826{
10827#if 0 /* Unfinished; Data table missing */
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010828 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10829 unsigned short index,temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010830
10831 if((SiS_Pr->SiS_UseROM) {
10832 if(!(ROMAddr[0x237] & 0x01)) return;
10833 if(!(ROMAddr[0x237] & 0x04)) return;
10834 /* No rom pointer in BIOS header! */
10835 }
10836
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010837 temp = GetOEMLCDPtr(SiS_Pr, 1);
10838 if(temp == 0xFFFF) return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010839
10840 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
10841 for(i=0x14, j=0; i<=0x17; i++, j++) {
10842 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
10843 }
10844 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
10845
10846 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
10847 SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
10848 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
10849 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
10850 for(i=0x1b, j=3; i<=0x1d; i++, j++) {
10851 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
10852 }
10853#endif
10854}
10855
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010856static unsigned short
10857GetOEMTVPtr(struct SiS_Private *SiS_Pr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010858{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010859 unsigned short index;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010860
10861 index = 0;
10862 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) index += 4;
10863 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10864 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) index += 2;
10865 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
10866 else if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
10867 } else {
10868 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
10869 if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
10870 }
10871 return index;
10872}
10873
10874static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010875SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010876{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010877 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10878 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010879
10880 if(SiS_Pr->SiS_UseROM) {
10881 if(!(ROMAddr[0x238] & 0x01)) return;
10882 if(!(ROMAddr[0x238] & 0x02)) return;
10883 romptr = SISGETROMW(0x241);
10884 }
10885
10886 temp = GetOEMTVPtr(SiS_Pr);
10887
10888 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
10889
10890 if(romptr) {
10891 romptr += (temp * 2);
10892 romptr = SISGETROMW(romptr);
10893 romptr += index;
10894 temp = ROMAddr[romptr];
10895 } else {
10896 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10897 temp = SiS300_OEMTVDelay301[temp][index];
10898 } else {
10899 temp = SiS300_OEMTVDelayLVDS[temp][index];
10900 }
10901 }
10902 temp &= 0x3c;
10903 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
10904}
10905
10906static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010907SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010908{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010909 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10910 unsigned short index,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010911
10912 if(SiS_Pr->SiS_UseROM) {
10913 if(!(ROMAddr[0x238] & 0x01)) return;
10914 if(!(ROMAddr[0x238] & 0x04)) return;
10915 romptr = SISGETROMW(0x243);
10916 }
10917
10918 temp = GetOEMTVPtr(SiS_Pr);
10919
10920 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
10921
10922 if(romptr) {
10923 romptr += (temp * 2);
10924 romptr = SISGETROMW(romptr);
10925 romptr += index;
10926 temp = ROMAddr[romptr];
10927 } else {
10928 temp = SiS300_OEMTVFlicker[temp][index];
10929 }
10930 temp &= 0x70;
10931 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
10932}
10933
10934static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010935SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010936{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010937 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10938 unsigned short index,i,j,temp,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010939
10940 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
10941
10942 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
10943
10944 if(SiS_Pr->SiS_UseROM) {
10945 if(!(ROMAddr[0x238] & 0x01)) return;
10946 if(!(ROMAddr[0x238] & 0x08)) return;
10947 romptr = SISGETROMW(0x245);
10948 }
10949
10950 temp = GetOEMTVPtr(SiS_Pr);
10951
10952 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
10953
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010954 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010955 for(i=0x31, j=0; i<=0x34; i++, j++) {
10956 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
10957 }
10958 } else {
10959 if(romptr) {
10960 romptr += (temp * 2);
10961 romptr = SISGETROMW(romptr);
10962 romptr += (index * 4);
10963 for(i=0x31, j=0; i<=0x34; i++, j++) {
10964 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10965 }
10966 } else {
10967 for(i=0x31, j=0; i<=0x34; i++, j++) {
10968 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
10969 }
10970 }
10971 }
10972}
10973
10974static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010975SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070010976{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010977 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10978 unsigned short index,temp,i,j,romptr=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070010979
10980 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
10981
10982 if(SiS_Pr->SiS_UseROM) {
10983 if(!(ROMAddr[0x238] & 0x01)) return;
10984 if(!(ROMAddr[0x238] & 0x10)) return;
10985 romptr = SISGETROMW(0x247);
10986 }
10987
10988 temp = GetOEMTVPtr(SiS_Pr);
10989
10990 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
10991 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
10992 /* NTSCJ uses NTSC filters */
10993
10994 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
10995
Thomas Winischhofer544393f2005-09-09 13:04:45 -070010996 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070010997 for(i=0x35, j=0; i<=0x38; i++, j++) {
10998 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
10999 }
11000 for(i=0x48; i<=0x4A; i++, j++) {
11001 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
11002 }
11003 } else {
11004 if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
11005 romptr += (temp * 2);
11006 romptr = SISGETROMW(romptr);
11007 romptr += (index * 4);
11008 for(i=0x35, j=0; i<=0x38; i++, j++) {
11009 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11010 }
11011 } else {
11012 for(i=0x35, j=0; i<=0x38; i++, j++) {
11013 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
11014 }
11015 }
11016 }
11017}
11018
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011019static unsigned short
11020SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011021{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011022 unsigned short ModeIdIndex;
11023 unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011024
11025 if(*ModeNo <= 5) *ModeNo |= 1;
11026
11027 for(ModeIdIndex=0; ; ModeIdIndex++) {
11028 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
11029 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF) return 0;
11030 }
11031
11032 if(*ModeNo != 0x07) {
11033 if(*ModeNo > 0x03) return ModeIdIndex;
11034 if(VGAINFO & 0x80) return ModeIdIndex;
11035 ModeIdIndex++;
11036 }
11037
11038 if(VGAINFO & 0x10) ModeIdIndex++; /* 400 lines */
11039 /* else 350 lines */
11040 return ModeIdIndex;
11041}
11042
11043static void
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011044SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
11045 unsigned short RefTableIndex)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011046{
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011047 unsigned short OEMModeIdIndex = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011048
11049 if(!SiS_Pr->UseCustomMode) {
11050 OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
11051 if(!(OEMModeIdIndex)) return;
11052 }
11053
11054 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011055 SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011056 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011057 SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011058 }
11059 }
11060 if(SiS_Pr->UseCustomMode) return;
11061 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011062 SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011063 if(SiS_Pr->SiS_VBType & VB_SISVB) {
Thomas Winischhofer544393f2005-09-09 13:04:45 -070011064 SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
11065 SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
11066 SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011067 }
11068 }
11069}
11070#endif
11071