]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/video/fbdev/sis/init301.c
Merge tag 'wireless-drivers-for-davem-2017-11-22' of git://git.kernel.org/pub/scm...
[mirror_ubuntu-bionic-kernel.git] / drivers / video / fbdev / sis / init301.c
CommitLineData
1da177e4
LT
1/* $XFree86$ */
2/* $XdotOrg$ */
3/*
4 * Mode initializing code (CRT2 section)
544393fe
TW
5 * for SiS 300/305/540/630/730,
6 * SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
7 * XGI V3XT/V5/V8, Z7
8 * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
1da177e4 9 *
544393fe 10 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
1da177e4
LT
11 *
12 * If distributed as part of the Linux kernel, the following license terms
13 * apply:
14 *
15 * * This program is free software; you can redistribute it and/or modify
16 * * it under the terms of the GNU General Public License as published by
17 * * the Free Software Foundation; either version 2 of the named License,
18 * * or any later version.
19 * *
20 * * This program is distributed in the hope that it will be useful,
21 * * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * * GNU General Public License for more details.
24 * *
25 * * You should have received a copy of the GNU General Public License
26 * * along with this program; if not, write to the Free Software
27 * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
28 *
29 * Otherwise, the following license terms apply:
30 *
31 * * Redistribution and use in source and binary forms, with or without
32 * * modification, are permitted provided that the following conditions
33 * * are met:
34 * * 1) Redistributions of source code must retain the above copyright
35 * * notice, this list of conditions and the following disclaimer.
36 * * 2) Redistributions in binary form must reproduce the above copyright
37 * * notice, this list of conditions and the following disclaimer in the
38 * * documentation and/or other materials provided with the distribution.
39 * * 3) The name of the author may not be used to endorse or promote products
40 * * derived from this software without specific prior written permission.
41 * *
544393fe 42 * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1da177e4
LT
43 * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 *
53 * Author: Thomas Winischhofer <thomas@winischhofer.net>
54 *
55 * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
56 * Used by permission.
57 *
1da177e4
LT
58 */
59
60#if 1
61#define SET_EMI /* 302LV/ELV: Set EMI values */
62#endif
63
544393fe
TW
64#if 1
65#define SET_PWD /* 301/302LV: Set PWD */
66#endif
67
1da177e4
LT
68#define COMPAL_HACK /* Needed for Compal 1400x1050 (EMI) */
69#define COMPAQ_HACK /* Needed for Inventec/Compaq 1280x1024 (EMI) */
70#define ASUS_HACK /* Needed for Asus A2H 1024x768 (EMI) */
71
72#include "init301.h"
73
f7854e5d 74#ifdef CONFIG_FB_SIS_300
1da177e4
LT
75#include "oem300.h"
76#endif
77
f7854e5d 78#ifdef CONFIG_FB_SIS_315
1da177e4
LT
79#include "oem310.h"
80#endif
81
82#define SiS_I2CDELAY 1000
83#define SiS_I2CDELAYSHORT 150
84
544393fe 85static unsigned short SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
544393fe 86static void SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
1da177e4
LT
87
88/*********************************************/
89/* HELPER: Lock/Unlock CRT2 */
90/*********************************************/
91
92void
544393fe 93SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
1da177e4 94{
544393fe
TW
95 if(SiS_Pr->ChipType == XGI_20)
96 return;
97 else if(SiS_Pr->ChipType >= SIS_315H)
1da177e4
LT
98 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
99 else
100 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
101}
102
544393fe 103static
544393fe
TW
104void
105SiS_LockCRT2(struct SiS_Private *SiS_Pr)
1da177e4 106{
544393fe
TW
107 if(SiS_Pr->ChipType == XGI_20)
108 return;
109 else if(SiS_Pr->ChipType >= SIS_315H)
1da177e4
LT
110 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
544393fe 120SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
1da177e4 121{
544393fe 122 if(SiS_Pr->ChipType >= SIS_661) {
1da177e4
LT
123 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
f7854e5d 133#ifdef CONFIG_FB_SIS_315
544393fe
TW
134static unsigned char *
135GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
1da177e4 136{
544393fe
TW
137 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
138 unsigned char *myptr = NULL;
139 unsigned short romindex = 0, reg = 0, idx = 0;
1da177e4
LT
140
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) &&
544393fe 149 ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
1da177e4 150
544393fe
TW
151 if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
152 else reg = 0x7d;
1da177e4
LT
153
154 idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
155
156 if(idx < (8*26)) {
544393fe 157 myptr = (unsigned char *)&SiS_LCDStruct661[idx];
1da177e4
LT
158 }
159 romindex = SISGETROMW(0x100);
160 if(romindex) {
161 romindex += idx;
162 myptr = &ROMAddr[romindex];
163 }
164 }
165 return myptr;
166}
167
544393fe
TW
168static unsigned short
169GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
1da177e4 170{
544393fe
TW
171 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
172 unsigned short romptr = 0;
1da177e4
LT
173
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) &&
544393fe 182 ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
1da177e4
LT
183 romptr = SISGETROMW(0x102);
184 romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
185 }
186
544393fe 187 return romptr;
1da177e4
LT
188}
189#endif
190
191/*********************************************/
192/* Adjust Rate for CRT2 */
193/*********************************************/
194
c30660ea 195static bool
544393fe
TW
196SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
197 unsigned short RRTI, unsigned short *i)
1da177e4 198{
544393fe 199 unsigned short checkmask=0, modeid, infoflag;
1da177e4 200
544393fe 201 modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
1da177e4 202
544393fe 203 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1da177e4 204
544393fe 205 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
1da177e4 206
544393fe
TW
207 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 }
1da177e4 217
544393fe 218 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
1da177e4 219
544393fe
TW
220 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 }
1da177e4 228
544393fe 229 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1da177e4 230
544393fe 231 checkmask |= SupportHiVision;
1da177e4 232
544393fe 233 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
1da177e4 234
544393fe
TW
235 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 }
1da177e4 244
544393fe 245 }
1da177e4 246
544393fe 247 } else { /* LVDS */
1da177e4 248
544393fe
TW
249 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
250 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
251 checkmask |= SupportCHTV;
252 }
253 }
1da177e4 254
544393fe
TW
255 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
256 checkmask |= SupportLCD;
257 }
1da177e4 258
544393fe 259 }
1da177e4 260
544393fe
TW
261 /* 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;
c30660ea 264 if(infoflag & checkmask) return true;
544393fe
TW
265 if((*i) == 0) break;
266 }
1da177e4 267
544393fe
TW
268 /* 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;
c30660ea 274 if(infoflag & checkmask) return true;
544393fe 275 }
c30660ea 276 return false;
1da177e4
LT
277}
278
279/*********************************************/
280/* Get rate index */
281/*********************************************/
282
544393fe
TW
283unsigned short
284SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
285{
286 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 };
1da177e4 295
544393fe
TW
296 /* Do NOT check for UseCustomMode here, will skrew up FIFO */
297 if(ModeNo == 0xfe) return 0;
1da177e4 298
544393fe
TW
299 if(ModeNo <= 0x13) {
300 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
301 } else {
302 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
303 }
1da177e4 304
544393fe
TW
305 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
306 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
307 if(modeflag & HalfDCLK) return 0;
308 }
309 }
1da177e4 310
544393fe 311 if(ModeNo < 0x14) return 0xFFFF;
1da177e4 312
544393fe
TW
313 index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
314 backupindex = index;
1da177e4 315
544393fe 316 if(index > 0) index--;
1da177e4 317
544393fe
TW
318 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 }
1da177e4 337
544393fe
TW
338 RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
339 ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
1da177e4 340
544393fe
TW
341 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 }
1da177e4 349
544393fe
TW
350 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);
359
360 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 }
1da177e4 366
544393fe 367 i--;
1da177e4 368
544393fe
TW
369 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 }
1da177e4 375
544393fe 376 return (RRTI + i);
1da177e4
LT
377}
378
379/*********************************************/
380/* STORE CRT2 INFO in CR34 */
381/*********************************************/
382
383static void
544393fe 384SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1da177e4 385{
544393fe 386 unsigned short temp1, temp2;
1da177e4 387
544393fe
TW
388 /* 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);
1da177e4
LT
393}
394
395/*********************************************/
396/* HELPER: GET SOME DATA FROM BIOS ROM */
397/*********************************************/
398
f7854e5d 399#ifdef CONFIG_FB_SIS_300
c30660ea 400static bool
544393fe 401SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
1da177e4 402{
544393fe
TW
403 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
404 unsigned short temp,temp1;
1da177e4 405
544393fe
TW
406 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);
c30660ea 410 if(temp1 & temp) return true;
544393fe
TW
411 }
412 }
c30660ea 413 return false;
1da177e4
LT
414}
415
c30660ea 416static bool
544393fe 417SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
1da177e4 418{
544393fe
TW
419 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
420 unsigned short temp,temp1;
1da177e4 421
544393fe
TW
422 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);
c30660ea 426 if(temp1 & temp) return true;
544393fe
TW
427 }
428 }
c30660ea 429 return false;
1da177e4
LT
430}
431#endif
432
433/*********************************************/
434/* HELPER: DELAY FUNCTIONS */
435/*********************************************/
436
437void
544393fe 438SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
1da177e4 439{
b860e73a
DR
440 while (delaytime-- > 0)
441 SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05);
1da177e4
LT
442}
443
f7854e5d 444#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1da177e4 445static void
544393fe 446SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
1da177e4 447{
544393fe 448 SiS_DDC2Delay(SiS_Pr, delay * 36);
1da177e4
LT
449}
450#endif
451
f7854e5d 452#ifdef CONFIG_FB_SIS_315
1da177e4 453static void
544393fe 454SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
1da177e4 455{
544393fe
TW
456 while(delay--) {
457 SiS_GenericDelay(SiS_Pr, 6623);
458 }
1da177e4
LT
459}
460#endif
461
f7854e5d 462#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1da177e4 463static void
544393fe 464SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
1da177e4 465{
544393fe
TW
466 while(delay--) {
467 SiS_GenericDelay(SiS_Pr, 66);
468 }
1da177e4
LT
469}
470#endif
471
472static void
544393fe 473SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
1da177e4 474{
f7854e5d 475#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
544393fe
TW
476 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
477 unsigned short PanelID, DelayIndex, Delay=0;
1da177e4
LT
478#endif
479
544393fe 480 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 481
f7854e5d 482#ifdef CONFIG_FB_SIS_300
1da177e4
LT
483
484 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
485 if(SiS_Pr->SiS_VBType & VB_SISVB) {
544393fe
TW
486 if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
487 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
1da177e4
LT
488 }
489 DelayIndex = PanelID >> 4;
490 if((DelayTime >= 2) && ((PanelID & 0x0f) == 1)) {
544393fe 491 Delay = 3;
1da177e4 492 } else {
544393fe
TW
493 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 }
1da177e4 499 if(SiS_Pr->SiS_UseROM) {
544393fe
TW
500 if(ROMAddr[0x220] & 0x40) {
501 if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
502 else Delay = (unsigned short)ROMAddr[0x226];
503 }
504 }
1da177e4
LT
505 }
506 SiS_ShortDelay(SiS_Pr, Delay);
507
f7854e5d 508#endif /* CONFIG_FB_SIS_300 */
1da177e4
LT
509
510 } else {
511
f7854e5d 512#ifdef CONFIG_FB_SIS_315
1da177e4 513
544393fe
TW
514 if((SiS_Pr->ChipType >= SIS_661) ||
515 (SiS_Pr->ChipType <= SIS_315PRO) ||
516 (SiS_Pr->ChipType == SIS_330) ||
1da177e4
LT
517 (SiS_Pr->SiS_ROMNew)) {
518
544393fe 519 if(!(DelayTime & 0x01)) {
1da177e4 520 SiS_DDC2Delay(SiS_Pr, 0x1000);
544393fe 521 } else {
1da177e4 522 SiS_DDC2Delay(SiS_Pr, 0x4000);
544393fe 523 }
1da177e4
LT
524
525 } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
544393fe 526 (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
1da177e4
LT
527 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */
528
544393fe
TW
529 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
530 PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
1da177e4
LT
531 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)) {
544393fe
TW
540 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 }
1da177e4 548 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
544393fe
TW
549 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 }
1da177e4
LT
558 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;
544393fe
TW
564 if(!(DelayTime & 0x01)) {
565 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
566 } else {
567 Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
568 }
1da177e4
LT
569 Delay <<= 8;
570 SiS_DDC2Delay(SiS_Pr, Delay);
571
572 }
573
f7854e5d 574#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
575
576 }
577}
578
f7854e5d 579#ifdef CONFIG_FB_SIS_315
1da177e4 580static void
544393fe 581SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
1da177e4
LT
582{
583 int i;
544393fe
TW
584 for(i = 0; i < DelayLoop; i++) {
585 SiS_PanelDelay(SiS_Pr, DelayTime);
1da177e4
LT
586 }
587}
588#endif
589
590/*********************************************/
591/* HELPER: WAIT-FOR-RETRACE FUNCTIONS */
592/*********************************************/
593
594void
544393fe 595SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
1da177e4 596{
544393fe 597 unsigned short watchdog;
1da177e4 598
544393fe
TW
599 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
600 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
1da177e4 601
544393fe
TW
602 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);
1da177e4
LT
606}
607
f7854e5d 608#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1da177e4 609static void
544393fe 610SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
1da177e4 611{
544393fe 612 unsigned short watchdog;
1da177e4 613
544393fe
TW
614 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);
1da177e4
LT
618}
619#endif
620
621static void
544393fe 622SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
1da177e4 623{
544393fe 624 if(SiS_Pr->ChipType < SIS_315H) {
f7854e5d 625#ifdef CONFIG_FB_SIS_300
544393fe
TW
626 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 }
1da177e4 634#endif
544393fe 635 } else {
f7854e5d 636#ifdef CONFIG_FB_SIS_315
544393fe
TW
637 if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
638 SiS_WaitRetrace1(SiS_Pr);
639 } else {
640 SiS_WaitRetrace2(SiS_Pr, 0x30);
641 }
1da177e4 642#endif
544393fe 643 }
1da177e4
LT
644}
645
646static void
544393fe 647SiS_VBWait(struct SiS_Private *SiS_Pr)
1da177e4 648{
544393fe 649 unsigned short tempal,temp,i,j;
1da177e4 650
544393fe
TW
651 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 }
1da177e4
LT
665}
666
667static void
544393fe 668SiS_VBLongWait(struct SiS_Private *SiS_Pr)
1da177e4 669{
544393fe
TW
670 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
671 SiS_VBWait(SiS_Pr);
672 } else {
673 SiS_WaitRetrace1(SiS_Pr);
674 }
1da177e4
LT
675}
676
677/*********************************************/
678/* HELPER: MISC */
679/*********************************************/
680
f7854e5d 681#ifdef CONFIG_FB_SIS_300
c30660ea 682static bool
544393fe 683SiS_Is301B(struct SiS_Private *SiS_Pr)
1da177e4 684{
c30660ea
RK
685 if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
686 return false;
1da177e4
LT
687}
688#endif
689
c30660ea 690static bool
544393fe 691SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
1da177e4 692{
544393fe 693 if(SiS_Pr->ChipType == SIS_730) {
c30660ea 694 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
544393fe 695 }
c30660ea
RK
696 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
697 return false;
1da177e4
LT
698}
699
c30660ea 700bool
544393fe 701SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
1da177e4 702{
f7854e5d 703#ifdef CONFIG_FB_SIS_315
544393fe
TW
704 if(SiS_Pr->ChipType >= SIS_315H) {
705 if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
c30660ea 706 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
544393fe
TW
707 }
708 }
1da177e4 709#endif
c30660ea 710 return false;
1da177e4
LT
711}
712
c30660ea 713bool
544393fe 714SiS_IsVAMode(struct SiS_Private *SiS_Pr)
1da177e4 715{
f7854e5d 716#ifdef CONFIG_FB_SIS_315
544393fe 717 unsigned short flag;
1da177e4 718
544393fe
TW
719 if(SiS_Pr->ChipType >= SIS_315H) {
720 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
c30660ea 721 if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
544393fe 722 }
1da177e4 723#endif
c30660ea 724 return false;
1da177e4
LT
725}
726
f7854e5d 727#ifdef CONFIG_FB_SIS_315
c30660ea 728static bool
544393fe 729SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
1da177e4 730{
c30660ea
RK
731 if(SiS_IsVAMode(SiS_Pr)) return true;
732 if(SiS_CRT2IsLCD(SiS_Pr)) return true;
733 return false;
1da177e4
LT
734}
735#endif
736
c30660ea 737static bool
544393fe 738SiS_IsDualLink(struct SiS_Private *SiS_Pr)
1da177e4 739{
f7854e5d 740#ifdef CONFIG_FB_SIS_315
544393fe
TW
741 if(SiS_Pr->ChipType >= SIS_315H) {
742 if((SiS_CRT2IsLCD(SiS_Pr)) ||
743 (SiS_IsVAMode(SiS_Pr))) {
c30660ea 744 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
544393fe
TW
745 }
746 }
1da177e4 747#endif
c30660ea 748 return false;
1da177e4
LT
749}
750
f7854e5d 751#ifdef CONFIG_FB_SIS_315
c30660ea 752static bool
544393fe 753SiS_TVEnabled(struct SiS_Private *SiS_Pr)
1da177e4 754{
c30660ea 755 if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
544393fe 756 if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
c30660ea 757 if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
544393fe 758 }
c30660ea 759 return false;
1da177e4
LT
760}
761#endif
762
f7854e5d 763#ifdef CONFIG_FB_SIS_315
c30660ea 764static bool
544393fe 765SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
1da177e4 766{
c30660ea
RK
767 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
768 return false;
1da177e4
LT
769}
770#endif
771
f7854e5d 772#ifdef CONFIG_FB_SIS_315
c30660ea 773static bool
544393fe 774SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
1da177e4 775{
544393fe 776 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
c30660ea 777 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
544393fe 778 }
c30660ea 779 return false;
1da177e4
LT
780}
781#endif
782
f7854e5d 783#ifdef CONFIG_FB_SIS_315
c30660ea 784static bool
544393fe 785SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
1da177e4 786{
544393fe 787 unsigned short flag;
1da177e4 788
544393fe
TW
789 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) ||
c30660ea
RK
793 (flag == 0xb0) || (flag == 0x90)) return false;
794 } else if(SiS_Pr->ChipType >= SIS_661) return false;
795 return true;
1da177e4
LT
796}
797#endif
798
f7854e5d 799#ifdef CONFIG_FB_SIS_315
c30660ea 800static bool
544393fe 801SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
1da177e4 802{
544393fe
TW
803 if(SiS_Pr->ChipType >= SIS_315H) {
804 /* YPrPb = 0x08 */
c30660ea 805 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
544393fe 806 }
c30660ea 807 return false;
1da177e4
LT
808}
809#endif
810
f7854e5d 811#ifdef CONFIG_FB_SIS_315
c30660ea 812static bool
544393fe 813SiS_IsChScart(struct SiS_Private *SiS_Pr)
1da177e4 814{
544393fe
TW
815 if(SiS_Pr->ChipType >= SIS_315H) {
816 /* Scart = 0x04 */
c30660ea 817 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
544393fe 818 }
c30660ea 819 return false;
1da177e4
LT
820}
821#endif
822
f7854e5d 823#ifdef CONFIG_FB_SIS_315
c30660ea 824static bool
544393fe 825SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
1da177e4 826{
544393fe 827 unsigned short flag;
1da177e4 828
544393fe
TW
829 if(SiS_Pr->ChipType >= SIS_315H) {
830 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
c30660ea 831 if(flag & SetCRT2ToTV) return true;
544393fe 832 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
c30660ea
RK
833 if(flag & EnableCHYPbPr) return true; /* = YPrPb = 0x08 */
834 if(flag & EnableCHScart) return true; /* = Scart = 0x04 - TW */
544393fe
TW
835 } else {
836 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
c30660ea 837 if(flag & SetCRT2ToTV) return true;
544393fe 838 }
c30660ea 839 return false;
1da177e4
LT
840}
841#endif
842
f7854e5d 843#ifdef CONFIG_FB_SIS_315
c30660ea 844static bool
544393fe 845SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
1da177e4 846{
544393fe 847 unsigned short flag;
1da177e4 848
544393fe
TW
849 if(SiS_Pr->ChipType >= SIS_315H) {
850 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
c30660ea 851 if(flag & SetCRT2ToLCD) return true;
544393fe 852 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
c30660ea 853 if(flag & SetToLCDA) return true;
544393fe
TW
854 } else {
855 flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
c30660ea 856 if(flag & SetCRT2ToLCD) return true;
544393fe 857 }
c30660ea 858 return false;
1da177e4
LT
859}
860#endif
861
c30660ea 862static bool
544393fe 863SiS_HaveBridge(struct SiS_Private *SiS_Pr)
1da177e4 864{
544393fe 865 unsigned short flag;
1da177e4 866
544393fe 867 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
c30660ea 868 return true;
544393fe
TW
869 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
870 flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
c30660ea 871 if((flag == 1) || (flag == 2)) return true;
544393fe 872 }
c30660ea 873 return false;
1da177e4
LT
874}
875
c30660ea 876static bool
544393fe 877SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
1da177e4 878{
544393fe 879 unsigned short flag;
1da177e4 880
544393fe
TW
881 if(SiS_HaveBridge(SiS_Pr)) {
882 flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
883 if(SiS_Pr->ChipType < SIS_315H) {
884 flag &= 0xa0;
c30660ea 885 if((flag == 0x80) || (flag == 0x20)) return true;
544393fe
TW
886 } else {
887 flag &= 0x50;
c30660ea 888 if((flag == 0x40) || (flag == 0x10)) return true;
544393fe
TW
889 }
890 }
c30660ea 891 return false;
1da177e4
LT
892}
893
c30660ea 894static bool
544393fe 895SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
1da177e4 896{
544393fe 897 unsigned short flag1;
1da177e4 898
544393fe 899 flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
c30660ea
RK
900 if(flag1 & (SetInSlaveMode >> 8)) return true;
901 return false;
1da177e4
LT
902}
903
904/*********************************************/
905/* GET VIDEO BRIDGE CONFIG INFO */
906/*********************************************/
907
908/* Setup general purpose IO for Chrontel communication */
f7854e5d 909#ifdef CONFIG_FB_SIS_300
1da177e4 910void
544393fe 911SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
1da177e4 912{
544393fe 913 unsigned int acpibase;
1da177e4
LT
914 unsigned short temp;
915
916 if(!(SiS_Pr->SiS_ChSW)) return;
917
544393fe 918 acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
1da177e4 919 acpibase &= 0xFFFF;
544393fe
TW
920 if(!acpibase) return;
921 temp = SiS_GetRegShort((acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
1da177e4 922 temp &= 0xFEFF;
544393fe
TW
923 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) */
1da177e4
LT
926 temp &= 0xFEFF;
927 if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
544393fe
TW
928 SiS_SetRegShort((acpibase + 0x3a), temp);
929 temp = SiS_GetRegShort((acpibase + 0x3a));
1da177e4 930}
544393fe 931#endif
1da177e4
LT
932
933void
544393fe
TW
934SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
935 unsigned short ModeIdIndex, int checkcrt2mode)
1da177e4 936{
544393fe
TW
937 unsigned short tempax, tempbx, temp;
938 unsigned short modeflag, resinfo = 0;
1da177e4 939
544393fe 940 SiS_Pr->SiS_SetFlag = 0;
1da177e4 941
544393fe 942 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4 943
544393fe 944 SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
1da177e4 945
544393fe
TW
946 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;
1da177e4 959
f7854e5d 960#ifdef CONFIG_FB_SIS_315
544393fe
TW
961 if(SiS_Pr->ChipType >= SIS_315H) {
962 if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
1da177e4 963 if(ModeNo == 0x03) {
544393fe 964 /* Mode 0x03 is never in driver mode */
1da177e4
LT
965 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
966 }
967 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
544393fe 968 /* Reset LCDA setting if not driver mode */
1da177e4
LT
969 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
970 }
971 if(IS_SIS650) {
544393fe 972 if(SiS_Pr->SiS_UseLCDA) {
1da177e4
LT
973 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
974 if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
544393fe 975 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
1da177e4
LT
976 }
977 }
978 }
979 }
980 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
544393fe
TW
981 if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
982 tempbx |= SetCRT2ToLCDA;
1da177e4
LT
983 }
984 }
985
544393fe 986 if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
1da177e4 987 tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
544393fe
TW
988 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;
1da177e4
LT
993 }
994 }
544393fe 995 }
1da177e4
LT
996
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) {
544393fe 1003 if(temp & EnableCHYPbPr) {
1da177e4
LT
1004 tempbx |= SetCRT2ToCHYPbPr;
1005 }
1006 }
1007 }
1008 }
1009
f7854e5d 1010#endif /* CONFIG_FB_SIS_315 */
1da177e4 1011
544393fe
TW
1012 if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
1013 tempbx &= ~(SetCRT2ToRAMDAC);
1014 }
1015
1016 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1da177e4 1017 temp = SetCRT2ToSVIDEO |
544393fe
TW
1018 SetCRT2ToAVIDEO |
1019 SetCRT2ToSCART |
1020 SetCRT2ToLCDA |
1021 SetCRT2ToLCD |
1022 SetCRT2ToRAMDAC |
1023 SetCRT2ToHiVision |
1da177e4 1024 SetCRT2ToYPbPr525750;
544393fe
TW
1025 } else {
1026 if(SiS_Pr->ChipType >= SIS_315H) {
1027 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1028 temp = SetCRT2ToAVIDEO |
1da177e4
LT
1029 SetCRT2ToSVIDEO |
1030 SetCRT2ToSCART |
1031 SetCRT2ToLCDA |
1032 SetCRT2ToLCD |
1033 SetCRT2ToCHYPbPr;
544393fe
TW
1034 } else {
1035 temp = SetCRT2ToLCDA |
1da177e4
LT
1036 SetCRT2ToLCD;
1037 }
1038 } else {
544393fe
TW
1039 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1040 temp = SetCRT2ToTV | SetCRT2ToLCD;
1041 } else {
1042 temp = SetCRT2ToLCD;
1da177e4
LT
1043 }
1044 }
544393fe
TW
1045 }
1046
1047 if(!(tempbx & temp)) {
1048 tempax = DisableCRT2Display;
1049 tempbx = 0;
1050 }
1da177e4 1051
544393fe 1052 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1da177e4 1053
544393fe 1054 unsigned short clearmask = ( DriverMode |
1da177e4
LT
1055 DisableCRT2Display |
1056 LoadDACFlag |
1057 SetNotSimuMode |
1058 SetInSlaveMode |
1059 SetPALTV |
1060 SwitchCRT2 |
1061 SetSimuScanMode );
544393fe
TW
1062
1063 if(tempbx & SetCRT2ToLCDA) tempbx &= (clearmask | SetCRT2ToLCDA);
1da177e4
LT
1064 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);
544393fe
TW
1069
1070 } else {
1071
1072 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4 1073 if(tempbx & SetCRT2ToLCDA) {
544393fe 1074 tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
1da177e4
LT
1075 }
1076 }
544393fe
TW
1077 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1078 if(tempbx & SetCRT2ToTV) {
1079 tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
1da177e4 1080 }
1da177e4 1081 }
544393fe
TW
1082 if(tempbx & SetCRT2ToLCD) {
1083 tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
1084 }
1085 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4
LT
1086 if(tempbx & SetCRT2ToLCDA) {
1087 tempbx |= SetCRT2ToLCD;
1088 }
1089 }
544393fe 1090
1da177e4
LT
1091 }
1092
544393fe
TW
1093 if(tempax & DisableCRT2Display) {
1094 if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1095 tempbx = SetSimuScanMode | DisableCRT2Display;
1096 }
1097 }
1da177e4 1098
544393fe 1099 if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
1da177e4
LT
1100
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)) ) {
544393fe 1105 modeflag &= (~CRT2Mode);
1da177e4
LT
1106 }
1107 }
1108
544393fe
TW
1109 if(!(tempbx & SetSimuScanMode)) {
1110 if(tempbx & SwitchCRT2) {
1111 if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1112 if(resinfo != SIS_RI_1600x1200) {
1113 tempbx |= SetSimuScanMode;
1114 }
1da177e4 1115 }
544393fe
TW
1116 } else {
1117 if(SiS_BridgeIsEnabled(SiS_Pr)) {
1118 if(!(tempbx & DriverMode)) {
1119 if(SiS_BridgeInSlavemode(SiS_Pr)) {
1da177e4 1120 tempbx |= SetSimuScanMode;
544393fe
TW
1121 }
1122 }
1123 }
1124 }
1125 }
1da177e4 1126
544393fe
TW
1127 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 }
1da177e4 1140
544393fe 1141 }
1da177e4 1142
544393fe 1143 SiS_Pr->SiS_VBInfo = tempbx;
1da177e4 1144
f7854e5d 1145#ifdef CONFIG_FB_SIS_300
544393fe
TW
1146 if(SiS_Pr->ChipType == SIS_630) {
1147 SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1148 }
1149#endif
1150
544393fe
TW
1151#if 0
1152 printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
1da177e4
LT
1153 SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1154#endif
1da177e4
LT
1155}
1156
1157/*********************************************/
1158/* DETERMINE YPbPr MODE */
1159/*********************************************/
1160
1161void
544393fe 1162SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
1da177e4
LT
1163{
1164
544393fe 1165 unsigned char temp;
1da177e4 1166
544393fe
TW
1167 /* 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 */
1da177e4 1174
544393fe
TW
1175 SiS_Pr->SiS_YPbPr = 0;
1176 if(SiS_Pr->ChipType >= SIS_661) return;
1da177e4 1177
544393fe
TW
1178 if(SiS_Pr->SiS_VBType) {
1179 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1180 SiS_Pr->SiS_YPbPr = YPbPrHiVision;
1181 }
1182 }
1da177e4 1183
544393fe
TW
1184 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 }
1da177e4
LT
1197
1198}
1199
1200/*********************************************/
1201/* DETERMINE TVMode flag */
1202/*********************************************/
1203
1204void
544393fe 1205SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 1206{
544393fe
TW
1207 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1208 unsigned short temp, temp1, resinfo = 0, romindex = 0;
1209 unsigned char OutputSelect = *SiS_Pr->pSiS_OutputSelect;
1da177e4 1210
544393fe 1211 SiS_Pr->SiS_TVMode = 0;
1da177e4 1212
544393fe
TW
1213 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
1214 if(SiS_Pr->UseCustomMode) return;
1da177e4 1215
544393fe
TW
1216 if(ModeNo > 0x13) {
1217 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1218 }
1da177e4 1219
544393fe 1220 if(SiS_Pr->ChipType < SIS_661) {
1da177e4 1221
544393fe 1222 if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
1da177e4 1223
544393fe
TW
1224 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 }
1da177e4 1300
544393fe 1301 } else { /* 661 and later */
1da177e4 1302
544393fe
TW
1303 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 }
1da177e4 1353
544393fe 1354 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
1da177e4 1355
544393fe 1356 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1da177e4 1357
544393fe
TW
1358 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 }
1da177e4 1366
544393fe
TW
1367 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1368 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
1369 SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1370 }
1371 }
1da177e4 1372
544393fe
TW
1373 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 }
1da177e4 1382
544393fe
TW
1383 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 }
1da177e4 1394
544393fe 1395 }
1da177e4 1396
544393fe 1397 SiS_Pr->SiS_VBInfo &= ~SetPALTV;
1da177e4
LT
1398}
1399
1400/*********************************************/
1401/* GET LCD INFO */
1402/*********************************************/
1403
544393fe
TW
1404static unsigned short
1405SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
1da177e4 1406{
544393fe 1407 unsigned short temp = SiS_Pr->SiS_LCDResInfo;
1da177e4 1408 /* Translate my LCDResInfo to BIOS value */
544393fe
TW
1409 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 }
1da177e4
LT
1414 return temp;
1415}
1416
1417static void
544393fe 1418SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
1da177e4 1419{
f7854e5d 1420#ifdef CONFIG_FB_SIS_315
544393fe
TW
1421 unsigned char *ROMAddr;
1422 unsigned short temp;
1da177e4 1423
544393fe 1424 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
1da177e4 1425 if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
c30660ea 1426 SiS_Pr->SiS_NeedRomModeData = true;
1da177e4
LT
1427 SiS_Pr->PanelHT = temp;
1428 }
1429 if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
c30660ea 1430 SiS_Pr->SiS_NeedRomModeData = true;
544393fe 1431 SiS_Pr->PanelVT = temp;
1da177e4
LT
1432 }
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 =
544393fe 1439 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
1da177e4
LT
1440 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
1da177e4
LT
1445 }
1446#endif
1447}
1448
1449static void
544393fe
TW
1450SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
1451 const unsigned char *nonscalingmodes)
1452{
1453 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 }
1da177e4
LT
1463}
1464
1465void
544393fe 1466SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 1467{
544393fe 1468 unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
c30660ea 1469 bool panelcanscale = false;
f7854e5d 1470#ifdef CONFIG_FB_SIS_300
544393fe
TW
1471 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1472 static const unsigned char SiS300SeriesLCDRes[] =
1da177e4
LT
1473 { 0, 1, 2, 3, 7, 4, 5, 8,
1474 0, 0, 10, 0, 0, 0, 0, 15 };
1475#endif
f7854e5d 1476#ifdef CONFIG_FB_SIS_315
544393fe 1477 unsigned char *myptr = NULL;
1da177e4 1478#endif
1da177e4
LT
1479
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 */
c30660ea 1487 SiS_Pr->SiS_NeedRomModeData = false;
1da177e4 1488
544393fe 1489 /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
c30660ea 1490 SiS_Pr->Alternate1600x1200 = false;
544393fe 1491
1da177e4
LT
1492 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
1493
544393fe
TW
1494 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1495
1496 if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
1da177e4
LT
1497 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
544393fe 1507 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
1da177e4 1508 SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
544393fe 1509 } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
1da177e4
LT
1510 SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
1511 } else {
1512 SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1513 }
1514 temp &= 0x0f;
f7854e5d 1515#ifdef CONFIG_FB_SIS_300
544393fe 1516 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4
LT
1517 /* 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 */
f7854e5d 1527#ifdef CONFIG_FB_SIS_315
544393fe
TW
1528 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;
1da177e4 1534 }
544393fe 1535#endif
1da177e4 1536
544393fe 1537 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
1da177e4
LT
1538 if(temp == Panel310_1280x768) {
1539 temp = Panel_1280x768_2;
1540 }
1541 if(SiS_Pr->SiS_ROMNew) {
544393fe 1542 if(temp == Panel661_1280x800) {
1da177e4
LT
1543 temp = Panel_1280x800_2;
1544 }
1545 }
1546 }
1547
1548 SiS_Pr->SiS_LCDResInfo = temp;
1549
f7854e5d 1550#ifdef CONFIG_FB_SIS_300
1da177e4
LT
1551 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1552 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
544393fe 1553 SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
1da177e4 1554 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
544393fe
TW
1555 SiS_Pr->SiS_LCDResInfo = Panel_848x480;
1556 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
1557 SiS_Pr->SiS_LCDResInfo = Panel_856x480;
1da177e4
LT
1558 }
1559 }
544393fe 1560#endif
1da177e4
LT
1561
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
544393fe 1574 /* These must/can't scale no matter what */
1da177e4 1575 switch(SiS_Pr->SiS_LCDResInfo) {
544393fe
TW
1576 case Panel_320x240_1:
1577 case Panel_320x240_2:
1578 case Panel_320x240_3:
1da177e4
LT
1579 case Panel_1280x960:
1580 SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
544393fe
TW
1581 break;
1582 case Panel_640x480:
1583 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1da177e4
LT
1584 }
1585
c30660ea 1586 panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
1da177e4
LT
1587
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. */
f7854e5d 1592#ifdef CONFIG_FB_SIS_315
544393fe 1593 if(SiS_Pr->ChipType >= SIS_661) {
1da177e4 1594 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
544393fe 1595 if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1da177e4 1596 }
544393fe
TW
1597 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1598 if(SiS_Pr->SiS_ROMNew) {
1da177e4 1599 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
544393fe
TW
1600 } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
1601 if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1da177e4
LT
1602 }
1603 }
544393fe 1604 } else if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4 1605 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
544393fe 1606 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1da177e4
LT
1607 }
1608 if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
544393fe 1609 SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
1da177e4 1610 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
544393fe
TW
1611 if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
1612 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1da177e4
LT
1613 if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1614 }
1615 } else if(!(SiS_Pr->SiS_ROMNew)) {
544393fe
TW
1616 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
1617 if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
1da177e4
LT
1618 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
1619 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1620 }
544393fe 1621 if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
1da177e4 1622 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
544393fe 1623 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
1da177e4
LT
1624 (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
1625 SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1626 }
544393fe 1627 }
1da177e4
LT
1628 }
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) {
544393fe
TW
1638 /* Always center screen on SiS LVDS (if scaling is disabled) */
1639 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1da177e4 1640 } else {
544393fe
TW
1641 /* 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;
1da177e4
LT
1644 }
1645 }
1646
1647 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1648 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1649
1650 switch(SiS_Pr->SiS_LCDResInfo) {
544393fe
TW
1651 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;
1da177e4
LT
1655 SiS_Pr->PanelVCLKIdx300 = VCLK28;
1656 SiS_Pr->PanelVCLKIdx315 = VCLK28;
1657 break;
1658 case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480;
544393fe 1659 SiS_Pr->PanelVRE = 3;
1da177e4
LT
1660 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;
544393fe 1671 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 800;
1da177e4
LT
1672 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1673 SiS_Pr->PanelVRS = 2 /* 88 */ ; SiS_Pr->PanelVRE = 6;
544393fe 1674 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1da177e4 1675 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
544393fe 1676 break;
1da177e4 1677 case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
544393fe 1678 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
1da177e4
LT
1679 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1680 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
544393fe 1681 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 1682 SiS_Pr->PanelHRS = 23;
544393fe 1683 SiS_Pr->PanelVRE = 5;
1da177e4
LT
1684 }
1685 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1686 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
544393fe 1687 SiS_GetLCDInfoBIOS(SiS_Pr);
1da177e4
LT
1688 break;
1689 case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768;
544393fe
TW
1690 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
1691 SiS_Pr->PanelHRS = 24; SiS_Pr->PanelHRE = 136;
1da177e4 1692 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
544393fe 1693 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 1694 SiS_Pr->PanelHRS = 23;
544393fe 1695 SiS_Pr->PanelVRE = 5;
1da177e4 1696 }
544393fe 1697 SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1da177e4 1698 SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
544393fe 1699 break;
1da177e4 1700 case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864;
544393fe 1701 break;
1da177e4 1702 case Panel_1280x720: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 720;
544393fe 1703 SiS_Pr->PanelHT = 1650; SiS_Pr->PanelVT = 750;
1da177e4
LT
1704 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 */
544393fe 1708 SiS_GetLCDInfoBIOS(SiS_Pr);
1da177e4
LT
1709 break;
1710 case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768;
544393fe 1711 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1da177e4
LT
1712 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 806;
1713 SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
1714 SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
1715 } else {
544393fe 1716 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 802;
a9a3cac6 1717 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1da177e4
LT
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;
544393fe 1724 SiS_Pr->PanelHT = 1660; SiS_Pr->PanelVT = 806;
1da177e4
LT
1725 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1726 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1727 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
544393fe 1728 SiS_GetLCDInfoBIOS(SiS_Pr);
1da177e4
LT
1729 break;
1730 case Panel_1280x800: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
544393fe 1731 SiS_Pr->PanelHT = 1408; SiS_Pr->PanelVT = 816;
1da177e4
LT
1732 SiS_Pr->PanelHRS = 21; SiS_Pr->PanelHRE = 24;
1733 SiS_Pr->PanelVRS = 4; SiS_Pr->PanelVRE = 3;
1734 SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
544393fe 1735 SiS_GetLCDInfoBIOS(SiS_Pr);
1da177e4
LT
1736 break;
1737 case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 800;
544393fe 1738 SiS_Pr->PanelHT = 1552; SiS_Pr->PanelVT = 812;
1da177e4
LT
1739 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;
544393fe
TW
1742 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);
1da177e4
LT
1750 break;
1751 case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960;
544393fe 1752 SiS_Pr->PanelHT = 1800; SiS_Pr->PanelVT = 1000;
1da177e4
LT
1753 SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1754 SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
544393fe 1755 if(resinfo == SIS_RI_1280x1024) {
1da177e4
LT
1756 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;
544393fe 1761 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1da177e4
LT
1762 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;
544393fe 1766 SiS_GetLCDInfoBIOS(SiS_Pr);
1da177e4
LT
1767 break;
1768 case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
544393fe
TW
1769 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1770 SiS_Pr->PanelHRS = 48; SiS_Pr->PanelHRE = 112;
1da177e4
LT
1771 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1772 SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
544393fe 1773 SiS_GetLCDInfoBIOS(SiS_Pr);
1da177e4
LT
1774 break;
1775 case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
544393fe 1776 SiS_Pr->PanelHT = 2160; SiS_Pr->PanelVT = 1250;
1da177e4
LT
1777 SiS_Pr->PanelHRS = 64; SiS_Pr->PanelHRE = 192;
1778 SiS_Pr->PanelVRS = 1; SiS_Pr->PanelVRE = 3;
1779 SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
544393fe
TW
1780 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;
c30660ea 1786 SiS_Pr->Alternate1600x1200 = true;
544393fe
TW
1787 }
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);
1da177e4
LT
1794 break;
1795 case Panel_1680x1050: SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
544393fe 1796 SiS_Pr->PanelHT = 1900; SiS_Pr->PanelVT = 1066;
1da177e4
LT
1797 SiS_Pr->PanelHRS = 26; SiS_Pr->PanelHRE = 76;
1798 SiS_Pr->PanelVRS = 3; SiS_Pr->PanelVRE = 6;
1799 SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
544393fe 1800 SiS_GetLCDInfoBIOS(SiS_Pr);
1da177e4
LT
1801 break;
1802 case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
544393fe
TW
1803 SiS_Pr->PanelHT = 1688; SiS_Pr->PanelVT = 1066;
1804 break;
1da177e4 1805 case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480;
544393fe
TW
1806 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;
1da177e4 1811 case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
544393fe 1812 SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
1da177e4
LT
1813 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];
544393fe 1817 SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
1da177e4
LT
1818 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) {
544393fe
TW
1829 int idx;
1830 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1da177e4 1831 SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
544393fe 1832 if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
1da177e4 1833 else idx = VCLK_CUSTOM_315;
544393fe
TW
1834 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;
1da177e4
LT
1840 }
1841 }
1842 break;
1843 default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768;
544393fe 1844 SiS_Pr->PanelHT = 1344; SiS_Pr->PanelVT = 806;
1da177e4
LT
1845 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) ||
544393fe
TW
1853 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1854 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
1da177e4
LT
1855 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) ||
544393fe
TW
1861 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
1862 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
1da177e4
LT
1863 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 */
544393fe 1880 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1da177e4
LT
1881 break;
1882
1883 case Panel_800x600: {
544393fe 1884 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
1885 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: {
544393fe 1891 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
1892 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: {
544393fe 1900 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
1901 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 */
544393fe 1912 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
1913 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) {
544393fe
TW
1920 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1921 }
1922 break;
1da177e4 1923 }
544393fe 1924 break;
1da177e4
LT
1925 }
1926 case Panel_1280x800: { /* SiS TMDS special (Averatec 6200 series) */
544393fe 1927 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
1928 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);
544393fe 1933 break;
1da177e4
LT
1934 }
1935 case Panel_1280x800_2: { /* SiS LVDS */
544393fe 1936 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
1937 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) {
544393fe
TW
1945 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1946 }
1947 break;
1da177e4 1948 }
544393fe 1949 break;
1da177e4 1950 }
544393fe
TW
1951 case Panel_1280x854: { /* SiS LVDS */
1952 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
1953 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,
544393fe 1955 SIS_RI_1152x768,0xff
1da177e4
LT
1956 };
1957 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
544393fe
TW
1958 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;
1967 }
1968 case Panel_1280x960: {
1969 static const unsigned char nonscalingmodes[] = {
1970 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,
1973 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[] = {
1da177e4
LT
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,
544393fe 1983 SIS_RI_1280x854,SIS_RI_1280x960,0xff
1da177e4
LT
1984 };
1985 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1986 break;
1987 }
1988 case Panel_1400x1050: {
544393fe 1989 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
1990 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,
544393fe
TW
1992 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
1993 SIS_RI_1280x960,0xff
1da177e4
LT
1994 };
1995 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
544393fe 1996 switch(resinfo) {
1da177e4 1997 case SIS_RI_1280x720: if(SiS_Pr->UsePanelScaler == -1) {
544393fe
TW
1998 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1999 }
2000 break;
1da177e4 2001 case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
544393fe 2002 break;
1da177e4
LT
2003 }
2004 break;
2005 }
2006 case Panel_1600x1200: {
544393fe 2007 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
2008 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,
544393fe 2011 SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
1da177e4
LT
2012 };
2013 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
544393fe 2014 break;
1da177e4
LT
2015 }
2016 case Panel_1680x1050: {
544393fe 2017 static const unsigned char nonscalingmodes[] = {
1da177e4
LT
2018 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,
544393fe
TW
2020 SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
2021 SIS_RI_1360x1024,0xff
1da177e4
LT
2022 };
2023 SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2024 break;
2025 }
2026 }
2027 }
2028
f7854e5d 2029#ifdef CONFIG_FB_SIS_300
1da177e4 2030 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
544393fe
TW
2031 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) */
1da177e4
LT
2033 }
2034 }
2035
544393fe 2036 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 2037 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
544393fe 2038 if(SiS_Pr->SiS_UseROM) {
1da177e4 2039 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
544393fe
TW
2040 if(!(ROMAddr[0x235] & 0x02)) {
2041 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2042 }
1da177e4 2043 }
544393fe
TW
2044 }
2045 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4 2046 if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
544393fe 2047 SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
1da177e4
LT
2048 }
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:
544393fe 2065 SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
1da177e4
LT
2066 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
544393fe 2082 if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
1da177e4
LT
2083 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 */
544393fe 2092 if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
1da177e4
LT
2093
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) {
544393fe 2098 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
1da177e4
LT
2099 }
2100 } else if(ModeNo > 0x13) {
2101 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
544393fe
TW
2102 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2103 if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
2104 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
1da177e4
LT
2105 }
2106 }
2107 }
2108 }
2109 }
2110 }
2111
2112 if(modeflag & HalfDCLK) {
544393fe 2113 if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
1da177e4 2114 SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
544393fe 2115 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1da177e4
LT
2116 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) {
544393fe
TW
2120 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 }
1da177e4
LT
2125 }
2126 }
2127
2128 }
2129
2130 /* VESA timing */
2131 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2132 if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
544393fe 2133 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
1da177e4
LT
2134 }
2135 } else {
2136 SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2137 }
2138
544393fe 2139#if 0
1da177e4
LT
2140 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
1da177e4
LT
2143}
2144
2145/*********************************************/
2146/* GET VCLK */
2147/*********************************************/
2148
544393fe
TW
2149unsigned short
2150SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2151 unsigned short RefreshRateTableIndex)
1da177e4 2152{
544393fe 2153 unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
32ad6195 2154 unsigned short resinfo, tempbx;
544393fe 2155 const unsigned char *CHTVVCLKPtr = NULL;
1da177e4
LT
2156
2157 if(ModeNo <= 0x13) {
1da177e4
LT
2158 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
2159 CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2160 VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
544393fe 2161 VCLKIndexGENCRT = VCLKIndexGEN;
1da177e4 2162 } else {
1da177e4
LT
2163 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2164 CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2165 VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
544393fe
TW
2166 VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
2167 (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
1da177e4
LT
2168 }
2169
2170 if(SiS_Pr->SiS_VBType & VB_SISVB) { /* 30x/B/LV */
2171
2172 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2173
544393fe
TW
2174 CRT2Index >>= 6;
2175 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
1da177e4 2176
544393fe 2177 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4
LT
2178 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2179 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
544393fe 2180 VCLKIndex = VCLKIndexGEN;
1da177e4
LT
2181 }
2182 } else {
2183 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2184 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2185 switch(resinfo) {
544393fe 2186 /* Correct those whose IndexGEN doesn't match VBVCLK array */
1da177e4
LT
2187 case SIS_RI_720x480: VCLKIndex = VCLK_720x480; break;
2188 case SIS_RI_720x576: VCLKIndex = VCLK_720x576; break;
2189 case SIS_RI_768x576: VCLKIndex = VCLK_768x576; break;
2190 case SIS_RI_848x480: VCLKIndex = VCLK_848x480; break;
2191 case SIS_RI_856x480: VCLKIndex = VCLK_856x480; break;
2192 case SIS_RI_800x480: VCLKIndex = VCLK_800x480; break;
2193 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
2194 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
544393fe 2195 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
1da177e4
LT
2196 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
2197 default: VCLKIndex = VCLKIndexGEN;
2198 }
2199
2200 if(ModeNo <= 0x13) {
544393fe 2201 if(SiS_Pr->ChipType <= SIS_315PRO) {
1da177e4 2202 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
544393fe 2203 } else {
1da177e4
LT
2204 if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
2205 }
2206 }
544393fe 2207 if(SiS_Pr->ChipType <= SIS_315PRO) {
1da177e4
LT
2208 if(VCLKIndex == 0) VCLKIndex = 0x41;
2209 if(VCLKIndex == 1) VCLKIndex = 0x43;
2210 if(VCLKIndex == 4) VCLKIndex = 0x44;
2211 }
2212 }
2213 }
2214
544393fe 2215 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
1da177e4
LT
2216
2217 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
544393fe
TW
2218 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
2219 else VCLKIndex = HiTVVCLK;
2220 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) VCLKIndex = HiTVSimuVCLK;
2221 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK;
2222 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) VCLKIndex = TVVCLKDIV2;
2223 else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
2224 else VCLKIndex = TVVCLK;
2225
2226 if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
2227 else VCLKIndex += TVCLKBASE_315;
2228
2229 } else { /* VGA2 */
2230
2231 VCLKIndex = VCLKIndexGENCRT;
2232 if(SiS_Pr->ChipType < SIS_315H) {
2233 if(ModeNo > 0x13) {
2234 if( (SiS_Pr->ChipType == SIS_630) &&
2235 (SiS_Pr->ChipRevision >= 0x30)) {
1da177e4
LT
2236 if(VCLKIndex == 0x14) VCLKIndex = 0x34;
2237 }
2238 /* Better VGA2 clock for 1280x1024@75 */
2239 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
2240 }
544393fe
TW
2241 }
2242 }
1da177e4
LT
2243
2244 } else { /* If not programming CRT2 */
2245
544393fe
TW
2246 VCLKIndex = VCLKIndexGENCRT;
2247 if(SiS_Pr->ChipType < SIS_315H) {
2248 if(ModeNo > 0x13) {
2249 if( (SiS_Pr->ChipType != SIS_630) &&
2250 (SiS_Pr->ChipType != SIS_300) ) {
1da177e4
LT
2251 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2252 }
2253 }
544393fe 2254 }
1da177e4
LT
2255 }
2256
2257 } else { /* LVDS */
2258
2259 VCLKIndex = CRT2Index;
2260
2261 if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2262
544393fe 2263 if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
1da177e4
LT
2264
2265 VCLKIndex &= 0x1f;
544393fe 2266 tempbx = 0;
1da177e4 2267 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
544393fe 2268 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1da177e4
LT
2269 tempbx += 2;
2270 if(SiS_Pr->SiS_ModeType > ModeVGA) {
2271 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
2272 }
2273 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2274 tempbx = 4;
2275 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2276 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2277 tempbx = 6;
2278 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2279 }
2280 }
544393fe
TW
2281 switch(tempbx) {
2282 case 0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC; break;
2283 case 1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC; break;
2284 case 2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL; break;
2285 case 3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
1da177e4 2286 case 4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM; break;
544393fe
TW
2287 case 5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM; break;
2288 case 6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN; break;
2289 case 7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN; break;
1da177e4
LT
2290 case 8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL; break;
2291 default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL; break;
544393fe
TW
2292 }
2293 VCLKIndex = CHTVVCLKPtr[VCLKIndex];
1da177e4 2294
544393fe 2295 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
1da177e4 2296
544393fe 2297 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4
LT
2298 VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2299 } else {
2300 VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2301 }
2302
f7854e5d 2303#ifdef CONFIG_FB_SIS_300
1da177e4
LT
2304 /* Special Timing: Barco iQ Pro R series */
2305 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2306
544393fe
TW
2307 /* Special Timing: 848x480 and 856x480 parallel lvds panels */
2308 if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
2309 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 2310 VCLKIndex = VCLK34_300;
544393fe 2311 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
1da177e4
LT
2312 } else {
2313 VCLKIndex = VCLK34_315;
2314 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2315 }
2316 }
544393fe 2317#endif
1da177e4 2318
544393fe 2319 } else {
1da177e4 2320
544393fe
TW
2321 VCLKIndex = VCLKIndexGENCRT;
2322 if(SiS_Pr->ChipType < SIS_315H) {
2323 if(ModeNo > 0x13) {
2324 if( (SiS_Pr->ChipType == SIS_630) &&
2325 (SiS_Pr->ChipRevision >= 0x30) ) {
1da177e4 2326 if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
544393fe
TW
2327 }
2328 }
1da177e4 2329 }
544393fe 2330 }
1da177e4
LT
2331
2332 } else { /* if not programming CRT2 */
2333
544393fe
TW
2334 VCLKIndex = VCLKIndexGENCRT;
2335 if(SiS_Pr->ChipType < SIS_315H) {
2336 if(ModeNo > 0x13) {
2337 if( (SiS_Pr->ChipType != SIS_630) &&
2338 (SiS_Pr->ChipType != SIS_300) ) {
1da177e4
LT
2339 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2340 }
2341#if 0
544393fe 2342 if(SiS_Pr->ChipType == SIS_730) {
1da177e4
LT
2343 if(VCLKIndex == 0x0b) VCLKIndex = 0x40; /* 1024x768-70 */
2344 if(VCLKIndex == 0x0d) VCLKIndex = 0x41; /* 1024x768-75 */
2345 }
2346#endif
2347 }
2348 }
2349
2350 }
2351
2352 }
2353
544393fe 2354 return VCLKIndex;
1da177e4
LT
2355}
2356
2357/*********************************************/
2358/* SET CRT2 MODE TYPE REGISTERS */
2359/*********************************************/
2360
2361static void
544393fe 2362SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 2363{
544393fe
TW
2364 unsigned short i, j, modeflag, tempah=0;
2365 short tempcl;
f7854e5d 2366#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
544393fe 2367 unsigned short tempbl;
1da177e4 2368#endif
f7854e5d 2369#ifdef CONFIG_FB_SIS_315
544393fe
TW
2370 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
2371 unsigned short tempah2, tempbl2;
1da177e4
LT
2372#endif
2373
544393fe 2374 modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4
LT
2375
2376 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2377
2378 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
2379 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
2380
2381 } else {
2382
2383 for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
544393fe 2384 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4
LT
2385 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
2386 }
2387
2388 tempcl = SiS_Pr->SiS_ModeType;
2389
544393fe 2390 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 2391
f7854e5d 2392#ifdef CONFIG_FB_SIS_300 /* ---- 300 series ---- */
1da177e4 2393
544393fe
TW
2394 /* For 301BDH: (with LCD via LVDS) */
2395 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
1da177e4
LT
2396 tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
2397 tempbl &= 0xef;
2398 tempbl |= 0x02;
2399 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2400 tempbl |= 0x10;
2401 tempbl &= 0xfd;
2402 }
2403 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
544393fe 2404 }
1da177e4 2405
544393fe
TW
2406 if(ModeNo > 0x13) {
2407 tempcl -= ModeVGA;
2408 if(tempcl >= 0) {
2409 tempah = ((0x10 >> tempcl) | 0x80);
2410 }
2411 } else tempah = 0x80;
1da177e4 2412
544393fe 2413 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
1da177e4 2414
f7854e5d 2415#endif /* CONFIG_FB_SIS_300 */
1da177e4
LT
2416
2417 } else {
2418
f7854e5d 2419#ifdef CONFIG_FB_SIS_315 /* ------- 315/330 series ------ */
1da177e4 2420
544393fe
TW
2421 if(ModeNo > 0x13) {
2422 tempcl -= ModeVGA;
2423 if(tempcl >= 0) {
2424 tempah = (0x08 >> tempcl);
2425 if (tempah == 0) tempah = 1;
2426 tempah |= 0x40;
2427 }
2428 } else tempah = 0x40;
1da177e4 2429
544393fe 2430 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
1da177e4 2431
f7854e5d 2432#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
2433
2434 }
2435
2436 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2437
544393fe
TW
2438 if(SiS_Pr->ChipType < SIS_315H) {
2439 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
1da177e4 2440 } else {
f7854e5d 2441#ifdef CONFIG_FB_SIS_315
544393fe
TW
2442 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2443 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2444 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2445 if(IS_SIS740) {
1da177e4
LT
2446 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2447 } else {
544393fe 2448 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
1da177e4 2449 }
544393fe
TW
2450 }
2451#endif
1da177e4
LT
2452 }
2453
2454 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2455
544393fe
TW
2456 tempah = 0x01;
2457 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2458 tempah |= 0x02;
2459 }
2460 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2461 tempah ^= 0x05;
2462 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
2463 tempah ^= 0x01;
2464 }
2465 }
1da177e4 2466
544393fe 2467 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 2468
544393fe 2469 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
1da177e4 2470
544393fe
TW
2471 tempah = (tempah << 5) & 0xFF;
2472 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2473 tempah = (tempah >> 5) & 0xFF;
1da177e4 2474
544393fe 2475 } else {
1da177e4 2476
544393fe
TW
2477 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x08;
2478 else if(!(SiS_IsDualEdge(SiS_Pr))) tempah |= 0x08;
2479 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
2480 tempah &= ~0x08;
1da177e4 2481
544393fe 2482 }
1da177e4 2483
544393fe
TW
2484 if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
2485 tempah |= 0x10;
2486 }
1da177e4
LT
2487
2488 tempah |= 0x80;
544393fe 2489 if(SiS_Pr->SiS_VBType & VB_SIS301) {
1da177e4 2490 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
544393fe 2491 }
1da177e4 2492
544393fe 2493 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
1da177e4 2494 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
544393fe
TW
2495 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2496 tempah |= 0x20;
1da177e4 2497 }
544393fe
TW
2498 }
2499 }
1da177e4 2500
544393fe 2501 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
1da177e4
LT
2502
2503 tempah = 0x80;
2504 if(SiS_Pr->SiS_VBType & VB_SIS301) {
2505 if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
2506 }
2507
544393fe 2508 if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
1da177e4 2509
544393fe 2510 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
1da177e4 2511 if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
544393fe
TW
2512 tempah |= 0x40;
2513 }
2514 }
1da177e4 2515
544393fe 2516 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
1da177e4
LT
2517
2518 } else { /* LVDS */
2519
544393fe 2520 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4 2521
f7854e5d 2522#ifdef CONFIG_FB_SIS_315
1da177e4
LT
2523 /* LVDS can only be slave in 8bpp modes */
2524 tempah = 0x80;
2525 if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
2526 if(SiS_Pr->SiS_VBInfo & DriverMode) {
2527 tempah |= 0x02;
2528 }
2529 }
2530
544393fe 2531 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) tempah |= 0x02;
1da177e4 2532
544393fe 2533 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah ^= 0x01;
1da177e4 2534
544393fe 2535 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
1da177e4 2536
544393fe 2537 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
1da177e4
LT
2538#endif
2539
544393fe 2540 } else {
1da177e4 2541
f7854e5d 2542#ifdef CONFIG_FB_SIS_300
1da177e4
LT
2543 tempah = 0;
2544 if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
544393fe
TW
2545 tempah |= 0x02;
2546 }
1da177e4
LT
2547 tempah <<= 5;
2548
544393fe 2549 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
1da177e4
LT
2550
2551 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2552#endif
2553
544393fe 2554 }
1da177e4
LT
2555
2556 }
2557
2558 } /* LCDA */
2559
2560 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2561
544393fe 2562 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4 2563
f7854e5d 2564#ifdef CONFIG_FB_SIS_315
544393fe 2565 /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
1da177e4
LT
2566
2567 /* The following is nearly unpreditable and varies from machine
2568 * to machine. Especially the 301DH seems to be a real trouble
2569 * maker. Some BIOSes simply set the registers (like in the
2570 * NoLCD-if-statements here), some set them according to the
2571 * LCDA stuff. It is very likely that some machines are not
2572 * treated correctly in the following, very case-orientated
2573 * code. What do I do then...?
2574 */
2575
2576 /* 740 variants match for 30xB, 301B-DH, 30xLV */
2577
544393fe
TW
2578 if(!(IS_SIS740)) {
2579 tempah = 0x04; /* For all bridges */
2580 tempbl = 0xfb;
2581 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2582 tempah = 0x00;
2583 if(SiS_IsDualEdge(SiS_Pr)) {
1da177e4
LT
2584 tempbl = 0xff;
2585 }
544393fe
TW
2586 }
2587 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
1da177e4
LT
2588 }
2589
2590 /* The following two are responsible for eventually wrong colors
2591 * in TV output. The DH (VB_NoLCD) conditions are unknown; the
2592 * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
2593 * in a 650 box (Jake). What is the criteria?
544393fe
TW
2594 * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
2595 * treatment like the 651+301B-DH(b0) case. Seems more to be the
2596 * chipset than the bridge revision.
1da177e4
LT
2597 */
2598
544393fe 2599 if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
1da177e4
LT
2600 tempah = 0x30;
2601 tempbl = 0xc0;
2602 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2603 ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
2604 tempah = 0x00;
2605 tempbl = 0x00;
2606 }
2607 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
2608 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
2609 } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
2610 /* Fixes "TV-blue-bug" on 315+301 */
544393fe 2611 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf); /* For 301 */
1da177e4 2612 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
544393fe
TW
2613 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
2614 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30); /* For 30xLV */
1da177e4 2615 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
544393fe
TW
2616 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* For 301B-DH */
2617 tempah = 0x30; tempah2 = 0xc0;
2618 tempbl = 0xcf; tempbl2 = 0x3f;
2619 if(SiS_Pr->SiS_TVBlue == 0) {
2620 tempah = tempah2 = 0x00;
2621 } else if(SiS_Pr->SiS_TVBlue == -1) {
2622 /* Set on 651/M650, clear on 315/650 */
2623 if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
2624 tempah = tempah2 = 0x00;
2625 }
2626 }
2627 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2628 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
1da177e4 2629 } else {
544393fe 2630 tempah = 0x30; tempah2 = 0xc0; /* For 30xB, 301C */
1da177e4
LT
2631 tempbl = 0xcf; tempbl2 = 0x3f;
2632 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2633 tempah = tempah2 = 0x00;
544393fe 2634 if(SiS_IsDualEdge(SiS_Pr)) {
1da177e4
LT
2635 tempbl = tempbl2 = 0xff;
2636 }
2637 }
2638 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2639 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2640 }
2641
2642 if(IS_SIS740) {
2643 tempah = 0x80;
2644 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
2645 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
2646 } else {
2647 tempah = 0x00;
544393fe
TW
2648 tempbl = 0x7f;
2649 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2650 tempbl = 0xff;
2651 if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
2652 }
2653 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
1da177e4
LT
2654 }
2655
f7854e5d 2656#endif /* CONFIG_FB_SIS_315 */
1da177e4 2657
544393fe 2658 } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4 2659
f7854e5d 2660#ifdef CONFIG_FB_SIS_300
544393fe 2661 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
1da177e4 2662
544393fe
TW
2663 if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2664 ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
1da177e4
LT
2665 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
2666 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
2667 } else {
2668 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
2669 }
2670#endif
2671
2672 }
2673
544393fe
TW
2674 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
2675 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
2676 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
1da177e4
LT
2677 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
2678 }
2679 }
2680
2681 } else { /* LVDS */
2682
f7854e5d 2683#ifdef CONFIG_FB_SIS_315
544393fe 2684 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4 2685
544393fe 2686 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1da177e4 2687
544393fe 2688 tempah = 0x04;
1da177e4 2689 tempbl = 0xfb;
544393fe
TW
2690 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2691 tempah = 0x00;
2692 if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
2693 }
1da177e4
LT
2694 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2695
2696 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2697 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2698 }
2699
2700 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2701
544393fe 2702 } else if(SiS_Pr->ChipType == SIS_550) {
1da177e4
LT
2703
2704 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2705 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2706
2707 }
2708
2709 }
2710#endif
2711
2712 }
2713
2714}
2715
2716/*********************************************/
2717/* GET RESOLUTION DATA */
2718/*********************************************/
2719
544393fe
TW
2720unsigned short
2721SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 2722{
544393fe
TW
2723 if(ModeNo <= 0x13)
2724 return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
2725 else
2726 return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
1da177e4
LT
2727}
2728
2729static void
544393fe 2730SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 2731{
544393fe 2732 unsigned short xres, yres, modeflag=0, resindex;
1da177e4 2733
544393fe
TW
2734 if(SiS_Pr->UseCustomMode) {
2735 xres = SiS_Pr->CHDisplay;
2736 if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
2737 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2738 /* DoubleScanMode-check done in CheckCalcCustomMode()! */
2739 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
2740 return;
2741 }
1da177e4 2742
544393fe 2743 resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
1da177e4 2744
544393fe
TW
2745 if(ModeNo <= 0x13) {
2746 xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
2747 yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
2748 } else {
2749 xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
2750 yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
2751 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2752 }
1da177e4 2753
544393fe 2754 if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
1da177e4 2755
544393fe
TW
2756 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
2757 if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
2758 if(yres == 350) yres = 400;
2759 }
2760 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
2761 if(ModeNo == 0x12) yres = 400;
2762 }
2763 }
1da177e4 2764
544393fe
TW
2765 if(modeflag & HalfDCLK) xres <<= 1;
2766 if(modeflag & DoubleScanMode) yres <<= 1;
1da177e4 2767
544393fe 2768 }
1da177e4 2769
544393fe 2770 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
1da177e4 2771
544393fe
TW
2772 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2773 switch(SiS_Pr->SiS_LCDResInfo) {
1da177e4
LT
2774 case Panel_1024x768:
2775 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
544393fe
TW
2776 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2777 if(yres == 350) yres = 357;
2778 if(yres == 400) yres = 420;
2779 if(yres == 480) yres = 525;
2780 }
2781 }
1da177e4
LT
2782 break;
2783 case Panel_1280x1024:
2784 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2785 /* BIOS bug - does this regardless of scaling */
544393fe
TW
2786 if(yres == 400) yres = 405;
2787 }
2788 if(yres == 350) yres = 360;
2789 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
2790 if(yres == 360) yres = 375;
1da177e4 2791 }
1da177e4
LT
2792 break;
2793 case Panel_1600x1200:
2794 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
544393fe
TW
2795 if(yres == 1024) yres = 1056;
2796 }
1da177e4 2797 break;
544393fe
TW
2798 }
2799 }
1da177e4 2800
544393fe 2801 } else {
1da177e4 2802
544393fe
TW
2803 if(SiS_Pr->SiS_VBType & VB_SISVB) {
2804 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
2805 if(xres == 720) xres = 640;
2806 }
2807 } else if(xres == 720) xres = 640;
1da177e4 2808
544393fe
TW
2809 if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
2810 yres = 400;
2811 if(SiS_Pr->ChipType >= SIS_315H) {
2812 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
2813 } else {
2814 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
2815 }
2816 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
2817 }
1da177e4 2818
544393fe
TW
2819 }
2820 SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2821 SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
1da177e4
LT
2822}
2823
2824/*********************************************/
2825/* GET CRT2 TIMING DATA */
2826/*********************************************/
2827
1da177e4 2828static void
544393fe
TW
2829SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
2830 unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
2831 unsigned short *ResIndex)
1da177e4 2832{
544393fe 2833 unsigned short tempbx=0, tempal=0, resinfo=0;
1da177e4
LT
2834
2835 if(ModeNo <= 0x13) {
2836 tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2837 } else {
2838 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2839 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2840 }
2841
2842 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
2843
2844 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
2845
544393fe 2846 tempbx = SiS_Pr->SiS_LCDResInfo;
1da177e4
LT
2847 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
2848
544393fe 2849 /* patch index */
1da177e4
LT
2850 if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
2851 if (resinfo == SIS_RI_1280x800) tempal = 9;
2852 else if(resinfo == SIS_RI_1400x1050) tempal = 11;
2853 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
544393fe
TW
2854 (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
2855 (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
1da177e4
LT
2856 if (resinfo == SIS_RI_1280x768) tempal = 9;
2857 }
2858
544393fe 2859 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1da177e4
LT
2860 /* Pass 1:1 only (center-screen handled outside) */
2861 /* This is never called for the panel's native resolution */
2862 /* since Pass1:1 will not be set in this case */
2863 tempbx = 100;
2864 if(ModeNo >= 0x13) {
2865 tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
2866 }
2867 }
2868
f7854e5d 2869#ifdef CONFIG_FB_SIS_315
1da177e4
LT
2870 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
2871 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
2872 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
544393fe
TW
2873 tempbx = 200;
2874 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
1da177e4
LT
2875 }
2876 }
2877 }
2878#endif
2879
2880 } else { /* TV */
2881
544393fe
TW
2882 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2883 /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
2884 tempbx = 2;
2885 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1da177e4 2886 tempbx = 13;
544393fe
TW
2887 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
2888 }
1da177e4 2889 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
544393fe
TW
2890 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempbx = 7;
2891 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
2892 else tempbx = 5;
2893 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2894 } else {
2895 if(SiS_Pr->SiS_TVMode & TVSetPAL) tempbx = 3;
2896 else tempbx = 4;
2897 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) tempbx += 5;
2898 }
1da177e4
LT
2899
2900 }
2901
2902 tempal &= 0x3F;
2903
2904 if(ModeNo > 0x13) {
2905 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
544393fe
TW
2906 switch(resinfo) {
2907 case SIS_RI_720x480:
1da177e4 2908 tempal = 6;
544393fe
TW
2909 if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) tempal = 9;
2910 break;
2911 case SIS_RI_720x576:
2912 case SIS_RI_768x576:
2913 case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
2914 tempal = 6;
2915 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2916 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 8;
1da177e4 2917 }
544393fe
TW
2918 break;
2919 case SIS_RI_800x480:
2920 tempal = 4;
2921 break;
2922 case SIS_RI_512x384:
2923 case SIS_RI_1024x768:
2924 tempal = 7;
2925 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2926 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempal = 8;
1da177e4 2927 }
544393fe
TW
2928 break;
2929 case SIS_RI_1280x720:
2930 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
2931 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempal = 9;
1da177e4 2932 }
544393fe 2933 break;
1da177e4
LT
2934 }
2935 }
2936 }
2937
2938 *CRT2Index = tempbx;
2939 *ResIndex = tempal;
2940
2941 } else { /* LVDS, 301B-DH (if running on LCD) */
2942
2943 tempbx = 0;
2944 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
2945
544393fe
TW
2946 tempbx = 90;
2947 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2948 tempbx = 92;
1da177e4
LT
2949 if(SiS_Pr->SiS_ModeType > ModeVGA) {
2950 if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
2951 }
544393fe
TW
2952 if(SiS_Pr->SiS_TVMode & TVSetPALM) tempbx = 94;
2953 else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
2954 }
2955 if(tempbx != 99) {
2956 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
2957 }
1da177e4
LT
2958
2959 } else {
2960
544393fe
TW
2961 switch(SiS_Pr->SiS_LCDResInfo) {
2962 case Panel_640x480: tempbx = 12; break;
2963 case Panel_320x240_1: tempbx = 10; break;
2964 case Panel_320x240_2:
2965 case Panel_320x240_3: tempbx = 14; break;
2966 case Panel_800x600: tempbx = 16; break;
2967 case Panel_1024x600: tempbx = 18; break;
2968 case Panel_1152x768:
2969 case Panel_1024x768: tempbx = 20; break;
2970 case Panel_1280x768: tempbx = 22; break;
2971 case Panel_1280x1024: tempbx = 24; break;
2972 case Panel_1400x1050: tempbx = 26; break;
2973 case Panel_1600x1200: tempbx = 28; break;
f7854e5d 2974#ifdef CONFIG_FB_SIS_300
1da177e4 2975 case Panel_Barco1366: tempbx = 80; break;
544393fe 2976#endif
1da177e4
LT
2977 }
2978
2979 switch(SiS_Pr->SiS_LCDResInfo) {
544393fe
TW
2980 case Panel_320x240_1:
2981 case Panel_320x240_2:
2982 case Panel_320x240_3:
1da177e4 2983 case Panel_640x480:
1da177e4
LT
2984 break;
2985 default:
2986 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
2987 }
2988
544393fe 2989 if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
1da177e4 2990
f7854e5d 2991#ifdef CONFIG_FB_SIS_300
1da177e4
LT
2992 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
2993 tempbx = 82;
2994 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
544393fe 2995 } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
1da177e4
LT
2996 tempbx = 84;
2997 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
2998 }
544393fe 2999#endif
1da177e4
LT
3000
3001 }
3002
3003 (*CRT2Index) = tempbx;
3004 (*ResIndex) = tempal & 0x1F;
3005 }
3006}
3007
3008static void
544393fe
TW
3009SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3010 unsigned short RefreshRateTableIndex)
1da177e4 3011{
544393fe
TW
3012 unsigned short tempax=0, tempbx=0, index, dotclock;
3013 unsigned short temp1=0, modeflag=0, tempcx=0;
1da177e4
LT
3014
3015 SiS_Pr->SiS_RVBHCMAX = 1;
3016 SiS_Pr->SiS_RVBHCFACT = 1;
3017
3018 if(ModeNo <= 0x13) {
3019
3020 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3021 index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
3022
3023 tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
3024 tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
3025 temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
3026
544393fe
TW
3027 dotclock = (modeflag & Charx8Dot) ? 8 : 9;
3028
1da177e4
LT
3029 } else {
3030
3031 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
544393fe 3032 index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
1da177e4
LT
3033
3034 tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
3035 tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
3036 tempax &= 0x03FF;
3037 tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
3038 tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
3039 tempcx &= 0x0100;
3040 tempcx <<= 2;
3041 tempbx |= tempcx;
3042 temp1 = SiS_Pr->SiS_CRT1Table[index].CR[7];
3043
544393fe
TW
3044 dotclock = 8;
3045
1da177e4
LT
3046 }
3047
3048 if(temp1 & 0x01) tempbx |= 0x0100;
3049 if(temp1 & 0x20) tempbx |= 0x0200;
3050
3051 tempax += 5;
544393fe
TW
3052 tempax *= dotclock;
3053 if(modeflag & HalfDCLK) tempax <<= 1;
1da177e4
LT
3054
3055 tempbx++;
3056
3057 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3058 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
3059}
3060
3061static void
544393fe
TW
3062SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3063 unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
3064{
3065 unsigned short ResIndex;
3066
3067 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3068 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3069 if(SiS_Pr->UseCustomMode) {
3070 ResIndex = SiS_Pr->CHTotal;
3071 if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
3072 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
3073 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3074 } else {
3075 if(ModeNo < 0x13) {
3076 ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3077 } else {
3078 ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3079 }
3080 if(ResIndex == 0x09) {
3081 if(SiS_Pr->Alternate1600x1200) ResIndex = 0x20; /* 1600x1200 LCDA */
3082 else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
3083 }
3084 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
3085 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
3086 SiS_Pr->SiS_HT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
3087 SiS_Pr->SiS_VT = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
3088 }
3089 } else {
3090 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3091 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3092 }
3093 } else {
3094 /* This handles custom modes and custom panels */
3095 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3096 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3097 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3098 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3099 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
3100 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
3101 }
3102}
3103
3104static void
3105SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3106 unsigned short RefreshRateTableIndex)
1da177e4 3107{
544393fe
TW
3108 unsigned short CRT2Index, ResIndex, backup;
3109 const struct SiS_LVDSData *LVDSData = NULL;
1da177e4 3110
544393fe 3111 SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4
LT
3112
3113 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3114 SiS_Pr->SiS_RVBHCMAX = 1;
3115 SiS_Pr->SiS_RVBHCFACT = 1;
3116 SiS_Pr->SiS_NewFlickerMode = 0;
3117 SiS_Pr->SiS_RVBHRS = 50;
3118 SiS_Pr->SiS_RY1COE = 0;
3119 SiS_Pr->SiS_RY2COE = 0;
3120 SiS_Pr->SiS_RY3COE = 0;
3121 SiS_Pr->SiS_RY4COE = 0;
544393fe 3122 SiS_Pr->SiS_RVBHRS2 = 0;
1da177e4
LT
3123 }
3124
3125 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3126
f7854e5d 3127#ifdef CONFIG_FB_SIS_315
544393fe
TW
3128 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3129 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4
LT
3130#endif
3131
3132 } else {
3133
3134 /* 301BDH needs LVDS Data */
544393fe 3135 backup = SiS_Pr->SiS_IF_DEF_LVDS;
1da177e4
LT
3136 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3137 SiS_Pr->SiS_IF_DEF_LVDS = 1;
3138 }
3139
3140 SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
544393fe 3141 &CRT2Index, &ResIndex);
1da177e4 3142
544393fe 3143 SiS_Pr->SiS_IF_DEF_LVDS = backup;
1da177e4 3144
544393fe
TW
3145 switch(CRT2Index) {
3146 case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1; break;
3147 case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2; break;
3148 case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1; break;
3149 case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1; break;
3150 case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1; break;
3151 case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
f7854e5d 3152#ifdef CONFIG_FB_SIS_300
1da177e4
LT
3153 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break;
3154 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break;
3155 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break;
1da177e4
LT
3156 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1; break;
3157 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2; break;
544393fe
TW
3158#endif
3159 case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData; break;
3160 case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData; break;
3161 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData; break;
3162 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData; break;
3163 case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
3164 case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
3165 case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
3166 case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
3167 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break;
1da177e4
LT
3168 }
3169
544393fe
TW
3170 if(LVDSData) {
3171 SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
3172 SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
3173 SiS_Pr->SiS_HT = (LVDSData+ResIndex)->LCDHT;
3174 SiS_Pr->SiS_VT = (LVDSData+ResIndex)->LCDVT;
3175 } else {
3176 SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3177 }
3178
3179 if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
3180 (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
3181 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
3182 if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
3183 (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
3184 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3185 SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
f7854e5d 3186#ifdef CONFIG_FB_SIS_300
544393fe
TW
3187 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3188 if(ResIndex < 0x08) {
3189 SiS_Pr->SiS_HDE = 1280;
3190 SiS_Pr->SiS_VDE = 1024;
3191 }
3192 }
3193#endif
1da177e4
LT
3194 }
3195 }
3196 }
3197}
3198
3199static void
544393fe
TW
3200SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3201 unsigned short RefreshRateTableIndex)
3202{
3203 unsigned char *ROMAddr = NULL;
3204 unsigned short tempax, tempbx, modeflag, romptr=0;
3205 unsigned short resinfo, CRT2Index, ResIndex;
3206 const struct SiS_LCDData *LCDPtr = NULL;
3207 const struct SiS_TVData *TVPtr = NULL;
f7854e5d 3208#ifdef CONFIG_FB_SIS_315
544393fe 3209 short resinfo661;
1da177e4
LT
3210#endif
3211
3212 if(ModeNo <= 0x13) {
3213 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3214 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
3215 } else if(SiS_Pr->UseCustomMode) {
3216 modeflag = SiS_Pr->CModeFlag;
3217 resinfo = 0;
3218 } else {
3219 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3220 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
f7854e5d 3221#ifdef CONFIG_FB_SIS_315
1da177e4
LT
3222 resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3223 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
544393fe
TW
3224 (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
3225 (resinfo661 >= 0) &&
1da177e4 3226 (SiS_Pr->SiS_NeedRomModeData) ) {
544393fe 3227 if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
1da177e4 3228 if((romptr = (SISGETROMW(21)))) {
544393fe
TW
3229 romptr += (resinfo661 * 10);
3230 ROMAddr = SiS_Pr->VirtualRomBase;
1da177e4
LT
3231 }
3232 }
3233 }
3234#endif
3235 }
544393fe 3236
1da177e4
LT
3237 SiS_Pr->SiS_NewFlickerMode = 0;
3238 SiS_Pr->SiS_RVBHRS = 50;
3239 SiS_Pr->SiS_RY1COE = 0;
3240 SiS_Pr->SiS_RY2COE = 0;
3241 SiS_Pr->SiS_RY3COE = 0;
3242 SiS_Pr->SiS_RY4COE = 0;
544393fe 3243 SiS_Pr->SiS_RVBHRS2 = 0;
1da177e4 3244
544393fe 3245 SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
1da177e4 3246
544393fe 3247 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
1da177e4
LT
3248
3249 if(SiS_Pr->UseCustomMode) {
3250
544393fe
TW
3251 SiS_Pr->SiS_RVBHCMAX = 1;
3252 SiS_Pr->SiS_RVBHCFACT = 1;
1da177e4 3253 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
544393fe
TW
3254 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3255
3256 tempax = SiS_Pr->CHTotal;
3257 if(modeflag & HalfDCLK) tempax <<= 1;
3258 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3259 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
1da177e4
LT
3260
3261 } else {
3262
544393fe 3263 SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
3264
3265 }
3266
3267 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3268
3269 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
544393fe 3270 &CRT2Index,&ResIndex);
1da177e4
LT
3271
3272 switch(CRT2Index) {
544393fe
TW
3273 case 2: TVPtr = SiS_Pr->SiS_ExtHiTVData; break;
3274 case 3: TVPtr = SiS_Pr->SiS_ExtPALData; break;
3275 case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
3276 case 5: TVPtr = SiS_Pr->SiS_Ext525iData; break;
3277 case 6: TVPtr = SiS_Pr->SiS_Ext525pData; break;
3278 case 7: TVPtr = SiS_Pr->SiS_Ext750pData; break;
3279 case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
3280 case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
3281 case 10: TVPtr = SiS_Pr->SiS_St525iData; break;
3282 case 11: TVPtr = SiS_Pr->SiS_St525pData; break;
3283 case 12: TVPtr = SiS_Pr->SiS_St750pData; break;
3284 case 13: TVPtr = SiS_Pr->SiS_St1HiTVData; break;
3285 case 14: TVPtr = SiS_Pr->SiS_St2HiTVData; break;
3286 default: TVPtr = SiS_Pr->SiS_StPALData; break;
1da177e4
LT
3287 }
3288
3289 SiS_Pr->SiS_RVBHCMAX = (TVPtr+ResIndex)->RVBHCMAX;
3290 SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
3291 SiS_Pr->SiS_VGAHT = (TVPtr+ResIndex)->VGAHT;
3292 SiS_Pr->SiS_VGAVT = (TVPtr+ResIndex)->VGAVT;
3293 SiS_Pr->SiS_HDE = (TVPtr+ResIndex)->TVHDE;
3294 SiS_Pr->SiS_VDE = (TVPtr+ResIndex)->TVVDE;
544393fe 3295 SiS_Pr->SiS_RVBHRS2 = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
1da177e4 3296 if(modeflag & HalfDCLK) {
544393fe
TW
3297 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
3298 if(SiS_Pr->SiS_RVBHRS2) {
3299 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3300 tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
3301 if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
3302 else SiS_Pr->SiS_RVBHRS2 += tempax;
3303 }
3304 } else {
3305 SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
1da177e4 3306 }
544393fe 3307 SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
1da177e4
LT
3308
3309 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3310
544393fe
TW
3311 if((resinfo == SIS_RI_960x600) ||
3312 (resinfo == SIS_RI_1024x768) ||
3313 (resinfo == SIS_RI_1280x1024) ||
3314 (resinfo == SIS_RI_1280x720)) {
1da177e4
LT
3315 SiS_Pr->SiS_NewFlickerMode = 0x40;
3316 }
3317
544393fe 3318 if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1da177e4 3319
544393fe
TW
3320 SiS_Pr->SiS_HT = ExtHiTVHT;
3321 SiS_Pr->SiS_VT = ExtHiTVVT;
3322 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3323 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
3324 SiS_Pr->SiS_HT = StHiTVHT;
3325 SiS_Pr->SiS_VT = StHiTVVT;
3326 }
3327 }
1da177e4
LT
3328
3329 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3330
544393fe
TW
3331 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3332 SiS_Pr->SiS_HT = 1650;
3333 SiS_Pr->SiS_VT = 750;
1da177e4
LT
3334 } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3335 SiS_Pr->SiS_HT = NTSCHT;
544393fe 3336 if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
1da177e4 3337 SiS_Pr->SiS_VT = NTSCVT;
544393fe
TW
3338 } else {
3339 SiS_Pr->SiS_HT = NTSCHT;
1da177e4 3340 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
544393fe
TW
3341 SiS_Pr->SiS_VT = NTSCVT;
3342 }
1da177e4
LT
3343
3344 } else {
3345
544393fe
TW
3346 SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
3347 SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
3348 SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
3349 SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
1da177e4 3350
544393fe
TW
3351 if(modeflag & HalfDCLK) {
3352 SiS_Pr->SiS_RY1COE = 0x00;
3353 SiS_Pr->SiS_RY2COE = 0xf4;
3354 SiS_Pr->SiS_RY3COE = 0x10;
3355 SiS_Pr->SiS_RY4COE = 0x38;
3356 }
1da177e4 3357
544393fe
TW
3358 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
3359 SiS_Pr->SiS_HT = NTSCHT;
1da177e4 3360 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
544393fe
TW
3361 SiS_Pr->SiS_VT = NTSCVT;
3362 } else {
3363 SiS_Pr->SiS_HT = PALHT;
3364 SiS_Pr->SiS_VT = PALVT;
3365 }
1da177e4
LT
3366
3367 }
3368
3369 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3370
3371 SiS_Pr->SiS_RVBHCMAX = 1;
3372 SiS_Pr->SiS_RVBHCFACT = 1;
3373
3374 if(SiS_Pr->UseCustomMode) {
3375
1da177e4 3376 SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
544393fe
TW
3377 SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
3378
3379 tempax = SiS_Pr->CHTotal;
3380 if(modeflag & HalfDCLK) tempax <<= 1;
3381 SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3382 SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
1da177e4
LT
3383
3384 } else {
3385
c30660ea 3386 bool gotit = false;
1da177e4 3387
544393fe 3388 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
1da177e4 3389
544393fe
TW
3390 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
3391 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3392 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3393 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
c30660ea 3394 gotit = true;
1da177e4
LT
3395
3396 } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3397
f7854e5d 3398#ifdef CONFIG_FB_SIS_315
1da177e4 3399 SiS_Pr->SiS_RVBHCMAX = ROMAddr[romptr];
544393fe
TW
3400 SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3401 SiS_Pr->SiS_VGAHT = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
3402 SiS_Pr->SiS_VGAVT = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
3403 SiS_Pr->SiS_HT = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
3404 SiS_Pr->SiS_VT = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
3405 SiS_Pr->SiS_RVBHRS2 = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
3406 if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
3407 SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
3408 tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
3409 if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
3410 else SiS_Pr->SiS_RVBHRS2 += tempax;
3411 }
c30660ea 3412 if(SiS_Pr->SiS_VGAHT) gotit = true;
1da177e4
LT
3413 else {
3414 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
3415 SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
544393fe
TW
3416 SiS_Pr->SiS_RVBHCMAX = 1;
3417 SiS_Pr->SiS_RVBHCFACT = 1;
1da177e4 3418 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
544393fe
TW
3419 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3420 SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3421 SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3422 SiS_Pr->SiS_RVBHRS2 = 0;
c30660ea 3423 gotit = true;
1da177e4
LT
3424 }
3425#endif
3426
3427 }
3428
3429 if(!gotit) {
3430
544393fe
TW
3431 SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3432 &CRT2Index,&ResIndex);
1da177e4 3433
544393fe 3434 switch(CRT2Index) {
1da177e4
LT
3435 case Panel_1024x768 : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3436 case Panel_1024x768 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break;
3437 case Panel_1280x720 :
3438 case Panel_1280x720 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data; break;
3439 case Panel_1280x768_2 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
544393fe 3440 case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data; break;
1da177e4
LT
3441 case Panel_1280x800 :
3442 case Panel_1280x800 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data; break;
3443 case Panel_1280x800_2 :
3444 case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data; break;
544393fe
TW
3445 case Panel_1280x854 :
3446 case Panel_1280x854 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data; break;
1da177e4
LT
3447 case Panel_1280x960 :
3448 case Panel_1280x960 + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break;
544393fe
TW
3449 case Panel_1280x1024 : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break;
3450 case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3451 case Panel_1400x1050 : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break;
3452 case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break;
3453 case Panel_1600x1200 : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break;
3454 case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break;
1da177e4
LT
3455 case Panel_1680x1050 :
3456 case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data; break;
3457 case 100 : LCDPtr = SiS_Pr->SiS_NoScaleData; break;
f7854e5d 3458#ifdef CONFIG_FB_SIS_315
1da177e4
LT
3459 case 200 : LCDPtr = SiS310_ExtCompaq1280x1024Data; break;
3460 case 201 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
3461#endif
544393fe
TW
3462 default : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break;
3463 }
1da177e4 3464
544393fe
TW
3465 SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
3466 SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3467 SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
3468 SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
3469 SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
3470 SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
1da177e4
LT
3471
3472 }
3473
3474 tempax = SiS_Pr->PanelXRes;
544393fe 3475 tempbx = SiS_Pr->PanelYRes;
1da177e4 3476
544393fe
TW
3477 switch(SiS_Pr->SiS_LCDResInfo) {
3478 case Panel_1024x768:
3479 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3480 if(SiS_Pr->ChipType < SIS_315H) {
3481 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3482 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3483 }
3484 } else {
3485 if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
3486 else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
3487 else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
3488 else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
3489 else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3490 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3491 }
3492 break;
3493 case Panel_1280x960:
3494 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
3495 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
3496 else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
3497 break;
3498 case Panel_1280x1024:
3499 if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
3500 else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
3501 else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
3502 break;
3503 case Panel_1600x1200:
1da177e4 3504 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
544393fe
TW
3505 if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
3506 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
3507 }
3508 break;
3509 }
1da177e4 3510
544393fe
TW
3511 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3512 tempax = SiS_Pr->SiS_VGAHDE;
3513 tempbx = SiS_Pr->SiS_VGAVDE;
3514 }
1da177e4 3515
544393fe
TW
3516 SiS_Pr->SiS_HDE = tempax;
3517 SiS_Pr->SiS_VDE = tempbx;
1da177e4
LT
3518 }
3519 }
3520}
3521
3522static void
544393fe
TW
3523SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3524 unsigned short RefreshRateTableIndex)
1da177e4
LT
3525{
3526
544393fe 3527 if(SiS_Pr->SiS_VBType & VB_SISVB) {
1da177e4 3528
544393fe
TW
3529 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3530 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3531 } else {
3532 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3533 /* Need LVDS Data for LCD on 301B-DH */
3534 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3535 } else {
3536 SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3537 }
3538 }
1da177e4 3539
544393fe 3540 } else {
1da177e4 3541
544393fe 3542 SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4 3543
544393fe 3544 }
1da177e4
LT
3545}
3546
3547/*********************************************/
3548/* GET LVDS DES (SKEW) DATA */
3549/*********************************************/
3550
544393fe
TW
3551static const struct SiS_LVDSDes *
3552SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
1da177e4 3553{
544393fe 3554 const struct SiS_LVDSDes *PanelDesPtr = NULL;
1da177e4 3555
f7854e5d 3556#ifdef CONFIG_FB_SIS_300
544393fe
TW
3557 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3558
3559 if(SiS_Pr->ChipType < SIS_315H) {
3560 if(SiS_Pr->SiS_LCDTypeInfo == 4) {
3561 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3562 PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
3563 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3564 PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
3565 }
3566 } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3567 PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
3568 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3569 PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
3570 }
3571 }
3572 }
3573 }
3574 }
3575#endif
3576 return PanelDesPtr;
3577}
1da177e4 3578
544393fe
TW
3579static void
3580SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
3581 unsigned short RefreshRateTableIndex)
3582{
3583 unsigned short modeflag, ResIndex;
3584 const struct SiS_LVDSDes *PanelDesPtr = NULL;
1da177e4 3585
544393fe
TW
3586 SiS_Pr->SiS_LCDHDES = 0;
3587 SiS_Pr->SiS_LCDVDES = 0;
1da177e4 3588
544393fe 3589 /* Some special cases */
1da177e4 3590 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
544393fe
TW
3591
3592 /* Trumpion */
3593 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
3594 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3595 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3596 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3597 }
1da177e4 3598 }
544393fe 3599 return;
1da177e4 3600 }
1da177e4 3601
544393fe
TW
3602 /* 640x480 on LVDS */
3603 if(SiS_Pr->ChipType < SIS_315H) {
3604 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
3605 SiS_Pr->SiS_LCDHDES = 8;
3606 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3607 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3608 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3609 return;
3610 }
1da177e4 3611 }
1da177e4 3612
544393fe 3613 } /* LCD */
1da177e4
LT
3614
3615 if( (SiS_Pr->UseCustomMode) ||
3616 (SiS_Pr->SiS_LCDResInfo == Panel_Custom) ||
3617 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
544393fe
TW
3618 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ||
3619 (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
1da177e4
LT
3620 return;
3621 }
3622
544393fe
TW
3623 if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3624 else ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3625
3626 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
1da177e4 3627
f7854e5d 3628#ifdef CONFIG_FB_SIS_315
1da177e4 3629 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
544393fe
TW
3630 /* non-pass 1:1 only, see above */
3631 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3632 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3633 }
3634 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3635 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3636 }
3637 }
3638 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3639 switch(SiS_Pr->SiS_CustomT) {
3640 case CUT_UNIWILL1024:
3641 case CUT_UNIWILL10242:
3642 case CUT_CLEVO1400:
3643 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3644 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3645 }
3646 break;
3647 }
3648 switch(SiS_Pr->SiS_LCDResInfo) {
3649 case Panel_1280x1024:
3650 if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
3651 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3652 }
3653 break;
3654 case Panel_1280x800: /* Verified for Averatec 6240 */
3655 case Panel_1280x800_2: /* Verified for Asus A4L */
3656 case Panel_1280x854: /* Not verified yet FIXME */
3657 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3658 break;
3659 }
3660 }
3661#endif
3662
3663 } else {
3664
3665 if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
3666
3667 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
3668 if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
3669 }
3670
3671 } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
3672
3673 SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
3674 SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
3675
3676 } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3677
3678 if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3679 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
1da177e4
LT
3680 }
3681 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3682 SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
544393fe
TW
3683 } else {
3684 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 3685 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
544393fe
TW
3686 } else {
3687 switch(SiS_Pr->SiS_LCDResInfo) {
3688 case Panel_800x600:
3689 case Panel_1024x768:
3690 case Panel_1280x1024:
3691 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3692 break;
3693 case Panel_1400x1050:
3694 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3695 break;
3696 }
1da177e4 3697 }
1da177e4 3698 }
544393fe
TW
3699
3700 } else {
3701
3702 if(SiS_Pr->ChipType < SIS_315H) {
f7854e5d 3703#ifdef CONFIG_FB_SIS_300
544393fe
TW
3704 switch(SiS_Pr->SiS_LCDResInfo) {
3705 case Panel_800x600:
3706 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3707 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3708 } else {
3709 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
3710 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
3711 if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
3712 else SiS_Pr->SiS_LCDVDES -= 4;
3713 }
3714 break;
3715 case Panel_1024x768:
3716 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3717 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3718 } else {
3719 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3720 if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
3721 if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
3722 }
3723 break;
3724 case Panel_1024x600:
3725 default:
3726 if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
3727 (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
3728 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3729 } else {
3730 SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
3731 }
3732 break;
3733 }
3734
3735 switch(SiS_Pr->SiS_LCDTypeInfo) {
3736 case 1:
3737 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
3738 break;
3739 case 3: /* 640x480 only? */
3740 SiS_Pr->SiS_LCDHDES = 8;
3741 if (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
3742 else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
3743 else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
3744 break;
3745 }
3746#endif
3747 } else {
f7854e5d 3748#ifdef CONFIG_FB_SIS_315
544393fe
TW
3749 switch(SiS_Pr->SiS_LCDResInfo) {
3750 case Panel_1024x768:
3751 case Panel_1280x1024:
3752 if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3753 SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3754 }
3755 break;
3756 case Panel_320x240_1:
3757 case Panel_320x240_2:
3758 case Panel_320x240_3:
3759 SiS_Pr->SiS_LCDVDES = 524;
3760 break;
1da177e4 3761 }
544393fe 3762#endif
1da177e4
LT
3763 }
3764 }
1da177e4
LT
3765
3766 if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
544393fe
TW
3767 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3768 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
1da177e4 3769 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
544393fe
TW
3770 } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3771 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
3772 if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
3773 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4
LT
3774 if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
3775 } else {
f7854e5d 3776#ifdef CONFIG_FB_SIS_315
544393fe
TW
3777 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) SiS_Pr->SiS_LCDHDES = 480;
3778 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
1da177e4 3779 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
544393fe
TW
3780 if(!(modeflag & HalfDCLK)) {
3781 SiS_Pr->SiS_LCDHDES = 320;
3782 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
1da177e4 3783 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
544393fe
TW
3784 }
3785#endif
3786 }
3787 }
3788 }
3789 }
1da177e4
LT
3790 }
3791 }
3792}
3793
3794/*********************************************/
3795/* DISABLE VIDEO BRIDGE */
3796/*********************************************/
3797
f7854e5d 3798#ifdef CONFIG_FB_SIS_315
544393fe
TW
3799static int
3800SiS_HandlePWD(struct SiS_Private *SiS_Pr)
3801{
3802 int ret = 0;
3803#ifdef SET_PWD
3804 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3805 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
3806 unsigned char drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
3807 unsigned short temp;
3808
3809 if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
3810 (romptr) &&
3811 (SiS_Pr->SiS_PWDOffset) ) {
3812 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
3813 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
3814 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
3815 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
3816 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
3817 temp = 0x00;
3818 if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
3819 temp = 0x80;
3820 ret = 1;
3821 }
3822 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
544393fe
TW
3823 }
3824#endif
3825 return ret;
3826}
3827#endif
3828
1da177e4
LT
3829/* NEVER use any variables (VBInfo), this will be called
3830 * from outside the context of modeswitch!
3831 * MUST call getVBType before calling this
3832 */
3833void
544393fe 3834SiS_DisableBridge(struct SiS_Private *SiS_Pr)
1da177e4 3835{
f7854e5d 3836#ifdef CONFIG_FB_SIS_315
544393fe 3837 unsigned short tempah, pushax=0, modenum;
1da177e4 3838#endif
544393fe 3839 unsigned short temp=0;
1da177e4
LT
3840
3841 if(SiS_Pr->SiS_VBType & VB_SISVB) {
3842
544393fe 3843 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ===== For 30xB/C/LV ===== */
1da177e4 3844
544393fe 3845 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 3846
f7854e5d 3847#ifdef CONFIG_FB_SIS_300 /* 300 series */
1da177e4 3848
544393fe
TW
3849 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
3850 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3851 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
1da177e4 3852 } else {
544393fe 3853 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
1da177e4 3854 }
544393fe 3855 SiS_PanelDelay(SiS_Pr, 3);
1da177e4
LT
3856 }
3857 if(SiS_Is301B(SiS_Pr)) {
3858 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
3859 SiS_ShortDelay(SiS_Pr,1);
544393fe 3860 }
1da177e4
LT
3861 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
3862 SiS_DisplayOff(SiS_Pr);
3863 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3864 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
544393fe
TW
3865 SiS_UnLockCRT2(SiS_Pr);
3866 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
1da177e4
LT
3867 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
3868 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
3869 }
544393fe
TW
3870 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
3871 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
3872 SiS_PanelDelay(SiS_Pr, 2);
3873 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3874 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
1da177e4 3875 } else {
544393fe 3876 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
1da177e4
LT
3877 }
3878 }
3879
f7854e5d 3880#endif /* CONFIG_FB_SIS_300 */
1da177e4
LT
3881
3882 } else {
3883
f7854e5d 3884#ifdef CONFIG_FB_SIS_315 /* 315 series */
1da177e4 3885
544393fe 3886 int didpwd = 0;
c30660ea
RK
3887 bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
3888 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
1da177e4
LT
3889
3890 modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
3891
544393fe 3892 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4
LT
3893
3894#ifdef SET_EMI
544393fe 3895 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
1da177e4 3896 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
544393fe 3897 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
1da177e4
LT
3898 }
3899 }
3900#endif
544393fe
TW
3901
3902 didpwd = SiS_HandlePWD(SiS_Pr);
3903
3904 if( (modenum <= 0x13) ||
3905 (SiS_IsVAMode(SiS_Pr)) ||
3906 (!(SiS_IsDualEdge(SiS_Pr))) ) {
3907 if(!didpwd) {
3908 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
3909 if(custom1) SiS_PanelDelay(SiS_Pr, 3);
3910 } else {
3911 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
3912 }
1da177e4
LT
3913 }
3914
3915 if(!custom1) {
3916 SiS_DDC2Delay(SiS_Pr,0xff00);
3917 SiS_DDC2Delay(SiS_Pr,0xe000);
544393fe
TW
3918 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
3919 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
1da177e4
LT
3920 if(IS_SIS740) {
3921 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
3922 }
544393fe 3923 SiS_PanelDelay(SiS_Pr, 3);
1da177e4
LT
3924 }
3925
544393fe 3926 }
1da177e4 3927
544393fe
TW
3928 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
3929 /* if(SiS_Pr->ChipType < SIS_340) {*/
3930 tempah = 0xef;
3931 if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
3932 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
3933 /*}*/
1da177e4
LT
3934 }
3935
544393fe 3936 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4
LT
3937 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
3938 }
3939
3940 tempah = 0x3f;
544393fe 3941 if(SiS_IsDualEdge(SiS_Pr)) {
1da177e4 3942 tempah = 0x7f;
544393fe 3943 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
1da177e4
LT
3944 }
3945 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
3946
544393fe
TW
3947 if((SiS_IsVAMode(SiS_Pr)) ||
3948 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
1da177e4
LT
3949
3950 SiS_DisplayOff(SiS_Pr);
544393fe
TW
3951 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3952 SiS_PanelDelay(SiS_Pr, 2);
1da177e4
LT
3953 }
3954 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3955 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
3956
3957 }
3958
544393fe
TW
3959 if((!(SiS_IsVAMode(SiS_Pr))) ||
3960 ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
1da177e4 3961
544393fe 3962 if(!(SiS_IsDualEdge(SiS_Pr))) {
1da177e4
LT
3963 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
3964 SiS_DisplayOff(SiS_Pr);
3965 }
3966 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
3967
544393fe
TW
3968 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
3969 SiS_PanelDelay(SiS_Pr, 2);
1da177e4
LT
3970 }
3971
3972 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3973 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
544393fe 3974 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
1da177e4
LT
3975 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
3976 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
3977
3978 }
3979
544393fe 3980 if(SiS_IsNotM650orLater(SiS_Pr)) {
1da177e4
LT
3981 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
3982 }
3983
544393fe 3984 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4 3985
544393fe
TW
3986 if( (!(SiS_IsVAMode(SiS_Pr))) &&
3987 (!(SiS_CRT2IsLCD(SiS_Pr))) &&
3988 (!(SiS_IsDualEdge(SiS_Pr))) ) {
1da177e4 3989
544393fe
TW
3990 if(custom1) SiS_PanelDelay(SiS_Pr, 2);
3991 if(!didpwd) {
3992 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
3993 }
3994 if(custom1) SiS_PanelDelay(SiS_Pr, 4);
3995 }
1da177e4 3996
544393fe
TW
3997 if(!custom1) {
3998 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
3999 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4000 if(SiS_IsVAorLCD(SiS_Pr)) {
4001 SiS_PanelDelayLoop(SiS_Pr, 3, 20);
1da177e4
LT
4002 }
4003 }
1da177e4 4004 }
544393fe
TW
4005
4006 }
1da177e4 4007
f7854e5d 4008#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
4009
4010 }
4011
4012 } else { /* ============ For 301 ================ */
4013
544393fe 4014 if(SiS_Pr->ChipType < SIS_315H) {
f7854e5d 4015#ifdef CONFIG_FB_SIS_300
544393fe
TW
4016 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4017 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4018 SiS_PanelDelay(SiS_Pr, 3);
1da177e4
LT
4019 }
4020#endif
4021 }
4022
544393fe
TW
4023 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
4024 SiS_DisplayOff(SiS_Pr);
1da177e4 4025
544393fe
TW
4026 if(SiS_Pr->ChipType >= SIS_315H) {
4027 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
1da177e4
LT
4028 }
4029
544393fe 4030 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF); /* disable lock mode */
1da177e4 4031
544393fe
TW
4032 if(SiS_Pr->ChipType >= SIS_315H) {
4033 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4034 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
1da177e4
LT
4035 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4036 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4037 } else {
f7854e5d 4038#ifdef CONFIG_FB_SIS_300
544393fe
TW
4039 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
4040 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4041 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4042 SiS_PanelDelay(SiS_Pr, 2);
4043 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
1da177e4
LT
4044 }
4045#endif
4046 }
4047
4048 }
4049
4050 } else { /* ============ For LVDS =============*/
4051
544393fe 4052 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 4053
f7854e5d 4054#ifdef CONFIG_FB_SIS_300 /* 300 series */
1da177e4
LT
4055
4056 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
544393fe 4057 SiS_SetCH700x(SiS_Pr,0x0E,0x09);
1da177e4
LT
4058 }
4059
544393fe 4060 if(SiS_Pr->ChipType == SIS_730) {
1da177e4 4061 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
544393fe 4062 SiS_WaitVBRetrace(SiS_Pr);
1da177e4 4063 }
544393fe
TW
4064 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4065 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4066 SiS_PanelDelay(SiS_Pr, 3);
1da177e4
LT
4067 }
4068 } else {
4069 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4070 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
544393fe
TW
4071 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4072 SiS_WaitVBRetrace(SiS_Pr);
1da177e4
LT
4073 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
4074 SiS_DisplayOff(SiS_Pr);
544393fe
TW
4075 }
4076 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4077 SiS_PanelDelay(SiS_Pr, 3);
4078 }
4079 }
1da177e4
LT
4080 }
4081 }
4082
4083 SiS_DisplayOff(SiS_Pr);
4084
4085 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4086
4087 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
544393fe 4088 SiS_UnLockCRT2(SiS_Pr);
1da177e4
LT
4089 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4090 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4091
544393fe
TW
4092 if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
4093 (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
4094 SiS_PanelDelay(SiS_Pr, 2);
4095 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
1da177e4
LT
4096 }
4097
f7854e5d 4098#endif /* CONFIG_FB_SIS_300 */
1da177e4
LT
4099
4100 } else {
4101
f7854e5d 4102#ifdef CONFIG_FB_SIS_315 /* 315 series */
1da177e4 4103
544393fe
TW
4104 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4105 /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
4106 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
4107 /* } */
4108 }
1da177e4
LT
4109
4110 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4111
544393fe 4112 if(SiS_Pr->ChipType == SIS_740) {
1da177e4
LT
4113 temp = SiS_GetCH701x(SiS_Pr,0x61);
4114 if(temp < 1) {
544393fe
TW
4115 SiS_SetCH701x(SiS_Pr,0x76,0xac);
4116 SiS_SetCH701x(SiS_Pr,0x66,0x00);
1da177e4
LT
4117 }
4118
544393fe
TW
4119 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4120 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4121 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
1da177e4
LT
4122 }
4123 }
4124
544393fe
TW
4125 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4126 (SiS_IsVAMode(SiS_Pr)) ) {
1da177e4 4127 SiS_Chrontel701xBLOff(SiS_Pr);
544393fe 4128 SiS_Chrontel701xOff(SiS_Pr);
1da177e4
LT
4129 }
4130
544393fe
TW
4131 if(SiS_Pr->ChipType != SIS_740) {
4132 if( (!(SiS_IsDualEdge(SiS_Pr))) ||
4133 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
4134 SiS_SetCH701x(SiS_Pr,0x49,0x01);
4135 }
1da177e4
LT
4136 }
4137
4138 }
4139
4140 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
544393fe
TW
4141 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
4142 SiS_PanelDelay(SiS_Pr, 3);
1da177e4
LT
4143 }
4144
4145 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
544393fe
TW
4146 (!(SiS_IsDualEdge(SiS_Pr))) ||
4147 (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
1da177e4
LT
4148 SiS_DisplayOff(SiS_Pr);
4149 }
4150
4151 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
544393fe
TW
4152 (!(SiS_IsDualEdge(SiS_Pr))) ||
4153 (!(SiS_IsVAMode(SiS_Pr))) ) {
1da177e4
LT
4154 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4155 }
4156
544393fe 4157 if(SiS_Pr->ChipType == SIS_740) {
1da177e4
LT
4158 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4159 }
4160
4161 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4162
4163 if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
544393fe
TW
4164 (!(SiS_IsDualEdge(SiS_Pr))) ||
4165 (!(SiS_IsVAMode(SiS_Pr))) ) {
1da177e4
LT
4166 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4167 }
4168
4169 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
544393fe 4170 if(SiS_CRT2IsLCD(SiS_Pr)) {
1da177e4 4171 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
544393fe
TW
4172 if(SiS_Pr->ChipType == SIS_550) {
4173 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
4174 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
1da177e4
LT
4175 }
4176 }
4177 } else {
544393fe
TW
4178 if(SiS_Pr->ChipType == SIS_740) {
4179 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4180 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
1da177e4 4181 }
544393fe 4182 } else if(SiS_IsVAMode(SiS_Pr)) {
1da177e4
LT
4183 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4184 }
4185 }
4186
4187 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
544393fe 4188 if(SiS_IsDualEdge(SiS_Pr)) {
1da177e4
LT
4189 /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
4190 } else {
4191 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
4192 }
4193 }
4194
544393fe 4195 SiS_UnLockCRT2(SiS_Pr);
1da177e4 4196
544393fe 4197 if(SiS_Pr->ChipType == SIS_550) {
1da177e4
LT
4198 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
4199 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
4200 } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0) ||
544393fe
TW
4201 (!(SiS_IsDualEdge(SiS_Pr))) ||
4202 (!(SiS_IsVAMode(SiS_Pr))) ) {
1da177e4
LT
4203 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4204 }
4205
4206 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
544393fe
TW
4207 if(SiS_CRT2IsLCD(SiS_Pr)) {
4208 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4209 SiS_PanelDelay(SiS_Pr, 2);
4210 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
1da177e4
LT
4211 }
4212 }
4213 }
4214
f7854e5d 4215#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
4216
4217 } /* 315 series */
4218
4219 } /* LVDS */
4220
4221}
4222
4223/*********************************************/
4224/* ENABLE VIDEO BRIDGE */
4225/*********************************************/
4226
4227/* NEVER use any variables (VBInfo), this will be called
4228 * from outside the context of a mode switch!
4229 * MUST call getVBType before calling this
4230 */
544393fe 4231static
544393fe
TW
4232void
4233SiS_EnableBridge(struct SiS_Private *SiS_Pr)
1da177e4 4234{
544393fe 4235 unsigned short temp=0, tempah;
f7854e5d 4236#ifdef CONFIG_FB_SIS_315
544393fe 4237 unsigned short temp1, pushax=0;
c30660ea 4238 bool delaylong = false;
1da177e4
LT
4239#endif
4240
4241 if(SiS_Pr->SiS_VBType & VB_SISVB) {
4242
544393fe 4243 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* ====== For 301B et al ====== */
1da177e4 4244
544393fe 4245 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 4246
f7854e5d 4247#ifdef CONFIG_FB_SIS_300 /* 300 series */
1da177e4 4248
544393fe
TW
4249 if(SiS_CRT2IsLCD(SiS_Pr)) {
4250 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4
LT
4251 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4252 } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
544393fe 4253 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
1da177e4 4254 }
544393fe
TW
4255 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
4256 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4257 SiS_PanelDelay(SiS_Pr, 0);
1da177e4
LT
4258 }
4259 }
4260 }
4261
4262 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
544393fe 4263 (SiS_CRT2IsLCD(SiS_Pr))) {
1da177e4
LT
4264
4265 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* Enable CRT2 */
544393fe
TW
4266 SiS_DisplayOn(SiS_Pr);
4267 SiS_UnLockCRT2(SiS_Pr);
1da177e4
LT
4268 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4269 if(SiS_BridgeInSlavemode(SiS_Pr)) {
544393fe
TW
4270 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4271 } else {
4272 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4273 }
1da177e4
LT
4274 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4275 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
544393fe
TW
4276 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4277 SiS_PanelDelay(SiS_Pr, 1);
4278 }
4279 SiS_WaitVBRetrace(SiS_Pr);
4280 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4281 }
1da177e4
LT
4282 }
4283
4284 } else {
4285
4286 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
544393fe
TW
4287 if(SiS_BridgeInSlavemode(SiS_Pr)) {
4288 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4289 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4290 }
4291 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
1da177e4
LT
4292 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4293 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4294 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
4295 SiS_DisplayOn(SiS_Pr);
544393fe
TW
4296 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4297 if(SiS_CRT2IsLCD(SiS_Pr)) {
4298 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4299 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4300 SiS_PanelDelay(SiS_Pr, 1);
4301 }
1da177e4 4302 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
544393fe 4303 }
1da177e4
LT
4304 }
4305 }
4306
4307 }
4308
4309
f7854e5d 4310#endif /* CONFIG_FB_SIS_300 */
1da177e4
LT
4311
4312 } else {
4313
f7854e5d 4314#ifdef CONFIG_FB_SIS_315 /* 315 series */
1da177e4
LT
4315
4316#ifdef SET_EMI
544393fe
TW
4317 unsigned char r30=0, r31=0, r32=0, r33=0, cr36=0;
4318 int didpwd = 0;
4319 /* unsigned short emidelay=0; */
1da177e4
LT
4320#endif
4321
544393fe 4322 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4
LT
4323 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
4324#ifdef SET_EMI
544393fe 4325 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
1da177e4
LT
4326 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4327 }
4328#endif
4329 }
4330
544393fe
TW
4331 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4332 /*if(SiS_Pr->ChipType < SIS_340) { */
1da177e4 4333 tempah = 0x10;
544393fe
TW
4334 if(SiS_LCDAEnabled(SiS_Pr)) {
4335 if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
4336 else tempah = 0x08;
1da177e4
LT
4337 }
4338 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
544393fe 4339 /*}*/
1da177e4
LT
4340 }
4341
544393fe 4342 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4
LT
4343
4344 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4345 SiS_DisplayOff(SiS_Pr);
4346 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4347 if(IS_SIS740) {
4348 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4349 }
4350
544393fe
TW
4351 didpwd = SiS_HandlePWD(SiS_Pr);
4352
4353 if(SiS_IsVAorLCD(SiS_Pr)) {
4354 if(!didpwd) {
4355 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
4356 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4357 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4358 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4359 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4360 SiS_GenericDelay(SiS_Pr, 17664);
4361 }
4362 }
4363 } else {
4364 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
4365 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4366 SiS_GenericDelay(SiS_Pr, 17664);
1da177e4
LT
4367 }
4368 }
4369 }
4370
4371 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
544393fe 4372 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
c30660ea 4373 delaylong = true;
1da177e4
LT
4374 }
4375
4376 }
4377
544393fe 4378 if(!(SiS_IsVAMode(SiS_Pr))) {
1da177e4 4379
544393fe 4380 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
1da177e4 4381 if(SiS_BridgeInSlavemode(SiS_Pr)) {
544393fe
TW
4382 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4383 if(!(tempah & SetCRT2ToRAMDAC)) {
4384 if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
1da177e4 4385 }
544393fe
TW
4386 }
4387 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
1da177e4
LT
4388
4389 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4390
4391 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4392 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4393
544393fe
TW
4394 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
4395 SiS_PanelDelay(SiS_Pr, 2);
1da177e4
LT
4396 }
4397
4398 } else {
4399
4400 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
4401
4402 }
4403
4404 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
4405 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4406
544393fe
TW
4407 if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
4408 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4409 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4410 /* Enable "LVDS PLL power on" (even on 301C) */
4411 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
4412 /* Enable "LVDS Driver Power on" (even on 301C) */
4413 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
4414 }
4415 }
4416
1da177e4 4417 tempah = 0xc0;
544393fe 4418 if(SiS_IsDualEdge(SiS_Pr)) {
1da177e4 4419 tempah = 0x80;
544393fe 4420 if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
1da177e4 4421 }
544393fe 4422 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
1da177e4 4423
544393fe 4424 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4 4425
544393fe 4426 SiS_PanelDelay(SiS_Pr, 2);
1da177e4
LT
4427
4428 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
4429 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4430
4431 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4432#ifdef SET_EMI
544393fe
TW
4433 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4434 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4435 SiS_GenericDelay(SiS_Pr, 2048);
1da177e4
LT
4436 }
4437#endif
4438 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
4439
544393fe 4440 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
1da177e4
LT
4441#ifdef SET_EMI
4442 cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
4443
4444 if(SiS_Pr->SiS_ROMNew) {
544393fe
TW
4445 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
4446 unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
1da177e4 4447 if(romptr) {
544393fe 4448 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
1da177e4
LT
4449 SiS_Pr->EMI_30 = 0;
4450 SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
4451 SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
4452 SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
4453 if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
4454 /* emidelay = SISGETROMW((romptr + 0x22)); */
c30660ea 4455 SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
1da177e4
LT
4456 }
4457 }
4458
4459 /* (P4_30|0x40) */
4460 /* Compal 1400x1050: 0x05, 0x60, 0x00 YES (1.10.7w; CR36=69) */
4461 /* Compal 1400x1050: 0x0d, 0x70, 0x40 YES (1.10.7x; CR36=69) */
4462 /* Acer 1280x1024: 0x12, 0xd0, 0x6b NO (1.10.9k; CR36=73) */
4463 /* Compaq 1280x1024: 0x0d, 0x70, 0x6b YES (1.12.04b; CR36=03) */
4464 /* Clevo 1024x768: 0x05, 0x60, 0x33 NO (1.10.8e; CR36=12, DL!) */
4465 /* Clevo 1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES (1.10.8y; CR36=?2) */
4466 /* Clevo 1024x768: 0x05, 0x60, 0x33 (if type != 3) YES (1.10.8y; CR36=?2) */
4467 /* Asus 1024x768: ? ? (1.10.8o; CR36=?2) */
4468 /* Asus 1024x768: 0x08, 0x10, 0x3c (problematic) YES (1.10.8q; CR36=22) */
4469
4470 if(SiS_Pr->HaveEMI) {
4471 r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
4472 r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
4473 } else {
4474 r30 = 0;
4475 }
4476
4477 /* EMI_30 is read at driver start; however, the BIOS sets this
4478 * (if it is used) only if the LCD is in use. In case we caught
4479 * the machine while on TV output, this bit is not set and we
4480 * don't know if it should be set - hence our detection is wrong.
4481 * Work-around this here:
4482 */
4483
4484 if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
4485 switch((cr36 & 0x0f)) {
4486 case 2:
4487 r30 |= 0x40;
4488 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
4489 if(!SiS_Pr->HaveEMI) {
4490 r31 = 0x05; r32 = 0x60; r33 = 0x33;
4491 if((cr36 & 0xf0) == 0x30) {
4492 r31 = 0x0d; r32 = 0x70; r33 = 0x40;
4493 }
4494 }
4495 break;
4496 case 3: /* 1280x1024 */
4497 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
4498 if(!SiS_Pr->HaveEMI) {
4499 r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4500 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4501 r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
4502 }
4503 }
4504 break;
4505 case 9: /* 1400x1050 */
4506 r30 |= 0x40;
4507 if(!SiS_Pr->HaveEMI) {
4508 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4509 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4510 r31 = 0x0d; r32 = 0x70; r33 = 0x40; /* BIOS values */
4511 }
4512 }
4513 break;
4514 case 11: /* 1600x1200 - unknown */
4515 r30 |= 0x40;
4516 if(!SiS_Pr->HaveEMI) {
4517 r31 = 0x05; r32 = 0x60; r33 = 0x00;
4518 }
4519 }
4520 }
4521
4522 /* BIOS values don't work so well sometimes */
4523 if(!SiS_Pr->OverruleEMI) {
4524#ifdef COMPAL_HACK
4525 if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
544393fe 4526 if((cr36 & 0x0f) == 0x09) {
1da177e4
LT
4527 r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
4528 }
4529 }
4530#endif
4531#ifdef COMPAQ_HACK
4532 if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
544393fe 4533 if((cr36 & 0x0f) == 0x03) {
1da177e4
LT
4534 r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4535 }
4536 }
4537#endif
4538#ifdef ASUS_HACK
4539 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
544393fe 4540 if((cr36 & 0x0f) == 0x02) {
1da177e4
LT
4541 /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 2 */
4542 /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33; */ /* rev 3 */
4543 /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 4 */
4544 /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40; */ /* rev 5 */
4545 }
4546 }
4547#endif
544393fe 4548 }
1da177e4
LT
4549
4550 if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
4551 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
544393fe 4552 SiS_GenericDelay(SiS_Pr, 2048);
1da177e4
LT
4553 }
4554 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
4555 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
4556 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
4557#endif /* SET_EMI */
4558
4559 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
4560
4561#ifdef SET_EMI
544393fe
TW
4562 if( (SiS_LCDAEnabled(SiS_Pr)) ||
4563 (SiS_CRT2IsLCD(SiS_Pr)) ) {
4564 if(r30 & 0x40) {
4565 /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
4566 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
1da177e4 4567 if(delaylong) {
544393fe 4568 SiS_PanelDelayLoop(SiS_Pr, 3, 5);
c30660ea 4569 delaylong = false;
1da177e4 4570 }
544393fe
TW
4571 SiS_WaitVBRetrace(SiS_Pr);
4572 SiS_WaitVBRetrace(SiS_Pr);
1da177e4 4573 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
544393fe 4574 SiS_GenericDelay(SiS_Pr, 1280);
1da177e4 4575 }
544393fe
TW
4576 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40); /* Enable */
4577 /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
4578 }
1da177e4
LT
4579 }
4580#endif
4581 }
4582 }
4583
544393fe
TW
4584 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4585 if(SiS_IsVAorLCD(SiS_Pr)) {
4586 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
1da177e4 4587 if(delaylong) {
544393fe 4588 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
1da177e4 4589 }
544393fe
TW
4590 SiS_WaitVBRetrace(SiS_Pr);
4591 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
4592 SiS_GenericDelay(SiS_Pr, 2048);
4593 SiS_WaitVBRetrace(SiS_Pr);
4594 }
4595 if(!didpwd) {
4596 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4597 } else {
4598 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
1da177e4 4599 }
1da177e4
LT
4600 }
4601 }
4602
4603 SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4604 SiS_DisplayOn(SiS_Pr);
4605 SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
4606
4607 }
4608
544393fe 4609 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
1da177e4
LT
4610 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4611 }
4612
f7854e5d 4613#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
4614
4615 }
4616
4617 } else { /* ============ For 301 ================ */
4618
544393fe
TW
4619 if(SiS_Pr->ChipType < SIS_315H) {
4620 if(SiS_CRT2IsLCD(SiS_Pr)) {
4621 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4622 SiS_PanelDelay(SiS_Pr, 0);
1da177e4
LT
4623 }
4624 }
4625
4626 temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF; /* lock mode */
4627 if(SiS_BridgeInSlavemode(SiS_Pr)) {
544393fe
TW
4628 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4629 if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
1da177e4
LT
4630 }
4631 SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4632
4633 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
4634
544393fe
TW
4635 if(SiS_Pr->ChipType >= SIS_315H) {
4636 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4637 if(!(temp & 0x80)) {
4638 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80); /* BVBDOENABLE=1 */
1da177e4
LT
4639 }
4640 }
4641
4642 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20); /* enable VB processor */
4643
4644 SiS_VBLongWait(SiS_Pr);
4645 SiS_DisplayOn(SiS_Pr);
544393fe
TW
4646 if(SiS_Pr->ChipType >= SIS_315H) {
4647 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
1da177e4
LT
4648 }
4649 SiS_VBLongWait(SiS_Pr);
4650
544393fe
TW
4651 if(SiS_Pr->ChipType < SIS_315H) {
4652 if(SiS_CRT2IsLCD(SiS_Pr)) {
4653 SiS_PanelDelay(SiS_Pr, 1);
4654 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
1da177e4
LT
4655 }
4656 }
4657
4658 }
4659
4660 } else { /* =================== For LVDS ================== */
4661
544393fe 4662 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 4663
f7854e5d 4664#ifdef CONFIG_FB_SIS_300 /* 300 series */
1da177e4 4665
544393fe
TW
4666 if(SiS_CRT2IsLCD(SiS_Pr)) {
4667 if(SiS_Pr->ChipType == SIS_730) {
4668 SiS_PanelDelay(SiS_Pr, 1);
4669 SiS_PanelDelay(SiS_Pr, 1);
4670 SiS_PanelDelay(SiS_Pr, 1);
1da177e4 4671 }
544393fe
TW
4672 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4673 if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
4674 SiS_PanelDelay(SiS_Pr, 0);
1da177e4
LT
4675 }
4676 }
4677
4678 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4679 SiS_DisplayOn(SiS_Pr);
544393fe 4680 SiS_UnLockCRT2(SiS_Pr);
1da177e4
LT
4681 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4682 if(SiS_BridgeInSlavemode(SiS_Pr)) {
544393fe 4683 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
1da177e4 4684 } else {
544393fe 4685 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
1da177e4
LT
4686 }
4687
4688 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
544393fe
TW
4689 if(!(SiS_CRT2IsLCD(SiS_Pr))) {
4690 SiS_WaitVBRetrace(SiS_Pr);
4691 SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
4692 }
1da177e4
LT
4693 }
4694
544393fe
TW
4695 if(SiS_CRT2IsLCD(SiS_Pr)) {
4696 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4697 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4698 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
4699 SiS_PanelDelay(SiS_Pr, 1);
4700 SiS_PanelDelay(SiS_Pr, 1);
4701 }
4702 SiS_WaitVBRetrace(SiS_Pr);
4703 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
4704 }
1da177e4
LT
4705 }
4706 }
4707
f7854e5d 4708#endif /* CONFIG_FB_SIS_300 */
1da177e4
LT
4709
4710 } else {
4711
f7854e5d 4712#ifdef CONFIG_FB_SIS_315 /* 315 series */
1da177e4 4713
544393fe
TW
4714 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
4715 /*if(SiS_Pr->ChipType < SIS_340) {*/ /* XGI needs this */
4716 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
4717 /*}*/
1da177e4
LT
4718 }
4719
4720 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
544393fe
TW
4721 if(SiS_CRT2IsLCD(SiS_Pr)) {
4722 SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
4723 SiS_PanelDelay(SiS_Pr, 0);
4724 }
1da177e4
LT
4725 }
4726
4727 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
544393fe 4728 SiS_UnLockCRT2(SiS_Pr);
1da177e4
LT
4729
4730 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4731
4732 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
544393fe 4733 temp = SiS_GetCH701x(SiS_Pr,0x66);
1da177e4
LT
4734 temp &= 0x20;
4735 SiS_Chrontel701xBLOff(SiS_Pr);
4736 }
4737
544393fe
TW
4738 if(SiS_Pr->ChipType != SIS_550) {
4739 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
1da177e4
LT
4740 }
4741
544393fe
TW
4742 if(SiS_Pr->ChipType == SIS_740) {
4743 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4744 if(SiS_IsLCDOrLCDA(SiS_Pr)) {
4745 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
1da177e4
LT
4746 }
4747 }
4748 }
4749
4750 temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4751 if(!(temp1 & 0x80)) {
544393fe 4752 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
1da177e4
LT
4753 }
4754
4755 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
544393fe
TW
4756 if(temp) {
4757 SiS_Chrontel701xBLOn(SiS_Pr);
1da177e4
LT
4758 }
4759 }
4760
4761 if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
544393fe 4762 if(SiS_CRT2IsLCD(SiS_Pr)) {
1da177e4 4763 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
544393fe 4764 if(SiS_Pr->ChipType == SIS_550) {
1da177e4
LT
4765 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
4766 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
4767 }
4768 }
544393fe
TW
4769 } else if(SiS_IsVAMode(SiS_Pr)) {
4770 if(SiS_Pr->ChipType != SIS_740) {
4771 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
1da177e4
LT
4772 }
4773 }
4774
544393fe
TW
4775 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4776 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
1da177e4
LT
4777 }
4778
4779 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
544393fe
TW
4780 if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
4781 SiS_Chrontel701xOn(SiS_Pr);
4782 }
4783 if( (SiS_IsVAMode(SiS_Pr)) ||
4784 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4785 SiS_ChrontelDoSomething1(SiS_Pr);
4786 }
1da177e4
LT
4787 }
4788
4789 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
544393fe
TW
4790 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4791 if( (SiS_IsVAMode(SiS_Pr)) ||
4792 (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
4793 SiS_Chrontel701xBLOn(SiS_Pr);
4794 SiS_ChrontelInitTVVSync(SiS_Pr);
4795 }
4796 }
1da177e4 4797 } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
544393fe
TW
4798 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
4799 if(SiS_CRT2IsLCD(SiS_Pr)) {
4800 SiS_PanelDelay(SiS_Pr, 1);
4801 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
1da177e4
LT
4802 }
4803 }
4804 }
4805
f7854e5d 4806#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
4807
4808 } /* 310 series */
4809
4810 } /* LVDS */
4811
4812}
4813
4814/*********************************************/
4815/* SET PART 1 REGISTER GROUP */
4816/*********************************************/
4817
4818/* Set CRT2 OFFSET / PITCH */
4819static void
544393fe
TW
4820SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
4821 unsigned short RRTI)
1da177e4 4822{
544393fe
TW
4823 unsigned short offset;
4824 unsigned char temp;
1da177e4 4825
544393fe 4826 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
1da177e4 4827
544393fe 4828 offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
1da177e4 4829
544393fe
TW
4830 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
4831 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
1da177e4 4832
544393fe
TW
4833 temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
4834 if(offset & 0x07) temp++;
4835 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
1da177e4
LT
4836}
4837
4838/* Set CRT2 sync and PanelLink mode */
4839static void
544393fe 4840SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
1da177e4 4841{
544393fe 4842 unsigned short tempah=0, tempbl, infoflag;
1da177e4 4843
544393fe 4844 tempbl = 0xC0;
1da177e4 4845
544393fe
TW
4846 if(SiS_Pr->UseCustomMode) {
4847 infoflag = SiS_Pr->CInfoFlag;
4848 } else {
4849 infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
4850 }
1da177e4 4851
544393fe 4852 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
1da177e4 4853
544393fe
TW
4854 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4855 tempah = 0;
4856 } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
4857 tempah = SiS_Pr->SiS_LCDInfo;
4858 } else tempah = infoflag >> 8;
4859 tempah &= 0xC0;
4860 tempah |= 0x20;
4861 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4862 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4863 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
4864 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
4865 tempah |= 0xf0;
4866 }
4867 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4868 (SiS_Pr->SiS_IF_DEF_DSTN) ||
4869 (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
4870 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
4871 (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
4872 tempah |= 0x30;
4873 }
4874 if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4875 (SiS_Pr->SiS_IF_DEF_DSTN) ) {
4876 tempah &= ~0xc0;
4877 }
4878 }
4879 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4880 if(SiS_Pr->ChipType >= SIS_315H) {
4881 tempah >>= 3;
4882 tempah &= 0x18;
4883 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
4884 /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
4885 } else {
4886 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
4887 }
4888 } else {
4889 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4890 }
1da177e4 4891
544393fe 4892 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1da177e4 4893
544393fe 4894 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 4895
f7854e5d 4896#ifdef CONFIG_FB_SIS_300 /* ---- 300 series --- */
1da177e4 4897
544393fe 4898 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) { /* 630 - 301B(-DH) */
1da177e4 4899
544393fe
TW
4900 tempah = infoflag >> 8;
4901 tempbl = 0;
4902 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4903 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4904 tempah = SiS_Pr->SiS_LCDInfo;
4905 tempbl = (tempah >> 6) & 0x03;
4906 }
4907 }
4908 tempah &= 0xC0;
4909 tempah |= 0x20;
4910 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4911 tempah |= 0xc0;
4912 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4913 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
4914 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4915 }
1da177e4 4916
544393fe 4917 } else { /* 630 - 301 */
1da177e4 4918
544393fe
TW
4919 tempah = ((infoflag >> 8) & 0xc0) | 0x20;
4920 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4921 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
1da177e4 4922
544393fe 4923 }
1da177e4 4924
f7854e5d 4925#endif /* CONFIG_FB_SIS_300 */
1da177e4 4926
544393fe 4927 } else {
1da177e4 4928
f7854e5d 4929#ifdef CONFIG_FB_SIS_315 /* ------- 315 series ------ */
1da177e4 4930
544393fe 4931 if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* 315 - LVDS */
1da177e4 4932
544393fe
TW
4933 tempbl = 0;
4934 if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
4935 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
4936 tempah = infoflag >> 8;
4937 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4938 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
4939 }
4940 } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
4941 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
4942 tempah = infoflag >> 8;
4943 tempbl = 0x03;
4944 } else {
4945 tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
4946 tempbl = (tempah >> 6) & 0x03;
4947 tempbl |= 0x08;
4948 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
4949 }
4950 tempah &= 0xC0;
4951 tempah |= 0x20;
4952 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4953 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) tempah |= 0xc0;
4954 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4955 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
4956 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4957 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4958 }
4959 }
1da177e4 4960
544393fe 4961 } else { /* 315 - TMDS */
1da177e4 4962
544393fe
TW
4963 tempah = tempbl = infoflag >> 8;
4964 if(!SiS_Pr->UseCustomMode) {
4965 tempbl = 0;
4966 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4967 if(ModeNo <= 0x13) {
4968 tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
4969 }
4970 }
4971 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
4972 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
4973 if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4974 tempah = SiS_Pr->SiS_LCDInfo;
1da177e4
LT
4975 tempbl = (tempah >> 6) & 0x03;
4976 }
544393fe
TW
4977 }
4978 }
4979 }
4980 tempah &= 0xC0;
4981 tempah |= 0x20;
4982 if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4983 if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4984 /* Imitate BIOS bug */
4985 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempah |= 0xc0;
4986 }
4987 if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4988 tempah >>= 3;
4989 tempah &= 0x18;
4990 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
4991 } else {
4992 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4993 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
4994 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4995 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4996 }
4997 }
4998 }
1da177e4 4999
544393fe 5000 }
f7854e5d 5001#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
5002 }
5003 }
5004}
5005
544393fe 5006/* Set CRT2 FIFO on 300/540/630/730 */
f7854e5d 5007#ifdef CONFIG_FB_SIS_300
1da177e4 5008static void
544393fe
TW
5009SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
5010{
5011 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5012 unsigned short temp, index, modeidindex, refreshratetableindex;
5013 unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
5014 unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
5015 unsigned int data, pci50, pciA0;
5016 static const unsigned char colortharray[] = {
5017 1, 1, 2, 2, 3, 4
1da177e4
LT
5018 };
5019
5020 SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
5021
5022 if(!SiS_Pr->CRT1UsesCustomMode) {
5023
5024 CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */
5025 SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
5026 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
5027 SiS_Pr->SiS_SelectCRT2Rate = 0;
544393fe 5028 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
1da177e4
LT
5029
5030 if(CRT1ModeNo >= 0x13) {
544393fe
TW
5031 /* Get VCLK */
5032 index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
5033 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
1da177e4 5034
544393fe
TW
5035 /* Get colordepth */
5036 colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
5037 if(!colorth) colorth++;
1da177e4
LT
5038 }
5039
5040 } else {
5041
5042 CRT1ModeNo = 0xfe;
544393fe
TW
5043
5044 /* Get VCLK */
5045 VCLK = SiS_Pr->CSRClock_CRT1;
5046
5047 /* Get color depth */
5048 colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
1da177e4
LT
5049
5050 }
5051
5052 if(CRT1ModeNo >= 0x13) {
544393fe
TW
5053 /* Get MCLK */
5054 if(SiS_Pr->ChipType == SIS_300) {
5055 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
5056 } else {
5057 index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
5058 }
5059 index &= 0x07;
5060 MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
1da177e4 5061
544393fe
TW
5062 temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
5063 if(!temp) temp++;
5064 temp <<= 2;
1da177e4 5065
544393fe 5066 data2 = temp - ((colorth * VCLK) / MCLK);
1da177e4 5067
544393fe
TW
5068 temp = (28 * 16) % data2;
5069 data2 = (28 * 16) / data2;
5070 if(temp) data2++;
1da177e4 5071
544393fe 5072 if(SiS_Pr->ChipType == SIS_300) {
1da177e4 5073
544393fe
TW
5074 SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
5075 data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
5076
5077 } else {
5078
544393fe
TW
5079 pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
5080 pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
1da177e4 5081
544393fe 5082 if(SiS_Pr->ChipType == SIS_730) {
1da177e4 5083
544393fe
TW
5084 index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
5085 index += (unsigned short)(((pci50 >> 9)) & 0x03);
1da177e4 5086
544393fe
TW
5087 /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
5088 index = 0; /* -- do it like the BIOS anyway... */
1da177e4 5089
544393fe 5090 } else {
1da177e4 5091
544393fe
TW
5092 pci50 >>= 24;
5093 pciA0 >>= 24;
1da177e4 5094
544393fe
TW
5095 index = (pci50 >> 1) & 0x07;
5096
5097 if(pci50 & 0x01) index += 6;
5098 if(!(pciA0 & 0x01)) index += 24;
5099
5100 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
1da177e4 5101
544393fe 5102 }
1da177e4 5103
544393fe
TW
5104 data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
5105 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
1da177e4 5106
544393fe 5107 }
1da177e4 5108
544393fe 5109 data += data2; /* CRT1 Request Period */
1da177e4 5110
544393fe
TW
5111 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5112 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
1da177e4 5113
544393fe 5114 if(!SiS_Pr->UseCustomMode) {
1da177e4 5115
544393fe
TW
5116 CRT2ModeNo = ModeNo;
5117 SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
1da177e4 5118
544393fe 5119 refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
1da177e4 5120
544393fe
TW
5121 /* Get VCLK */
5122 index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
5123 VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
1da177e4 5124
544393fe
TW
5125 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5126 if(SiS_Pr->SiS_UseROM) {
5127 if(ROMAddr[0x220] & 0x01) {
5128 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
5129 }
5130 }
5131 }
5132
5133 } else {
5134
5135 /* Get VCLK */
5136 CRT2ModeNo = 0xfe;
5137 VCLK = SiS_Pr->CSRClock;
5138
5139 }
1da177e4 5140
544393fe
TW
5141 /* Get colordepth */
5142 colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
5143 if(!colorth) colorth++;
1da177e4 5144
544393fe
TW
5145 data = data * VCLK * colorth;
5146 temp = data % (MCLK << 4);
5147 data = data / (MCLK << 4);
5148 if(temp) data++;
1da177e4 5149
544393fe
TW
5150 if(data < 6) data = 6;
5151 else if(data > 0x14) data = 0x14;
1da177e4 5152
544393fe
TW
5153 if(SiS_Pr->ChipType == SIS_300) {
5154 temp = 0x16;
5155 if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
5156 temp = 0x13;
5157 } else {
5158 temp = 0x16;
5159 if(( (SiS_Pr->ChipType == SIS_630) ||
5160 (SiS_Pr->ChipType == SIS_730) ) &&
5161 (SiS_Pr->ChipRevision >= 0x30))
5162 temp = 0x1b;
5163 }
5164 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
1da177e4 5165
544393fe
TW
5166 if((SiS_Pr->ChipType == SIS_630) &&
5167 (SiS_Pr->ChipRevision >= 0x30)) {
5168 if(data > 0x13) data = 0x13;
5169 }
5170 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
1da177e4
LT
5171
5172 } else { /* If mode <= 0x13, we just restore everything */
5173
544393fe
TW
5174 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5175 SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
1da177e4
LT
5176
5177 }
5178}
5179#endif
5180
5181/* Set CRT2 FIFO on 315/330 series */
f7854e5d 5182#ifdef CONFIG_FB_SIS_315
1da177e4 5183static void
544393fe 5184SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
1da177e4
LT
5185{
5186 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
544393fe 5187 if( (SiS_Pr->ChipType == SIS_760) &&
1da177e4
LT
5188 (SiS_Pr->SiS_SysFlags & SF_760LFB) &&
5189 (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
5190 (SiS_Pr->SiS_VGAHDE >= 1280) &&
5191 (SiS_Pr->SiS_VGAVDE >= 1024) ) {
5192 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
5193 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
5194 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5195 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
5196 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5197 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
5198 } else {
5199 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
5200 }
5201
5202}
5203#endif
5204
544393fe
TW
5205static unsigned short
5206SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
1da177e4 5207{
544393fe 5208 unsigned int tempax,tempbx;
1da177e4
LT
5209
5210 tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
5211 tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
5212 tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
544393fe 5213 return (unsigned short)tempax;
1da177e4
LT
5214}
5215
5216/* Set Part 1 / SiS bridge slave mode */
5217static void
544393fe
TW
5218SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
5219 unsigned short RefreshRateTableIndex)
5220{
5221 unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
5222 static const unsigned short CRTranslation[] = {
5223 /* CR0 CR1 CR2 CR3 CR4 CR5 CR6 CR7 */
5224 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
5225 /* CR8 CR9 SR0A SR0B SR0C SR0D SR0E CR0F */
5226 0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
5227 /* CR10 CR11 CR12 CR13 CR14 CR15 CR16 CR17 */
5228 0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
5229 };
1da177e4
LT
5230
5231 if(ModeNo <= 0x13) {
5232 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
1da177e4
LT
5233 } else if(SiS_Pr->UseCustomMode) {
5234 modeflag = SiS_Pr->CModeFlag;
1da177e4
LT
5235 xres = SiS_Pr->CHDisplay;
5236 } else {
5237 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1da177e4
LT
5238 xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
5239 }
5240
5241 /* The following is only done if bridge is in slave mode: */
5242
544393fe
TW
5243 if(SiS_Pr->ChipType >= SIS_315H) {
5244 if(xres >= 1600) { /* BIOS: == 1600 */
1da177e4
LT
5245 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
5246 }
5247 }
5248
544393fe 5249 SiS_Pr->CHTotal = 8224; /* Max HT, 0x2020, results in 0x3ff in registers */
1da177e4 5250
544393fe
TW
5251 SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
5252 if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
1da177e4 5253
544393fe 5254 SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
1da177e4 5255 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
544393fe 5256 SiS_Pr->CHBlankStart += 16;
1da177e4
LT
5257 }
5258
544393fe
TW
5259 SiS_Pr->CHBlankEnd = 32;
5260 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5261 if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
1da177e4
LT
5262 }
5263
544393fe
TW
5264 temp = SiS_Pr->SiS_VGAHT - 96;
5265 if(!(modeflag & HalfDCLK)) temp -= 32;
5266 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
5267 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
5268 temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
5269 temp -= 3;
5270 temp <<= 3;
5271 } else {
5272 if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
1da177e4 5273 }
544393fe 5274 SiS_Pr->CHSyncStart = temp;
1da177e4 5275
544393fe 5276 SiS_Pr->CHSyncEnd = 0xffe8; /* results in 0x2000 in registers */
1da177e4 5277
544393fe 5278 SiS_Pr->CVTotal = 2049; /* Max VT, 0x0801, results in 0x7ff in registers */
1da177e4 5279
544393fe
TW
5280 VGAVDE = SiS_Pr->SiS_VGAVDE;
5281 if (VGAVDE == 357) VGAVDE = 350;
5282 else if(VGAVDE == 360) VGAVDE = 350;
5283 else if(VGAVDE == 375) VGAVDE = 350;
5284 else if(VGAVDE == 405) VGAVDE = 400;
5285 else if(VGAVDE == 420) VGAVDE = 400;
5286 else if(VGAVDE == 525) VGAVDE = 480;
5287 else if(VGAVDE == 1056) VGAVDE = 1024;
5288 SiS_Pr->CVDisplay = VGAVDE;
1da177e4 5289
544393fe 5290 SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
1da177e4 5291
544393fe
TW
5292 SiS_Pr->CVBlankEnd = 1;
5293 if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
1da177e4 5294
544393fe
TW
5295 temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
5296 SiS_Pr->CVSyncStart = VGAVDE + temp;
1da177e4 5297
544393fe
TW
5298 temp >>= 3;
5299 SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
1da177e4 5300
544393fe
TW
5301 SiS_CalcCRRegisters(SiS_Pr, 0);
5302 SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
1da177e4 5303
544393fe
TW
5304 for(i = 0; i <= 7; i++) {
5305 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
1da177e4 5306 }
544393fe
TW
5307 for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
5308 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
1da177e4 5309 }
544393fe
TW
5310 for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
5311 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
1da177e4 5312 }
544393fe
TW
5313 for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
5314 SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
1da177e4
LT
5315 }
5316
544393fe
TW
5317 temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
5318 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
1da177e4 5319
544393fe
TW
5320 temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
5321 if(modeflag & DoubleScanMode) temp |= 0x80;
5322 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
1da177e4 5323
544393fe
TW
5324 temp = 0;
5325 temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
5326 if(modeflag & HalfDCLK) temp |= 0x08;
5327 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
1da177e4 5328
544393fe
TW
5329 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00); /* CR14: (text mode: underline location) */
5330 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00); /* CR17: n/a */
1da177e4 5331
544393fe 5332 temp = 0;
1da177e4 5333 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
544393fe 5334 temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
1da177e4 5335 }
544393fe 5336 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* SR0E, dither[7] */
1da177e4
LT
5337
5338 temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
544393fe 5339 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp); /* ? */
1da177e4
LT
5340}
5341
5342/* Setup panel link
5343 * This is used for LVDS, LCDA and Chrontel TV output
5344 * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
5345 */
5346static void
544393fe
TW
5347SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5348 unsigned short RefreshRateTableIndex)
1da177e4 5349{
544393fe
TW
5350 unsigned short modeflag, resinfo = 0;
5351 unsigned short push2, tempax, tempbx, tempcx, temp;
5352 unsigned int tempeax = 0, tempebx, tempecx, tempvcfact = 0;
c30660ea 5353 bool islvds = false, issis = false, chkdclkfirst = false;
f7854e5d 5354#ifdef CONFIG_FB_SIS_300
544393fe 5355 unsigned short crt2crtc = 0;
1da177e4 5356#endif
f7854e5d 5357#ifdef CONFIG_FB_SIS_315
544393fe 5358 unsigned short pushcx;
1da177e4
LT
5359#endif
5360
5361 if(ModeNo <= 0x13) {
5362 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5363 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
f7854e5d 5364#ifdef CONFIG_FB_SIS_300
1da177e4
LT
5365 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5366#endif
5367 } else if(SiS_Pr->UseCustomMode) {
5368 modeflag = SiS_Pr->CModeFlag;
1da177e4
LT
5369 } else {
5370 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5371 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
f7854e5d 5372#ifdef CONFIG_FB_SIS_300
544393fe 5373 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
1da177e4
LT
5374#endif
5375 }
5376
5377 /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
5378 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
c30660ea 5379 islvds = true;
1da177e4
LT
5380 }
5381
5382 /* is really sis if sis bridge, but not 301B-DH */
5383 if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
c30660ea 5384 issis = true;
1da177e4
LT
5385 }
5386
544393fe 5387 if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
1da177e4 5388 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
c30660ea 5389 chkdclkfirst = true;
1da177e4
LT
5390 }
5391 }
5392
f7854e5d 5393#ifdef CONFIG_FB_SIS_315
544393fe 5394 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
1da177e4
LT
5395 if(IS_SIS330) {
5396 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5397 } else if(IS_SIS740) {
5398 if(islvds) {
5399 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5400 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
5401 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5402 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5403 }
5404 } else {
5405 if(islvds) {
5406 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5407 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
5408 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5409 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
544393fe 5410 if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
1da177e4
LT
5411 if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
5412 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5413 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
5414 }
5415 }
5416 }
5417 }
5418 }
5419#endif
5420
5421 /* Horizontal */
5422
5423 tempax = SiS_Pr->SiS_LCDHDES;
5424 if(islvds) {
5425 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
544393fe
TW
5426 if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
5427 if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
5428 (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
5429 tempax -= 8;
1da177e4
LT
5430 }
5431 }
5432 }
5433 }
5434
5435 temp = (tempax & 0x0007);
5436 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp); /* BPLHDESKEW[2:0] */
5437 temp = (tempax >> 3) & 0x00FF;
5438 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp); /* BPLHDESKEW[10:3] */
5439
5440 tempbx = SiS_Pr->SiS_HDE;
5441 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
1da177e4
LT
5442 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5443 tempbx = SiS_Pr->PanelXRes;
5444 }
544393fe
TW
5445 if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
5446 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
5447 (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
5448 tempbx >>= 1;
5449 }
1da177e4
LT
5450 }
5451
5452 tempax += tempbx;
5453 if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
5454
5455 temp = tempax;
5456 if(temp & 0x07) temp += 8;
5457 temp >>= 3;
5458 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp); /* BPLHDEE */
5459
5460 tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
5461
5462 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5463 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5464 if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
5465 }
5466 }
5467
5468 tempcx += tempax;
5469 if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
5470
5471 temp = (tempcx >> 3) & 0x00FF;
5472 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5473 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
544393fe
TW
5474 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5475 switch(ModeNo) {
5476 case 0x04:
5477 case 0x05:
5478 case 0x0d: temp = 0x56; break;
5479 case 0x10: temp = 0x60; break;
5480 case 0x13: temp = 0x5f; break;
5481 case 0x40:
5482 case 0x41:
5483 case 0x4f:
5484 case 0x43:
5485 case 0x44:
5486 case 0x62:
5487 case 0x56:
5488 case 0x53:
5489 case 0x5d:
5490 case 0x5e: temp = 0x54; break;
5491 }
5492 }
1da177e4
LT
5493 }
5494 }
5495 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp); /* BPLHRS */
5496
5497 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5498 temp += 2;
5499 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
544393fe
TW
5500 temp += 8;
5501 if(SiS_Pr->PanelHRE != 999) {
5502 temp = tempcx + SiS_Pr->PanelHRE;
1da177e4
LT
5503 if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
5504 temp >>= 3;
544393fe 5505 }
1da177e4
LT
5506 }
5507 } else {
5508 temp += 10;
5509 }
5510
5511 temp &= 0x1F;
5512 temp |= ((tempcx & 0x07) << 5);
1da177e4
LT
5513 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp); /* BPLHRE */
5514
5515 /* Vertical */
5516
5517 tempax = SiS_Pr->SiS_VGAVDE;
5518 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5519 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5520 tempax = SiS_Pr->PanelYRes;
5521 }
5522 }
5523
5524 tempbx = SiS_Pr->SiS_LCDVDES + tempax;
5525 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5526
5527 push2 = tempbx;
5528
5529 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
544393fe 5530 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 5531 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
544393fe 5532 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
1da177e4
LT
5533 tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
5534 }
5535 }
5536 }
5537 if(islvds) tempcx >>= 1;
5538 else tempcx >>= 2;
5539
5540 if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
5541 (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
5542 (SiS_Pr->PanelVRS != 999) ) {
5543 tempcx = SiS_Pr->PanelVRS;
5544 tempbx += tempcx;
5545 if(issis) tempbx++;
5546 } else {
5547 tempbx += tempcx;
544393fe 5548 if(SiS_Pr->ChipType < SIS_315H) tempbx++;
1da177e4
LT
5549 else if(issis) tempbx++;
5550 }
5551
544393fe 5552 if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
1da177e4
LT
5553
5554 temp = tempbx & 0x00FF;
5555 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5556 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
544393fe 5557 if(ModeNo == 0x10) temp = 0xa9;
1da177e4
LT
5558 }
5559 }
544393fe 5560 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp); /* BPLVRS */
1da177e4
LT
5561
5562 tempcx >>= 3;
5563 tempcx++;
5564
5565 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5566 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5567 if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
5568 }
5569 }
5570
5571 tempcx += tempbx;
5572 temp = tempcx & 0x000F;
5573 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); /* BPLVRE */
5574
5575 temp = ((tempbx >> 8) & 0x07) << 3;
5576 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5577 if(SiS_Pr->SiS_HDE != 640) {
5578 if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5579 }
5580 } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5581 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40;
5582 tempbx = 0x87;
544393fe
TW
5583 if((SiS_Pr->ChipType >= SIS_315H) ||
5584 (SiS_Pr->ChipRevision >= 0x30)) {
1da177e4
LT
5585 tempbx = 0x07;
5586 if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
5587 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03) temp |= 0x80;
5588 }
544393fe 5589 /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
1da177e4
LT
5590 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5591 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5592 if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
5593 } else {
5594 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
5595 }
5596 }
5597 }
5598 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
5599
544393fe 5600 tempbx = push2; /* BPLVDEE */
1da177e4 5601
544393fe 5602 tempcx = SiS_Pr->SiS_LCDVDES; /* BPLVDES */
1da177e4
LT
5603
5604 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5605 switch(SiS_Pr->SiS_LCDResInfo) {
5606 case Panel_640x480:
544393fe
TW
5607 tempbx = SiS_Pr->SiS_VGAVDE - 1;
5608 tempcx = SiS_Pr->SiS_VGAVDE;
1da177e4
LT
5609 break;
5610 case Panel_800x600:
544393fe
TW
5611 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5612 if(resinfo == SIS_RI_800x600) tempcx++;
5613 }
1da177e4
LT
5614 break;
5615 case Panel_1024x600:
544393fe
TW
5616 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5617 if(resinfo == SIS_RI_1024x600) tempcx++;
5618 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1da177e4
LT
5619 if(resinfo == SIS_RI_800x600) tempcx++;
5620 }
544393fe 5621 }
1da177e4
LT
5622 break;
5623 case Panel_1024x768:
544393fe
TW
5624 if(SiS_Pr->ChipType < SIS_315H) {
5625 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5626 if(resinfo == SIS_RI_1024x768) tempcx++;
1da177e4 5627 }
544393fe 5628 }
1da177e4
LT
5629 break;
5630 }
5631 }
5632
5633 temp = ((tempbx >> 8) & 0x07) << 3;
544393fe 5634 temp |= ((tempcx >> 8) & 0x07);
1da177e4 5635 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
1da177e4
LT
5636 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
5637 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
5638
5639 /* Vertical scaling */
5640
544393fe 5641 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 5642
f7854e5d 5643#ifdef CONFIG_FB_SIS_300 /* 300 series */
1da177e4 5644 tempeax = SiS_Pr->SiS_VGAVDE << 6;
544393fe
TW
5645 temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
5646 tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
1da177e4
LT
5647 if(temp) tempeax++;
5648
5649 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
5650
544393fe 5651 temp = (unsigned short)(tempeax & 0x00FF);
1da177e4
LT
5652 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp); /* BPLVCFACT */
5653 tempvcfact = temp;
f7854e5d 5654#endif /* CONFIG_FB_SIS_300 */
1da177e4
LT
5655
5656 } else {
5657
f7854e5d 5658#ifdef CONFIG_FB_SIS_315 /* 315 series */
1da177e4
LT
5659 tempeax = SiS_Pr->SiS_VGAVDE << 18;
5660 tempebx = SiS_Pr->SiS_VDE;
5661 temp = (tempeax % tempebx);
5662 tempeax = tempeax / tempebx;
5663 if(temp) tempeax++;
5664 tempvcfact = tempeax;
5665
544393fe 5666 temp = (unsigned short)(tempeax & 0x00FF);
1da177e4 5667 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
544393fe 5668 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
1da177e4 5669 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
544393fe 5670 temp = (unsigned short)((tempeax & 0x00030000) >> 16);
1da177e4
LT
5671 if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
5672 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
5673
544393fe
TW
5674 if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
5675 temp = (unsigned short)(tempeax & 0x00FF);
1da177e4 5676 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
544393fe 5677 temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
1da177e4 5678 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
544393fe 5679 temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
1da177e4
LT
5680 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
5681 temp = 0;
5682 if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
5683 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
5684 }
5685#endif
5686
5687 }
5688
5689 /* Horizontal scaling */
5690
5691 tempeax = SiS_Pr->SiS_VGAHDE; /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
5692 if(chkdclkfirst) {
5693 if(modeflag & HalfDCLK) tempeax >>= 1;
5694 }
5695 tempebx = tempeax << 16;
5696 if(SiS_Pr->SiS_HDE == tempeax) {
5697 tempecx = 0xFFFF;
5698 } else {
5699 tempecx = tempebx / SiS_Pr->SiS_HDE;
544393fe 5700 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4
LT
5701 if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
5702 }
5703 }
5704
544393fe 5705 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4
LT
5706 tempeax = (tempebx / tempecx) - 1;
5707 } else {
5708 tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
5709 }
5710 tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
544393fe 5711 temp = (unsigned short)(tempecx & 0x00FF);
1da177e4
LT
5712 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
5713
544393fe 5714 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4 5715 tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
544393fe 5716 tempbx = (unsigned short)(tempeax & 0xFFFF);
1da177e4
LT
5717 } else {
5718 tempeax = SiS_Pr->SiS_VGAVDE << 6;
5719 tempbx = tempvcfact & 0x3f;
5720 if(tempbx == 0) tempbx = 64;
5721 tempeax /= tempbx;
544393fe 5722 tempbx = (unsigned short)(tempeax & 0xFFFF);
1da177e4
LT
5723 }
5724 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
5725 if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
5726 if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
5727 else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) tempbx = 1;
5728 }
5729
5730 temp = ((tempbx >> 8) & 0x07) << 3;
5731 temp = temp | ((tempecx >> 8) & 0x07);
5732 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
5733 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
5734
544393fe 5735 tempecx >>= 16; /* BPLHCFACT */
1da177e4
LT
5736 if(!chkdclkfirst) {
5737 if(modeflag & HalfDCLK) tempecx >>= 1;
5738 }
544393fe 5739 temp = (unsigned short)((tempecx & 0xFF00) >> 8);
1da177e4 5740 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
544393fe 5741 temp = (unsigned short)(tempecx & 0x00FF);
1da177e4
LT
5742 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
5743
f7854e5d 5744#ifdef CONFIG_FB_SIS_315
544393fe 5745 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4 5746 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
544393fe 5747 if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
1da177e4
LT
5748 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
5749 }
5750 } else {
5751 if(islvds) {
544393fe 5752 if(SiS_Pr->ChipType == SIS_740) {
1da177e4
LT
5753 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
5754 } else {
5755 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
5756 }
5757 }
5758 }
5759 }
5760#endif
5761
f7854e5d 5762#ifdef CONFIG_FB_SIS_300
1da177e4 5763 if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
544393fe
TW
5764 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
5765 unsigned char *trumpdata;
5766 int i, j = crt2crtc;
5767 unsigned char TrumpMode13[4] = { 0x01, 0x10, 0x2c, 0x00 };
5768 unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
5769 unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
5770
5771 if(SiS_Pr->SiS_UseROM) {
5772 trumpdata = &ROMAddr[0x8001 + (j * 80)];
5773 } else {
5774 if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
5775 trumpdata = &SiS300_TrumpionData[j][0];
5776 }
1da177e4
LT
5777
5778 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
5779 for(i=0; i<5; i++) {
544393fe 5780 SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
1da177e4
LT
5781 }
5782 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
544393fe 5783 if(ModeNo == 0x13) {
1da177e4
LT
5784 for(i=0; i<4; i++) {
5785 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
5786 }
5787 } else if(ModeNo == 0x10) {
5788 for(i=0; i<4; i++) {
5789 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
5790 SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
5791 }
5792 }
5793 }
5794 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
5795 }
5796#endif
5797
f7854e5d 5798#ifdef CONFIG_FB_SIS_315
1da177e4
LT
5799 if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5800 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
5801 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
5802 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
5803 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
5804 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
5805 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
5806 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
544393fe
TW
5807 tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
5808 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5809 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5810 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
1da177e4 5811 tempax += 64;
544393fe
TW
5812 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
5813 temp = (tempax >> 8) << 3;
1da177e4 5814 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
544393fe
TW
5815 tempax += 32; /* Blpe = lBlps+32 */
5816 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
5817 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml = 0 */
5818 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
1da177e4
LT
5819
5820 tempax = SiS_Pr->SiS_VDE;
544393fe
TW
5821 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5822 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5823 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
1da177e4 5824 tempax >>= 1;
544393fe
TW
5825 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
5826 temp = (tempax >> 8) << 3;
1da177e4
LT
5827 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
5828
5829 tempeax = SiS_Pr->SiS_HDE;
544393fe
TW
5830 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5831 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5832 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
5833 tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
5834 temp = tempeax & 0x7f;
5835 tempeax >>= 7;
1da177e4 5836 if(temp) tempeax++;
544393fe
TW
5837 temp = tempeax & 0x3f;
5838 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
5839 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
1da177e4
LT
5840 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
5841 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
544393fe 5842 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
1da177e4
LT
5843
5844 tempax = SiS_Pr->SiS_HDE;
544393fe
TW
5845 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5846 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5847 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5848 tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
1da177e4
LT
5849 pushcx = tempax;
5850 temp = tempax & 0x00FF;
5851 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
5852 temp = ((tempax & 0xFF00) >> 8) << 3;
17d6ce11 5853 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x44, 0x07, temp);
1da177e4 5854
544393fe
TW
5855 tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
5856 if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
5857 SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
5858 SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
5859 tempeax = tempax * pushcx;
5860 temp = tempeax & 0xFF;
1da177e4 5861 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
544393fe 5862 temp = (tempeax & 0xFF00) >> 8;
1da177e4 5863 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
544393fe 5864 temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
1da177e4 5865 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
544393fe 5866 temp = ((tempeax & 0x01000000) >> 24) << 7;
17d6ce11 5867 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port, 0x3C, 0x7F, temp);
1da177e4
LT
5868
5869 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
5870 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
5871 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
5872 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
5873 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
5874
5875 if(SiS_Pr->SiS_IF_DEF_FSTN) {
5876 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
5877 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
5878 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
5879 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
5880 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
5881 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
5882 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
5883 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
5884 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
5885 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
5886 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
5887 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
5888 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
5889 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
5890 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
5891 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
5892 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
5893 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
5894 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
5895 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
5896 }
5897 }
f7854e5d 5898#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
5899}
5900
5901/* Set Part 1 */
5902static void
544393fe
TW
5903SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
5904 unsigned short RefreshRateTableIndex)
1da177e4 5905{
f7854e5d 5906#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
544393fe 5907 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1da177e4 5908#endif
544393fe
TW
5909 unsigned short temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
5910 unsigned short pushbx=0, CRT1Index=0, modeflag, resinfo=0;
f7854e5d 5911#ifdef CONFIG_FB_SIS_315
544393fe 5912 unsigned short tempbl=0;
1da177e4
LT
5913#endif
5914
5915 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
544393fe 5916 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
5917 return;
5918 }
5919
5920 if(ModeNo <= 0x13) {
5921 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5922 } else if(SiS_Pr->UseCustomMode) {
5923 modeflag = SiS_Pr->CModeFlag;
5924 } else {
544393fe 5925 CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
1da177e4
LT
5926 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5927 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5928 }
5929
544393fe 5930 SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4 5931
544393fe 5932 if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
1da177e4
LT
5933 (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
5934 (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
5935
544393fe 5936 if(SiS_Pr->ChipType < SIS_315H ) {
f7854e5d 5937#ifdef CONFIG_FB_SIS_300
544393fe 5938 SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
1da177e4
LT
5939#endif
5940 } else {
f7854e5d 5941#ifdef CONFIG_FB_SIS_315
544393fe 5942 SiS_SetCRT2FIFO_310(SiS_Pr);
1da177e4
LT
5943#endif
5944 }
5945
5946 /* 1. Horizontal setup */
5947
544393fe 5948 if(SiS_Pr->ChipType < SIS_315H ) {
1da177e4 5949
f7854e5d 5950#ifdef CONFIG_FB_SIS_300 /* ------------- 300 series --------------*/
1da177e4 5951
544393fe
TW
5952 temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
5953 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
1da177e4 5954
544393fe
TW
5955 temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
5956 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
1da177e4 5957
544393fe
TW
5958 temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
5959 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
1da177e4
LT
5960
5961 pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA2HRS 0x0B,0x0C */
544393fe
TW
5962 tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
5963 tempbx = pushbx + tempcx;
5964 tempcx <<= 1;
5965 tempcx += tempbx;
1da177e4
LT
5966
5967 bridgeadd = 12;
5968
f7854e5d 5969#endif /* CONFIG_FB_SIS_300 */
1da177e4
LT
5970
5971 } else {
5972
f7854e5d 5973#ifdef CONFIG_FB_SIS_315 /* ------------------- 315/330 series --------------- */
1da177e4
LT
5974
5975 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */
5976 if(modeflag & HalfDCLK) {
5977 if(SiS_Pr->SiS_VBType & VB_SISVB) {
5978 tempcx >>= 1;
5979 } else {
5980 tempax = SiS_Pr->SiS_VGAHDE >> 1;
5981 tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
5982 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
5983 tempcx = SiS_Pr->SiS_HT - tempax;
5984 }
5985 }
5986 }
5987 tempcx--;
5988 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx); /* CRT2 Horizontal Total */
5989 temp = (tempcx >> 4) & 0xF0;
5990 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp); /* CRT2 Horizontal Total Overflow [7:4] */
5991
5992 tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HDEE 0x0A,0x0C */
5993 tempbx = SiS_Pr->SiS_VGAHDE;
5994 tempcx -= tempbx;
5995 tempcx >>= 2;
5996 if(modeflag & HalfDCLK) {
5997 tempbx >>= 1;
5998 tempcx >>= 1;
5999 }
6000 tempbx += 16;
6001
6002 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx); /* CRT2 Horizontal Display Enable End */
6003
6004 pushbx = tempbx;
6005 tempcx >>= 1;
6006 tempbx += tempcx;
6007 tempcx += tempbx;
6008
6009 bridgeadd = 16;
6010
6011 if(SiS_Pr->SiS_VBType & VB_SISVB) {
544393fe 6012 if(SiS_Pr->ChipType >= SIS_661) {
1da177e4
LT
6013 if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
6014 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
6015 if(resinfo == SIS_RI_1280x1024) {
6016 tempcx = (tempcx & 0xff00) | 0x30;
6017 } else if(resinfo == SIS_RI_1600x1200) {
6018 tempcx = (tempcx & 0xff00) | 0xff;
6019 }
6020 }
6021 }
6022 }
6023
f7854e5d 6024#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
6025
6026 } /* 315/330 series */
6027
6028 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6029
544393fe 6030 if(SiS_Pr->UseCustomMode) {
1da177e4
LT
6031 tempbx = SiS_Pr->CHSyncStart + bridgeadd;
6032 tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
6033 tempax = SiS_Pr->SiS_VGAHT;
6034 if(modeflag & HalfDCLK) tempax >>= 1;
6035 tempax--;
6036 if(tempcx > tempax) tempcx = tempax;
6037 }
6038
6039 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6040 unsigned char cr4, cr14, cr5, cr15;
6041 if(SiS_Pr->UseCustomMode) {
6042 cr4 = SiS_Pr->CCRT1CRTC[4];
6043 cr14 = SiS_Pr->CCRT1CRTC[14];
6044 cr5 = SiS_Pr->CCRT1CRTC[5];
6045 cr15 = SiS_Pr->CCRT1CRTC[15];
6046 } else {
6047 cr4 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
6048 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
6049 cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
6050 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
6051 }
544393fe
TW
6052 tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
6053 tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
1da177e4
LT
6054 tempcx &= 0x00FF;
6055 tempcx |= (tempbx & 0xFF00);
544393fe
TW
6056 tempbx += bridgeadd;
6057 tempcx += bridgeadd;
1da177e4
LT
6058 tempax = SiS_Pr->SiS_VGAHT;
6059 if(modeflag & HalfDCLK) tempax >>= 1;
6060 tempax--;
6061 if(tempcx > tempax) tempcx = tempax;
544393fe 6062 }
1da177e4 6063
544393fe
TW
6064 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
6065 tempbx = 1040;
6066 tempcx = 1044; /* HWCursor bug! */
6067 }
1da177e4
LT
6068
6069 }
6070
6071 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx); /* CRT2 Horizontal Retrace Start */
6072
6073 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx); /* CRT2 Horizontal Retrace End */
6074
6075 temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
6076 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp); /* Overflow */
6077
6078 /* 2. Vertical setup */
6079
6080 tempcx = SiS_Pr->SiS_VGAVT - 1;
6081 temp = tempcx & 0x00FF;
6082
544393fe 6083 if(SiS_Pr->ChipType < SIS_661) {
1da177e4 6084 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
544393fe 6085 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4
LT
6086 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6087 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6088 temp--;
6089 }
544393fe 6090 }
1da177e4 6091 } else {
544393fe
TW
6092 temp--;
6093 }
6094 } else if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4
LT
6095 temp--;
6096 }
6097 }
6098 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp); /* CRT2 Vertical Total */
6099
6100 tempbx = SiS_Pr->SiS_VGAVDE - 1;
6101 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx); /* CRT2 Vertical Display Enable End */
6102
6103 temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
6104 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp); /* Overflow */
6105
544393fe
TW
6106 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
6107 tempbx++;
6108 tempax = tempbx;
1da177e4
LT
6109 tempcx++;
6110 tempcx -= tempax;
6111 tempcx >>= 2;
6112 tempbx += tempcx;
6113 if(tempcx < 4) tempcx = 4;
6114 tempcx >>= 2;
6115 tempcx += tempbx;
6116 tempcx++;
6117 } else {
544393fe
TW
6118 tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
6119 tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
1da177e4
LT
6120 }
6121
6122 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6123 if(SiS_Pr->UseCustomMode) {
6124 tempbx = SiS_Pr->CVSyncStart;
6125 tempcx = SiS_Pr->CVSyncEnd;
6126 }
544393fe 6127 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
1da177e4
LT
6128 unsigned char cr8, cr7, cr13;
6129 if(SiS_Pr->UseCustomMode) {
6130 cr8 = SiS_Pr->CCRT1CRTC[8];
6131 cr7 = SiS_Pr->CCRT1CRTC[7];
6132 cr13 = SiS_Pr->CCRT1CRTC[13];
6133 tempcx = SiS_Pr->CCRT1CRTC[9];
6134 } else {
6135 cr8 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
6136 cr7 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
6137 cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
6138 tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
6139 }
544393fe
TW
6140 tempbx = cr8;
6141 if(cr7 & 0x04) tempbx |= 0x0100;
6142 if(cr7 & 0x80) tempbx |= 0x0200;
6143 if(cr13 & 0x08) tempbx |= 0x0400;
6144 }
1da177e4
LT
6145 }
6146 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx); /* CRT2 Vertical Retrace Start */
6147
6148 temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
6149 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp); /* CRT2 Vert. Retrace End; Overflow */
6150
6151 /* 3. Panel delay compensation */
6152
544393fe 6153 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4 6154
f7854e5d 6155#ifdef CONFIG_FB_SIS_300 /* ---------- 300 series -------------- */
1da177e4
LT
6156
6157 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6158 temp = 0x20;
544393fe 6159 if(SiS_Pr->ChipType == SIS_300) {
1da177e4
LT
6160 temp = 0x10;
6161 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) temp = 0x2c;
6162 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6163 }
6164 if(SiS_Pr->SiS_VBType & VB_SIS301) {
6165 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6166 }
6167 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) temp = 0x24;
6168 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) temp = 0x2c;
6169 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08;
6170 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
544393fe
TW
6171 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
6172 else temp = 0x20;
6173 }
1da177e4
LT
6174 if(SiS_Pr->SiS_UseROM) {
6175 if(ROMAddr[0x220] & 0x80) {
544393fe
TW
6176 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
6177 temp = ROMAddr[0x221];
1da177e4
LT
6178 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
6179 temp = ROMAddr[0x222];
6180 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
6181 temp = ROMAddr[0x223];
6182 else
6183 temp = ROMAddr[0x224];
1da177e4
LT
6184 }
6185 }
6186 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
544393fe 6187 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
1da177e4
LT
6188 }
6189
6190 } else {
6191 temp = 0x20;
6192 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6193 if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
6194 }
6195 if(SiS_Pr->SiS_UseROM) {
6196 if(ROMAddr[0x220] & 0x80) {
544393fe 6197 temp = ROMAddr[0x220];
1da177e4
LT
6198 }
6199 }
6200 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
544393fe 6201 if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
1da177e4 6202 }
544393fe 6203 }
1da177e4 6204
544393fe
TW
6205 temp &= 0x3c;
6206
6207 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
1da177e4 6208
f7854e5d 6209#endif /* CONFIG_FB_SIS_300 */
1da177e4
LT
6210
6211 } else {
6212
f7854e5d 6213#ifdef CONFIG_FB_SIS_315 /* --------------- 315/330 series ---------------*/
1da177e4 6214
544393fe 6215 if(SiS_Pr->ChipType < SIS_661) {
1da177e4
LT
6216
6217 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6218
544393fe
TW
6219 if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
6220 else temp = 0x00;
1da177e4
LT
6221
6222 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
6223 tempbl = 0xF0;
544393fe 6224 if(SiS_Pr->ChipType == SIS_650) {
1da177e4
LT
6225 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6226 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
6227 }
6228 }
6229
6230 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
6231 temp = 0x08;
6232 tempbl = 0;
6233 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
6234 if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
6235 }
6236 }
6237
6238 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp); /* Panel Link Delay Compensation */
6239 }
6240
6241 } /* < 661 */
6242
544393fe
TW
6243 tempax = 0;
6244 if(modeflag & DoubleScanMode) tempax |= 0x80;
6245 if(modeflag & HalfDCLK) tempax |= 0x40;
6246 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
1da177e4 6247
f7854e5d 6248#endif /* CONFIG_FB_SIS_315 */
1da177e4
LT
6249
6250 }
6251
6252 } /* Slavemode */
6253
6254 if(SiS_Pr->SiS_VBType & VB_SISVB) {
6255 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
544393fe
TW
6256 /* For 301BDH with LCD, we set up the Panel Link */
6257 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4 6258 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
544393fe 6259 SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
6260 }
6261 } else {
544393fe
TW
6262 if(SiS_Pr->ChipType < SIS_315H) {
6263 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
6264 } else {
6265 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
544393fe
TW
6266 if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6267 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
6268 }
1da177e4 6269 } else {
544393fe 6270 SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
1da177e4
LT
6271 }
6272 }
6273 }
6274}
6275
6276/*********************************************/
6277/* SET PART 2 REGISTER GROUP */
6278/*********************************************/
6279
f7854e5d 6280#ifdef CONFIG_FB_SIS_315
544393fe
TW
6281static unsigned char *
6282SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
1da177e4 6283{
544393fe
TW
6284 const unsigned char *tableptr = NULL;
6285 unsigned short a, b, p = 0;
1da177e4
LT
6286
6287 a = SiS_Pr->SiS_VGAHDE;
6288 b = SiS_Pr->SiS_HDE;
6289 if(tabletype) {
6290 a = SiS_Pr->SiS_VGAVDE;
6291 b = SiS_Pr->SiS_VDE;
6292 }
6293
6294 if(a < b) {
6295 tableptr = SiS_Part2CLVX_1;
6296 } else if(a == b) {
6297 tableptr = SiS_Part2CLVX_2;
6298 } else {
6299 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6300 tableptr = SiS_Part2CLVX_4;
6301 } else {
6302 tableptr = SiS_Part2CLVX_3;
6303 }
6304 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6305 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) tableptr = SiS_Part2CLVX_3;
6306 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tableptr = SiS_Part2CLVX_3;
6307 else tableptr = SiS_Part2CLVX_5;
6308 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6309 tableptr = SiS_Part2CLVX_6;
6310 }
6311 do {
6312 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
6313 p += 0x42;
6314 } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
6315 if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
6316 }
6317 p += 2;
544393fe 6318 return ((unsigned char *)&tableptr[p]);
1da177e4
LT
6319}
6320
6321static void
544393fe
TW
6322SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6323 unsigned short RefreshRateTableIndex)
1da177e4 6324{
544393fe
TW
6325 unsigned char *tableptr;
6326 unsigned char temp;
1da177e4 6327 int i, j;
1da177e4 6328
544393fe 6329 if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
1da177e4 6330
544393fe 6331 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
1da177e4
LT
6332 for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
6333 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6334 }
6335 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
544393fe 6336 tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
1da177e4
LT
6337 for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
6338 SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6339 }
6340 }
6341 temp = 0x10;
6342 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
6343 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
6344}
6345
c30660ea 6346static bool
544393fe
TW
6347SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
6348 unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
6349 unsigned short *ResIndex)
1da177e4
LT
6350{
6351
c30660ea 6352 if(SiS_Pr->ChipType < SIS_315H) return false;
1da177e4
LT
6353
6354 if(ModeNo <= 0x13)
6355 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6356 else
6357 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6358
6359 (*ResIndex) &= 0x3f;
6360 (*CRT2Index) = 0;
6361
6362 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6363 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6364 (*CRT2Index) = 200;
6365 }
6366 }
6367
6368 if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
6369 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6370 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
6371 }
6372 }
544393fe 6373 return (((*CRT2Index) != 0));
1da177e4
LT
6374}
6375#endif
6376
f7854e5d 6377#ifdef CONFIG_FB_SIS_300
1da177e4 6378static void
544393fe 6379SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
1da177e4 6380{
544393fe
TW
6381 unsigned short tempcx;
6382 static const unsigned char atable[] = {
1da177e4
LT
6383 0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
6384 0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
6385 };
6386
6387 if(!SiS_Pr->UseCustomMode) {
544393fe
TW
6388 if( ( ( (SiS_Pr->ChipType == SIS_630) ||
6389 (SiS_Pr->ChipType == SIS_730) ) &&
6390 (SiS_Pr->ChipRevision > 2) ) &&
6391 (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
6392 (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
6393 (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
6394 if(ModeNo == 0x13) {
6395 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
6396 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
6397 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
6398 } else if((crt2crtc & 0x3F) == 4) {
6399 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
6400 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
6401 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
6402 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
6403 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
6404 }
1da177e4
LT
6405 }
6406
544393fe
TW
6407 if(SiS_Pr->ChipType < SIS_315H) {
6408 if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
6409 crt2crtc &= 0x1f;
6410 tempcx = 0;
6411 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6412 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6413 tempcx += 7;
6414 }
6415 }
6416 tempcx += crt2crtc;
6417 if(crt2crtc >= 4) {
6418 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
6419 }
1da177e4 6420
544393fe
TW
6421 if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6422 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6423 if(crt2crtc == 4) {
6424 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
6425 }
6426 }
6427 }
6428 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
6429 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
6430 }
1da177e4
LT
6431 }
6432 }
6433}
6434
6435/* For ECS A907. Highly preliminary. */
6436static void
544393fe
TW
6437SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
6438 unsigned short ModeNo)
1da177e4 6439{
544393fe
TW
6440 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
6441 unsigned short crt2crtc, resindex;
6442 int i, j;
1da177e4 6443
544393fe
TW
6444 if(SiS_Pr->ChipType != SIS_300) return;
6445 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
1da177e4
LT
6446 if(SiS_Pr->UseCustomMode) return;
6447
6448 if(ModeNo <= 0x13) {
6449 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6450 } else {
6451 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6452 }
6453
6454 resindex = crt2crtc & 0x3F;
6455 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6456 else CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
6457
6458 /* The BIOS code (1.16.51,56) is obviously a fragment! */
6459 if(ModeNo > 0x13) {
6460 CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6461 resindex = 4;
6462 }
6463
6464 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6465 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6466 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
544393fe 6467 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
1da177e4
LT
6468 }
6469 for(j = 0x1c; j <= 0x1d; i++, j++ ) {
544393fe 6470 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
1da177e4
LT
6471 }
6472 for(j = 0x1f; j <= 0x21; i++, j++ ) {
544393fe 6473 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
1da177e4
LT
6474 }
6475 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6476 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6477}
6478#endif
6479
6480static void
544393fe 6481SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1da177e4 6482{
544393fe 6483 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
1da177e4
LT
6484 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
6485 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
6486
6487 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6488 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
b90b3eca 6489 static const unsigned char specialtv[] = {
1da177e4
LT
6490 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
6491 0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
6492 0x58,0xe4,0x73,0xda,0x13
6493 };
6494 int i, j;
6495 for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
6496 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
6497 }
6498 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
6499 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
6500 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6501 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
6502 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
6503 } else {
6504 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14); /* 15 */
6505 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a); /* 1b */
6506 }
6507 }
6508 }
6509 } else {
6510 if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
6511 (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
6512 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b); /* 21 */
6513 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54); /* 5a */
6514 } else {
6515 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a); /* 21 */
6516 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53); /* 5a */
6517 }
6518 }
6519}
6520
6521static void
544393fe 6522SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1da177e4 6523{
544393fe 6524 unsigned short temp;
1da177e4
LT
6525
6526 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6527 if(SiS_Pr->SiS_VGAVDE == 525) {
6528 temp = 0xc3;
6529 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6530 temp++;
544393fe 6531 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
1da177e4
LT
6532 }
6533 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6534 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
6535 } else if(SiS_Pr->SiS_VGAVDE == 420) {
6536 temp = 0x4d;
6537 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6538 temp++;
544393fe 6539 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
1da177e4
LT
6540 }
6541 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6542 }
6543 }
6544
6545 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6546 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
544393fe 6547 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
1da177e4
LT
6548 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
6549 /* Not always for LV, see SetGrp2 */
6550 }
6551 temp = 1;
6552 if(ModeNo <= 0x13) temp = 3;
6553 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
6554 }
6555#if 0
6556 /* 651+301C, for 1280x768 - do I really need that? */
6557 if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
6558 if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
6559 if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
6560 ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
6561 SiS_SetReg(SiS_Part2Port,0x01,0x2b);
6562 SiS_SetReg(SiS_Part2Port,0x02,0x13);
6563 SiS_SetReg(SiS_Part2Port,0x04,0xe5);
6564 SiS_SetReg(SiS_Part2Port,0x05,0x08);
6565 SiS_SetReg(SiS_Part2Port,0x06,0xe2);
6566 SiS_SetReg(SiS_Part2Port,0x1c,0x21);
6567 SiS_SetReg(SiS_Part2Port,0x1d,0x45);
6568 SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
6569 SiS_SetReg(SiS_Part2Port,0x20,0x00);
6570 SiS_SetReg(SiS_Part2Port,0x21,0xa9);
6571 SiS_SetReg(SiS_Part2Port,0x23,0x0b);
6572 SiS_SetReg(SiS_Part2Port,0x25,0x04);
6573 }
6574 }
6575 }
6576#endif
6577 }
6578}
6579
6580static void
544393fe
TW
6581SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
6582 unsigned short RefreshRateTableIndex)
6583{
6584 unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
6585 unsigned short push2, modeflag, crt2crtc, bridgeoffset;
6586 unsigned int longtemp, PhaseIndex;
c30660ea 6587 bool newtvphase;
544393fe 6588 const unsigned char *TimingPoint;
f7854e5d 6589#ifdef CONFIG_FB_SIS_315
544393fe
TW
6590 unsigned short resindex, CRT2Index;
6591 const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
1da177e4
LT
6592
6593 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
6594#endif
6595
6596 if(ModeNo <= 0x13) {
6597 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6598 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6599 } else if(SiS_Pr->UseCustomMode) {
6600 modeflag = SiS_Pr->CModeFlag;
6601 crt2crtc = 0;
6602 } else {
6603 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6604 crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6605 }
6606
6607 temp = 0;
6608 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
6609 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
6610 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) temp |= 0x02;
6611 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp |= 0x01;
6612
6613 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) temp |= 0x10;
6614
6615 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
6616
544393fe 6617 PhaseIndex = 0x01; /* SiS_PALPhase */
1da177e4
LT
6618 TimingPoint = SiS_Pr->SiS_PALTiming;
6619
c30660ea 6620 newtvphase = false;
544393fe
TW
6621 if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
6622 ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6623 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
c30660ea 6624 newtvphase = true;
544393fe
TW
6625 }
6626
1da177e4
LT
6627 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6628
6629 TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
6630 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6631 TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
6632 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6633 TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
1da177e4
LT
6634 }
6635 }
6636
6637 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6638
544393fe
TW
6639 i = 0;
6640 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) i = 2;
6641 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
1da177e4 6642
544393fe
TW
6643 TimingPoint = &SiS_YPbPrTable[i][0];
6644
6645 PhaseIndex = 0x00; /* SiS_NTSCPhase */
1da177e4
LT
6646
6647 } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6648
544393fe 6649 if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
1da177e4
LT
6650
6651 } else {
6652
6653 TimingPoint = SiS_Pr->SiS_NTSCTiming;
544393fe
TW
6654 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00; /* SiS_PALPhase : SiS_NTSCPhase */
6655 if(newtvphase) PhaseIndex += 8; /* SiS_PALPhase2 : SiS_NTSCPhase2 */
1da177e4 6656
1da177e4
LT
6657 }
6658
544393fe
TW
6659 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
6660 PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03; /* SiS_PALMPhase : SiS_PALNPhase */
6661 if(newtvphase) PhaseIndex += 8; /* SiS_PALMPhase2 : SiS_PALNPhase2 */
1da177e4
LT
6662 }
6663
6664 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
1da177e4 6665 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
544393fe 6666 PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
1da177e4 6667 } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
544393fe
TW
6668 PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
6669 } else {
6670 PhaseIndex = 0x10; /* SiS_SpecialPhase */
1da177e4
LT
6671 }
6672 }
6673
544393fe
TW
6674 for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
6675 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
1da177e4
LT
6676 }
6677
544393fe 6678 for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
1da177e4
LT
6679 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6680 }
544393fe 6681 for(i = 0x39; i <= 0x45; i++, j++) {
1da177e4
LT
6682 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6683 }
6684
6685 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6686 if(SiS_Pr->SiS_ModeType != ModeText) {
6687 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
6688 }
6689 }
6690
6691 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
6692
6693 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
6694 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
6695 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
6696 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
6697
544393fe
TW
6698 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempax = 950;
6699 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempax = 680;
6700 else if(SiS_Pr->SiS_TVMode & TVSetPAL) tempax = 520;
6701 else tempax = 440; /* NTSC, YPbPr 525 */
1da177e4 6702
544393fe 6703 if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
1da177e4
LT
6704 ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
6705 ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
6706
6707 tempax -= SiS_Pr->SiS_VDE;
544393fe
TW
6708 tempax >>= 1;
6709 if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
6710 tempax >>= 1;
6711 }
1da177e4
LT
6712 tempax &= 0x00ff;
6713
544393fe 6714 temp = tempax + (unsigned short)TimingPoint[0];
1da177e4
LT
6715 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
6716
544393fe 6717 temp = tempax + (unsigned short)TimingPoint[1];
1da177e4
LT
6718 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
6719
6720 if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
6721 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
544393fe
TW
6722 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
6723 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
1da177e4
LT
6724 } else {
6725 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
6726 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
6727 }
6728 }
6729
6730 }
6731
6732 tempcx = SiS_Pr->SiS_HT;
544393fe 6733 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
1da177e4 6734 tempcx--;
544393fe 6735 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
1da177e4
LT
6736 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
6737 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
6738
6739 tempcx = SiS_Pr->SiS_HT >> 1;
544393fe 6740 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
1da177e4
LT
6741 tempcx += 7;
6742 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6743 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
6744
6745 tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
6746 tempbx += tempcx;
6747 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
6748 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
6749
6750 tempbx += 8;
6751 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6752 tempbx -= 4;
6753 tempcx = tempbx;
6754 }
6755 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
6756
6757 j += 2;
6758 tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
6759 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
6760 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
6761
6762 tempcx += 8;
6763 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
6764 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
6765
6766 tempcx = SiS_Pr->SiS_HT >> 1;
544393fe 6767 if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
1da177e4
LT
6768 j += 2;
6769 tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
6770 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
6771
6772 tempcx -= 11;
6773 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6774 tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
6775 }
6776 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
6777
6778 tempbx = SiS_Pr->SiS_VDE;
6779 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6780 if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
6781 if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
6782 if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
6783 } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6784 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
6785 tempbx >>= 1;
544393fe 6786 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4
LT
6787 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6788 if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
6789 } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6790 if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6791 if(crt2crtc == 4) tempbx++;
6792 }
6793 }
6794 }
6795 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6796 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6797 if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
6798 }
6799 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6800 if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
6801 }
6802 }
6803 }
6804 tempbx -= 2;
6805 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
6806
6807 temp = (tempcx >> 8) & 0x0F;
6808 temp |= ((tempbx >> 2) & 0xC0);
6809 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6810 temp |= 0x10;
6811 if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
6812 }
6813 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
6814
544393fe 6815 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
1da177e4
LT
6816 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
6817 }
6818
544393fe 6819 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4
LT
6820 tempbx = SiS_Pr->SiS_VDE;
6821 if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
6822 (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
6823 tempbx >>= 1;
6824 }
6825 tempbx -= 3;
6826 temp = ((tempbx >> 3) & 0x60) | 0x18;
6827 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
6828 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
6829
544393fe 6830 if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
1da177e4
LT
6831 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
6832 }
6833 }
6834
6835 tempbx = 0;
6836 if(!(modeflag & HalfDCLK)) {
6837 if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
6838 tempax = 0;
6839 tempbx |= 0x20;
6840 }
6841 }
6842
6843 tempch = tempcl = 0x01;
6844 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
544393fe
TW
6845 if(SiS_Pr->SiS_VGAHDE >= 960) {
6846 if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
1da177e4 6847 tempcl = 0x20;
544393fe
TW
6848 if(SiS_Pr->SiS_VGAHDE >= 1280) {
6849 tempch = 20;
1da177e4 6850 tempbx &= ~0x20;
544393fe
TW
6851 } else {
6852 tempch = 25; /* OK */
6853 }
1da177e4
LT
6854 }
6855 }
6856 }
6857
6858 if(!(tempbx & 0x20)) {
6859 if(modeflag & HalfDCLK) tempcl <<= 1;
6860 longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
544393fe 6861 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
1da177e4
LT
6862 tempax = longtemp / SiS_Pr->SiS_HDE;
6863 if(longtemp % SiS_Pr->SiS_HDE) tempax++;
6864 tempbx |= ((tempax >> 8) & 0x1F);
6865 tempcx = tempax >> 13;
6866 }
6867
6868 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
6869 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
6870
544393fe 6871 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4
LT
6872
6873 tempcx &= 0x07;
6874 if(tempbx & 0x20) tempcx = 0;
6875 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
6876
6877 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6878 tempbx = 0x0382;
6879 tempcx = 0x007e;
6880 } else {
6881 tempbx = 0x0369;
6882 tempcx = 0x0061;
6883 }
6884 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
6885 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
6886 temp = (tempcx & 0x0300) >> 6;
6887 temp |= ((tempbx >> 8) & 0x03);
6888 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6889 temp |= 0x10;
6890 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp |= 0x20;
6891 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
6892 }
6893 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
6894
6895 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
6896 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
6897
6898 SiS_SetTVSpecial(SiS_Pr, ModeNo);
6899
544393fe 6900 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
1da177e4
LT
6901 temp = 0;
6902 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
6903 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
6904 }
6905
6906 }
6907
6908 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6909 if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
6910 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
6911 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
6912 }
6913 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
6914 }
6915
6916 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6917 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6918 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
6919 }
6920 }
6921
6922 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
6923
6924 /* From here: Part2 LCD setup */
6925
6926 tempbx = SiS_Pr->SiS_HDE;
544393fe 6927 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
1da177e4
LT
6928 tempbx--; /* RHACTE = HDE - 1 */
6929 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
6930 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
6931
6932 temp = 0x01;
6933 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
6934 if(SiS_Pr->SiS_ModeType == ModeEGA) {
6935 if(SiS_Pr->SiS_VGAHDE >= 1024) {
6936 temp = 0x02;
544393fe
TW
6937 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
6938 temp = 0x01;
1da177e4
LT
6939 }
6940 }
6941 }
6942 }
6943 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
6944
6945 tempbx = SiS_Pr->SiS_VDE - 1;
6946 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
6947 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
6948
6949 tempcx = SiS_Pr->SiS_VT - 1;
6950 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
6951 temp = (tempcx >> 3) & 0xE0;
6952 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
6953 /* Enable dithering; only do this for 32bpp mode */
6954 if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
6955 temp |= 0x10;
6956 }
6957 }
6958 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
6959
6960 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
6961 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
6962
6963 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
6964 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
6965
f7854e5d 6966#ifdef CONFIG_FB_SIS_315
1da177e4 6967 if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
544393fe 6968 &CRT2Index, &resindex)) {
1da177e4 6969 switch(CRT2Index) {
544393fe
TW
6970 case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3; break;
6971 default:
1da177e4 6972 case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break;
1da177e4
LT
6973 }
6974
6975 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6976 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6977 for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
6978 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6979 }
6980 for(j = 0x1c; j <= 0x1d; i++, j++ ) {
6981 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6982 }
6983 for(j = 0x1f; j <= 0x21; i++, j++ ) {
6984 SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6985 }
6986 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6987 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6988
6989 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
6990
1da177e4
LT
6991 } else {
6992#endif
6993
6994 /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
6995 /* Clevo dual-link 1024x768 */
6996 /* Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct) */
6997 /* Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
6998
6999 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7000 if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7001 tempbx = SiS_Pr->SiS_VDE - 1;
7002 tempcx = SiS_Pr->SiS_VT - 1;
7003 } else {
7004 tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7005 tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7006 }
7007 } else {
7008 tempbx = SiS_Pr->PanelYRes;
7009 tempcx = SiS_Pr->SiS_VT;
7010 tempax = 1;
7011 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7012 tempax = SiS_Pr->PanelYRes;
7013 /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c; */ /* 651+301C */
7014 if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7015 tempax = tempcx = 0;
7016 } else {
7017 tempax -= SiS_Pr->SiS_VDE;
7018 }
7019 tempax >>= 1;
7020 }
7021 tempcx -= tempax; /* lcdvdes */
7022 tempbx -= tempax; /* lcdvdee */
7023 }
7024
7025 /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7026
1da177e4
LT
7027 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx); /* lcdvdes */
7028 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx); /* lcdvdee */
7029
7030 temp = (tempbx >> 5) & 0x38;
7031 temp |= ((tempcx >> 8) & 0x07);
7032 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7033
7034 tempax = SiS_Pr->SiS_VDE;
7035 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7036 tempax = SiS_Pr->PanelYRes;
7037 }
7038 tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7039 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7040 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7041 tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7042 }
7043 }
7044
7045 tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7046 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7047 if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7048 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7049 tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7050 if(tempax % 4) { tempax >>= 2; tempax++; }
7051 else { tempax >>= 2; }
7052 tempbx -= (tempax - 1);
7053 } else {
7054 tempbx -= 10;
7055 if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7056 }
7057 }
7058 }
7059 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7060 tempbx++;
7061 if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7062 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7063 tempbx = 770;
7064 tempcx = 3;
7065 }
7066 }
7067 }
7068
7069 /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7070
7071 if(SiS_Pr->UseCustomMode) {
7072 tempbx = SiS_Pr->CVSyncStart;
7073 }
7074
1da177e4
LT
7075 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx); /* lcdvrs */
7076
7077 temp = (tempbx >> 4) & 0xF0;
7078 tempbx += (tempcx + 1);
7079 temp |= (tempbx & 0x0F);
7080
7081 if(SiS_Pr->UseCustomMode) {
7082 temp &= 0xf0;
7083 temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7084 }
7085
1da177e4
LT
7086 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7087
f7854e5d 7088#ifdef CONFIG_FB_SIS_300
544393fe 7089 SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
1da177e4
LT
7090#endif
7091
7092 bridgeoffset = 7;
544393fe
TW
7093 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) bridgeoffset += 2;
7094 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
7095 if(SiS_IsDualLink(SiS_Pr)) bridgeoffset++;
7096 else if(SiS_Pr->SiS_VBType & VB_SIS302LV) bridgeoffset++; /* OK for Asus A4L 1280x800 */
7097 /* Higher bridgeoffset shifts to the LEFT */
1da177e4
LT
7098
7099 temp = 0;
7100 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7101 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
544393fe
TW
7102 temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7103 if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
1da177e4
LT
7104 }
7105 }
7106 temp += bridgeoffset;
7107 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp); /* lcdhdes */
7108 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7109
7110 tempcx = SiS_Pr->SiS_HT;
7111 tempax = tempbx = SiS_Pr->SiS_HDE;
7112 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7113 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7114 tempax = SiS_Pr->PanelXRes;
7115 tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7116 }
7117 }
544393fe 7118 if(SiS_IsDualLink(SiS_Pr)) {
1da177e4
LT
7119 tempcx >>= 1;
7120 tempbx >>= 1;
7121 tempax >>= 1;
7122 }
7123
1da177e4
LT
7124 tempbx += bridgeoffset;
7125
7126 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx); /* lcdhdee */
7127 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7128
7129 tempcx = (tempcx - tempax) >> 2;
7130
7131 tempbx += tempcx;
7132 push2 = tempbx;
7133
7134 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7135 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7136 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7137 if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7138 }
7139 }
7140 }
7141
7142 if(SiS_Pr->UseCustomMode) {
7143 tempbx = SiS_Pr->CHSyncStart;
544393fe
TW
7144 if(modeflag & HalfDCLK) tempbx <<= 1;
7145 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
1da177e4
LT
7146 tempbx += bridgeoffset;
7147 }
7148
1da177e4
LT
7149 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx); /* lcdhrs */
7150 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7151
7152 tempbx = push2;
7153
7154 tempcx <<= 1;
7155 if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7156 if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7157 }
7158 tempbx += tempcx;
7159
7160 if(SiS_Pr->UseCustomMode) {
7161 tempbx = SiS_Pr->CHSyncEnd;
544393fe
TW
7162 if(modeflag & HalfDCLK) tempbx <<= 1;
7163 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
1da177e4
LT
7164 tempbx += bridgeoffset;
7165 }
7166
1da177e4
LT
7167 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx); /* lcdhre */
7168
7169 SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7170
f7854e5d 7171#ifdef CONFIG_FB_SIS_300
544393fe 7172 SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
1da177e4 7173#endif
f7854e5d 7174#ifdef CONFIG_FB_SIS_315
1da177e4
LT
7175 } /* CRT2-LCD from table */
7176#endif
7177}
7178
7179/*********************************************/
7180/* SET PART 3 REGISTER GROUP */
7181/*********************************************/
7182
7183static void
544393fe 7184SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 7185{
544393fe
TW
7186 unsigned short i;
7187 const unsigned char *tempdi;
1da177e4
LT
7188
7189 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7190
7191#ifndef SIS_CP
7192 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7193#else
7194 SIS_CP_INIT301_CP
7195#endif
7196
7197 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7198 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7199 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7200 } else {
7201 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7202 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7203 }
7204
7205 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7206 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7207 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7208 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7209 }
7210
7211 tempdi = NULL;
7212 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7213 tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7214 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7215 tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7216 }
7217 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7218 if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7219 tempdi = SiS_HiTVGroup3_1;
7220 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7221 }
7222 }
7223 if(tempdi) {
7224 for(i=0; i<=0x3E; i++) {
7225 SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7226 }
544393fe 7227 if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
1da177e4
LT
7228 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7229 SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7230 }
7231 }
7232 }
7233
7234#ifdef SIS_CP
7235 SIS_CP_INIT301_CP2
7236#endif
7237}
7238
7239/*********************************************/
7240/* SET PART 4 REGISTER GROUP */
7241/*********************************************/
7242
f7854e5d 7243#ifdef CONFIG_FB_SIS_315
544393fe 7244#if 0
1da177e4 7245static void
544393fe 7246SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
1da177e4 7247{
544393fe 7248 unsigned short temp, temp1, temp2;
1da177e4
LT
7249
7250 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7251 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
544393fe 7252 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
1da177e4
LT
7253 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7254 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7255 temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
544393fe 7256 temp = (unsigned short)((int)(temp) + shift);
1da177e4
LT
7257 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7258 temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7259 temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
544393fe 7260 temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
1da177e4
LT
7261 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7262 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7263}
544393fe 7264#endif
1da177e4
LT
7265
7266static void
544393fe 7267SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 7268{
32ad6195 7269 unsigned short temp, temp1;
544393fe 7270 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1da177e4 7271
544393fe 7272 if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
1da177e4
LT
7273 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7274
544393fe
TW
7275 if(SiS_Pr->ChipType >= XGI_20) return;
7276
7277 if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
7278 if(!(ROMAddr[0x61] & 0x04)) return;
7279 }
7280
1da177e4
LT
7281 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7282 temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7283 if(!(temp & 0x01)) {
7284 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7285 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
544393fe 7286 if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
1da177e4
LT
7287 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7288 }
7289 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7290 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp = 0x0000;
7291 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7292 else if(SiS_Pr->SiS_TVMode & TVSetHiVision) temp = 0x0400;
7293 else temp = 0x0402;
544393fe 7294 if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
1da177e4
LT
7295 temp1 = 0;
7296 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7297 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7298 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7299 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
544393fe
TW
7300 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7301 if(ModeNo > 0x13) {
7302 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
7303 }
1da177e4
LT
7304 } else {
7305 temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7306 if(temp1 == 0x01) temp |= 0x01;
7307 if(temp1 == 0x03) temp |= 0x04; /* ? why not 0x10? */
7308 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
544393fe
TW
7309 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7310 if(ModeNo > 0x13) {
7311 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7312 }
1da177e4
LT
7313 }
7314
544393fe
TW
7315#if 0
7316 if(SiS_Pr->ChipType >= SIS_661) { /* ? */
1da177e4
LT
7317 if(SiS_Pr->SiS_TVMode & TVAspect43) {
7318 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7319 if(resinfo == SIS_RI_1024x768) {
7320 SiS_ShiftXPos(SiS_Pr, 97);
7321 } else {
7322 SiS_ShiftXPos(SiS_Pr, 111);
7323 }
7324 } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7325 SiS_ShiftXPos(SiS_Pr, 136);
7326 }
7327 }
7328 }
544393fe
TW
7329#endif
7330
1da177e4 7331 }
544393fe 7332
1da177e4
LT
7333}
7334#endif
7335
7336static void
544393fe
TW
7337SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7338 unsigned short RefreshRateTableIndex)
1da177e4 7339{
544393fe 7340 unsigned short vclkindex, temp, reg1, reg2;
1da177e4
LT
7341
7342 if(SiS_Pr->UseCustomMode) {
7343 reg1 = SiS_Pr->CSR2B;
7344 reg2 = SiS_Pr->CSR2C;
7345 } else {
544393fe 7346 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
7347 reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7348 reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7349 }
7350
544393fe
TW
7351 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7352 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
1da177e4
LT
7353 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7354 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7355 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7356 } else {
7357 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7358 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7359 }
7360 } else {
7361 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7362 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7363 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7364 }
544393fe
TW
7365 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7366 temp = 0x08;
7367 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7368 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7369}
7370
7371static void
7372SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
7373{
7374 if(SiS_Pr->ChipType >= SIS_315H) {
7375 if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
7376 if((SiS_CRT2IsLCD(SiS_Pr)) ||
7377 (SiS_IsVAMode(SiS_Pr))) {
7378 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
7379 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7380 } else {
7381 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7382 }
7383 }
7384 }
7385 }
7386 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
7387 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7388#ifdef SET_EMI
7389 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7390#endif
7391 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7392 }
1da177e4
LT
7393}
7394
7395static void
544393fe
TW
7396SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7397 unsigned short RefreshRateTableIndex)
1da177e4 7398{
544393fe
TW
7399 unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
7400 unsigned int tempebx, tempeax, templong;
1da177e4
LT
7401
7402 if(ModeNo <= 0x13) {
7403 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7404 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7405 } else if(SiS_Pr->UseCustomMode) {
7406 modeflag = SiS_Pr->CModeFlag;
7407 resinfo = 0;
7408 } else {
7409 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7410 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7411 }
7412
544393fe
TW
7413 if(SiS_Pr->ChipType >= SIS_315H) {
7414 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7415 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7416 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7417 }
1da177e4
LT
7418 }
7419 }
7420
544393fe 7421 if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
1da177e4 7422 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
544393fe 7423 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
1da177e4
LT
7424 }
7425 }
7426
544393fe 7427 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4 7428 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
544393fe
TW
7429 SiS_SetDualLinkEtc(SiS_Pr);
7430 return;
1da177e4
LT
7431 }
7432 }
7433
7434 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7435
7436 tempbx = SiS_Pr->SiS_RVBHCMAX;
7437 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7438
7439 temp = (tempbx >> 1) & 0x80;
7440
7441 tempcx = SiS_Pr->SiS_VGAHT - 1;
7442 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7443
7444 temp |= ((tempcx >> 5) & 0x78);
7445
7446 tempcx = SiS_Pr->SiS_VGAVT - 1;
7447 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7448 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7449
7450 temp |= ((tempcx >> 8) & 0x07);
7451 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7452
7453 tempbx = SiS_Pr->SiS_VGAHDE;
544393fe
TW
7454 if(modeflag & HalfDCLK) tempbx >>= 1;
7455 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
1da177e4
LT
7456
7457 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7458 temp = 0;
7459 if(tempbx > 800) temp = 0x60;
7460 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7461 temp = 0;
544393fe
TW
7462 if(tempbx > 1024) temp = 0xC0;
7463 else if(tempbx >= 960) temp = 0xA0;
1da177e4
LT
7464 } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7465 temp = 0;
7466 if(tempbx >= 1280) temp = 0x40;
7467 else if(tempbx >= 1024) temp = 0x20;
7468 } else {
7469 temp = 0x80;
7470 if(tempbx >= 1024) temp = 0xA0;
7471 }
7472
544393fe
TW
7473 temp |= SiS_Pr->Init_P4_0E;
7474
1da177e4 7475 if(SiS_Pr->SiS_VBType & VB_SIS301) {
544393fe
TW
7476 if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
7477 temp &= 0xf0;
7478 temp |= 0x0A;
7479 }
1da177e4
LT
7480 }
7481
7482 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7483
7484 tempeax = SiS_Pr->SiS_VGAVDE;
7485 tempebx = SiS_Pr->SiS_VDE;
7486 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7487 if(!(temp & 0xE0)) tempebx >>=1;
7488 }
7489
7490 tempcx = SiS_Pr->SiS_RVBHRS;
7491 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7492 tempcx >>= 8;
7493 tempcx |= 0x40;
7494
7495 if(tempeax <= tempebx) {
7496 tempcx ^= 0x40;
7497 } else {
7498 tempeax -= tempebx;
7499 }
7500
7501 tempeax *= (256 * 1024);
7502 templong = tempeax % tempebx;
7503 tempeax /= tempebx;
7504 if(templong) tempeax++;
7505
544393fe 7506 temp = (unsigned short)(tempeax & 0x000000FF);
1da177e4 7507 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
544393fe 7508 temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
1da177e4 7509 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
544393fe 7510 temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
1da177e4
LT
7511 temp |= (tempcx & 0x4F);
7512 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7513
544393fe 7514 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4
LT
7515
7516 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7517
7518 /* Calc Linebuffer max address and set/clear decimode */
7519 tempbx = 0;
7520 if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7521 tempax = SiS_Pr->SiS_VGAHDE;
544393fe
TW
7522 if(modeflag & HalfDCLK) tempax >>= 1;
7523 if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
1da177e4
LT
7524 if(tempax > 800) {
7525 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7526 tempax -= 800;
544393fe 7527 } else {
1da177e4 7528 tempbx = 0x08;
544393fe
TW
7529 if(tempax == 960) tempax *= 25; /* Correct */
7530 else if(tempax == 1024) tempax *= 25;
7531 else tempax *= 20;
1da177e4
LT
7532 temp = tempax % 32;
7533 tempax /= 32;
7534 if(temp) tempax++;
7535 tempax++;
544393fe
TW
7536 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7537 if(resinfo == SIS_RI_1024x768 ||
7538 resinfo == SIS_RI_1024x576 ||
7539 resinfo == SIS_RI_1280x1024 ||
7540 resinfo == SIS_RI_1280x720) {
7541 /* Otherwise white line or garbage at right edge */
1da177e4
LT
7542 tempax = (tempax & 0xff00) | 0x20;
7543 }
7544 }
7545 }
7546 }
7547 tempax--;
7548 temp = ((tempax >> 4) & 0x30) | tempbx;
7549 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7550 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7551
7552 temp = 0x0036; tempbx = 0xD0;
544393fe 7553 if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
1da177e4
LT
7554 temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7555 }
7556 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7557 if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7558 temp |= 0x01;
7559 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7560 if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7561 temp &= ~0x01;
7562 }
7563 }
7564 }
7565 }
7566 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7567
7568 tempbx = SiS_Pr->SiS_HT >> 1;
544393fe 7569 if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
1da177e4
LT
7570 tempbx -= 2;
7571 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7572 temp = (tempbx >> 5) & 0x38;
7573 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7574
544393fe 7575 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4
LT
7576 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7577 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7578 /* LCD-too-dark-error-source, see FinalizeLCD() */
7579 }
1da177e4
LT
7580 }
7581
544393fe
TW
7582 SiS_SetDualLinkEtc(SiS_Pr);
7583
1da177e4
LT
7584 } /* 301B */
7585
544393fe 7586 SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
7587}
7588
7589/*********************************************/
7590/* SET PART 5 REGISTER GROUP */
7591/*********************************************/
7592
7593static void
544393fe 7594SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4
LT
7595{
7596
7597 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7598
7599 if(SiS_Pr->SiS_ModeType == ModeVGA) {
7600 if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7601 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
544393fe 7602 SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4
LT
7603 }
7604 }
7605}
7606
7607/*********************************************/
7608/* MODIFY CRT1 GROUP FOR SLAVE MODE */
7609/*********************************************/
7610
c30660ea 7611static bool
544393fe
TW
7612SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7613 unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
7614 unsigned short *DisplayType)
7615 {
7616 unsigned short modeflag = 0;
c30660ea 7617 bool checkhd = true;
544393fe
TW
7618
7619 /* Pass 1:1 not supported here */
7620
7621 if(ModeNo <= 0x13) {
7622 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7623 (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7624 } else {
7625 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7626 (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7627 }
7628
7629 (*ResIndex) &= 0x3F;
7630
7631 if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7632
7633 (*DisplayType) = 80;
7634 if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
7635 (*DisplayType) = 82;
7636 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7637 if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
7638 }
7639 }
7640 if((*DisplayType) != 84) {
7641 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
7642 }
7643
7644 } else {
7645
7646 (*DisplayType = 0);
7647 switch(SiS_Pr->SiS_LCDResInfo) {
7648 case Panel_320x240_1: (*DisplayType) = 50;
c30660ea 7649 checkhd = false;
544393fe
TW
7650 break;
7651 case Panel_320x240_2: (*DisplayType) = 14;
7652 break;
7653 case Panel_320x240_3: (*DisplayType) = 18;
7654 break;
7655 case Panel_640x480: (*DisplayType) = 10;
7656 break;
7657 case Panel_1024x600: (*DisplayType) = 26;
7658 break;
c30660ea 7659 default: return true;
544393fe
TW
7660 }
7661
7662 if(checkhd) {
7663 if(modeflag & HalfDCLK) (*DisplayType)++;
7664 }
7665
7666 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
7667 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
7668 }
7669
7670 }
7671
c30660ea 7672 return true;
544393fe 7673}
1da177e4 7674
544393fe
TW
7675static void
7676SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7677 unsigned short RefreshRateTableIndex)
7678{
7679 unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
7680 const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
7681 static const unsigned short CRIdx[] = {
7682 0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
7683 0x07, 0x10, 0x11, 0x15, 0x16
7684 };
1da177e4
LT
7685
7686 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
7687 (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
544393fe
TW
7688 (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
7689 (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
1da177e4
LT
7690 return;
7691
544393fe
TW
7692 if(SiS_Pr->SiS_IF_DEF_LVDS) {
7693 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7694 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7695 }
7696 } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
7697 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7698 } else return;
7699
7700 if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
7701
7702 if(SiS_Pr->ChipType < SIS_315H) {
7703 if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
7704 }
7705
1da177e4
LT
7706 if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7707 &ResIndex, &DisplayType))) {
7708 return;
7709 }
7710
544393fe
TW
7711 switch(DisplayType) {
7712 case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1; break; /* xSTN */
7713 case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2; break; /* xSTN */
7714 case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H; break; /* xSTN */
7715 case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3; break; /* xSTN */
7716 case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H; break; /* xSTN */
7717 case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
7718 case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
7719#if 0 /* Works better with calculated numbers */
7720 case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1; break;
7721 case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H; break;
7722 case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2; break;
7723 case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H; break;
7724#endif
7725 case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC; break;
7726 case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC; break;
7727 case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL; break;
7728 case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
7729 case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
1da177e4
LT
7730 }
7731
544393fe
TW
7732 if(LVDSCRT1Ptr) {
7733
7734 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
7735
7736 for(i = 0; i <= 10; i++) {
7737 tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
7738 SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
7739 }
7740
7741 for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
7742 tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
7743 SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
7744 }
7745
7746 tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
7747 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
7748
7749 if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7750 else modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7751
7752 tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
7753 if(modeflag & DoubleScanMode) tempah |= 0x80;
7754 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
7755
7756 } else {
7757
7758 SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
7759
7760 }
1da177e4
LT
7761}
7762
7763/*********************************************/
7764/* SET CRT2 ECLK */
7765/*********************************************/
7766
7767static void
544393fe
TW
7768SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7769 unsigned short RefreshRateTableIndex)
1da177e4 7770{
544393fe
TW
7771 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
7772 unsigned short clkbase, vclkindex = 0;
7773 unsigned char sr2b, sr2c;
1da177e4 7774
544393fe
TW
7775 if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7776 SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
7777 if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
7778 RefreshRateTableIndex--;
7779 }
7780 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7781 RefreshRateTableIndex);
7782 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
1da177e4 7783 } else {
544393fe
TW
7784 vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7785 RefreshRateTableIndex);
1da177e4
LT
7786 }
7787
7788 sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
7789 sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
7790
7791 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
7792 if(SiS_Pr->SiS_UseROM) {
7793 if(ROMAddr[0x220] & 0x01) {
544393fe 7794 sr2b = ROMAddr[0x227];
1da177e4
LT
7795 sr2c = ROMAddr[0x228];
7796 }
7797 }
7798 }
7799
7800 clkbase = 0x02B;
7801 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7802 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
544393fe 7803 clkbase += 3;
1da177e4
LT
7804 }
7805 }
7806
7807 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
7808 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7809 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7810 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
7811 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7812 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7813 SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
7814 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7815 SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7816}
7817
7818/*********************************************/
7819/* SET UP CHRONTEL CHIPS */
7820/*********************************************/
7821
7822static void
544393fe
TW
7823SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7824 unsigned short RefreshRateTableIndex)
1da177e4 7825{
544393fe
TW
7826 unsigned short TVType, resindex;
7827 const struct SiS_CHTVRegData *CHTVRegData = NULL;
1da177e4 7828
544393fe
TW
7829 if(ModeNo <= 0x13)
7830 resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7831 else
7832 resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
1da177e4 7833
544393fe 7834 resindex &= 0x3F;
1da177e4 7835
544393fe
TW
7836 TVType = 0;
7837 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7838 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7839 TVType += 2;
7840 if(SiS_Pr->SiS_ModeType > ModeVGA) {
7841 if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
7842 }
7843 if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7844 TVType = 4;
7845 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7846 } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
7847 TVType = 6;
7848 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7849 }
7850 }
7851
7852 switch(TVType) {
7853 case 0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
7854 case 1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
7855 case 2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL; break;
7856 case 3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
7857 case 4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
7858 case 5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
7859 case 6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
7860 case 7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
7861 case 8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
7862 default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL; break;
7863 }
7864
7865
7866 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
1da177e4 7867
f7854e5d 7868#ifdef CONFIG_FB_SIS_300
1da177e4 7869
544393fe 7870 /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
1da177e4 7871
544393fe
TW
7872 /* We don't support modes >800x600 */
7873 if (resindex > 5) return;
1da177e4 7874
544393fe
TW
7875 if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7876 SiS_SetCH700x(SiS_Pr,0x04,0x43); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
7877 SiS_SetCH700x(SiS_Pr,0x09,0x69); /* Black level for PAL (105)*/
7878 } else {
7879 SiS_SetCH700x(SiS_Pr,0x04,0x03); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
7880 SiS_SetCH700x(SiS_Pr,0x09,0x71); /* Black level for NTSC (113)*/
7881 }
7882
7883 SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]); /* Mode register */
7884 SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]); /* Start active video register */
7885 SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]); /* Position overflow register */
7886 SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]); /* Horiz Position register */
7887 SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]); /* Vertical Position register */
7888
7889 /* Set minimum flicker filter for Luma channel (SR1-0=00),
1da177e4
LT
7890 minimum text enhancement (S3-2=10),
7891 maximum flicker filter for Chroma channel (S5-4=10)
7892 =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
544393fe
TW
7893 */
7894 SiS_SetCH700x(SiS_Pr,0x01,0x28);
1da177e4 7895
544393fe 7896 /* Set video bandwidth
9aaeded7
AB
7897 High bandwidth Luma composite video filter(S0=1)
7898 low bandwidth Luma S-video filter (S2-1=00)
1da177e4
LT
7899 disable peak filter in S-video channel (S3=0)
7900 high bandwidth Chroma Filter (S5-4=11)
7901 =00110001=0x31
544393fe
TW
7902 */
7903 SiS_SetCH700x(SiS_Pr,0x03,0xb1); /* old: 3103 */
1da177e4 7904
544393fe 7905 /* Register 0x3D does not exist in non-macrovision register map
1da177e4 7906 (Maybe this is a macrovision register?)
544393fe 7907 */
1da177e4 7908#ifndef SIS_CP
544393fe 7909 SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
1da177e4
LT
7910#endif
7911
544393fe
TW
7912 /* Register 0x10 only contains 1 writable bit (S0) for sensing,
7913 all other bits a read-only. Macrovision?
7914 */
7915 SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
1da177e4 7916
544393fe
TW
7917 /* Register 0x11 only contains 3 writable bits (S0-S2) for
7918 contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
7919 */
7920 SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
1da177e4 7921
544393fe
TW
7922 /* Clear DSEN
7923 */
7924 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
7925
7926 if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { /* ---- NTSC ---- */
7927 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
7928 if(resindex == 0x04) { /* 640x480 overscan: Mode 16 */
7929 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7930 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on, no need to set FSCI */
7931 } else if(resindex == 0x05) { /* 800x600 overscan: Mode 23 */
7932 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* 0x18-0x1f: FSCI 469,762,048 */
7933 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
7934 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
7935 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
7936 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
7937 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
7938 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
7939 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
7940 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF); /* Loop filter on for mode 23 */
7941 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); /* ACIV off, need to set FSCI */
7942 }
7943 } else {
7944 if(resindex == 0x04) { /* ----- 640x480 underscan; Mode 17 */
7945 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7946 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7947 } else if(resindex == 0x05) { /* ----- 800x600 underscan: Mode 24 */
1da177e4 7948#if 0
544393fe
TW
7949 SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0); /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
7950 SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0); /* FSCI for mode 24 is 428,554,851 */
7951 SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0); /* 198b3a63 */
7952 SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
7953 SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
7954 SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
7955 SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
7956 SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
7957 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off for mode 24 */
7958 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE); * ACIV off, need to set FSCI */
7959#endif /* All alternatives wrong (datasheet wrong?), don't use FSCI */
7960 SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
7961 SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7962 }
1da177e4 7963 }
544393fe 7964 } else { /* ---- PAL ---- */
d3e329b3
GS
7965 /* We don't play around with FSCI in PAL mode */
7966 SiS_SetCH70xxANDOR(SiS_Pr, 0x20, 0x00, 0xEF); /* loop filter off */
7967 SiS_SetCH70xxANDOR(SiS_Pr, 0x21, 0x01, 0xFE); /* ACIV on */
544393fe
TW
7968 }
7969
1da177e4
LT
7970#endif /* 300 */
7971
544393fe 7972 } else {
1da177e4 7973
544393fe 7974 /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
1da177e4 7975
f7854e5d 7976#ifdef CONFIG_FB_SIS_315
1da177e4 7977
544393fe
TW
7978 unsigned short temp;
7979
7980 /* We don't support modes >1024x768 */
7981 if (resindex > 6) return;
7982
7983 temp = CHTVRegData[resindex].Reg[0];
7984 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
7985 SiS_SetCH701x(SiS_Pr,0x00,temp);
7986
7987 SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
7988 SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
7989 SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
7990 SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
7991 SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
7992 SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
7993
7994 temp = CHTVRegData[resindex].Reg[7];
7995 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
7996 SiS_SetCH701x(SiS_Pr,0x07,temp);
7997
7998 SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
7999 SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
8000 SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
8001 SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
8002 SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
8003 SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
8004 SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
8005 SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
8006
8007 temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8008 /* D1 should be set for PAL, PAL-N and NTSC-J,
8009 but I won't do that for PAL unless somebody
8010 tells me to do so. Since the BIOS uses
8011 non-default CIV values and blacklevels,
8012 this might be compensated anyway.
8013 */
8014 if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8015 SiS_SetCH701x(SiS_Pr,0x21,temp);
1da177e4
LT
8016
8017#endif /* 315 */
8018
544393fe 8019 }
1da177e4
LT
8020
8021#ifdef SIS_CP
544393fe 8022 SIS_CP_INIT301_CP3
1da177e4
LT
8023#endif
8024
8025}
8026
f7854e5d 8027#ifdef CONFIG_FB_SIS_315 /* ----------- 315 series only ---------- */
544393fe 8028
1da177e4 8029void
544393fe 8030SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
1da177e4 8031{
544393fe 8032 unsigned short temp;
1da177e4 8033
544393fe
TW
8034 /* Enable Chrontel 7019 LCD panel backlight */
8035 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8036 if(SiS_Pr->ChipType == SIS_740) {
8037 SiS_SetCH701x(SiS_Pr,0x66,0x65);
8038 } else {
8039 temp = SiS_GetCH701x(SiS_Pr,0x66);
8040 temp |= 0x20;
8041 SiS_SetCH701x(SiS_Pr,0x66,temp);
8042 }
8043 }
1da177e4
LT
8044}
8045
8046void
544393fe 8047SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
1da177e4 8048{
544393fe 8049 unsigned short temp;
1da177e4 8050
544393fe
TW
8051 /* Disable Chrontel 7019 LCD panel backlight */
8052 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8053 temp = SiS_GetCH701x(SiS_Pr,0x66);
8054 temp &= 0xDF;
8055 SiS_SetCH701x(SiS_Pr,0x66,temp);
8056 }
1da177e4
LT
8057}
8058
1da177e4 8059static void
544393fe
TW
8060SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
8061{
8062 static const unsigned char regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8063 static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8064 static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8065 static const unsigned char asus1024_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8066 static const unsigned char asus1400_740[] = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8067 static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8068 static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8069 const unsigned char *tableptr = NULL;
1da177e4
LT
8070 int i;
8071
8072 /* Set up Power up/down timing */
8073
544393fe 8074 if(SiS_Pr->ChipType == SIS_740) {
1da177e4 8075 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
544393fe
TW
8076 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8077 else tableptr = table1024_740;
1da177e4 8078 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
544393fe 8079 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
1da177e4
LT
8080 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8081 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8082 else tableptr = table1400_740;
8083 } else return;
8084 } else {
8085 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
544393fe 8086 tableptr = table1024_650;
1da177e4 8087 } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
544393fe 8088 (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
1da177e4 8089 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
544393fe 8090 tableptr = table1400_650;
1da177e4
LT
8091 } else return;
8092 }
8093
8094 for(i=0; i<5; i++) {
544393fe 8095 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
1da177e4
LT
8096 }
8097}
8098
8099static void
544393fe
TW
8100SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
8101{
8102 const unsigned char *tableptr = NULL;
8103 unsigned short tempbh;
1da177e4 8104 int i;
544393fe
TW
8105 static const unsigned char regtable[] = {
8106 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8107 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
8108 };
8109 static const unsigned char table1024_740[] = {
8110 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8111 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
8112 };
8113 static const unsigned char table1280_740[] = {
8114 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8115 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8116 };
8117 static const unsigned char table1400_740[] = {
8118 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8119 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8120 };
8121 static const unsigned char table1600_740[] = {
8122 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8123 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
8124 };
8125 static const unsigned char table1024_650[] = {
8126 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8127 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
8128 };
8129 static const unsigned char table1280_650[] = {
8130 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8131 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
8132 };
8133 static const unsigned char table1400_650[] = {
8134 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8135 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
8136 };
8137 static const unsigned char table1600_650[] = {
8138 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8139 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
8140 };
1da177e4 8141
544393fe 8142 if(SiS_Pr->ChipType == SIS_740) {
1da177e4
LT
8143 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_740;
8144 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8145 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8146 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8147 else return;
8148 } else {
8149 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tableptr = table1024_650;
8150 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8151 else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8152 else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8153 else return;
8154 }
8155
8156 tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8157 if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8158 tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8159 if(tempbh == 0xc8) {
8160 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8161 } else if(tempbh == 0xdb) {
8162 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8163 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8164 } else if(tempbh == 0xde) {
8165 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8166 }
8167 }
8168
544393fe
TW
8169 if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
8170 else tempbh = 0x0c;
1da177e4
LT
8171
8172 for(i = 0; i < tempbh; i++) {
544393fe 8173 SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
1da177e4 8174 }
544393fe 8175 SiS_ChrontelPowerSequencing(SiS_Pr);
1da177e4
LT
8176 tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8177 tempbh |= 0xc0;
544393fe 8178 SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
1da177e4 8179
544393fe 8180 if(SiS_Pr->ChipType == SIS_740) {
1da177e4
LT
8181 tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8182 tempbh &= 0xfb;
544393fe 8183 SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
1da177e4
LT
8184 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8185 tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8186 tempbh |= 0x40;
544393fe 8187 SiS_SetCH701x(SiS_Pr,0x64,tempbh);
1da177e4
LT
8188 tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8189 tempbh &= 0x3f;
544393fe 8190 SiS_SetCH701x(SiS_Pr,0x03,tempbh);
1da177e4
LT
8191 }
8192}
8193
8194static void
544393fe 8195SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
1da177e4
LT
8196{
8197 unsigned char temp, temp1;
8198
8199 temp1 = SiS_GetCH701x(SiS_Pr,0x49);
544393fe 8200 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
1da177e4
LT
8201 temp = SiS_GetCH701x(SiS_Pr,0x47);
8202 temp &= 0x7f; /* Use external VSYNC */
544393fe
TW
8203 SiS_SetCH701x(SiS_Pr,0x47,temp);
8204 SiS_LongDelay(SiS_Pr, 3);
1da177e4
LT
8205 temp = SiS_GetCH701x(SiS_Pr,0x47);
8206 temp |= 0x80; /* Use internal VSYNC */
544393fe
TW
8207 SiS_SetCH701x(SiS_Pr,0x47,temp);
8208 SiS_SetCH701x(SiS_Pr,0x49,temp1);
1da177e4
LT
8209}
8210
8211static void
544393fe 8212SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
1da177e4 8213{
544393fe 8214 unsigned short temp;
1da177e4
LT
8215
8216 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
544393fe 8217 if(SiS_Pr->ChipType == SIS_740) {
1da177e4
LT
8218 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8219 temp |= 0x04; /* Invert XCLK phase */
544393fe 8220 SiS_SetCH701x(SiS_Pr,0x1c,temp);
1da177e4 8221 }
544393fe 8222 if(SiS_IsYPbPr(SiS_Pr)) {
1da177e4
LT
8223 temp = SiS_GetCH701x(SiS_Pr,0x01);
8224 temp &= 0x3f;
8225 temp |= 0x80; /* Enable YPrPb (HDTV) */
544393fe 8226 SiS_SetCH701x(SiS_Pr,0x01,temp);
1da177e4 8227 }
544393fe 8228 if(SiS_IsChScart(SiS_Pr)) {
1da177e4
LT
8229 temp = SiS_GetCH701x(SiS_Pr,0x01);
8230 temp &= 0x3f;
8231 temp |= 0xc0; /* Enable SCART + CVBS */
544393fe 8232 SiS_SetCH701x(SiS_Pr,0x01,temp);
1da177e4 8233 }
544393fe 8234 if(SiS_Pr->ChipType == SIS_740) {
1da177e4 8235 SiS_ChrontelResetVSync(SiS_Pr);
544393fe 8236 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
1da177e4 8237 } else {
544393fe 8238 SiS_SetCH701x(SiS_Pr,0x49,0x20); /* Enable TV path */
1da177e4 8239 temp = SiS_GetCH701x(SiS_Pr,0x49);
544393fe 8240 if(SiS_IsYPbPr(SiS_Pr)) {
1da177e4
LT
8241 temp = SiS_GetCH701x(SiS_Pr,0x73);
8242 temp |= 0x60;
544393fe 8243 SiS_SetCH701x(SiS_Pr,0x73,temp);
1da177e4
LT
8244 }
8245 temp = SiS_GetCH701x(SiS_Pr,0x47);
8246 temp &= 0x7f;
544393fe
TW
8247 SiS_SetCH701x(SiS_Pr,0x47,temp);
8248 SiS_LongDelay(SiS_Pr, 2);
1da177e4
LT
8249 temp = SiS_GetCH701x(SiS_Pr,0x47);
8250 temp |= 0x80;
544393fe 8251 SiS_SetCH701x(SiS_Pr,0x47,temp);
1da177e4
LT
8252 }
8253 }
8254}
8255
8256static void
544393fe 8257SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
1da177e4 8258{
544393fe 8259 unsigned short temp;
1da177e4
LT
8260
8261 /* Complete power down of LVDS */
8262 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
544393fe
TW
8263 if(SiS_Pr->ChipType == SIS_740) {
8264 SiS_LongDelay(SiS_Pr, 1);
8265 SiS_GenericDelay(SiS_Pr, 5887);
8266 SiS_SetCH701x(SiS_Pr,0x76,0xac);
8267 SiS_SetCH701x(SiS_Pr,0x66,0x00);
1da177e4 8268 } else {
544393fe 8269 SiS_LongDelay(SiS_Pr, 2);
1da177e4
LT
8270 temp = SiS_GetCH701x(SiS_Pr,0x76);
8271 temp &= 0xfc;
544393fe
TW
8272 SiS_SetCH701x(SiS_Pr,0x76,temp);
8273 SiS_SetCH701x(SiS_Pr,0x66,0x00);
1da177e4
LT
8274 }
8275 }
8276}
8277
8278static void
544393fe 8279SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
1da177e4 8280{
544393fe 8281 unsigned short temp;
1da177e4 8282
544393fe 8283 if(SiS_Pr->ChipType == SIS_740) {
1da177e4
LT
8284
8285 temp = SiS_GetCH701x(SiS_Pr,0x4a); /* Version ID */
8286 temp &= 0x01;
8287 if(!temp) {
8288
544393fe 8289 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
1da177e4 8290 temp = SiS_GetCH701x(SiS_Pr,0x49);
544393fe 8291 SiS_SetCH701x(SiS_Pr,0x49,0x3e);
1da177e4 8292 }
544393fe 8293
1da177e4 8294 /* Reset Chrontel 7019 datapath */
544393fe
TW
8295 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8296 SiS_LongDelay(SiS_Pr, 1);
8297 SiS_SetCH701x(SiS_Pr,0x48,0x18);
1da177e4 8298
544393fe 8299 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
1da177e4 8300 SiS_ChrontelResetVSync(SiS_Pr);
544393fe 8301 SiS_SetCH701x(SiS_Pr,0x49,temp);
1da177e4
LT
8302 }
8303
8304 } else {
8305
8306 /* Clear/set/clear GPIO */
8307 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8308 temp &= 0xef;
544393fe 8309 SiS_SetCH701x(SiS_Pr,0x5c,temp);
1da177e4
LT
8310 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8311 temp |= 0x10;
544393fe 8312 SiS_SetCH701x(SiS_Pr,0x5c,temp);
1da177e4
LT
8313 temp = SiS_GetCH701x(SiS_Pr,0x5c);
8314 temp &= 0xef;
544393fe 8315 SiS_SetCH701x(SiS_Pr,0x5c,temp);
1da177e4
LT
8316 temp = SiS_GetCH701x(SiS_Pr,0x61);
8317 if(!temp) {
544393fe 8318 SiS_SetCH701xForLCD(SiS_Pr);
1da177e4
LT
8319 }
8320 }
8321
8322 } else { /* 650 */
8323 /* Reset Chrontel 7019 datapath */
544393fe
TW
8324 SiS_SetCH701x(SiS_Pr,0x48,0x10);
8325 SiS_LongDelay(SiS_Pr, 1);
8326 SiS_SetCH701x(SiS_Pr,0x48,0x18);
1da177e4
LT
8327 }
8328}
8329
8330static void
544393fe 8331SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
1da177e4 8332{
544393fe 8333 unsigned short temp;
1da177e4 8334
544393fe 8335 if(SiS_Pr->ChipType == SIS_740) {
1da177e4 8336
544393fe 8337 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
1da177e4
LT
8338 SiS_ChrontelResetVSync(SiS_Pr);
8339 }
8340
8341 } else {
8342
544393fe 8343 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* Power up LVDS block */
1da177e4
LT
8344 temp = SiS_GetCH701x(SiS_Pr,0x49);
8345 temp &= 1;
8346 if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */
8347 temp = SiS_GetCH701x(SiS_Pr,0x47);
8348 temp &= 0x70;
544393fe
TW
8349 SiS_SetCH701x(SiS_Pr,0x47,temp); /* enable VSYNC */
8350 SiS_LongDelay(SiS_Pr, 3);
1da177e4
LT
8351 temp = SiS_GetCH701x(SiS_Pr,0x47);
8352 temp |= 0x80;
544393fe 8353 SiS_SetCH701x(SiS_Pr,0x47,temp); /* disable VSYNC */
1da177e4
LT
8354 }
8355
8356 }
8357}
8358
8359static void
544393fe 8360SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1da177e4 8361{
544393fe 8362 unsigned short temp,temp1;
1da177e4 8363
544393fe 8364 if(SiS_Pr->ChipType == SIS_740) {
1da177e4
LT
8365
8366 temp = SiS_GetCH701x(SiS_Pr,0x61);
8367 if(temp < 1) {
8368 temp++;
544393fe 8369 SiS_SetCH701x(SiS_Pr,0x61,temp);
1da177e4 8370 }
544393fe
TW
8371 SiS_SetCH701x(SiS_Pr,0x66,0x45); /* Panel power on */
8372 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on */
8373 SiS_LongDelay(SiS_Pr, 1);
8374 SiS_GenericDelay(SiS_Pr, 5887);
1da177e4
LT
8375
8376 } else { /* 650 */
8377
8378 temp1 = 0;
8379 temp = SiS_GetCH701x(SiS_Pr,0x61);
8380 if(temp < 2) {
8381 temp++;
544393fe 8382 SiS_SetCH701x(SiS_Pr,0x61,temp);
1da177e4
LT
8383 temp1 = 1;
8384 }
544393fe 8385 SiS_SetCH701x(SiS_Pr,0x76,0xac);
1da177e4
LT
8386 temp = SiS_GetCH701x(SiS_Pr,0x66);
8387 temp |= 0x5f;
544393fe 8388 SiS_SetCH701x(SiS_Pr,0x66,temp);
1da177e4 8389 if(ModeNo > 0x13) {
544393fe
TW
8390 if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8391 SiS_GenericDelay(SiS_Pr, 1023);
1da177e4 8392 } else {
544393fe 8393 SiS_GenericDelay(SiS_Pr, 767);
1da177e4
LT
8394 }
8395 } else {
8396 if(!temp1)
544393fe 8397 SiS_GenericDelay(SiS_Pr, 767);
1da177e4
LT
8398 }
8399 temp = SiS_GetCH701x(SiS_Pr,0x76);
8400 temp |= 0x03;
544393fe 8401 SiS_SetCH701x(SiS_Pr,0x76,temp);
1da177e4
LT
8402 temp = SiS_GetCH701x(SiS_Pr,0x66);
8403 temp &= 0x7f;
544393fe
TW
8404 SiS_SetCH701x(SiS_Pr,0x66,temp);
8405 SiS_LongDelay(SiS_Pr, 1);
1da177e4
LT
8406
8407 }
8408}
8409
8410static void
544393fe 8411SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
1da177e4 8412{
e4ccde33 8413 unsigned short temp;
1da177e4
LT
8414
8415 SiS_LongDelay(SiS_Pr, 1);
1da177e4
LT
8416
8417 do {
8418 temp = SiS_GetCH701x(SiS_Pr,0x66);
8419 temp &= 0x04; /* PLL stable? -> bail out */
8420 if(temp == 0x04) break;
8421
544393fe 8422 if(SiS_Pr->ChipType == SIS_740) {
1da177e4 8423 /* Power down LVDS output, PLL normal operation */
544393fe 8424 SiS_SetCH701x(SiS_Pr,0x76,0xac);
1da177e4
LT
8425 }
8426
544393fe 8427 SiS_SetCH701xForLCD(SiS_Pr);
1da177e4 8428
1da177e4
LT
8429 temp = SiS_GetCH701x(SiS_Pr,0x76);
8430 temp &= 0xfb; /* Reset PLL */
544393fe
TW
8431 SiS_SetCH701x(SiS_Pr,0x76,temp);
8432 SiS_LongDelay(SiS_Pr, 2);
1da177e4
LT
8433 temp = SiS_GetCH701x(SiS_Pr,0x76);
8434 temp |= 0x04; /* PLL normal operation */
544393fe
TW
8435 SiS_SetCH701x(SiS_Pr,0x76,temp);
8436 if(SiS_Pr->ChipType == SIS_740) {
8437 SiS_SetCH701x(SiS_Pr,0x78,0xe0); /* PLL loop filter */
1da177e4 8438 } else {
544393fe 8439 SiS_SetCH701x(SiS_Pr,0x78,0x60);
1da177e4 8440 }
544393fe 8441 SiS_LongDelay(SiS_Pr, 2);
1da177e4
LT
8442 } while(0);
8443
544393fe 8444 SiS_SetCH701x(SiS_Pr,0x77,0x00); /* MV? */
1da177e4
LT
8445}
8446
8447static void
544393fe 8448SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
1da177e4 8449{
544393fe 8450 unsigned short temp;
1da177e4
LT
8451
8452 temp = SiS_GetCH701x(SiS_Pr,0x03);
8453 temp |= 0x80; /* Set datapath 1 to TV */
8454 temp &= 0xbf; /* Set datapath 2 to LVDS */
544393fe 8455 SiS_SetCH701x(SiS_Pr,0x03,temp);
1da177e4 8456
544393fe 8457 if(SiS_Pr->ChipType == SIS_740) {
1da177e4
LT
8458
8459 temp = SiS_GetCH701x(SiS_Pr,0x1c);
8460 temp &= 0xfb; /* Normal XCLK phase */
544393fe 8461 SiS_SetCH701x(SiS_Pr,0x1c,temp);
1da177e4
LT
8462
8463 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8464
8465 temp = SiS_GetCH701x(SiS_Pr,0x64);
8466 temp |= 0x40; /* ? Bit not defined */
544393fe 8467 SiS_SetCH701x(SiS_Pr,0x64,temp);
1da177e4
LT
8468
8469 temp = SiS_GetCH701x(SiS_Pr,0x03);
8470 temp &= 0x3f; /* D1 input to both LVDS and TV */
544393fe 8471 SiS_SetCH701x(SiS_Pr,0x03,temp);
1da177e4
LT
8472
8473 if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
544393fe 8474 SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
1da177e4 8475 SiS_LongDelay(SiS_Pr, 1);
544393fe
TW
8476 SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
8477 SiS_ChrontelResetDB(SiS_Pr);
8478 SiS_ChrontelDoSomething2(SiS_Pr);
8479 SiS_ChrontelDoSomething3(SiS_Pr, 0);
1da177e4
LT
8480 } else {
8481 temp = SiS_GetCH701x(SiS_Pr,0x66);
8482 if(temp != 0x45) {
544393fe
TW
8483 SiS_ChrontelResetDB(SiS_Pr);
8484 SiS_ChrontelDoSomething2(SiS_Pr);
8485 SiS_ChrontelDoSomething3(SiS_Pr, 0);
1da177e4
LT
8486 }
8487 }
8488
8489 } else { /* 650 */
8490
544393fe
TW
8491 SiS_ChrontelResetDB(SiS_Pr);
8492 SiS_ChrontelDoSomething2(SiS_Pr);
1da177e4 8493 temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
544393fe
TW
8494 SiS_ChrontelDoSomething3(SiS_Pr,temp);
8495 SiS_SetCH701x(SiS_Pr,0x76,0xaf); /* All power on, LVDS normal operation */
1da177e4
LT
8496
8497 }
8498
8499}
8500#endif /* 315 series */
8501
8502/*********************************************/
8503/* MAIN: SET CRT2 REGISTER GROUP */
8504/*********************************************/
8505
c30660ea 8506bool
544393fe 8507SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1da177e4 8508{
f7854e5d 8509#ifdef CONFIG_FB_SIS_300
544393fe 8510 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1da177e4 8511#endif
544393fe 8512 unsigned short ModeIdIndex, RefreshRateTableIndex;
1da177e4
LT
8513
8514 SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8515
8516 if(!SiS_Pr->UseCustomMode) {
8517 SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8518 } else {
8519 ModeIdIndex = 0;
8520 }
8521
8522 /* Used for shifting CR33 */
8523 SiS_Pr->SiS_SelectCRT2Rate = 4;
8524
544393fe 8525 SiS_UnLockCRT2(SiS_Pr);
1da177e4 8526
544393fe 8527 RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4
LT
8528
8529 SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8530
8531 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
544393fe
TW
8532 SiS_DisableBridge(SiS_Pr);
8533 if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
1da177e4
LT
8534 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8535 }
544393fe 8536 SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4
LT
8537 }
8538
8539 if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
544393fe 8540 SiS_LockCRT2(SiS_Pr);
1da177e4 8541 SiS_DisplayOn(SiS_Pr);
c30660ea 8542 return true;
1da177e4
LT
8543 }
8544
544393fe 8545 SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
8546
8547 /* Set up Panel Link for LVDS and LCDA */
8548 SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8549 if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8550 ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
544393fe
TW
8551 ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
8552 SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
8553 }
8554
1da177e4 8555 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
544393fe 8556 SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
8557 }
8558
8559 if(SiS_Pr->SiS_VBType & VB_SISVB) {
8560
544393fe 8561 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
1da177e4 8562
544393fe 8563 SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
f7854e5d 8564#ifdef CONFIG_FB_SIS_315
544393fe 8565 SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4 8566#endif
544393fe
TW
8567 SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
8568 SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
f7854e5d 8569#ifdef CONFIG_FB_SIS_315
544393fe 8570 SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4 8571#endif
544393fe 8572 SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4 8573
544393fe 8574 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
1da177e4 8575
544393fe
TW
8576 /* For 301BDH (Panel link initialization): */
8577 if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8578
8579 if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8580 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8581 SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8582 }
8583 }
8584 SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8585 }
8586 }
1da177e4
LT
8587
8588 } else {
8589
544393fe 8590 SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
1da177e4 8591
544393fe 8592 SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
1da177e4 8593
544393fe 8594 SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
1da177e4 8595
544393fe
TW
8596 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8597 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8598 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8599 if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
f7854e5d 8600#ifdef CONFIG_FB_SIS_315
544393fe 8601 SiS_SetCH701xForLCD(SiS_Pr);
1da177e4 8602#endif
544393fe
TW
8603 }
8604 }
8605 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8606 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8607 }
8608 }
8609 }
1da177e4
LT
8610
8611 }
8612
f7854e5d 8613#ifdef CONFIG_FB_SIS_300
544393fe 8614 if(SiS_Pr->ChipType < SIS_315H) {
1da177e4
LT
8615 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8616 if(SiS_Pr->SiS_UseOEM) {
8617 if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8618 if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
544393fe 8619 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
8620 }
8621 } else {
544393fe 8622 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4
LT
8623 }
8624 }
8625 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
544393fe 8626 if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1da177e4 8627 (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
544393fe 8628 SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
1da177e4
LT
8629 }
8630 SiS_DisplayOn(SiS_Pr);
8631 }
8632 }
8633 }
8634#endif
8635
f7854e5d 8636#ifdef CONFIG_FB_SIS_315
544393fe 8637 if(SiS_Pr->ChipType >= SIS_315H) {
1da177e4 8638 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
544393fe
TW
8639 if(SiS_Pr->ChipType < SIS_661) {
8640 SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
8641 SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4 8642 } else {
544393fe 8643 SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
1da177e4 8644 }
544393fe 8645 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
1da177e4
LT
8646 }
8647 }
8648#endif
8649
8650 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
544393fe 8651 SiS_EnableBridge(SiS_Pr);
1da177e4
LT
8652 }
8653
8654 SiS_DisplayOn(SiS_Pr);
8655
8656 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8657 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8658 /* Disable LCD panel when using TV */
544393fe 8659 SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
1da177e4
LT
8660 } else {
8661 /* Disable TV when using LCD */
544393fe 8662 SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
1da177e4
LT
8663 }
8664 }
8665
8666 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
544393fe 8667 SiS_LockCRT2(SiS_Pr);
1da177e4
LT
8668 }
8669
c30660ea 8670 return true;
1da177e4
LT
8671}
8672
8673
8674/*********************************************/
8675/* ENABLE/DISABLE LCD BACKLIGHT (SIS) */
8676/*********************************************/
8677
8678void
544393fe 8679SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
1da177e4
LT
8680{
8681 /* Switch on LCD backlight on SiS30xLV */
8682 SiS_DDC2Delay(SiS_Pr,0xff00);
8683 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
8684 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
544393fe 8685 SiS_WaitVBRetrace(SiS_Pr);
1da177e4
LT
8686 }
8687 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
8688 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
8689 }
8690}
8691
8692void
544393fe 8693SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
1da177e4
LT
8694{
8695 /* Switch off LCD backlight on SiS30xLV */
8696 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
544393fe 8697 SiS_DDC2Delay(SiS_Pr,0xff00);
1da177e4
LT
8698}
8699
8700/*********************************************/
8701/* DDC RELATED FUNCTIONS */
8702/*********************************************/
8703
8704static void
544393fe 8705SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
1da177e4
LT
8706{
8707 SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
8708 SiS_Pr->SiS_DDC_NClk = ~SiS_Pr->SiS_DDC_Clk;
8709 if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
8710 SiS_Pr->SiS_DDC_NData &= 0x0f;
8711 SiS_Pr->SiS_DDC_NClk &= 0x0f;
8712 }
8713}
8714
f7854e5d 8715#ifdef CONFIG_FB_SIS_300
544393fe
TW
8716static unsigned char *
8717SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
1da177e4
LT
8718{
8719 int i, j, num;
544393fe
TW
8720 unsigned short tempah,temp;
8721 unsigned char *mydataptr;
1da177e4
LT
8722
8723 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8724 mydataptr = dataptr;
8725 num = *mydataptr++;
8726 if(!num) return mydataptr;
8727 if(i) {
8728 SiS_SetStop(SiS_Pr);
544393fe 8729 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
1da177e4
LT
8730 }
8731 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8732 tempah = SiS_Pr->SiS_DDC_DeviceAddr;
8733 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
8734 if(temp) continue; /* (ERROR: no ack) */
8735 tempah = *mydataptr++;
8736 temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write register number */
8737 if(temp) continue; /* (ERROR: no ack) */
8738 for(j=0; j<num; j++) {
8739 tempah = *mydataptr++;
8740 temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
8741 if(temp) break;
8742 }
8743 if(temp) continue;
8744 if(SiS_SetStop(SiS_Pr)) continue;
8745 return mydataptr;
8746 }
8747 return NULL;
8748}
8749
c30660ea 8750static bool
544393fe 8751SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
1da177e4
LT
8752{
8753 SiS_Pr->SiS_DDC_DeviceAddr = 0xF0; /* DAB (Device Address Byte) */
8754 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
544393fe
TW
8755 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8756 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
1da177e4
LT
8757 SiS_SetupDDCN(SiS_Pr);
8758
8759 SiS_SetSwitchDDC2(SiS_Pr);
8760
8761 while(*dataptr) {
8762 dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
c30660ea 8763 if(!dataptr) return false;
1da177e4 8764 }
c30660ea 8765 return true;
1da177e4
LT
8766}
8767#endif
8768
8769/* The Chrontel 700x is connected to the 630/730 via
8770 * the 630/730's DDC/I2C port.
8771 *
8772 * On 630(S)T chipset, the index changed from 0x11 to
8773 * 0x0a, possibly for working around the DDC problems
8774 */
8775
c30660ea 8776static bool
544393fe 8777SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
1da177e4 8778{
544393fe 8779 unsigned short temp, i;
1da177e4
LT
8780
8781 for(i=0; i<20; i++) { /* Do 20 attempts to write */
8782 if(i) {
544393fe
TW
8783 SiS_SetStop(SiS_Pr);
8784 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
8785 }
8786 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8787 temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
8788 if(temp) continue; /* (ERROR: no ack) */
8789 temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor)); /* Write RAB (700x: set bit 7, see datasheet) */
8790 if(temp) continue; /* (ERROR: no ack) */
8791 temp = SiS_WriteDDC2Data(SiS_Pr, val); /* Write data */
8792 if(temp) continue; /* (ERROR: no ack) */
8793 if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
1da177e4 8794 SiS_Pr->SiS_ChrontelInit = 1;
c30660ea 8795 return true;
1da177e4 8796 }
c30660ea 8797 return false;
1da177e4
LT
8798}
8799
1da177e4 8800/* Write to Chrontel 700x */
1da177e4 8801void
544393fe 8802SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
1da177e4
LT
8803{
8804 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
8805
544393fe
TW
8806 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8807
1da177e4
LT
8808 if(!(SiS_Pr->SiS_ChrontelInit)) {
8809 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
544393fe
TW
8810 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8811 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
1da177e4
LT
8812 SiS_SetupDDCN(SiS_Pr);
8813 }
8814
544393fe 8815 if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
1da177e4 8816 (!(SiS_Pr->SiS_ChrontelInit)) ) {
544393fe
TW
8817 SiS_Pr->SiS_DDC_Index = 0x0a;
8818 SiS_Pr->SiS_DDC_Data = 0x80;
8819 SiS_Pr->SiS_DDC_Clk = 0x40;
1da177e4
LT
8820 SiS_SetupDDCN(SiS_Pr);
8821
544393fe 8822 SiS_SetChReg(SiS_Pr, reg, val, 0x80);
1da177e4
LT
8823 }
8824}
8825
8826/* Write to Chrontel 701x */
8827/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
8828void
544393fe 8829SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
1da177e4
LT
8830{
8831 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
544393fe
TW
8832 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
8833 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
1da177e4 8834 SiS_SetupDDCN(SiS_Pr);
544393fe
TW
8835 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
8836 SiS_SetChReg(SiS_Pr, reg, val, 0);
1da177e4
LT
8837}
8838
544393fe 8839static
544393fe
TW
8840void
8841SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
1da177e4
LT
8842{
8843 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
544393fe 8844 SiS_SetCH700x(SiS_Pr, reg, val);
1da177e4 8845 else
544393fe 8846 SiS_SetCH701x(SiS_Pr, reg, val);
1da177e4
LT
8847}
8848
544393fe
TW
8849static unsigned short
8850SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
1da177e4 8851{
544393fe 8852 unsigned short tempah, temp, i;
1da177e4
LT
8853
8854 for(i=0; i<20; i++) { /* Do 20 attempts to read */
8855 if(i) {
544393fe
TW
8856 SiS_SetStop(SiS_Pr);
8857 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
8858 }
8859 if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
8860 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr); /* Write DAB (S0=0=write) */
8861 if(temp) continue; /* (ERROR: no ack) */
8862 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor); /* Write RAB (700x: | 0x80) */
8863 if(temp) continue; /* (ERROR: no ack) */
8864 if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
8865 temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
8866 if(temp) continue; /* (ERROR: no ack) */
8867 tempah = SiS_ReadDDC2Data(SiS_Pr); /* Read byte */
8868 if(SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
1da177e4 8869 SiS_Pr->SiS_ChrontelInit = 1;
544393fe 8870 return tempah;
1da177e4
LT
8871 }
8872 return 0xFFFF;
8873}
8874
1da177e4
LT
8875/* Read from Chrontel 700x */
8876/* Parameter is [Register no (S7-S0)] */
544393fe
TW
8877unsigned short
8878SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
1da177e4 8879{
544393fe 8880 unsigned short result;
1da177e4
LT
8881
8882 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
8883
544393fe
TW
8884 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8885
1da177e4
LT
8886 if(!(SiS_Pr->SiS_ChrontelInit)) {
8887 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
544393fe
TW
8888 SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
8889 SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
1da177e4
LT
8890 SiS_SetupDDCN(SiS_Pr);
8891 }
8892
8893 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8894
8895 if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
8896 (!SiS_Pr->SiS_ChrontelInit) ) {
8897
8898 SiS_Pr->SiS_DDC_Index = 0x0a;
8899 SiS_Pr->SiS_DDC_Data = 0x80;
8900 SiS_Pr->SiS_DDC_Clk = 0x40;
8901 SiS_SetupDDCN(SiS_Pr);
8902
8903 result = SiS_GetChReg(SiS_Pr,0x80);
8904 }
544393fe 8905 return result;
1da177e4
LT
8906}
8907
8908/* Read from Chrontel 701x */
8909/* Parameter is [Register no (S7-S0)] */
544393fe
TW
8910unsigned short
8911SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
1da177e4
LT
8912{
8913 SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
544393fe
TW
8914 SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
8915 SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
1da177e4
LT
8916 SiS_SetupDDCN(SiS_Pr);
8917 SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
8918
8919 SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8920
544393fe 8921 return SiS_GetChReg(SiS_Pr,0);
1da177e4
LT
8922}
8923
8924/* Read from Chrontel 70xx */
8925/* Parameter is [Register no (S7-S0)] */
544393fe 8926static
544393fe
TW
8927unsigned short
8928SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
1da177e4
LT
8929{
8930 if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
544393fe 8931 return SiS_GetCH700x(SiS_Pr, tempbx);
1da177e4 8932 else
544393fe
TW
8933 return SiS_GetCH701x(SiS_Pr, tempbx);
8934}
8935
8936void
8937SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
8938 unsigned char myor, unsigned short myand)
8939{
8940 unsigned short tempbl;
8941
8942 tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
8943 SiS_SetCH70xx(SiS_Pr, reg, tempbl);
1da177e4
LT
8944}
8945
8946/* Our own DDC functions */
544393fe 8947static
544393fe
TW
8948unsigned short
8949SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
c30660ea 8950 unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
544393fe 8951 unsigned int VBFlags2)
1da177e4
LT
8952{
8953 unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
8954 unsigned char flag, cr32;
544393fe 8955 unsigned short temp = 0, myadaptnum = adaptnum;
1da177e4
LT
8956
8957 if(adaptnum != 0) {
544393fe
TW
8958 if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
8959 if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
8960 }
8961
1da177e4 8962 /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
544393fe 8963
1da177e4
LT
8964 SiS_Pr->SiS_ChrontelInit = 0; /* force re-detection! */
8965
8966 SiS_Pr->SiS_DDC_SecAddr = 0;
8967 SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
8968 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
8969 SiS_Pr->SiS_DDC_Index = 0x11;
8970 flag = 0xff;
8971
8972 cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
8973
8974#if 0
544393fe 8975 if(VBFlags2 & VB2_SISBRIDGE) {
1da177e4
LT
8976 if(myadaptnum == 0) {
8977 if(!(cr32 & 0x20)) {
8978 myadaptnum = 2;
8979 if(!(cr32 & 0x10)) {
8980 myadaptnum = 1;
8981 if(!(cr32 & 0x08)) {
8982 myadaptnum = 0;
8983 }
8984 }
8985 }
8986 }
8987 }
8988#endif
8989
8990 if(VGAEngine == SIS_300_VGA) { /* 300 series */
544393fe 8991
1da177e4
LT
8992 if(myadaptnum != 0) {
8993 flag = 0;
544393fe 8994 if(VBFlags2 & VB2_SISBRIDGE) {
1da177e4
LT
8995 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
8996 SiS_Pr->SiS_DDC_Index = 0x0f;
8997 }
8998 }
8999
544393fe 9000 if(!(VBFlags2 & VB2_301)) {
1da177e4
LT
9001 if((cr32 & 0x80) && (checkcr32)) {
9002 if(myadaptnum >= 1) {
9003 if(!(cr32 & 0x08)) {
544393fe 9004 myadaptnum = 1;
1da177e4
LT
9005 if(!(cr32 & 0x10)) return 0xFFFF;
9006 }
9007 }
9008 }
9009 }
9010
9011 temp = 4 - (myadaptnum * 2);
9012 if(flag) temp = 0;
9013
9014 } else { /* 315/330 series */
9015
544393fe 9016 /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
1da177e4 9017
544393fe 9018 if(VBFlags2 & VB2_SISBRIDGE) {
1da177e4
LT
9019 if(myadaptnum == 2) {
9020 myadaptnum = 1;
544393fe 9021 }
1da177e4
LT
9022 }
9023
9024 if(myadaptnum == 1) {
544393fe
TW
9025 flag = 0;
9026 if(VBFlags2 & VB2_SISBRIDGE) {
1da177e4
LT
9027 SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9028 SiS_Pr->SiS_DDC_Index = 0x0f;
9029 }
9030 }
9031
9032 if((cr32 & 0x80) && (checkcr32)) {
9033 if(myadaptnum >= 1) {
9034 if(!(cr32 & 0x08)) {
9035 myadaptnum = 1;
9036 if(!(cr32 & 0x10)) return 0xFFFF;
9037 }
9038 }
9039 }
9040
9041 temp = myadaptnum;
9042 if(myadaptnum == 1) {
9043 temp = 0;
544393fe 9044 if(VBFlags2 & VB2_LVDS) flag = 0xff;
1da177e4
LT
9045 }
9046
9047 if(flag) temp = 0;
9048 }
544393fe 9049
1da177e4
LT
9050 SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9051 SiS_Pr->SiS_DDC_Clk = 0x01 << temp;
9052
9053 SiS_SetupDDCN(SiS_Pr);
9054
1da177e4
LT
9055 return 0;
9056}
9057
544393fe
TW
9058static unsigned short
9059SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
1da177e4
LT
9060{
9061 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9062 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
544393fe 9063 return 0xFFFF;
1da177e4
LT
9064 }
9065 if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
544393fe 9066 return 0xFFFF;
1da177e4 9067 }
544393fe 9068 return 0;
1da177e4
LT
9069}
9070
544393fe
TW
9071static unsigned short
9072SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
1da177e4
LT
9073{
9074 if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9075 if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
544393fe 9076 return 0xFFFF;
1da177e4 9077 }
544393fe 9078 return 0;
1da177e4
LT
9079}
9080
544393fe
TW
9081static unsigned short
9082SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
1da177e4
LT
9083{
9084 if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
544393fe
TW
9085 if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
9086 return 0;
1da177e4
LT
9087}
9088
9089static void
544393fe 9090SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
1da177e4
LT
9091{
9092 SiS_SetSCLKLow(SiS_Pr);
9093 if(yesno) {
9094 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9095 SiS_Pr->SiS_DDC_Index,
9096 SiS_Pr->SiS_DDC_NData,
1da177e4
LT
9097 SiS_Pr->SiS_DDC_Data);
9098 } else {
9099 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9100 SiS_Pr->SiS_DDC_Index,
9101 SiS_Pr->SiS_DDC_NData,
1da177e4
LT
9102 0);
9103 }
9104 SiS_SetSCLKHigh(SiS_Pr);
9105}
9106
544393fe
TW
9107static unsigned short
9108SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
1da177e4
LT
9109{
9110 unsigned char mask, value;
544393fe 9111 unsigned short temp, ret=0;
c30660ea 9112 bool failed = false;
1da177e4
LT
9113
9114 SiS_SetSwitchDDC2(SiS_Pr);
9115 if(SiS_PrepareDDC(SiS_Pr)) {
9116 SiS_SetStop(SiS_Pr);
544393fe 9117 return 0xFFFF;
1da177e4
LT
9118 }
9119 mask = 0xf0;
9120 value = 0x20;
9121 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
544393fe 9122 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
1da177e4
LT
9123 SiS_SendACK(SiS_Pr, 0);
9124 if(temp == 0) {
9125 mask = 0xff;
9126 value = 0xff;
9127 } else {
c30660ea 9128 failed = true;
1da177e4 9129 ret = 0xFFFF;
1da177e4
LT
9130 }
9131 }
c30660ea 9132 if(!failed) {
544393fe 9133 temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
1da177e4
LT
9134 SiS_SendACK(SiS_Pr, 1);
9135 temp &= mask;
9136 if(temp == value) ret = 0;
9137 else {
9138 ret = 0xFFFF;
1da177e4
LT
9139 if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9140 if(temp == 0x30) ret = 0;
9141 }
9142 }
9143 }
9144 SiS_SetStop(SiS_Pr);
544393fe 9145 return ret;
1da177e4
LT
9146}
9147
544393fe 9148static
544393fe
TW
9149unsigned short
9150SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
1da177e4 9151{
544393fe 9152 unsigned short flag;
1da177e4
LT
9153
9154 flag = 0x180;
9155 SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9156 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9157 SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9158 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9159 SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9160 if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9161 if(!(flag & 0x1a)) flag = 0;
544393fe 9162 return flag;
1da177e4
LT
9163}
9164
544393fe 9165static
544393fe
TW
9166unsigned short
9167SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
1da177e4 9168{
544393fe 9169 unsigned short flag, length, i;
1da177e4
LT
9170 unsigned char chksum,gotcha;
9171
544393fe 9172 if(DDCdatatype > 4) return 0xFFFF;
1da177e4
LT
9173
9174 flag = 0;
9175 SiS_SetSwitchDDC2(SiS_Pr);
9176 if(!(SiS_PrepareDDC(SiS_Pr))) {
9177 length = 127;
9178 if(DDCdatatype != 1) length = 255;
9179 chksum = 0;
9180 gotcha = 0;
9181 for(i=0; i<length; i++) {
544393fe 9182 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
1da177e4
LT
9183 chksum += buffer[i];
9184 gotcha |= buffer[i];
9185 SiS_SendACK(SiS_Pr, 0);
9186 }
544393fe 9187 buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
1da177e4
LT
9188 chksum += buffer[i];
9189 SiS_SendACK(SiS_Pr, 1);
544393fe 9190 if(gotcha) flag = (unsigned short)chksum;
1da177e4
LT
9191 else flag = 0xFFFF;
9192 } else {
9193 flag = 0xFFFF;
9194 }
9195 SiS_SetStop(SiS_Pr);
544393fe 9196 return flag;
1da177e4
LT
9197}
9198
9199/* Our private DDC functions
9200
9201 It complies somewhat with the corresponding VESA function
9202 in arguments and return values.
9203
9204 Since this is probably called before the mode is changed,
9205 we use our pre-detected pSiS-values instead of SiS_Pr as
9206 regards chipset and video bridge type.
9207
9208 Arguments:
9209 adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9210 CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9211 LCDA is CRT1, but DDC is read from CRT2 port.
9212 DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9213 buffer: ptr to 256 data bytes which will be filled with read data.
9214
9215 Returns 0xFFFF if error, otherwise
9216 if DDCdatatype > 0: Returns 0 if reading OK (included a correct checksum)
9217 if DDCdatatype = 0: Returns supported DDC modes
9218
9219 */
544393fe
TW
9220unsigned short
9221SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9222 unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
9223 unsigned int VBFlags2)
1da177e4 9224{
544393fe
TW
9225 unsigned char sr1f, cr17=1;
9226 unsigned short result;
1da177e4 9227
544393fe
TW
9228 if(adaptnum > 2)
9229 return 0xFFFF;
9230
9231 if(DDCdatatype > 4)
9232 return 0xFFFF;
9233
9234 if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
9235 return 0xFFFF;
9236
c30660ea 9237 if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
544393fe 9238 return 0xFFFF;
1da177e4
LT
9239
9240 sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9241 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9242 if(VGAEngine == SIS_300_VGA) {
9243 cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9244 if(!cr17) {
9245 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9246 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9247 SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9248 }
9249 }
9250 if((sr1f) || (!cr17)) {
9251 SiS_WaitRetrace1(SiS_Pr);
9252 SiS_WaitRetrace1(SiS_Pr);
9253 SiS_WaitRetrace1(SiS_Pr);
9254 SiS_WaitRetrace1(SiS_Pr);
9255 }
9256
9257 if(DDCdatatype == 0) {
9258 result = SiS_ProbeDDC(SiS_Pr);
9259 } else {
9260 result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9261 if((!result) && (DDCdatatype == 1)) {
9262 if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9263 (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9264 (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9265 (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9266 (buffer[0x12] == 1)) {
544393fe
TW
9267 if(!SiS_Pr->DDCPortMixup) {
9268 if(adaptnum == 1) {
9269 if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9270 } else {
9271 if(buffer[0x14] & 0x80) result = 0xFFFE;
9272 }
1da177e4
LT
9273 }
9274 }
9275 }
9276 }
9277 SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9278 if(VGAEngine == SIS_300_VGA) {
9279 SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9280 }
9281 return result;
9282}
9283
1da177e4
LT
9284/* Generic I2C functions for Chrontel & DDC --------- */
9285
9286static void
544393fe 9287SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
1da177e4
LT
9288{
9289 SiS_SetSCLKHigh(SiS_Pr);
9290 SiS_WaitRetrace1(SiS_Pr);
9291
9292 SiS_SetSCLKLow(SiS_Pr);
9293 SiS_WaitRetrace1(SiS_Pr);
9294}
9295
544393fe
TW
9296unsigned short
9297SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
1da177e4
LT
9298{
9299 SiS_WaitRetrace1(SiS_Pr);
544393fe 9300 return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
1da177e4
LT
9301}
9302
9303/* Set I2C start condition */
9304/* This is done by a SD high-to-low transition while SC is high */
544393fe
TW
9305static unsigned short
9306SiS_SetStart(struct SiS_Private *SiS_Pr)
1da177e4 9307{
544393fe 9308 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
1da177e4 9309 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9310 SiS_Pr->SiS_DDC_Index,
9311 SiS_Pr->SiS_DDC_NData,
9312 SiS_Pr->SiS_DDC_Data); /* SD->high */
9313 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
1da177e4 9314 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9315 SiS_Pr->SiS_DDC_Index,
9316 SiS_Pr->SiS_DDC_NData,
9317 0x00); /* SD->low = start condition */
9318 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
1da177e4
LT
9319 return 0;
9320}
9321
9322/* Set I2C stop condition */
9323/* This is done by a SD low-to-high transition while SC is high */
544393fe
TW
9324static unsigned short
9325SiS_SetStop(struct SiS_Private *SiS_Pr)
1da177e4 9326{
544393fe 9327 if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
1da177e4 9328 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9329 SiS_Pr->SiS_DDC_Index,
9330 SiS_Pr->SiS_DDC_NData,
9331 0x00); /* SD->low */
9332 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
1da177e4 9333 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9334 SiS_Pr->SiS_DDC_Index,
9335 SiS_Pr->SiS_DDC_NData,
9336 SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
9337 if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
1da177e4
LT
9338 return 0;
9339}
9340
9341/* Write 8 bits of data */
544393fe
TW
9342static unsigned short
9343SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
1da177e4 9344{
544393fe 9345 unsigned short i,flag,temp;
1da177e4
LT
9346
9347 flag = 0x80;
544393fe
TW
9348 for(i = 0; i < 8; i++) {
9349 SiS_SetSCLKLow(SiS_Pr); /* SC->low */
1da177e4
LT
9350 if(tempax & flag) {
9351 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9352 SiS_Pr->SiS_DDC_Index,
9353 SiS_Pr->SiS_DDC_NData,
9354 SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
1da177e4
LT
9355 } else {
9356 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9357 SiS_Pr->SiS_DDC_Index,
9358 SiS_Pr->SiS_DDC_NData,
9359 0x00); /* Write bit (0) to SD */
1da177e4 9360 }
544393fe 9361 SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
1da177e4
LT
9362 flag >>= 1;
9363 }
544393fe
TW
9364 temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
9365 return temp;
1da177e4
LT
9366}
9367
544393fe
TW
9368static unsigned short
9369SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
1da177e4 9370{
544393fe 9371 unsigned short i, temp, getdata;
1da177e4 9372
544393fe
TW
9373 getdata = 0;
9374 for(i = 0; i < 8; i++) {
1da177e4
LT
9375 getdata <<= 1;
9376 SiS_SetSCLKLow(SiS_Pr);
9377 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9378 SiS_Pr->SiS_DDC_Index,
9379 SiS_Pr->SiS_DDC_NData,
1da177e4
LT
9380 SiS_Pr->SiS_DDC_Data);
9381 SiS_SetSCLKHigh(SiS_Pr);
9382 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9383 if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
9384 }
544393fe 9385 return getdata;
1da177e4
LT
9386}
9387
544393fe
TW
9388static unsigned short
9389SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
1da177e4
LT
9390{
9391 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9392 SiS_Pr->SiS_DDC_Index,
9393 SiS_Pr->SiS_DDC_NClk,
9394 0x00); /* SetSCLKLow() */
1da177e4
LT
9395 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9396 return 0;
9397}
9398
544393fe
TW
9399static unsigned short
9400SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
1da177e4 9401{
544393fe 9402 unsigned short temp, watchdog=1000;
1da177e4
LT
9403
9404 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9405 SiS_Pr->SiS_DDC_Index,
9406 SiS_Pr->SiS_DDC_NClk,
1da177e4
LT
9407 SiS_Pr->SiS_DDC_Clk); /* SetSCLKHigh() */
9408 do {
9409 temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9410 } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
9411 if (!watchdog) {
1da177e4
LT
9412 return 0xFFFF;
9413 }
9414 SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9415 return 0;
9416}
9417
9418/* Check I2C acknowledge */
9419/* Returns 0 if ack ok, non-0 if ack not ok */
544393fe
TW
9420static unsigned short
9421SiS_CheckACK(struct SiS_Private *SiS_Pr)
1da177e4 9422{
544393fe 9423 unsigned short tempah;
1da177e4
LT
9424
9425 SiS_SetSCLKLow(SiS_Pr); /* (SC->low) */
9426 SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
544393fe
TW
9427 SiS_Pr->SiS_DDC_Index,
9428 SiS_Pr->SiS_DDC_NData,
9429 SiS_Pr->SiS_DDC_Data); /* (SD->high) */
1da177e4
LT
9430 SiS_SetSCLKHigh(SiS_Pr); /* SC->high = clock impulse for ack */
9431 tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
9432 SiS_SetSCLKLow(SiS_Pr); /* SC->low = end of clock impulse */
544393fe
TW
9433 if(tempah & SiS_Pr->SiS_DDC_Data) return 1; /* Ack OK if bit = 0 */
9434 return 0;
1da177e4
LT
9435}
9436
9437/* End of I2C functions ----------------------- */
9438
9439
9440/* =============== SiS 315/330 O.E.M. ================= */
9441
f7854e5d 9442#ifdef CONFIG_FB_SIS_315
1da177e4 9443
544393fe
TW
9444static unsigned short
9445GetRAMDACromptr(struct SiS_Private *SiS_Pr)
1da177e4 9446{
544393fe
TW
9447 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9448 unsigned short romptr;
1da177e4 9449
544393fe 9450 if(SiS_Pr->ChipType < SIS_330) {
1da177e4 9451 romptr = SISGETROMW(0x128);
544393fe 9452 if(SiS_Pr->SiS_VBType & VB_SIS30xB)
1da177e4
LT
9453 romptr = SISGETROMW(0x12a);
9454 } else {
9455 romptr = SISGETROMW(0x1a8);
544393fe 9456 if(SiS_Pr->SiS_VBType & VB_SIS30xB)
1da177e4
LT
9457 romptr = SISGETROMW(0x1aa);
9458 }
544393fe 9459 return romptr;
1da177e4
LT
9460}
9461
544393fe
TW
9462static unsigned short
9463GetLCDromptr(struct SiS_Private *SiS_Pr)
1da177e4 9464{
544393fe
TW
9465 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9466 unsigned short romptr;
1da177e4 9467
544393fe 9468 if(SiS_Pr->ChipType < SIS_330) {
1da177e4 9469 romptr = SISGETROMW(0x120);
544393fe 9470 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
1da177e4
LT
9471 romptr = SISGETROMW(0x122);
9472 } else {
9473 romptr = SISGETROMW(0x1a0);
544393fe 9474 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
1da177e4
LT
9475 romptr = SISGETROMW(0x1a2);
9476 }
544393fe 9477 return romptr;
1da177e4
LT
9478}
9479
544393fe
TW
9480static unsigned short
9481GetTVromptr(struct SiS_Private *SiS_Pr)
1da177e4 9482{
544393fe
TW
9483 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9484 unsigned short romptr;
1da177e4 9485
544393fe 9486 if(SiS_Pr->ChipType < SIS_330) {
1da177e4 9487 romptr = SISGETROMW(0x114);
544393fe 9488 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
1da177e4
LT
9489 romptr = SISGETROMW(0x11a);
9490 } else {
9491 romptr = SISGETROMW(0x194);
544393fe 9492 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
1da177e4
LT
9493 romptr = SISGETROMW(0x19a);
9494 }
544393fe 9495 return romptr;
1da177e4
LT
9496}
9497
544393fe
TW
9498static unsigned short
9499GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
1da177e4 9500{
544393fe 9501 unsigned short index;
1da177e4 9502
544393fe
TW
9503 if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9504 if(!(SiS_IsNotM650orLater(SiS_Pr))) {
1da177e4
LT
9505 if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
9506 index >>= 4;
9507 index *= 3;
9508 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9509 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9510 return index;
9511 }
9512 }
9513 }
9514
9515 index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
9516 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) index -= 5;
544393fe
TW
9517 if(SiS_Pr->SiS_VBType & VB_SIS301C) { /* 1.15.20 and later (not VB specific) */
9518 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
9519 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
9520 } else {
9521 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
9522 }
1da177e4
LT
9523 index--;
9524 index *= 3;
9525 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9526 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9527 return index;
9528}
9529
544393fe
TW
9530static unsigned short
9531GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
1da177e4 9532{
544393fe 9533 unsigned short index;
1da177e4
LT
9534
9535 index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
9536 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9537 else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9538 return index;
9539}
9540
544393fe
TW
9541static unsigned short
9542GetTVPtrIndex(struct SiS_Private *SiS_Pr)
1da177e4 9543{
544393fe 9544 unsigned short index;
1da177e4
LT
9545
9546 index = 0;
9547 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9548 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
9549
9550 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
9551
9552 index <<= 1;
9553
9554 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
9555 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9556 index++;
9557 }
9558
9559 return index;
9560}
9561
544393fe
TW
9562static unsigned int
9563GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
1da177e4 9564{
544393fe 9565 unsigned short index = 0, temp = 0;
1da177e4
LT
9566
9567 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9568 if(SiS_Pr->SiS_TVMode & TVSetPALM) index = 2;
9569 if(SiS_Pr->SiS_TVMode & TVSetPALN) index = 3;
9570 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
9571 if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
9572 index = 4;
9573 if(SiS_Pr->SiS_TVMode & TVSetPALM) index++;
9574 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
9575 }
9576
544393fe 9577 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4
LT
9578 if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
9579 (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9580 index += addme;
9581 temp++;
9582 }
9583 temp += 0x0100;
9584 }
544393fe 9585 return (unsigned int)(index | (temp << 16));
1da177e4
LT
9586}
9587
544393fe
TW
9588static unsigned int
9589GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
1da177e4 9590{
544393fe 9591 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
1da177e4
LT
9592}
9593
9594#if 0
544393fe
TW
9595static unsigned int
9596GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
1da177e4 9597{
544393fe 9598 return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
1da177e4
LT
9599}
9600#endif
9601
9602static int
544393fe 9603GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
1da177e4
LT
9604{
9605 int index = 0;
9606
9607 if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 2;
9608 if(SiS_Pr->SiS_ROMNew) {
9609 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
9610 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
9611 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
9612 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 10;
9613 } else {
9614 if(SiS_Pr->SiS_TVMode & TVSetHiVision) index = 4;
9615 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
9616 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
9617 if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
9618 }
9619
9620 if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
9621
9622 return index;
9623}
9624
9625static void
544393fe 9626SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1da177e4 9627{
544393fe
TW
9628 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9629 unsigned short delay=0,index,myindex,temp,romptr=0;
c30660ea 9630 bool dochiptest = true;
1da177e4
LT
9631
9632 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9633 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
9634 } else {
9635 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
9636 }
9637
9638 /* Find delay (from ROM, internal tables, PCI subsystem) */
9639
9640 if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { /* ------------ VGA */
544393fe 9641
1da177e4 9642 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
544393fe 9643 romptr = GetRAMDACromptr(SiS_Pr);
1da177e4
LT
9644 }
9645 if(romptr) delay = ROMAddr[romptr];
9646 else {
9647 delay = 0x04;
544393fe 9648 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
1da177e4
LT
9649 if(IS_SIS650) {
9650 delay = 0x0a;
9651 } else if(IS_SIS740) {
9652 delay = 0x00;
1da177e4
LT
9653 } else {
9654 delay = 0x0c;
9655 }
9656 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9657 delay = 0x00;
9658 }
9659 }
9660
9661 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) { /* ---------- LCD/LCDA */
9662
c30660ea 9663 bool gotitfrompci = false;
1da177e4
LT
9664
9665 /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
9666
9667 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
9668 if(SiS_Pr->PDC != -1) {
9669 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
9670 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
9671 return;
9672 }
9673 } else {
9674 if(SiS_Pr->PDCA != -1) {
9675 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
9676 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
9677 return;
9678 }
9679 }
9680
9681 /* Custom Panel? */
9682
9683 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
9684 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9685 delay = 0x00;
9686 if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
9687 delay = 0x20;
9688 }
9689 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
9690 } else {
9691 delay = 0x0c;
544393fe
TW
9692 if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9693 delay = 0x03;
9694 if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
9695 delay = 0x00;
9696 }
9697 } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4
LT
9698 if(IS_SIS740) delay = 0x01;
9699 else delay = 0x03;
9700 }
9701 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
9702 }
9703 return;
9704 }
9705
9706 /* This is a piece of typical SiS crap: They code the OEM LCD
9707 * delay into the code, at no defined place in the BIOS.
9708 * We now have to start doing a PCI subsystem check here.
9709 */
9710
9711 switch(SiS_Pr->SiS_CustomT) {
9712 case CUT_COMPAQ1280:
9713 case CUT_COMPAQ12802:
9714 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
c30660ea
RK
9715 gotitfrompci = true;
9716 dochiptest = false;
1da177e4
LT
9717 delay = 0x03;
9718 }
9719 break;
9720 case CUT_CLEVO1400:
9721 case CUT_CLEVO14002:
c30660ea
RK
9722 gotitfrompci = true;
9723 dochiptest = false;
1da177e4
LT
9724 delay = 0x02;
9725 break;
9726 case CUT_CLEVO1024:
9727 case CUT_CLEVO10242:
9728 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
c30660ea
RK
9729 gotitfrompci = true;
9730 dochiptest = false;
1da177e4
LT
9731 delay = 0x33;
9732 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9733 delay &= 0x0f;
9734 }
9735 break;
9736 }
9737
9738 /* Could we find it through the PCI ID? If no, use ROM or table */
9739
9740 if(!gotitfrompci) {
9741
544393fe 9742 index = GetLCDPtrIndexBIOS(SiS_Pr);
1da177e4
LT
9743 myindex = GetLCDPtrIndex(SiS_Pr);
9744
544393fe 9745 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
1da177e4 9746
544393fe 9747 if(SiS_IsNotM650orLater(SiS_Pr)) {
1da177e4
LT
9748
9749 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9750 /* Always use the second pointer on 650; some BIOSes */
9751 /* still carry old 301 data at the first location */
9752 /* romptr = SISGETROMW(0x120); */
9753 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
9754 romptr = SISGETROMW(0x122);
9755 if(!romptr) return;
9756 delay = ROMAddr[(romptr + index)];
9757 } else {
9758 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9759 }
9760
9761 } else {
9762
9763 delay = SiS310_LCDDelayCompensation_651301LV[myindex];
9764 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
9765 delay = SiS310_LCDDelayCompensation_651302LV[myindex];
9766
9767 }
9768
9769 } else if(SiS_Pr->SiS_UseROM &&
9770 (!(SiS_Pr->SiS_ROMNew)) &&
9771 (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
9772 (SiS_Pr->SiS_LCDResInfo != Panel_1280x768) &&
544393fe
TW
9773 (SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
9774 (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200) &&
9775 ((romptr = GetLCDromptr(SiS_Pr)))) {
1da177e4
LT
9776
9777 /* Data for 1280x1024 wrong in 301B BIOS */
544393fe 9778 /* Data for 1600x1200 wrong in 301C BIOS */
1da177e4
LT
9779 delay = ROMAddr[(romptr + index)];
9780
9781 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9782
9783 if(IS_SIS740) delay = 0x03;
9784 else delay = 0x00;
9785
9786 } else {
9787
9788 delay = SiS310_LCDDelayCompensation_301[myindex];
544393fe 9789 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4 9790 if(IS_SIS740) delay = 0x01;
544393fe 9791 else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
1da177e4
LT
9792 else delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9793 } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9794 if(IS_SIS740) delay = 0x01; /* ? */
9795 else delay = 0x03;
544393fe
TW
9796 if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
9797 } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
1da177e4
LT
9798 if(IS_SIS740) delay = 0x01;
9799 else delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
9800 }
9801
9802 }
9803
9804 } /* got it from PCI */
9805
9806 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9807 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
c30660ea 9808 dochiptest = false;
1da177e4 9809 }
544393fe 9810
1da177e4
LT
9811 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* ------------ TV */
9812
9813 index = GetTVPtrIndex(SiS_Pr);
1da177e4 9814
544393fe
TW
9815 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9816
9817 if(SiS_IsNotM650orLater(SiS_Pr)) {
1da177e4
LT
9818
9819 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9820 /* Always use the second pointer on 650; some BIOSes */
9821 /* still carry old 301 data at the first location */
9822 /* romptr = SISGETROMW(0x114); */
9823 /* if(SiS_Pr->SiS_VBType & VB_SIS302LV) */
9824 romptr = SISGETROMW(0x11a);
9825 if(!romptr) return;
9826 delay = ROMAddr[romptr + index];
9827
9828 } else {
9829
9830 delay = SiS310_TVDelayCompensation_301B[index];
9831
9832 }
9833
9834 } else {
9835
9836 switch(SiS_Pr->SiS_CustomT) {
9837 case CUT_COMPAQ1280:
9838 case CUT_COMPAQ12802:
9839 case CUT_CLEVO1400:
9840 case CUT_CLEVO14002:
9841 delay = 0x02;
c30660ea 9842 dochiptest = false;
1da177e4
LT
9843 break;
9844 case CUT_CLEVO1024:
9845 case CUT_CLEVO10242:
9846 delay = 0x03;
c30660ea 9847 dochiptest = false;
1da177e4
LT
9848 break;
9849 default:
9850 delay = SiS310_TVDelayCompensation_651301LV[index];
9851 if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
9852 delay = SiS310_TVDelayCompensation_651302LV[index];
9853 }
9854 }
9855 }
9856
9857 } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9858
544393fe 9859 romptr = GetTVromptr(SiS_Pr);
1da177e4
LT
9860 if(!romptr) return;
9861 delay = ROMAddr[romptr + index];
9862
9863 } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9864
9865 delay = SiS310_TVDelayCompensation_LVDS[index];
9866
9867 } else {
9868
9869 delay = SiS310_TVDelayCompensation_301[index];
544393fe 9870 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4
LT
9871 if(IS_SIS740) {
9872 delay = SiS310_TVDelayCompensation_740301B[index];
9873 /* LV: use 301 data? BIOS bug? */
9874 } else {
9875 delay = SiS310_TVDelayCompensation_301B[index];
9876 if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
9877 }
9878 }
9879
9880 }
9881
544393fe 9882 if(SiS_LCDAEnabled(SiS_Pr)) {
1da177e4 9883 delay &= 0x0f;
c30660ea 9884 dochiptest = false;
1da177e4 9885 }
544393fe 9886
1da177e4
LT
9887 } else return;
9888
9889 /* Write delay */
9890
9891 if(SiS_Pr->SiS_VBType & VB_SISVB) {
9892
544393fe 9893 if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
1da177e4
LT
9894
9895 temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
9896 if(temp == 8) { /* 1400x1050 BIOS (COMPAL) */
9897 delay &= 0x0f;
9898 delay |= 0xb0;
9899 } else if(temp == 6) {
9900 delay &= 0x0f;
9901 delay |= 0xc0;
9902 } else if(temp > 7) { /* 1280x1024 BIOS (which one?) */
9903 delay = 0x35;
9904 }
9905 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9906
9907 } else {
9908
9909 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9910
9911 }
9912
9913 } else { /* LVDS */
9914
9915 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
9916 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9917 } else {
9918 if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
9919 delay <<= 4;
9920 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
9921 } else {
9922 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9923 }
9924 }
9925
9926 }
9927
9928}
9929
9930static void
544393fe 9931SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 9932{
544393fe
TW
9933 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9934 unsigned short index,temp,temp1,romptr=0;
1da177e4
LT
9935
9936 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
9937
9938 if(ModeNo<=0x13)
9939 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
9940 else
9941 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
9942
9943 temp = GetTVPtrIndex(SiS_Pr);
9944 temp >>= 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9945 temp1 = temp;
9946
9947 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
544393fe 9948 if(SiS_Pr->ChipType >= SIS_661) {
1da177e4
LT
9949 temp1 = GetOEMTVPtr661(SiS_Pr);
9950 temp1 >>= 1;
9951 romptr = SISGETROMW(0x260);
544393fe 9952 if(SiS_Pr->ChipType >= SIS_760) {
1da177e4
LT
9953 romptr = SISGETROMW(0x360);
9954 }
544393fe 9955 } else if(SiS_Pr->ChipType >= SIS_330) {
1da177e4
LT
9956 romptr = SISGETROMW(0x192);
9957 } else {
9958 romptr = SISGETROMW(0x112);
9959 }
9960 }
9961
9962 if(romptr) {
9963 temp1 <<= 1;
9964 temp = ROMAddr[romptr + temp1 + index];
9965 } else {
9966 temp = SiS310_TVAntiFlick1[temp][index];
9967 }
9968 temp <<= 4;
9969
9970 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp); /* index 0A D[6:4] */
9971}
9972
9973static void
544393fe 9974SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
1da177e4 9975{
544393fe
TW
9976 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
9977 unsigned short index,temp,temp1,romptr=0;
1da177e4
LT
9978
9979 temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9980
9981 if(ModeNo <= 0x13)
9982 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
9983 else
9984 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
9985
9986 if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
544393fe 9987 if(SiS_Pr->ChipType >= SIS_661) {
1da177e4 9988 romptr = SISGETROMW(0x26c);
544393fe 9989 if(SiS_Pr->ChipType >= SIS_760) {
1da177e4
LT
9990 romptr = SISGETROMW(0x36c);
9991 }
9992 temp1 = GetOEMTVPtr661(SiS_Pr);
9993 temp1 >>= 1;
544393fe 9994 } else if(SiS_Pr->ChipType >= SIS_330) {
1da177e4
LT
9995 romptr = SISGETROMW(0x1a4);
9996 } else {
9997 romptr = SISGETROMW(0x124);
9998 }
9999 }
10000
10001 if(romptr) {
10002 temp1 <<= 1;
10003 temp = ROMAddr[romptr + temp1 + index];
10004 } else {
10005 temp = SiS310_TVEdge1[temp][index];
10006 }
10007 temp <<= 5;
10008 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp); /* index 0A D[7:5] */
10009}
10010
10011static void
544393fe 10012SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
1da177e4 10013{
544393fe 10014 unsigned short index, temp, i, j;
1da177e4
LT
10015
10016 if(ModeNo <= 0x13) {
10017 index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
10018 } else {
10019 index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
10020 }
10021
10022 temp = GetTVPtrIndex(SiS_Pr) >> 1; /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10023
10024 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 1; /* NTSC-J uses PAL */
10025 else if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 3; /* PAL-M */
10026 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 4; /* PAL-N */
10027 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1; /* HiVision uses PAL */
10028
544393fe 10029 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4
LT
10030 for(i=0x35, j=0; i<=0x38; i++, j++) {
10031 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10032 }
10033 for(i=0x48; i<=0x4A; i++, j++) {
10034 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10035 }
10036 } else {
10037 for(i=0x35, j=0; i<=0x38; i++, j++) {
10038 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
10039 }
10040 }
10041}
10042
10043static void
544393fe 10044SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 10045{
544393fe
TW
10046 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10047 unsigned short index,temp,i,j,resinfo,romptr=0;
10048 unsigned int lindex;
1da177e4
LT
10049
10050 if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
10051
10052 /* NTSC-J data not in BIOS, and already set in SetGroup2 */
10053 if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
10054
544393fe 10055 if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
1da177e4
LT
10056 lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
10057 lindex <<= 2;
10058 for(j=0, i=0x31; i<=0x34; i++, j++) {
544393fe 10059 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
1da177e4
LT
10060 }
10061 return;
10062 }
10063
10064 /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
10065 if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
10066
10067 if(ModeNo<=0x13) {
10068 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10069 } else {
10070 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10071 }
10072
10073 temp = GetTVPtrIndex(SiS_Pr);
10074 /* 0: NTSC Graphics, 1: NTSC Text, 2: PAL Graphics,
10075 * 3: PAL Text, 4: HiTV Graphics 5: HiTV Text
10076 */
10077 if(SiS_Pr->SiS_UseROM) {
10078 romptr = SISGETROMW(0x116);
544393fe 10079 if(SiS_Pr->ChipType >= SIS_330) {
1da177e4
LT
10080 romptr = SISGETROMW(0x196);
10081 }
544393fe 10082 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4 10083 romptr = SISGETROMW(0x11c);
544393fe 10084 if(SiS_Pr->ChipType >= SIS_330) {
1da177e4
LT
10085 romptr = SISGETROMW(0x19c);
10086 }
10087 if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
10088 romptr = SISGETROMW(0x116);
544393fe 10089 if(SiS_Pr->ChipType >= SIS_330) {
1da177e4
LT
10090 romptr = SISGETROMW(0x196);
10091 }
10092 }
10093 }
10094 }
10095 if(romptr) {
10096 romptr += (temp << 2);
10097 for(j=0, i=0x31; i<=0x34; i++, j++) {
10098 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10099 }
10100 } else {
10101 index = temp % 2;
10102 temp >>= 1; /* 0:NTSC, 1:PAL, 2:HiTV */
10103 for(j=0, i=0x31; i<=0x34; i++, j++) {
544393fe 10104 if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
1da177e4
LT
10105 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10106 else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
10107 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
10108 else
10109 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10110 }
10111 }
10112
544393fe 10113 if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
1da177e4
LT
10114 if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
10115 if((resinfo == SIS_RI_640x480) ||
10116 (resinfo == SIS_RI_800x600)) {
10117 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
10118 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
10119 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
10120 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
10121 } else if(resinfo == SIS_RI_1024x768) {
10122 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
10123 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
10124 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
10125 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
10126 }
10127 }
10128 }
10129}
10130
10131static void
544393fe
TW
10132SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10133 unsigned short ModeIdIndex, unsigned short RTI)
1da177e4 10134{
544393fe
TW
10135 unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
10136 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1da177e4
LT
10137
10138 if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
10139 return;
10140
10141 /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
10142 /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
10143
10144 if(SiS_Pr->SiS_ROMNew) {
10145 if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) ||
10146 ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
10147 (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
10148 index = 25;
10149 if(SiS_Pr->UseCustomMode) {
10150 index = SiS_Pr->CSRClock;
10151 } else if(ModeNo > 0x13) {
544393fe 10152 index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
1da177e4
LT
10153 index = SiS_Pr->SiS_VCLKData[index].CLOCK;
10154 }
10155 if(index < 25) index = 25;
10156 index = ((index / 25) - 1) << 1;
10157 if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
10158 index++;
10159 }
10160 romptr = SISGETROMW(0x104);
10161 delay = ROMAddr[romptr + index];
10162 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
10163 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10164 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10165 } else {
10166 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10167 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10168 }
10169 return;
10170 }
10171 }
10172
10173 /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
10174
10175 if(SiS_Pr->UseCustomMode) delay = 0x04;
10176 else if(ModeNo <= 0x13) delay = 0x04;
10177 else delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
10178 delay |= (delay << 8);
10179
544393fe
TW
10180 if(SiS_Pr->ChipType >= XGI_20) {
10181
10182 delay = 0x0606;
10183 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10184
10185 delay = 0x0404;
10186 if(SiS_Pr->SiS_XGIROM) {
10187 index = GetTVPtrIndex(SiS_Pr);
10188 if((romptr = SISGETROMW(0x35e))) {
10189 delay = (ROMAddr[romptr + index] & 0x0f) << 1;
10190 delay |= (delay << 8);
10191 }
10192 }
10193
10194 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
10195 if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
10196 delay -= 0x0404;
10197 }
10198 }
10199 }
10200
10201 } else if(SiS_Pr->ChipType >= SIS_340) {
10202
10203 delay = 0x0606;
10204 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10205 delay = 0x0404;
10206 }
10207 /* TODO (eventually) */
10208
10209 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
1da177e4
LT
10210
10211 /* 3. TV */
10212
10213 index = GetOEMTVPtr661(SiS_Pr);
10214 if(SiS_Pr->SiS_ROMNew) {
10215 romptr = SISGETROMW(0x106);
10216 if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
10217 delay = ROMAddr[romptr + index];
10218 } else {
10219 delay = 0x04;
10220 if(index > 3) delay = 0;
10221 }
10222
10223 } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10224
10225 /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
10226
10227 if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
544393fe 10228 ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
1da177e4
LT
10229
10230 lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
10231
10232 /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
10233 delay = ROMAddr[romptr + lcdpdcindex + 1]; /* LCD */
10234 delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
10235
10236 } else {
10237
10238 /* TMDS: Set our own, since BIOS has no idea */
10239 /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
10240 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10241 switch(SiS_Pr->SiS_LCDResInfo) {
10242 case Panel_1024x768: delay = 0x0008; break;
10243 case Panel_1280x720: delay = 0x0004; break;
10244 case Panel_1280x768:
10245 case Panel_1280x768_2:delay = 0x0004; break;
10246 case Panel_1280x800:
10247 case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
544393fe 10248 case Panel_1280x854: delay = 0x0004; break; /* FIXME */
1da177e4
LT
10249 case Panel_1280x1024: delay = 0x1e04; break;
10250 case Panel_1400x1050: delay = 0x0004; break;
10251 case Panel_1600x1200: delay = 0x0400; break;
10252 case Panel_1680x1050: delay = 0x0e04; break;
10253 default:
10254 if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
10255 delay = 0x0008;
10256 } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
10257 delay = 0x1e04;
10258 } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
10259 delay = 0x0004;
10260 } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
10261 delay = 0x0400;
10262 } else
10263 delay = 0x0e04;
10264 break;
10265 }
10266 }
10267
10268 /* Override by detected or user-set values */
10269 /* (but only if, for some reason, we can't read value from BIOS) */
10270 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
10271 delay = SiS_Pr->PDC & 0x1f;
10272 }
10273 if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
10274 delay = (SiS_Pr->PDCA & 0x1f) << 8;
10275 }
10276
10277 }
10278
10279 }
10280
10281 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10282 delay >>= 8;
10283 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10284 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10285 } else {
10286 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10287 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10288 }
10289}
10290
10291static void
544393fe 10292SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
1da177e4 10293{
544393fe
TW
10294 unsigned short infoflag;
10295 unsigned char temp;
1da177e4
LT
10296
10297 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10298
10299 if(ModeNo <= 0x13) {
10300 infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
10301 } else if(SiS_Pr->UseCustomMode) {
10302 infoflag = SiS_Pr->CInfoFlag;
10303 } else {
10304 infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
10305 }
10306
10307 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10308 infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
10309 }
10310
10311 infoflag &= 0xc0;
10312
10313 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10314 temp = (infoflag >> 6) | 0x0c;
10315 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10316 temp ^= 0x04;
10317 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
10318 }
10319 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
10320 } else {
10321 temp = 0x30;
10322 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
10323 temp |= infoflag;
10324 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
10325 temp = 0;
10326 if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10327 if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
10328 }
10329 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
10330 }
10331
10332 }
10333}
10334
10335static void
544393fe 10336SetPanelParms661(struct SiS_Private *SiS_Pr)
1da177e4 10337{
544393fe
TW
10338 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10339 unsigned short romptr, temp1, temp2;
10340
10341 if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
10342 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
10343 }
1da177e4 10344
544393fe 10345 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4
LT
10346 if(SiS_Pr->LVDSHL != -1) {
10347 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10348 }
10349 }
10350
10351 if(SiS_Pr->SiS_ROMNew) {
10352
544393fe
TW
10353 if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
10354 if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1da177e4
LT
10355 temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
10356 temp2 = 0xfc;
10357 if(SiS_Pr->LVDSHL != -1) {
10358 temp1 &= 0xfc;
10359 temp2 = 0xf3;
10360 }
10361 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
10362 }
10363 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10364 temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
10365 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
10366 }
10367 }
10368
10369 }
10370}
10371
10372static void
544393fe 10373SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
1da177e4
LT
10374{
10375 if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
544393fe 10376 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
1da177e4 10377 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
544393fe
TW
10378 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10379 SetPanelParms661(SiS_Pr);
1da177e4
LT
10380 }
10381 } else {
544393fe 10382 SetDelayComp(SiS_Pr,ModeNo);
1da177e4
LT
10383 }
10384
10385 if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
544393fe
TW
10386 SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
10387 SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
10388 SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
1da177e4 10389 if(SiS_Pr->SiS_VBType & VB_SIS301) {
544393fe 10390 SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
1da177e4
LT
10391 }
10392 }
10393}
10394
10395static void
544393fe
TW
10396SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10397 unsigned short ModeIdIndex, unsigned short RRTI)
1da177e4
LT
10398{
10399 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10400
544393fe 10401 SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
1da177e4
LT
10402
10403 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
544393fe
TW
10404 SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10405 SetPanelParms661(SiS_Pr);
1da177e4
LT
10406 }
10407
10408 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
544393fe
TW
10409 SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
10410 SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
10411 SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4 10412 if(SiS_Pr->SiS_VBType & VB_SIS301) {
544393fe 10413 SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
1da177e4
LT
10414 }
10415 }
10416 }
10417}
10418
10419/* FinalizeLCD
10420 * This finalizes some CRT2 registers for the very panel used.
10421 * If we have a backup if these registers, we use it; otherwise
10422 * we set the register according to most BIOSes. However, this
10423 * function looks quite different in every BIOS, so you better
10424 * pray that we have a backup...
10425 */
10426static void
544393fe 10427SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 10428{
544393fe
TW
10429 unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
10430 unsigned short resinfo,modeflag;
1da177e4 10431
544393fe 10432 if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
1da177e4
LT
10433 if(SiS_Pr->SiS_ROMNew) return;
10434
10435 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10436 if(SiS_Pr->LVDSHL != -1) {
10437 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10438 }
10439 }
10440
10441 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10442 if(SiS_Pr->UseCustomMode) return;
10443
10444 switch(SiS_Pr->SiS_CustomT) {
10445 case CUT_COMPAQ1280:
10446 case CUT_COMPAQ12802:
10447 case CUT_CLEVO1400:
10448 case CUT_CLEVO14002:
10449 return;
10450 }
10451
10452 if(ModeNo <= 0x13) {
10453 resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10454 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10455 } else {
10456 resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10457 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10458 }
10459
10460 if(IS_SIS650) {
10461 if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
10462 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10463 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
10464 } else {
10465 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
10466 }
10467 }
10468 }
10469
10470 if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10471 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10472 /* Maybe all panels? */
10473 if(SiS_Pr->LVDSHL == -1) {
10474 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10475 }
10476 return;
10477 }
10478 }
10479
10480 if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
10481 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10482 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10483 if(SiS_Pr->LVDSHL == -1) {
10484 /* Maybe all panels? */
10485 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10486 }
10487 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10488 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10489 if(tempch == 3) {
10490 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10491 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10492 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10493 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10494 }
10495 }
10496 return;
10497 }
10498 }
10499 }
10500
10501 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10502 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
544393fe 10503 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
1da177e4
LT
10504 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
10505#ifdef SET_EMI
10506 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
10507#endif
10508 SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
10509 }
10510 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10511 if(SiS_Pr->LVDSHL == -1) {
10512 /* Maybe ACER only? */
10513 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10514 }
10515 }
10516 tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10517 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10518 if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
10519 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
10520 } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10521 if(tempch == 0x03) {
10522 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10523 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10524 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10525 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10526 }
c30660ea 10527 if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
1da177e4
LT
10528 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
10529 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
10530 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
10531 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
10532 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
10533 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
10534 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
10535 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
10536 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
10537 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
10538 } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) { /* 1.10.8w */
10539 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
10540 if(ModeNo <= 0x13) {
10541 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
10542 if((resinfo == 0) || (resinfo == 2)) return;
10543 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
10544 if((resinfo == 1) || (resinfo == 3)) return;
10545 }
10546 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10547 if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
10548 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02); /* 1.10.7u */
10549#if 0
10550 tempbx = 806; /* 0x326 */ /* other older BIOSes */
10551 tempbx--;
10552 temp = tempbx & 0xff;
10553 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
10554 temp = (tempbx >> 8) & 0x03;
10555 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
10556#endif
10557 }
10558 } else if(ModeNo <= 0x13) {
10559 if(ModeNo <= 1) {
10560 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
10561 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
10562 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10563 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10564 }
10565 if(!(modeflag & HalfDCLK)) {
10566 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
10567 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
10568 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
10569 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
10570 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
10571 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10572 if(ModeNo == 0x12) {
10573 switch(tempch) {
10574 case 0:
10575 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10576 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10577 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
10578 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10579 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
10580 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10581 break;
10582 case 2:
10583 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10584 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10585 break;
10586 case 3:
10587 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10588 break;
10589 }
10590 }
10591 }
10592 }
10593 }
10594 } else {
10595 tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
10596 tempcl &= 0x0f;
10597 tempbh &= 0x70;
10598 tempbh >>= 4;
10599 tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
10600 tempbx = (tempbh << 8) | tempbl;
10601 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10602 if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
10603 if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
10604 tempbx = 770;
10605 } else {
10606 if(tempbx > 770) tempbx = 770;
10607 if(SiS_Pr->SiS_VGAVDE < 600) {
10608 tempax = 768 - SiS_Pr->SiS_VGAVDE;
10609 tempax >>= 4; /* 1.10.7w; 1.10.6s: 3; */
10610 if(SiS_Pr->SiS_VGAVDE <= 480) tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
10611 tempbx -= tempax;
10612 }
10613 }
10614 } else return;
10615 }
10616 temp = tempbx & 0xff;
10617 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
10618 temp = ((tempbx & 0xff00) >> 4) | tempcl;
10619 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
10620 }
10621 }
10622}
10623
10624#endif
10625
10626/* ================= SiS 300 O.E.M. ================== */
10627
f7854e5d 10628#ifdef CONFIG_FB_SIS_300
1da177e4
LT
10629
10630static void
544393fe
TW
10631SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
10632 unsigned short RefTabIndex)
1da177e4 10633{
544393fe
TW
10634 unsigned short crt2crtc=0, modeflag, myindex=0;
10635 unsigned char temp;
1da177e4
LT
10636 int i;
10637
10638 if(ModeNo <= 0x13) {
10639 modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10640 crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
10641 } else {
10642 modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10643 crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
10644 }
10645
10646 crt2crtc &= 0x3f;
10647
10648 if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
10649 SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
10650 }
10651
10652 if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
10653 if(modeflag & HalfDCLK) myindex = 1;
10654
10655 if(SiS_Pr->SiS_SetFlag & LowModeTests) {
10656 for(i=0; i<7; i++) {
10657 if(barco_p1[myindex][crt2crtc][i][0]) {
10658 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
10659 barco_p1[myindex][crt2crtc][i][0],
10660 barco_p1[myindex][crt2crtc][i][2],
10661 barco_p1[myindex][crt2crtc][i][1]);
10662 }
10663 }
10664 }
10665 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
10666 if(temp & 0x80) {
10667 temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
10668 temp++;
10669 SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
10670 }
10671 }
10672}
10673
544393fe
TW
10674static unsigned short
10675GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
1da177e4 10676{
544393fe
TW
10677 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10678 unsigned short tempbx=0,romptr=0;
10679 static const unsigned char customtable300[] = {
10680 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1da177e4
LT
10681 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10682 };
544393fe
TW
10683 static const unsigned char customtable630[] = {
10684 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1da177e4
LT
10685 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10686 };
10687
544393fe 10688 if(SiS_Pr->ChipType == SIS_300) {
1da177e4
LT
10689
10690 tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
10691 if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
10692 tempbx -= 2;
10693 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
10694 if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10695 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
10696 }
10697 if(SiS_Pr->SiS_UseROM) {
10698 if(ROMAddr[0x235] & 0x80) {
10699 tempbx = SiS_Pr->SiS_LCDTypeInfo;
10700 if(Flag) {
10701 romptr = SISGETROMW(0x255);
10702 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10703 else tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
10704 if(tempbx == 0xFF) return 0xFFFF;
10705 }
10706 tempbx <<= 1;
10707 if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
10708 }
10709 }
10710
10711 } else {
10712
10713 if(Flag) {
10714 if(SiS_Pr->SiS_UseROM) {
10715 romptr = SISGETROMW(0x255);
10716 if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10717 else tempbx = 0xff;
10718 } else {
10719 tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
10720 }
10721 if(tempbx == 0xFF) return 0xFFFF;
10722 tempbx <<= 2;
10723 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10724 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10725 return tempbx;
10726 }
10727 tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
10728 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10729 if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10730
10731 }
10732
10733 return tempbx;
10734}
10735
10736static void
544393fe 10737SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
1da177e4 10738{
544393fe
TW
10739 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10740 unsigned short index,temp,romptr=0;
1da177e4
LT
10741
10742 if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10743
10744 if(SiS_Pr->SiS_UseROM) {
10745 if(!(ROMAddr[0x237] & 0x01)) return;
10746 if(!(ROMAddr[0x237] & 0x02)) return;
10747 romptr = SISGETROMW(0x24b);
10748 }
10749
10750 /* The Panel Compensation Delay should be set according to tables
544393fe 10751 * here. Unfortunately, various BIOS versions don't care about
1da177e4
LT
10752 * a uniform way using eg. ROM byte 0x220, but use different
10753 * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
544393fe 10754 * Thus we don't set this if the user selected a custom pdc or if
1da177e4
LT
10755 * we otherwise detected a valid pdc.
10756 */
10757 if(SiS_Pr->PDC != -1) return;
10758
544393fe 10759 temp = GetOEMLCDPtr(SiS_Pr, 0);
1da177e4
LT
10760
10761 if(SiS_Pr->UseCustomMode)
10762 index = 0;
10763 else
10764 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
10765
544393fe 10766 if(SiS_Pr->ChipType != SIS_300) {
1da177e4
LT
10767 if(romptr) {
10768 romptr += (temp * 2);
10769 romptr = SISGETROMW(romptr);
10770 romptr += index;
10771 temp = ROMAddr[romptr];
10772 } else {
10773 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10774 temp = SiS300_OEMLCDDelay2[temp][index];
10775 } else {
10776 temp = SiS300_OEMLCDDelay3[temp][index];
10777 }
10778 }
10779 } else {
10780 if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
10781 if(romptr) {
10782 romptr += (temp * 2);
10783 romptr = SISGETROMW(romptr);
10784 romptr += index;
10785 temp = ROMAddr[romptr];
10786 } else {
10787 temp = SiS300_OEMLCDDelay5[temp][index];
10788 }
10789 } else {
10790 if(SiS_Pr->SiS_UseROM) {
10791 romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
10792 if(romptr) {
10793 romptr += (temp * 2);
10794 romptr = SISGETROMW(romptr);
10795 romptr += index;
10796 temp = ROMAddr[romptr];
10797 } else {
10798 temp = SiS300_OEMLCDDelay4[temp][index];
10799 }
10800 } else {
10801 temp = SiS300_OEMLCDDelay4[temp][index];
10802 }
10803 }
10804 }
10805 temp &= 0x3c;
10806 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp); /* index 0A D[6:4] */
10807}
10808
10809static void
544393fe 10810SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4
LT
10811{
10812#if 0 /* Unfinished; Data table missing */
544393fe
TW
10813 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10814 unsigned short index,temp;
1da177e4
LT
10815
10816 if((SiS_Pr->SiS_UseROM) {
10817 if(!(ROMAddr[0x237] & 0x01)) return;
10818 if(!(ROMAddr[0x237] & 0x04)) return;
10819 /* No rom pointer in BIOS header! */
10820 }
10821
544393fe
TW
10822 temp = GetOEMLCDPtr(SiS_Pr, 1);
10823 if(temp == 0xFFFF) return;
1da177e4
LT
10824
10825 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
10826 for(i=0x14, j=0; i<=0x17; i++, j++) {
10827 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
10828 }
10829 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
10830
10831 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
10832 SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
10833 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
10834 SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
10835 for(i=0x1b, j=3; i<=0x1d; i++, j++) {
10836 SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
10837 }
10838#endif
10839}
10840
544393fe
TW
10841static unsigned short
10842GetOEMTVPtr(struct SiS_Private *SiS_Pr)
1da177e4 10843{
544393fe 10844 unsigned short index;
1da177e4
LT
10845
10846 index = 0;
10847 if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) index += 4;
10848 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10849 if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) index += 2;
10850 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
10851 else if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
10852 } else {
10853 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
10854 if(SiS_Pr->SiS_TVMode & TVSetPAL) index += 1;
10855 }
10856 return index;
10857}
10858
10859static void
544393fe 10860SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 10861{
544393fe
TW
10862 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10863 unsigned short index,temp,romptr=0;
1da177e4
LT
10864
10865 if(SiS_Pr->SiS_UseROM) {
10866 if(!(ROMAddr[0x238] & 0x01)) return;
10867 if(!(ROMAddr[0x238] & 0x02)) return;
10868 romptr = SISGETROMW(0x241);
10869 }
10870
10871 temp = GetOEMTVPtr(SiS_Pr);
10872
10873 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
10874
10875 if(romptr) {
10876 romptr += (temp * 2);
10877 romptr = SISGETROMW(romptr);
10878 romptr += index;
10879 temp = ROMAddr[romptr];
10880 } else {
10881 if(SiS_Pr->SiS_VBType & VB_SISVB) {
10882 temp = SiS300_OEMTVDelay301[temp][index];
10883 } else {
10884 temp = SiS300_OEMTVDelayLVDS[temp][index];
10885 }
10886 }
10887 temp &= 0x3c;
10888 SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
10889}
10890
10891static void
544393fe 10892SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 10893{
544393fe
TW
10894 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10895 unsigned short index,temp,romptr=0;
1da177e4
LT
10896
10897 if(SiS_Pr->SiS_UseROM) {
10898 if(!(ROMAddr[0x238] & 0x01)) return;
10899 if(!(ROMAddr[0x238] & 0x04)) return;
10900 romptr = SISGETROMW(0x243);
10901 }
10902
10903 temp = GetOEMTVPtr(SiS_Pr);
10904
10905 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
10906
10907 if(romptr) {
10908 romptr += (temp * 2);
10909 romptr = SISGETROMW(romptr);
10910 romptr += index;
10911 temp = ROMAddr[romptr];
10912 } else {
10913 temp = SiS300_OEMTVFlicker[temp][index];
10914 }
10915 temp &= 0x70;
10916 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
10917}
10918
10919static void
544393fe 10920SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
1da177e4 10921{
544393fe
TW
10922 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10923 unsigned short index,i,j,temp,romptr=0;
1da177e4
LT
10924
10925 if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
10926
10927 if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
10928
10929 if(SiS_Pr->SiS_UseROM) {
10930 if(!(ROMAddr[0x238] & 0x01)) return;
10931 if(!(ROMAddr[0x238] & 0x08)) return;
10932 romptr = SISGETROMW(0x245);
10933 }
10934
10935 temp = GetOEMTVPtr(SiS_Pr);
10936
10937 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
10938
544393fe 10939 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4
LT
10940 for(i=0x31, j=0; i<=0x34; i++, j++) {
10941 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
10942 }
10943 } else {
10944 if(romptr) {
10945 romptr += (temp * 2);
10946 romptr = SISGETROMW(romptr);
10947 romptr += (index * 4);
10948 for(i=0x31, j=0; i<=0x34; i++, j++) {
10949 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10950 }
10951 } else {
10952 for(i=0x31, j=0; i<=0x34; i++, j++) {
10953 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
10954 }
10955 }
10956 }
10957}
10958
10959static void
544393fe 10960SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1da177e4 10961{
544393fe
TW
10962 unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
10963 unsigned short index,temp,i,j,romptr=0;
1da177e4
LT
10964
10965 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
10966
10967 if(SiS_Pr->SiS_UseROM) {
10968 if(!(ROMAddr[0x238] & 0x01)) return;
10969 if(!(ROMAddr[0x238] & 0x10)) return;
10970 romptr = SISGETROMW(0x247);
10971 }
10972
10973 temp = GetOEMTVPtr(SiS_Pr);
10974
10975 if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
10976 else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
10977 /* NTSCJ uses NTSC filters */
10978
10979 index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
10980
544393fe 10981 if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1da177e4
LT
10982 for(i=0x35, j=0; i<=0x38; i++, j++) {
10983 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
10984 }
10985 for(i=0x48; i<=0x4A; i++, j++) {
10986 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
10987 }
10988 } else {
10989 if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
10990 romptr += (temp * 2);
10991 romptr = SISGETROMW(romptr);
10992 romptr += (index * 4);
10993 for(i=0x35, j=0; i<=0x38; i++, j++) {
10994 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10995 }
10996 } else {
10997 for(i=0x35, j=0; i<=0x38; i++, j++) {
10998 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
10999 }
11000 }
11001 }
11002}
11003
544393fe
TW
11004static unsigned short
11005SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
1da177e4 11006{
544393fe
TW
11007 unsigned short ModeIdIndex;
11008 unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
1da177e4
LT
11009
11010 if(*ModeNo <= 5) *ModeNo |= 1;
11011
11012 for(ModeIdIndex=0; ; ModeIdIndex++) {
11013 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
11014 if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF) return 0;
11015 }
11016
11017 if(*ModeNo != 0x07) {
11018 if(*ModeNo > 0x03) return ModeIdIndex;
11019 if(VGAINFO & 0x80) return ModeIdIndex;
11020 ModeIdIndex++;
11021 }
11022
11023 if(VGAINFO & 0x10) ModeIdIndex++; /* 400 lines */
11024 /* else 350 lines */
11025 return ModeIdIndex;
11026}
11027
11028static void
544393fe
TW
11029SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
11030 unsigned short RefTableIndex)
1da177e4 11031{
544393fe 11032 unsigned short OEMModeIdIndex = 0;
1da177e4
LT
11033
11034 if(!SiS_Pr->UseCustomMode) {
11035 OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
11036 if(!(OEMModeIdIndex)) return;
11037 }
11038
11039 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
544393fe 11040 SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
1da177e4 11041 if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
544393fe 11042 SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
1da177e4
LT
11043 }
11044 }
11045 if(SiS_Pr->UseCustomMode) return;
11046 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
544393fe 11047 SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
1da177e4 11048 if(SiS_Pr->SiS_VBType & VB_SISVB) {
544393fe
TW
11049 SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
11050 SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
11051 SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
1da177e4
LT
11052 }
11053 }
11054}
11055#endif
11056