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