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