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