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