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