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