Linux-libre 4.4.228-gnu
[librecmc/linux-libre.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 if(SiS_Pr->SiS_VGAHDE >= 1024) {
6850               tempch = 25;
6851            } else {
6852               tempch = 25; /* OK */
6853            }
6854         }
6855      }
6856   }
6857
6858   if(!(tempbx & 0x20)) {
6859      if(modeflag & HalfDCLK) tempcl <<= 1;
6860      longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
6861      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
6862      tempax = longtemp / SiS_Pr->SiS_HDE;
6863      if(longtemp % SiS_Pr->SiS_HDE) tempax++;
6864      tempbx |= ((tempax >> 8) & 0x1F);
6865      tempcx = tempax >> 13;
6866   }
6867
6868   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
6869   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
6870
6871   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
6872
6873      tempcx &= 0x07;
6874      if(tempbx & 0x20) tempcx = 0;
6875      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
6876
6877      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6878         tempbx = 0x0382;
6879         tempcx = 0x007e;
6880      } else {
6881         tempbx = 0x0369;
6882         tempcx = 0x0061;
6883      }
6884      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
6885      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
6886      temp = (tempcx & 0x0300) >> 6;
6887      temp |= ((tempbx >> 8) & 0x03);
6888      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6889         temp |= 0x10;
6890         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)      temp |= 0x20;
6891         else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
6892      }
6893      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
6894
6895      temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
6896      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
6897
6898      SiS_SetTVSpecial(SiS_Pr, ModeNo);
6899
6900      if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
6901         temp = 0;
6902         if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
6903         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
6904      }
6905
6906   }
6907
6908   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6909      if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
6910         temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
6911         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
6912      }
6913      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
6914   }
6915
6916   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6917      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6918         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
6919      }
6920   }
6921
6922   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
6923
6924   /* From here: Part2 LCD setup */
6925
6926   tempbx = SiS_Pr->SiS_HDE;
6927   if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
6928   tempbx--;                                     /* RHACTE = HDE - 1 */
6929   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
6930   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
6931
6932   temp = 0x01;
6933   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
6934      if(SiS_Pr->SiS_ModeType == ModeEGA) {
6935         if(SiS_Pr->SiS_VGAHDE >= 1024) {
6936            temp = 0x02;
6937            if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
6938               temp = 0x01;
6939            }
6940         }
6941      }
6942   }
6943   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
6944
6945   tempbx = SiS_Pr->SiS_VDE - 1;
6946   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
6947   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
6948
6949   tempcx = SiS_Pr->SiS_VT - 1;
6950   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
6951   temp = (tempcx >> 3) & 0xE0;
6952   if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
6953      /* Enable dithering; only do this for 32bpp mode */
6954      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
6955         temp |= 0x10;
6956      }
6957   }
6958   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
6959
6960   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
6961   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
6962
6963   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
6964   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
6965
6966 #ifdef CONFIG_FB_SIS_315
6967   if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
6968                                                 &CRT2Index, &resindex)) {
6969       switch(CRT2Index) {
6970         case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
6971         default:
6972         case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
6973       }
6974
6975       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6976       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6977       for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
6978         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6979       }
6980       for(j = 0x1c; j <= 0x1d; i++, j++ ) {
6981         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6982       }
6983       for(j = 0x1f; j <= 0x21; i++, j++ ) {
6984         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6985       }
6986       SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6987       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6988
6989       SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
6990
6991   } else {
6992 #endif
6993
6994     /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
6995     /*             Clevo dual-link 1024x768 */
6996     /*             Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
6997     /*             Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
6998
6999     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7000        if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7001           tempbx = SiS_Pr->SiS_VDE - 1;
7002           tempcx = SiS_Pr->SiS_VT - 1;
7003        } else {
7004           tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7005           tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7006        }
7007     } else {
7008        tempbx = SiS_Pr->PanelYRes;
7009        tempcx = SiS_Pr->SiS_VT;
7010        tempax = 1;
7011        if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7012           tempax = SiS_Pr->PanelYRes;
7013           /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
7014           if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7015              tempax = tempcx = 0;
7016           } else {
7017              tempax -= SiS_Pr->SiS_VDE;
7018           }
7019           tempax >>= 1;
7020        }
7021        tempcx -= tempax; /* lcdvdes */
7022        tempbx -= tempax; /* lcdvdee */
7023     }
7024
7025     /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7026
7027     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);      /* lcdvdes  */
7028     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);      /* lcdvdee  */
7029
7030     temp = (tempbx >> 5) & 0x38;
7031     temp |= ((tempcx >> 8) & 0x07);
7032     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7033
7034     tempax = SiS_Pr->SiS_VDE;
7035     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7036        tempax = SiS_Pr->PanelYRes;
7037     }
7038     tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7039     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7040        if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7041           tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7042        }
7043     }
7044
7045     tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7046     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7047        if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7048           if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7049              tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7050              if(tempax % 4) { tempax >>= 2; tempax++; }
7051              else           { tempax >>= 2;           }
7052              tempbx -= (tempax - 1);
7053           } else {
7054              tempbx -= 10;
7055              if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7056           }
7057        }
7058     }
7059     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7060        tempbx++;
7061        if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7062           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7063              tempbx = 770;
7064              tempcx = 3;
7065           }
7066        }
7067     }
7068
7069     /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7070
7071     if(SiS_Pr->UseCustomMode) {
7072        tempbx = SiS_Pr->CVSyncStart;
7073     }
7074
7075     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);          /* lcdvrs */
7076
7077     temp = (tempbx >> 4) & 0xF0;
7078     tempbx += (tempcx + 1);
7079     temp |= (tempbx & 0x0F);
7080
7081     if(SiS_Pr->UseCustomMode) {
7082        temp &= 0xf0;
7083        temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7084     }
7085
7086     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7087
7088 #ifdef CONFIG_FB_SIS_300
7089     SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
7090 #endif
7091
7092     bridgeoffset = 7;
7093     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)       bridgeoffset += 2;
7094     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV)       bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
7095     if(SiS_IsDualLink(SiS_Pr))                  bridgeoffset++;
7096     else if(SiS_Pr->SiS_VBType & VB_SIS302LV)   bridgeoffset++;    /* OK for Asus A4L 1280x800 */
7097     /* Higher bridgeoffset shifts to the LEFT */
7098
7099     temp = 0;
7100     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7101        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7102           temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7103           if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
7104        }
7105     }
7106     temp += bridgeoffset;
7107     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);             /* lcdhdes */
7108     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7109
7110     tempcx = SiS_Pr->SiS_HT;
7111     tempax = tempbx = SiS_Pr->SiS_HDE;
7112     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7113        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7114           tempax = SiS_Pr->PanelXRes;
7115           tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7116        }
7117     }
7118     if(SiS_IsDualLink(SiS_Pr)) {
7119        tempcx >>= 1;
7120        tempbx >>= 1;
7121        tempax >>= 1;
7122     }
7123
7124     tempbx += bridgeoffset;
7125
7126     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);          /* lcdhdee */
7127     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7128
7129     tempcx = (tempcx - tempax) >> 2;
7130
7131     tempbx += tempcx;
7132     push2 = tempbx;
7133
7134     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7135        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7136           if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7137              if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7138           }
7139        }
7140     }
7141
7142     if(SiS_Pr->UseCustomMode) {
7143        tempbx = SiS_Pr->CHSyncStart;
7144        if(modeflag & HalfDCLK) tempbx <<= 1;
7145        if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7146        tempbx += bridgeoffset;
7147     }
7148
7149     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);          /* lcdhrs */
7150     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7151
7152     tempbx = push2;
7153
7154     tempcx <<= 1;
7155     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7156        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7157     }
7158     tempbx += tempcx;
7159
7160     if(SiS_Pr->UseCustomMode) {
7161        tempbx = SiS_Pr->CHSyncEnd;
7162        if(modeflag & HalfDCLK) tempbx <<= 1;
7163        if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7164        tempbx += bridgeoffset;
7165     }
7166
7167     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);          /* lcdhre */
7168
7169     SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7170
7171 #ifdef CONFIG_FB_SIS_300
7172     SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
7173 #endif
7174 #ifdef CONFIG_FB_SIS_315
7175   } /* CRT2-LCD from table */
7176 #endif
7177 }
7178
7179 /*********************************************/
7180 /*         SET PART 3 REGISTER GROUP         */
7181 /*********************************************/
7182
7183 static void
7184 SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
7185 {
7186   unsigned short i;
7187   const unsigned char *tempdi;
7188
7189   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7190
7191 #ifndef SIS_CP
7192   SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7193 #else
7194   SIS_CP_INIT301_CP
7195 #endif
7196
7197   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7198      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7199      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7200   } else {
7201      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7202      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7203   }
7204
7205   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7206      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7207      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7208      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7209   }
7210
7211   tempdi = NULL;
7212   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7213      tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7214      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7215         tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7216      }
7217   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7218      if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7219         tempdi = SiS_HiTVGroup3_1;
7220         if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7221      }
7222   }
7223   if(tempdi) {
7224      for(i=0; i<=0x3E; i++) {
7225         SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7226      }
7227      if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
7228         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7229            SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7230         }
7231      }
7232   }
7233
7234 #ifdef SIS_CP
7235   SIS_CP_INIT301_CP2
7236 #endif
7237 }
7238
7239 /*********************************************/
7240 /*         SET PART 4 REGISTER GROUP         */
7241 /*********************************************/
7242
7243 #ifdef CONFIG_FB_SIS_315
7244 #if 0
7245 static void
7246 SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
7247 {
7248    unsigned short temp, temp1, temp2;
7249
7250    temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7251    temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
7252    temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7253    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7254    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7255    temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
7256    temp = (unsigned short)((int)(temp) + shift);
7257    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7258    temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7259    temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
7260    temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7261    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7262    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7263 }
7264 #endif
7265
7266 static void
7267 SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
7268 {
7269    unsigned short temp, temp1;
7270    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
7271
7272    if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
7273    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7274
7275    if(SiS_Pr->ChipType >= XGI_20) return;
7276
7277    if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
7278       if(!(ROMAddr[0x61] & 0x04)) return;
7279    }
7280
7281    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7282    temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7283    if(!(temp & 0x01)) {
7284       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7285       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
7286       if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
7287          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7288       }
7289       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7290       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
7291       else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7292       else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
7293       else                                         temp = 0x0402;
7294       if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
7295          temp1 = 0;
7296          if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7297          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7298          if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7299          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
7300          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7301          if(ModeNo > 0x13) {
7302             SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
7303          }
7304       } else {
7305          temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7306          if(temp1 == 0x01) temp |= 0x01;
7307          if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
7308          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
7309          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7310          if(ModeNo > 0x13) {
7311             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7312          }
7313       }
7314
7315 #if 0
7316       if(SiS_Pr->ChipType >= SIS_661) {                 /* ? */
7317          if(SiS_Pr->SiS_TVMode & TVAspect43) {
7318             if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7319                if(resinfo == SIS_RI_1024x768) {
7320                   SiS_ShiftXPos(SiS_Pr, 97);
7321                } else {
7322                   SiS_ShiftXPos(SiS_Pr, 111);
7323                }
7324             } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7325                SiS_ShiftXPos(SiS_Pr, 136);
7326             }
7327          }
7328       }
7329 #endif
7330
7331    }
7332
7333 }
7334 #endif
7335
7336 static void
7337 SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7338                  unsigned short RefreshRateTableIndex)
7339 {
7340   unsigned short vclkindex, temp, reg1, reg2;
7341
7342   if(SiS_Pr->UseCustomMode) {
7343      reg1 = SiS_Pr->CSR2B;
7344      reg2 = SiS_Pr->CSR2C;
7345   } else {
7346      vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
7347      reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7348      reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7349   }
7350
7351   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7352      if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
7353         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7354         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7355         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7356      } else {
7357         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7358         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7359      }
7360   } else {
7361      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7362      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7363      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7364   }
7365   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7366   temp = 0x08;
7367   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7368   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7369 }
7370
7371 static void
7372 SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
7373 {
7374   if(SiS_Pr->ChipType >= SIS_315H) {
7375      if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
7376         if((SiS_CRT2IsLCD(SiS_Pr)) ||
7377            (SiS_IsVAMode(SiS_Pr))) {
7378            if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
7379               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7380            } else {
7381               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7382            }
7383         }
7384      }
7385   }
7386   if(SiS_Pr->SiS_VBType & VB_SISEMI) {
7387      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7388 #ifdef SET_EMI
7389      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7390 #endif
7391      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7392   }
7393 }
7394
7395 static void
7396 SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7397                 unsigned short RefreshRateTableIndex)
7398 {
7399   unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
7400   unsigned int   tempebx, tempeax, templong;
7401
7402   if(ModeNo <= 0x13) {
7403      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7404      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7405   } else if(SiS_Pr->UseCustomMode) {
7406      modeflag = SiS_Pr->CModeFlag;
7407      resinfo = 0;
7408   } else {
7409      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7410      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7411   }
7412
7413   if(SiS_Pr->ChipType >= SIS_315H) {
7414      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7415         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7416            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7417         }
7418      }
7419   }
7420
7421   if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
7422      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7423         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
7424      }
7425   }
7426
7427   if(SiS_Pr->ChipType >= SIS_315H) {
7428      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7429         SiS_SetDualLinkEtc(SiS_Pr);
7430         return;
7431      }
7432   }
7433
7434   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7435
7436   tempbx = SiS_Pr->SiS_RVBHCMAX;
7437   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7438
7439   temp = (tempbx >> 1) & 0x80;
7440
7441   tempcx = SiS_Pr->SiS_VGAHT - 1;
7442   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7443
7444   temp |= ((tempcx >> 5) & 0x78);
7445
7446   tempcx = SiS_Pr->SiS_VGAVT - 1;
7447   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7448   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7449
7450   temp |= ((tempcx >> 8) & 0x07);
7451   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7452
7453   tempbx = SiS_Pr->SiS_VGAHDE;
7454   if(modeflag & HalfDCLK)    tempbx >>= 1;
7455   if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7456
7457   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7458      temp = 0;
7459      if(tempbx > 800)        temp = 0x60;
7460   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7461      temp = 0;
7462      if(tempbx > 1024)       temp = 0xC0;
7463      else if(tempbx >= 960)  temp = 0xA0;
7464   } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7465      temp = 0;
7466      if(tempbx >= 1280)      temp = 0x40;
7467      else if(tempbx >= 1024) temp = 0x20;
7468   } else {
7469      temp = 0x80;
7470      if(tempbx >= 1024)      temp = 0xA0;
7471   }
7472
7473   temp |= SiS_Pr->Init_P4_0E;
7474
7475   if(SiS_Pr->SiS_VBType & VB_SIS301) {
7476      if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
7477         temp &= 0xf0;
7478         temp |= 0x0A;
7479      }
7480   }
7481
7482   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7483
7484   tempeax = SiS_Pr->SiS_VGAVDE;
7485   tempebx = SiS_Pr->SiS_VDE;
7486   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7487      if(!(temp & 0xE0)) tempebx >>=1;
7488   }
7489
7490   tempcx = SiS_Pr->SiS_RVBHRS;
7491   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7492   tempcx >>= 8;
7493   tempcx |= 0x40;
7494
7495   if(tempeax <= tempebx) {
7496      tempcx ^= 0x40;
7497   } else {
7498      tempeax -= tempebx;
7499   }
7500
7501   tempeax *= (256 * 1024);
7502   templong = tempeax % tempebx;
7503   tempeax /= tempebx;
7504   if(templong) tempeax++;
7505
7506   temp = (unsigned short)(tempeax & 0x000000FF);
7507   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
7508   temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
7509   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
7510   temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
7511   temp |= (tempcx & 0x4F);
7512   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7513
7514   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
7515
7516      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7517
7518      /* Calc Linebuffer max address and set/clear decimode */
7519      tempbx = 0;
7520      if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7521      tempax = SiS_Pr->SiS_VGAHDE;
7522      if(modeflag & HalfDCLK)    tempax >>= 1;
7523      if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
7524      if(tempax > 800) {
7525         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7526            tempax -= 800;
7527         } else {
7528            tempbx = 0x08;
7529            if(tempax == 960)       tempax *= 25; /* Correct */
7530            else if(tempax == 1024) tempax *= 25;
7531            else                    tempax *= 20;
7532            temp = tempax % 32;
7533            tempax /= 32;
7534            if(temp) tempax++;
7535            tempax++;
7536            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7537               if(resinfo == SIS_RI_1024x768 ||
7538                  resinfo == SIS_RI_1024x576 ||
7539                  resinfo == SIS_RI_1280x1024 ||
7540                  resinfo == SIS_RI_1280x720) {
7541                  /* Otherwise white line or garbage at right edge */
7542                  tempax = (tempax & 0xff00) | 0x20;
7543               }
7544            }
7545         }
7546      }
7547      tempax--;
7548      temp = ((tempax >> 4) & 0x30) | tempbx;
7549      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7550      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7551
7552      temp = 0x0036; tempbx = 0xD0;
7553      if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
7554         temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7555      }
7556      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7557         if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7558            temp |= 0x01;
7559            if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7560               if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7561                  temp &= ~0x01;
7562               }
7563            }
7564         }
7565      }
7566      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7567
7568      tempbx = SiS_Pr->SiS_HT >> 1;
7569      if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
7570      tempbx -= 2;
7571      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7572      temp = (tempbx >> 5) & 0x38;
7573      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7574
7575      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
7576         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7577            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7578            /* LCD-too-dark-error-source, see FinalizeLCD() */
7579         }
7580      }
7581
7582      SiS_SetDualLinkEtc(SiS_Pr);
7583
7584   }  /* 301B */
7585
7586   SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
7587 }
7588
7589 /*********************************************/
7590 /*         SET PART 5 REGISTER GROUP         */
7591 /*********************************************/
7592
7593 static void
7594 SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
7595 {
7596
7597   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)  return;
7598
7599   if(SiS_Pr->SiS_ModeType == ModeVGA) {
7600      if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7601         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
7602         SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
7603      }
7604   }
7605 }
7606
7607 /*********************************************/
7608 /*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
7609 /*********************************************/
7610
7611 static bool
7612 SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7613                    unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
7614                    unsigned short *DisplayType)
7615  {
7616   unsigned short modeflag = 0;
7617   bool checkhd = true;
7618
7619   /* Pass 1:1 not supported here */
7620
7621   if(ModeNo <= 0x13) {
7622      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7623      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7624   } else {
7625      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7626      (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7627   }
7628
7629   (*ResIndex) &= 0x3F;
7630
7631   if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7632
7633      (*DisplayType) = 80;
7634      if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
7635         (*DisplayType) = 82;
7636         if(SiS_Pr->SiS_ModeType > ModeVGA) {
7637            if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
7638         }
7639      }
7640      if((*DisplayType) != 84) {
7641         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
7642      }
7643
7644   } else {
7645
7646      (*DisplayType = 0);
7647      switch(SiS_Pr->SiS_LCDResInfo) {
7648      case Panel_320x240_1: (*DisplayType) = 50;
7649                            checkhd = false;
7650                            break;
7651      case Panel_320x240_2: (*DisplayType) = 14;
7652                            break;
7653      case Panel_320x240_3: (*DisplayType) = 18;
7654                            break;
7655      case Panel_640x480:   (*DisplayType) = 10;
7656                            break;
7657      case Panel_1024x600:  (*DisplayType) = 26;
7658                            break;
7659      default: return true;
7660      }
7661
7662      if(checkhd) {
7663         if(modeflag & HalfDCLK) (*DisplayType)++;
7664      }
7665
7666      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
7667         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
7668      }
7669
7670   }
7671
7672   return true;
7673 }
7674
7675 static void
7676 SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7677                 unsigned short RefreshRateTableIndex)
7678 {
7679   unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
7680   const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
7681   static const unsigned short CRIdx[] = {
7682         0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
7683         0x07, 0x10, 0x11, 0x15, 0x16
7684   };
7685
7686   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
7687      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
7688      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
7689      (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
7690      return;
7691
7692   if(SiS_Pr->SiS_IF_DEF_LVDS) {
7693      if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7694         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7695      }
7696   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
7697      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
7698   } else return;
7699
7700   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
7701
7702   if(SiS_Pr->ChipType < SIS_315H) {
7703      if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
7704   }
7705
7706   if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7707                           &ResIndex, &DisplayType))) {
7708      return;
7709   }
7710
7711   switch(DisplayType) {
7712     case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1;           break; /* xSTN */
7713     case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2;           break; /* xSTN */
7714     case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H;         break; /* xSTN */
7715     case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3;           break; /* xSTN */
7716     case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H;         break; /* xSTN */
7717     case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1;           break;
7718     case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H;         break;
7719 #if 0 /* Works better with calculated numbers */
7720     case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1;          break;
7721     case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H;        break;
7722     case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2;          break;
7723     case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H;        break;
7724 #endif
7725     case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC;               break;
7726     case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC;               break;
7727     case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL;                break;
7728     case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL;                break;
7729     case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL;               break;
7730   }
7731
7732   if(LVDSCRT1Ptr) {
7733
7734      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
7735
7736      for(i = 0; i <= 10; i++) {
7737         tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
7738         SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
7739      }
7740
7741      for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
7742         tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
7743         SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
7744      }
7745
7746      tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
7747      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
7748
7749      if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7750      else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7751
7752      tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
7753      if(modeflag & DoubleScanMode) tempah |= 0x80;
7754      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
7755
7756   } else {
7757
7758      SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
7759
7760   }
7761 }
7762
7763 /*********************************************/
7764 /*              SET CRT2 ECLK                */
7765 /*********************************************/
7766
7767 static void
7768 SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7769            unsigned short RefreshRateTableIndex)
7770 {
7771   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
7772   unsigned short clkbase, vclkindex = 0;
7773   unsigned char  sr2b, sr2c;
7774
7775   if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7776      SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
7777      if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
7778         RefreshRateTableIndex--;
7779      }
7780      vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7781                                     RefreshRateTableIndex);
7782      SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
7783   } else {
7784      vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
7785                                     RefreshRateTableIndex);
7786   }
7787
7788   sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
7789   sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
7790
7791   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
7792      if(SiS_Pr->SiS_UseROM) {
7793         if(ROMAddr[0x220] & 0x01) {
7794            sr2b = ROMAddr[0x227];
7795            sr2c = ROMAddr[0x228];
7796         }
7797      }
7798   }
7799
7800   clkbase = 0x02B;
7801   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
7802      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
7803         clkbase += 3;
7804      }
7805   }
7806
7807   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
7808   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7809   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7810   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
7811   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7812   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7813   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
7814   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
7815   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
7816 }
7817
7818 /*********************************************/
7819 /*           SET UP CHRONTEL CHIPS           */
7820 /*********************************************/
7821
7822 static void
7823 SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
7824                unsigned short RefreshRateTableIndex)
7825 {
7826    unsigned short TVType, resindex;
7827    const struct SiS_CHTVRegData *CHTVRegData = NULL;
7828
7829    if(ModeNo <= 0x13)
7830       resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
7831    else
7832       resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
7833
7834    resindex &= 0x3F;
7835
7836    TVType = 0;
7837    if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7838    if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7839       TVType += 2;
7840       if(SiS_Pr->SiS_ModeType > ModeVGA) {
7841          if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
7842       }
7843       if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7844          TVType = 4;
7845          if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7846       } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
7847          TVType = 6;
7848          if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
7849       }
7850    }
7851
7852    switch(TVType) {
7853       case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
7854       case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
7855       case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
7856       case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
7857       case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
7858       case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
7859       case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
7860       case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
7861       case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
7862       default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
7863    }
7864
7865
7866    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
7867
7868 #ifdef CONFIG_FB_SIS_300
7869
7870       /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
7871
7872       /* We don't support modes >800x600 */
7873       if (resindex > 5) return;
7874
7875       if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7876          SiS_SetCH700x(SiS_Pr,0x04,0x43);  /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
7877          SiS_SetCH700x(SiS_Pr,0x09,0x69);  /* Black level for PAL (105)*/
7878       } else {
7879          SiS_SetCH700x(SiS_Pr,0x04,0x03);   /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
7880          SiS_SetCH700x(SiS_Pr,0x09,0x71);   /* Black level for NTSC (113)*/
7881       }
7882
7883       SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]);  /* Mode register */
7884       SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]);  /* Start active video register */
7885       SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]);  /* Position overflow register */
7886       SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]);  /* Horiz Position register */
7887       SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]);  /* Vertical Position register */
7888
7889       /* Set minimum flicker filter for Luma channel (SR1-0=00),
7890                 minimum text enhancement (S3-2=10),
7891                 maximum flicker filter for Chroma channel (S5-4=10)
7892                 =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
7893        */
7894       SiS_SetCH700x(SiS_Pr,0x01,0x28);
7895
7896       /* Set video bandwidth
7897             High bandwidth Luma composite video filter(S0=1)
7898             low bandwidth Luma S-video filter (S2-1=00)
7899             disable peak filter in S-video channel (S3=0)
7900             high bandwidth Chroma Filter (S5-4=11)
7901             =00110001=0x31
7902       */
7903       SiS_SetCH700x(SiS_Pr,0x03,0xb1);       /* old: 3103 */
7904
7905       /* Register 0x3D does not exist in non-macrovision register map
7906             (Maybe this is a macrovision register?)
7907        */
7908 #ifndef SIS_CP
7909       SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
7910 #endif
7911
7912       /* Register 0x10 only contains 1 writable bit (S0) for sensing,
7913              all other bits a read-only. Macrovision?
7914        */
7915       SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
7916
7917       /* Register 0x11 only contains 3 writable bits (S0-S2) for
7918              contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
7919        */
7920       SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
7921
7922       /* Clear DSEN
7923        */
7924       SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
7925
7926       if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {            /* ---- NTSC ---- */
7927          if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
7928             if(resindex == 0x04) {                      /* 640x480 overscan: Mode 16 */
7929                SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off */
7930                SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);       /* ACIV on, no need to set FSCI */
7931             } else if(resindex == 0x05) {               /* 800x600 overscan: Mode 23 */
7932                SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);       /* 0x18-0x1f: FSCI 469,762,048 */
7933                SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
7934                SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
7935                SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
7936                SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
7937                SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
7938                SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
7939                SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
7940                SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF);       /* Loop filter on for mode 23 */
7941                SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);       /* ACIV off, need to set FSCI */
7942             }
7943          } else {
7944             if(resindex == 0x04) {                      /* ----- 640x480 underscan; Mode 17 */
7945                SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off */
7946                SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7947             } else if(resindex == 0x05) {               /* ----- 800x600 underscan: Mode 24 */
7948 #if 0
7949                SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);       /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
7950                SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0);       /* FSCI for mode 24 is 428,554,851 */
7951                SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0);       /* 198b3a63 */
7952                SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
7953                SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
7954                SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
7955                SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
7956                SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
7957                SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off for mode 24 */
7958                SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);       * ACIV off, need to set FSCI */
7959 #endif         /* All alternatives wrong (datasheet wrong?), don't use FSCI */
7960                SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);        /* loop filter off */
7961                SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
7962             }
7963          }
7964       } else {                                          /* ---- PAL ---- */
7965          /* We don't play around with FSCI in PAL mode */
7966          if(resindex == 0x04) {
7967             SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);  /* loop filter off */
7968             SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);  /* ACIV on */
7969          } else {
7970             SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);  /* loop filter off */
7971             SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);  /* ACIV on */
7972          }
7973       }
7974
7975 #endif  /* 300 */
7976
7977    } else {
7978
7979       /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
7980
7981 #ifdef CONFIG_FB_SIS_315
7982
7983       unsigned short temp;
7984
7985       /* We don't support modes >1024x768 */
7986       if (resindex > 6) return;
7987
7988       temp = CHTVRegData[resindex].Reg[0];
7989       if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
7990       SiS_SetCH701x(SiS_Pr,0x00,temp);
7991
7992       SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
7993       SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
7994       SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
7995       SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
7996       SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
7997       SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
7998
7999       temp = CHTVRegData[resindex].Reg[7];
8000       if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
8001       SiS_SetCH701x(SiS_Pr,0x07,temp);
8002
8003       SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
8004       SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
8005       SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
8006       SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
8007       SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
8008       SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
8009       SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
8010       SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
8011
8012       temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8013       /* D1 should be set for PAL, PAL-N and NTSC-J,
8014          but I won't do that for PAL unless somebody
8015          tells me to do so. Since the BIOS uses
8016          non-default CIV values and blacklevels,
8017          this might be compensated anyway.
8018        */
8019       if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8020       SiS_SetCH701x(SiS_Pr,0x21,temp);
8021
8022 #endif  /* 315 */
8023
8024    }
8025
8026 #ifdef SIS_CP
8027    SIS_CP_INIT301_CP3
8028 #endif
8029
8030 }
8031
8032 #ifdef CONFIG_FB_SIS_315  /* ----------- 315 series only ---------- */
8033
8034 void
8035 SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
8036 {
8037    unsigned short temp;
8038
8039    /* Enable Chrontel 7019 LCD panel backlight */
8040    if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8041       if(SiS_Pr->ChipType == SIS_740) {
8042          SiS_SetCH701x(SiS_Pr,0x66,0x65);
8043       } else {
8044          temp = SiS_GetCH701x(SiS_Pr,0x66);
8045          temp |= 0x20;
8046          SiS_SetCH701x(SiS_Pr,0x66,temp);
8047       }
8048    }
8049 }
8050
8051 void
8052 SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
8053 {
8054    unsigned short temp;
8055
8056    /* Disable Chrontel 7019 LCD panel backlight */
8057    if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8058       temp = SiS_GetCH701x(SiS_Pr,0x66);
8059       temp &= 0xDF;
8060       SiS_SetCH701x(SiS_Pr,0x66,temp);
8061    }
8062 }
8063
8064 static void
8065 SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
8066 {
8067   static const unsigned char regtable[]      = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8068   static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8069   static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8070   static const unsigned char asus1024_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8071   static const unsigned char asus1400_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8072   static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8073   static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8074   const unsigned char *tableptr = NULL;
8075   int i;
8076
8077   /* Set up Power up/down timing */
8078
8079   if(SiS_Pr->ChipType == SIS_740) {
8080      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8081         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8082         else                                      tableptr = table1024_740;
8083      } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8084                (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8085                (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8086         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8087         else                                      tableptr = table1400_740;
8088      } else return;
8089   } else {
8090      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8091         tableptr = table1024_650;
8092      } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8093                (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8094                (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8095         tableptr = table1400_650;
8096      } else return;
8097   }
8098
8099   for(i=0; i<5; i++) {
8100      SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
8101   }
8102 }
8103
8104 static void
8105 SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
8106 {
8107   const unsigned char *tableptr = NULL;
8108   unsigned short tempbh;
8109   int i;
8110   static const unsigned char regtable[] = {
8111                 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8112                 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
8113   };
8114   static const unsigned char table1024_740[] = {
8115                 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8116                 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
8117   };
8118   static const unsigned char table1280_740[] = {
8119                 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8120                 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8121   };
8122   static const unsigned char table1400_740[] = {
8123                 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8124                 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
8125   };
8126   static const unsigned char table1600_740[] = {
8127                 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8128                 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
8129   };
8130   static const unsigned char table1024_650[] = {
8131                 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8132                 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
8133   };
8134   static const unsigned char table1280_650[] = {
8135                 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8136                 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
8137   };
8138   static const unsigned char table1400_650[] = {
8139                 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8140                 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
8141   };
8142   static const unsigned char table1600_650[] = {
8143                 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8144                 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
8145   };
8146
8147   if(SiS_Pr->ChipType == SIS_740) {
8148      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
8149      else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8150      else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8151      else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8152      else return;
8153   } else {
8154      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
8155      else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8156      else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8157      else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8158      else return;
8159   }
8160
8161   tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8162   if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8163      tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8164      if(tempbh == 0xc8) {
8165         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8166      } else if(tempbh == 0xdb) {
8167         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8168         if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8169      } else if(tempbh == 0xde) {
8170         if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8171      }
8172   }
8173
8174   if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
8175   else                            tempbh = 0x0c;
8176
8177   for(i = 0; i < tempbh; i++) {
8178      SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
8179   }
8180   SiS_ChrontelPowerSequencing(SiS_Pr);
8181   tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8182   tempbh |= 0xc0;
8183   SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
8184
8185   if(SiS_Pr->ChipType == SIS_740) {
8186      tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8187      tempbh &= 0xfb;
8188      SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
8189      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8190      tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8191      tempbh |= 0x40;
8192      SiS_SetCH701x(SiS_Pr,0x64,tempbh);
8193      tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8194      tempbh &= 0x3f;
8195      SiS_SetCH701x(SiS_Pr,0x03,tempbh);
8196   }
8197 }
8198
8199 static void
8200 SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
8201 {
8202   unsigned char temp, temp1;
8203
8204   temp1 = SiS_GetCH701x(SiS_Pr,0x49);
8205   SiS_SetCH701x(SiS_Pr,0x49,0x3e);
8206   temp = SiS_GetCH701x(SiS_Pr,0x47);
8207   temp &= 0x7f; /* Use external VSYNC */
8208   SiS_SetCH701x(SiS_Pr,0x47,temp);
8209   SiS_LongDelay(SiS_Pr, 3);
8210   temp = SiS_GetCH701x(SiS_Pr,0x47);
8211   temp |= 0x80; /* Use internal VSYNC */
8212   SiS_SetCH701x(SiS_Pr,0x47,temp);
8213   SiS_SetCH701x(SiS_Pr,0x49,temp1);
8214 }
8215
8216 static void
8217 SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
8218 {
8219   unsigned short temp;
8220
8221   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8222      if(SiS_Pr->ChipType == SIS_740) {
8223         temp = SiS_GetCH701x(SiS_Pr,0x1c);
8224         temp |= 0x04;   /* Invert XCLK phase */
8225         SiS_SetCH701x(SiS_Pr,0x1c,temp);
8226      }
8227      if(SiS_IsYPbPr(SiS_Pr)) {
8228         temp = SiS_GetCH701x(SiS_Pr,0x01);
8229         temp &= 0x3f;
8230         temp |= 0x80;   /* Enable YPrPb (HDTV) */
8231         SiS_SetCH701x(SiS_Pr,0x01,temp);
8232      }
8233      if(SiS_IsChScart(SiS_Pr)) {
8234         temp = SiS_GetCH701x(SiS_Pr,0x01);
8235         temp &= 0x3f;
8236         temp |= 0xc0;   /* Enable SCART + CVBS */
8237         SiS_SetCH701x(SiS_Pr,0x01,temp);
8238      }
8239      if(SiS_Pr->ChipType == SIS_740) {
8240         SiS_ChrontelResetVSync(SiS_Pr);
8241         SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
8242      } else {
8243         SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
8244         temp = SiS_GetCH701x(SiS_Pr,0x49);
8245         if(SiS_IsYPbPr(SiS_Pr)) {
8246            temp = SiS_GetCH701x(SiS_Pr,0x73);
8247            temp |= 0x60;
8248            SiS_SetCH701x(SiS_Pr,0x73,temp);
8249         }
8250         temp = SiS_GetCH701x(SiS_Pr,0x47);
8251         temp &= 0x7f;
8252         SiS_SetCH701x(SiS_Pr,0x47,temp);
8253         SiS_LongDelay(SiS_Pr, 2);
8254         temp = SiS_GetCH701x(SiS_Pr,0x47);
8255         temp |= 0x80;
8256         SiS_SetCH701x(SiS_Pr,0x47,temp);
8257      }
8258   }
8259 }
8260
8261 static void
8262 SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
8263 {
8264   unsigned short temp;
8265
8266   /* Complete power down of LVDS */
8267   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8268      if(SiS_Pr->ChipType == SIS_740) {
8269         SiS_LongDelay(SiS_Pr, 1);
8270         SiS_GenericDelay(SiS_Pr, 5887);
8271         SiS_SetCH701x(SiS_Pr,0x76,0xac);
8272         SiS_SetCH701x(SiS_Pr,0x66,0x00);
8273      } else {
8274         SiS_LongDelay(SiS_Pr, 2);
8275         temp = SiS_GetCH701x(SiS_Pr,0x76);
8276         temp &= 0xfc;
8277         SiS_SetCH701x(SiS_Pr,0x76,temp);
8278         SiS_SetCH701x(SiS_Pr,0x66,0x00);
8279      }
8280   }
8281 }
8282
8283 static void
8284 SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
8285 {
8286      unsigned short temp;
8287
8288      if(SiS_Pr->ChipType == SIS_740) {
8289
8290         temp = SiS_GetCH701x(SiS_Pr,0x4a);  /* Version ID */
8291         temp &= 0x01;
8292         if(!temp) {
8293
8294            if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8295               temp = SiS_GetCH701x(SiS_Pr,0x49);
8296               SiS_SetCH701x(SiS_Pr,0x49,0x3e);
8297            }
8298
8299            /* Reset Chrontel 7019 datapath */
8300            SiS_SetCH701x(SiS_Pr,0x48,0x10);
8301            SiS_LongDelay(SiS_Pr, 1);
8302            SiS_SetCH701x(SiS_Pr,0x48,0x18);
8303
8304            if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8305               SiS_ChrontelResetVSync(SiS_Pr);
8306               SiS_SetCH701x(SiS_Pr,0x49,temp);
8307            }
8308
8309         } else {
8310
8311            /* Clear/set/clear GPIO */
8312            temp = SiS_GetCH701x(SiS_Pr,0x5c);
8313            temp &= 0xef;
8314            SiS_SetCH701x(SiS_Pr,0x5c,temp);
8315            temp = SiS_GetCH701x(SiS_Pr,0x5c);
8316            temp |= 0x10;
8317            SiS_SetCH701x(SiS_Pr,0x5c,temp);
8318            temp = SiS_GetCH701x(SiS_Pr,0x5c);
8319            temp &= 0xef;
8320            SiS_SetCH701x(SiS_Pr,0x5c,temp);
8321            temp = SiS_GetCH701x(SiS_Pr,0x61);
8322            if(!temp) {
8323               SiS_SetCH701xForLCD(SiS_Pr);
8324            }
8325         }
8326
8327      } else { /* 650 */
8328         /* Reset Chrontel 7019 datapath */
8329         SiS_SetCH701x(SiS_Pr,0x48,0x10);
8330         SiS_LongDelay(SiS_Pr, 1);
8331         SiS_SetCH701x(SiS_Pr,0x48,0x18);
8332      }
8333 }
8334
8335 static void
8336 SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
8337 {
8338      unsigned short temp;
8339
8340      if(SiS_Pr->ChipType == SIS_740) {
8341
8342         if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8343            SiS_ChrontelResetVSync(SiS_Pr);
8344         }
8345
8346      } else {
8347
8348         SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* Power up LVDS block */
8349         temp = SiS_GetCH701x(SiS_Pr,0x49);
8350         temp &= 1;
8351         if(temp != 1) {  /* TV block powered? (0 = yes, 1 = no) */
8352            temp = SiS_GetCH701x(SiS_Pr,0x47);
8353            temp &= 0x70;
8354            SiS_SetCH701x(SiS_Pr,0x47,temp);  /* enable VSYNC */
8355            SiS_LongDelay(SiS_Pr, 3);
8356            temp = SiS_GetCH701x(SiS_Pr,0x47);
8357            temp |= 0x80;
8358            SiS_SetCH701x(SiS_Pr,0x47,temp);  /* disable VSYNC */
8359         }
8360
8361      }
8362 }
8363
8364 static void
8365 SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8366 {
8367      unsigned short temp,temp1;
8368
8369      if(SiS_Pr->ChipType == SIS_740) {
8370
8371         temp = SiS_GetCH701x(SiS_Pr,0x61);
8372         if(temp < 1) {
8373            temp++;
8374            SiS_SetCH701x(SiS_Pr,0x61,temp);
8375         }
8376         SiS_SetCH701x(SiS_Pr,0x66,0x45);  /* Panel power on */
8377         SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on */
8378         SiS_LongDelay(SiS_Pr, 1);
8379         SiS_GenericDelay(SiS_Pr, 5887);
8380
8381      } else {  /* 650 */
8382
8383         temp1 = 0;
8384         temp = SiS_GetCH701x(SiS_Pr,0x61);
8385         if(temp < 2) {
8386            temp++;
8387            SiS_SetCH701x(SiS_Pr,0x61,temp);
8388            temp1 = 1;
8389         }
8390         SiS_SetCH701x(SiS_Pr,0x76,0xac);
8391         temp = SiS_GetCH701x(SiS_Pr,0x66);
8392         temp |= 0x5f;
8393         SiS_SetCH701x(SiS_Pr,0x66,temp);
8394         if(ModeNo > 0x13) {
8395            if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
8396               SiS_GenericDelay(SiS_Pr, 1023);
8397            } else {
8398               SiS_GenericDelay(SiS_Pr, 767);
8399            }
8400         } else {
8401            if(!temp1)
8402               SiS_GenericDelay(SiS_Pr, 767);
8403         }
8404         temp = SiS_GetCH701x(SiS_Pr,0x76);
8405         temp |= 0x03;
8406         SiS_SetCH701x(SiS_Pr,0x76,temp);
8407         temp = SiS_GetCH701x(SiS_Pr,0x66);
8408         temp &= 0x7f;
8409         SiS_SetCH701x(SiS_Pr,0x66,temp);
8410         SiS_LongDelay(SiS_Pr, 1);
8411
8412      }
8413 }
8414
8415 static void
8416 SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
8417 {
8418      unsigned short temp;
8419
8420      SiS_LongDelay(SiS_Pr, 1);
8421
8422      do {
8423        temp = SiS_GetCH701x(SiS_Pr,0x66);
8424        temp &= 0x04;  /* PLL stable? -> bail out */
8425        if(temp == 0x04) break;
8426
8427        if(SiS_Pr->ChipType == SIS_740) {
8428           /* Power down LVDS output, PLL normal operation */
8429           SiS_SetCH701x(SiS_Pr,0x76,0xac);
8430        }
8431
8432        SiS_SetCH701xForLCD(SiS_Pr);
8433
8434        temp = SiS_GetCH701x(SiS_Pr,0x76);
8435        temp &= 0xfb;  /* Reset PLL */
8436        SiS_SetCH701x(SiS_Pr,0x76,temp);
8437        SiS_LongDelay(SiS_Pr, 2);
8438        temp = SiS_GetCH701x(SiS_Pr,0x76);
8439        temp |= 0x04;  /* PLL normal operation */
8440        SiS_SetCH701x(SiS_Pr,0x76,temp);
8441        if(SiS_Pr->ChipType == SIS_740) {
8442           SiS_SetCH701x(SiS_Pr,0x78,0xe0);      /* PLL loop filter */
8443        } else {
8444           SiS_SetCH701x(SiS_Pr,0x78,0x60);
8445        }
8446        SiS_LongDelay(SiS_Pr, 2);
8447     } while(0);
8448
8449     SiS_SetCH701x(SiS_Pr,0x77,0x00);  /* MV? */
8450 }
8451
8452 static void
8453 SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
8454 {
8455      unsigned short temp;
8456
8457      temp = SiS_GetCH701x(SiS_Pr,0x03);
8458      temp |= 0x80;      /* Set datapath 1 to TV   */
8459      temp &= 0xbf;      /* Set datapath 2 to LVDS */
8460      SiS_SetCH701x(SiS_Pr,0x03,temp);
8461
8462      if(SiS_Pr->ChipType == SIS_740) {
8463
8464         temp = SiS_GetCH701x(SiS_Pr,0x1c);
8465         temp &= 0xfb;   /* Normal XCLK phase */
8466         SiS_SetCH701x(SiS_Pr,0x1c,temp);
8467
8468         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8469
8470         temp = SiS_GetCH701x(SiS_Pr,0x64);
8471         temp |= 0x40;   /* ? Bit not defined */
8472         SiS_SetCH701x(SiS_Pr,0x64,temp);
8473
8474         temp = SiS_GetCH701x(SiS_Pr,0x03);
8475         temp &= 0x3f;   /* D1 input to both LVDS and TV */
8476         SiS_SetCH701x(SiS_Pr,0x03,temp);
8477
8478         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
8479            SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
8480            SiS_LongDelay(SiS_Pr, 1);
8481            SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
8482            SiS_ChrontelResetDB(SiS_Pr);
8483            SiS_ChrontelDoSomething2(SiS_Pr);
8484            SiS_ChrontelDoSomething3(SiS_Pr, 0);
8485         } else {
8486            temp = SiS_GetCH701x(SiS_Pr,0x66);
8487            if(temp != 0x45) {
8488               SiS_ChrontelResetDB(SiS_Pr);
8489               SiS_ChrontelDoSomething2(SiS_Pr);
8490               SiS_ChrontelDoSomething3(SiS_Pr, 0);
8491            }
8492         }
8493
8494      } else { /* 650 */
8495
8496         SiS_ChrontelResetDB(SiS_Pr);
8497         SiS_ChrontelDoSomething2(SiS_Pr);
8498         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
8499         SiS_ChrontelDoSomething3(SiS_Pr,temp);
8500         SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on, LVDS normal operation */
8501
8502      }
8503
8504 }
8505 #endif  /* 315 series  */
8506
8507 /*********************************************/
8508 /*      MAIN: SET CRT2 REGISTER GROUP        */
8509 /*********************************************/
8510
8511 bool
8512 SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
8513 {
8514 #ifdef CONFIG_FB_SIS_300
8515    unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
8516 #endif
8517    unsigned short ModeIdIndex, RefreshRateTableIndex;
8518
8519    SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8520
8521    if(!SiS_Pr->UseCustomMode) {
8522       SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8523    } else {
8524       ModeIdIndex = 0;
8525    }
8526
8527    /* Used for shifting CR33 */
8528    SiS_Pr->SiS_SelectCRT2Rate = 4;
8529
8530    SiS_UnLockCRT2(SiS_Pr);
8531
8532    RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
8533
8534    SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8535
8536    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8537       SiS_DisableBridge(SiS_Pr);
8538       if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
8539          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8540       }
8541       SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
8542    }
8543
8544    if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
8545       SiS_LockCRT2(SiS_Pr);
8546       SiS_DisplayOn(SiS_Pr);
8547       return true;
8548    }
8549
8550    SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8551
8552    /* Set up Panel Link for LVDS and LCDA */
8553    SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8554    if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8555        ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
8556        ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
8557       SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8558    }
8559
8560    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8561       SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8562    }
8563
8564    if(SiS_Pr->SiS_VBType & VB_SISVB) {
8565
8566       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8567
8568          SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8569 #ifdef CONFIG_FB_SIS_315
8570          SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8571 #endif
8572          SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
8573          SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8574 #ifdef CONFIG_FB_SIS_315
8575          SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
8576 #endif
8577          SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
8578
8579          SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
8580
8581          /* For 301BDH (Panel link initialization): */
8582          if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8583
8584             if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8585                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8586                   SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8587                }
8588             }
8589             SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8590          }
8591       }
8592
8593    } else {
8594
8595       SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
8596
8597       SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8598
8599       SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8600
8601       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8602          if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8603             if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8604                if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8605 #ifdef CONFIG_FB_SIS_315
8606                   SiS_SetCH701xForLCD(SiS_Pr);
8607 #endif
8608                }
8609             }
8610             if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8611                SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8612             }
8613          }
8614       }
8615
8616    }
8617
8618 #ifdef CONFIG_FB_SIS_300
8619    if(SiS_Pr->ChipType < SIS_315H) {
8620       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8621          if(SiS_Pr->SiS_UseOEM) {
8622             if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8623                if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
8624                   SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8625                }
8626             } else {
8627                SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8628             }
8629          }
8630          if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
8631             if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
8632                (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
8633                SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
8634             }
8635             SiS_DisplayOn(SiS_Pr);
8636          }
8637       }
8638    }
8639 #endif
8640
8641 #ifdef CONFIG_FB_SIS_315
8642    if(SiS_Pr->ChipType >= SIS_315H) {
8643       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8644          if(SiS_Pr->ChipType < SIS_661) {
8645             SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
8646             SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8647          } else {
8648             SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
8649          }
8650          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
8651       }
8652    }
8653 #endif
8654
8655    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8656       SiS_EnableBridge(SiS_Pr);
8657    }
8658
8659    SiS_DisplayOn(SiS_Pr);
8660
8661    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8662       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8663          /* Disable LCD panel when using TV */
8664          SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
8665       } else {
8666          /* Disable TV when using LCD */
8667          SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
8668       }
8669    }
8670
8671    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8672       SiS_LockCRT2(SiS_Pr);
8673    }
8674
8675    return true;
8676 }
8677
8678
8679 /*********************************************/
8680 /*     ENABLE/DISABLE LCD BACKLIGHT (SIS)    */
8681 /*********************************************/
8682
8683 void
8684 SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
8685 {
8686   /* Switch on LCD backlight on SiS30xLV */
8687   SiS_DDC2Delay(SiS_Pr,0xff00);
8688   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
8689      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
8690      SiS_WaitVBRetrace(SiS_Pr);
8691   }
8692   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
8693      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
8694   }
8695 }
8696
8697 void
8698 SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
8699 {
8700   /* Switch off LCD backlight on SiS30xLV */
8701   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
8702   SiS_DDC2Delay(SiS_Pr,0xff00);
8703 }
8704
8705 /*********************************************/
8706 /*          DDC RELATED FUNCTIONS            */
8707 /*********************************************/
8708
8709 static void
8710 SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
8711 {
8712   SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
8713   SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
8714   if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
8715      SiS_Pr->SiS_DDC_NData &= 0x0f;
8716      SiS_Pr->SiS_DDC_NClk  &= 0x0f;
8717   }
8718 }
8719
8720 #ifdef CONFIG_FB_SIS_300
8721 static unsigned char *
8722 SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
8723 {
8724   int i, j, num;
8725   unsigned short tempah,temp;
8726   unsigned char *mydataptr;
8727
8728   for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
8729      mydataptr = dataptr;
8730      num = *mydataptr++;
8731      if(!num) return mydataptr;
8732      if(i) {
8733         SiS_SetStop(SiS_Pr);
8734         SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
8735      }
8736      if(SiS_SetStart(SiS_Pr)) continue;         /* Set start condition */
8737      tempah = SiS_Pr->SiS_DDC_DeviceAddr;
8738      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write DAB (S0=0=write) */
8739      if(temp) continue;                         /*    (ERROR: no ack) */
8740      tempah = *mydataptr++;
8741      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write register number */
8742      if(temp) continue;                         /*    (ERROR: no ack) */
8743      for(j=0; j<num; j++) {
8744         tempah = *mydataptr++;
8745         temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
8746         if(temp) break;
8747      }
8748      if(temp) continue;
8749      if(SiS_SetStop(SiS_Pr)) continue;
8750      return mydataptr;
8751   }
8752   return NULL;
8753 }
8754
8755 static bool
8756 SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
8757 {
8758   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;            /* DAB (Device Address Byte) */
8759   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
8760   SiS_Pr->SiS_DDC_Data  = 0x02;                 /* Bitmask in IndexReg for Data */
8761   SiS_Pr->SiS_DDC_Clk   = 0x01;                 /* Bitmask in IndexReg for Clk */
8762   SiS_SetupDDCN(SiS_Pr);
8763
8764   SiS_SetSwitchDDC2(SiS_Pr);
8765
8766   while(*dataptr) {
8767      dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
8768      if(!dataptr) return false;
8769   }
8770   return true;
8771 }
8772 #endif
8773
8774 /* The Chrontel 700x is connected to the 630/730 via
8775  * the 630/730's DDC/I2C port.
8776  *
8777  * On 630(S)T chipset, the index changed from 0x11 to
8778  * 0x0a, possibly for working around the DDC problems
8779  */
8780
8781 static bool
8782 SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
8783 {
8784   unsigned short temp, i;
8785
8786   for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
8787      if(i) {
8788         SiS_SetStop(SiS_Pr);
8789         SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
8790      }
8791      if(SiS_SetStart(SiS_Pr)) continue;                                 /* Set start condition */
8792      temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr);      /* Write DAB (S0=0=write) */
8793      if(temp) continue;                                                 /*    (ERROR: no ack) */
8794      temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor));                    /* Write RAB (700x: set bit 7, see datasheet) */
8795      if(temp) continue;                                                 /*    (ERROR: no ack) */
8796      temp = SiS_WriteDDC2Data(SiS_Pr, val);                             /* Write data */
8797      if(temp) continue;                                                 /*    (ERROR: no ack) */
8798      if(SiS_SetStop(SiS_Pr)) continue;                                  /* Set stop condition */
8799      SiS_Pr->SiS_ChrontelInit = 1;
8800      return true;
8801   }
8802   return false;
8803 }
8804
8805 /* Write to Chrontel 700x */
8806 void
8807 SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
8808 {
8809   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
8810
8811   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8812
8813   if(!(SiS_Pr->SiS_ChrontelInit)) {
8814      SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
8815      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
8816      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
8817      SiS_SetupDDCN(SiS_Pr);
8818   }
8819
8820   if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
8821       (!(SiS_Pr->SiS_ChrontelInit)) ) {
8822      SiS_Pr->SiS_DDC_Index = 0x0a;
8823      SiS_Pr->SiS_DDC_Data  = 0x80;
8824      SiS_Pr->SiS_DDC_Clk   = 0x40;
8825      SiS_SetupDDCN(SiS_Pr);
8826
8827      SiS_SetChReg(SiS_Pr, reg, val, 0x80);
8828   }
8829 }
8830
8831 /* Write to Chrontel 701x */
8832 /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
8833 void
8834 SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
8835 {
8836   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
8837   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
8838   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
8839   SiS_SetupDDCN(SiS_Pr);
8840   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
8841   SiS_SetChReg(SiS_Pr, reg, val, 0);
8842 }
8843
8844 static
8845 void
8846 SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
8847 {
8848   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
8849      SiS_SetCH700x(SiS_Pr, reg, val);
8850   else
8851      SiS_SetCH701x(SiS_Pr, reg, val);
8852 }
8853
8854 static unsigned short
8855 SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
8856 {
8857   unsigned short tempah, temp, i;
8858
8859   for(i=0; i<20; i++) {                         /* Do 20 attempts to read */
8860      if(i) {
8861         SiS_SetStop(SiS_Pr);
8862         SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
8863      }
8864      if(SiS_SetStart(SiS_Pr)) continue;                                 /* Set start condition */
8865      temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr);       /* Write DAB (S0=0=write) */
8866      if(temp) continue;                                                 /*        (ERROR: no ack) */
8867      temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor);  /* Write RAB (700x: | 0x80) */
8868      if(temp) continue;                                                 /*        (ERROR: no ack) */
8869      if (SiS_SetStart(SiS_Pr)) continue;                                /* Re-start */
8870      temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
8871      if(temp) continue;                                                 /*        (ERROR: no ack) */
8872      tempah = SiS_ReadDDC2Data(SiS_Pr);                                 /* Read byte */
8873      if(SiS_SetStop(SiS_Pr)) continue;                                  /* Stop condition */
8874      SiS_Pr->SiS_ChrontelInit = 1;
8875      return tempah;
8876   }
8877   return 0xFFFF;
8878 }
8879
8880 /* Read from Chrontel 700x */
8881 /* Parameter is [Register no (S7-S0)] */
8882 unsigned short
8883 SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
8884 {
8885   unsigned short result;
8886
8887   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
8888
8889   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
8890
8891   if(!(SiS_Pr->SiS_ChrontelInit)) {
8892      SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
8893      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
8894      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
8895      SiS_SetupDDCN(SiS_Pr);
8896   }
8897
8898   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8899
8900   if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
8901       (!SiS_Pr->SiS_ChrontelInit) ) {
8902
8903      SiS_Pr->SiS_DDC_Index = 0x0a;
8904      SiS_Pr->SiS_DDC_Data  = 0x80;
8905      SiS_Pr->SiS_DDC_Clk   = 0x40;
8906      SiS_SetupDDCN(SiS_Pr);
8907
8908      result = SiS_GetChReg(SiS_Pr,0x80);
8909   }
8910   return result;
8911 }
8912
8913 /* Read from Chrontel 701x */
8914 /* Parameter is [Register no (S7-S0)] */
8915 unsigned short
8916 SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
8917 {
8918   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
8919   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
8920   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
8921   SiS_SetupDDCN(SiS_Pr);
8922   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
8923
8924   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
8925
8926   return SiS_GetChReg(SiS_Pr,0);
8927 }
8928
8929 /* Read from Chrontel 70xx */
8930 /* Parameter is [Register no (S7-S0)] */
8931 static
8932 unsigned short
8933 SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
8934 {
8935   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
8936      return SiS_GetCH700x(SiS_Pr, tempbx);
8937   else
8938      return SiS_GetCH701x(SiS_Pr, tempbx);
8939 }
8940
8941 void
8942 SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
8943                 unsigned char myor, unsigned short myand)
8944 {
8945   unsigned short tempbl;
8946
8947   tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
8948   SiS_SetCH70xx(SiS_Pr, reg, tempbl);
8949 }
8950
8951 /* Our own DDC functions */
8952 static
8953 unsigned short
8954 SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
8955                 unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
8956                 unsigned int VBFlags2)
8957 {
8958      unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
8959      unsigned char flag, cr32;
8960      unsigned short        temp = 0, myadaptnum = adaptnum;
8961
8962      if(adaptnum != 0) {
8963         if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
8964         if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
8965      }
8966
8967      /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
8968
8969      SiS_Pr->SiS_ChrontelInit = 0;   /* force re-detection! */
8970
8971      SiS_Pr->SiS_DDC_SecAddr = 0;
8972      SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
8973      SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
8974      SiS_Pr->SiS_DDC_Index = 0x11;
8975      flag = 0xff;
8976
8977      cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
8978
8979 #if 0
8980      if(VBFlags2 & VB2_SISBRIDGE) {
8981         if(myadaptnum == 0) {
8982            if(!(cr32 & 0x20)) {
8983               myadaptnum = 2;
8984               if(!(cr32 & 0x10)) {
8985                  myadaptnum = 1;
8986                  if(!(cr32 & 0x08)) {
8987                     myadaptnum = 0;
8988                  }
8989               }
8990            }
8991         }
8992      }
8993 #endif
8994
8995      if(VGAEngine == SIS_300_VGA) {             /* 300 series */
8996
8997         if(myadaptnum != 0) {
8998            flag = 0;
8999            if(VBFlags2 & VB2_SISBRIDGE) {
9000               SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9001               SiS_Pr->SiS_DDC_Index = 0x0f;
9002            }
9003         }
9004
9005         if(!(VBFlags2 & VB2_301)) {
9006            if((cr32 & 0x80) && (checkcr32)) {
9007               if(myadaptnum >= 1) {
9008                  if(!(cr32 & 0x08)) {
9009                      myadaptnum = 1;
9010                      if(!(cr32 & 0x10)) return 0xFFFF;
9011                  }
9012               }
9013            }
9014         }
9015
9016         temp = 4 - (myadaptnum * 2);
9017         if(flag) temp = 0;
9018
9019      } else {                                           /* 315/330 series */
9020
9021         /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
9022
9023         if(VBFlags2 & VB2_SISBRIDGE) {
9024            if(myadaptnum == 2) {
9025               myadaptnum = 1;
9026            }
9027         }
9028
9029         if(myadaptnum == 1) {
9030            flag = 0;
9031            if(VBFlags2 & VB2_SISBRIDGE) {
9032               SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9033               SiS_Pr->SiS_DDC_Index = 0x0f;
9034            }
9035         }
9036
9037         if((cr32 & 0x80) && (checkcr32)) {
9038            if(myadaptnum >= 1) {
9039               if(!(cr32 & 0x08)) {
9040                  myadaptnum = 1;
9041                  if(!(cr32 & 0x10)) return 0xFFFF;
9042               }
9043            }
9044         }
9045
9046         temp = myadaptnum;
9047         if(myadaptnum == 1) {
9048            temp = 0;
9049            if(VBFlags2 & VB2_LVDS) flag = 0xff;
9050         }
9051
9052         if(flag) temp = 0;
9053     }
9054
9055     SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9056     SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
9057
9058     SiS_SetupDDCN(SiS_Pr);
9059
9060     return 0;
9061 }
9062
9063 static unsigned short
9064 SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
9065 {
9066    if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9067    if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
9068       return 0xFFFF;
9069    }
9070    if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
9071       return 0xFFFF;
9072    }
9073    return 0;
9074 }
9075
9076 static unsigned short
9077 SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
9078 {
9079    if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9080    if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
9081       return 0xFFFF;
9082    }
9083    return 0;
9084 }
9085
9086 static unsigned short
9087 SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
9088 {
9089    if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
9090    if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
9091    return 0;
9092 }
9093
9094 static void
9095 SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
9096 {
9097    SiS_SetSCLKLow(SiS_Pr);
9098    if(yesno) {
9099       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9100                       SiS_Pr->SiS_DDC_Index,
9101                       SiS_Pr->SiS_DDC_NData,
9102                       SiS_Pr->SiS_DDC_Data);
9103    } else {
9104       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9105                       SiS_Pr->SiS_DDC_Index,
9106                       SiS_Pr->SiS_DDC_NData,
9107                       0);
9108    }
9109    SiS_SetSCLKHigh(SiS_Pr);
9110 }
9111
9112 static unsigned short
9113 SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
9114 {
9115     unsigned char mask, value;
9116     unsigned short  temp, ret=0;
9117     bool failed = false;
9118
9119     SiS_SetSwitchDDC2(SiS_Pr);
9120     if(SiS_PrepareDDC(SiS_Pr)) {
9121          SiS_SetStop(SiS_Pr);
9122          return 0xFFFF;
9123     }
9124     mask = 0xf0;
9125     value = 0x20;
9126     if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9127        temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9128        SiS_SendACK(SiS_Pr, 0);
9129        if(temp == 0) {
9130            mask = 0xff;
9131            value = 0xff;
9132        } else {
9133            failed = true;
9134            ret = 0xFFFF;
9135        }
9136     }
9137     if(!failed) {
9138        temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9139        SiS_SendACK(SiS_Pr, 1);
9140        temp &= mask;
9141        if(temp == value) ret = 0;
9142        else {
9143           ret = 0xFFFF;
9144           if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9145              if(temp == 0x30) ret = 0;
9146           }
9147        }
9148     }
9149     SiS_SetStop(SiS_Pr);
9150     return ret;
9151 }
9152
9153 static
9154 unsigned short
9155 SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
9156 {
9157    unsigned short flag;
9158
9159    flag = 0x180;
9160    SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9161    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9162    SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9163    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9164    SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9165    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9166    if(!(flag & 0x1a)) flag = 0;
9167    return flag;
9168 }
9169
9170 static
9171 unsigned short
9172 SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
9173 {
9174    unsigned short flag, length, i;
9175    unsigned char chksum,gotcha;
9176
9177    if(DDCdatatype > 4) return 0xFFFF;
9178
9179    flag = 0;
9180    SiS_SetSwitchDDC2(SiS_Pr);
9181    if(!(SiS_PrepareDDC(SiS_Pr))) {
9182       length = 127;
9183       if(DDCdatatype != 1) length = 255;
9184       chksum = 0;
9185       gotcha = 0;
9186       for(i=0; i<length; i++) {
9187          buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9188          chksum += buffer[i];
9189          gotcha |= buffer[i];
9190          SiS_SendACK(SiS_Pr, 0);
9191       }
9192       buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
9193       chksum += buffer[i];
9194       SiS_SendACK(SiS_Pr, 1);
9195       if(gotcha) flag = (unsigned short)chksum;
9196       else flag = 0xFFFF;
9197    } else {
9198       flag = 0xFFFF;
9199    }
9200    SiS_SetStop(SiS_Pr);
9201    return flag;
9202 }
9203
9204 /* Our private DDC functions
9205
9206    It complies somewhat with the corresponding VESA function
9207    in arguments and return values.
9208
9209    Since this is probably called before the mode is changed,
9210    we use our pre-detected pSiS-values instead of SiS_Pr as
9211    regards chipset and video bridge type.
9212
9213    Arguments:
9214        adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9215                  CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9216                  LCDA is CRT1, but DDC is read from CRT2 port.
9217        DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9218        buffer: ptr to 256 data bytes which will be filled with read data.
9219
9220    Returns 0xFFFF if error, otherwise
9221        if DDCdatatype > 0:  Returns 0 if reading OK (included a correct checksum)
9222        if DDCdatatype = 0:  Returns supported DDC modes
9223
9224  */
9225 unsigned short
9226 SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
9227               unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
9228               unsigned int VBFlags2)
9229 {
9230    unsigned char  sr1f, cr17=1;
9231    unsigned short result;
9232
9233    if(adaptnum > 2)
9234       return 0xFFFF;
9235
9236    if(DDCdatatype > 4)
9237       return 0xFFFF;
9238
9239    if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
9240       return 0xFFFF;
9241
9242    if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
9243       return 0xFFFF;
9244
9245    sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9246    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9247    if(VGAEngine == SIS_300_VGA) {
9248       cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9249       if(!cr17) {
9250          SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9251          SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9252          SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9253       }
9254    }
9255    if((sr1f) || (!cr17)) {
9256       SiS_WaitRetrace1(SiS_Pr);
9257       SiS_WaitRetrace1(SiS_Pr);
9258       SiS_WaitRetrace1(SiS_Pr);
9259       SiS_WaitRetrace1(SiS_Pr);
9260    }
9261
9262    if(DDCdatatype == 0) {
9263       result = SiS_ProbeDDC(SiS_Pr);
9264    } else {
9265       result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9266       if((!result) && (DDCdatatype == 1)) {
9267          if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9268             (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9269             (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9270             (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9271             (buffer[0x12] == 1)) {
9272             if(!SiS_Pr->DDCPortMixup) {
9273                if(adaptnum == 1) {
9274                   if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9275                } else {
9276                   if(buffer[0x14] & 0x80)    result = 0xFFFE;
9277                }
9278             }
9279          }
9280       }
9281    }
9282    SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9283    if(VGAEngine == SIS_300_VGA) {
9284       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9285    }
9286    return result;
9287 }
9288
9289 /* Generic I2C functions for Chrontel & DDC --------- */
9290
9291 static void
9292 SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
9293 {
9294   SiS_SetSCLKHigh(SiS_Pr);
9295   SiS_WaitRetrace1(SiS_Pr);
9296
9297   SiS_SetSCLKLow(SiS_Pr);
9298   SiS_WaitRetrace1(SiS_Pr);
9299 }
9300
9301 unsigned short
9302 SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
9303 {
9304    SiS_WaitRetrace1(SiS_Pr);
9305    return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
9306 }
9307
9308 /* Set I2C start condition */
9309 /* This is done by a SD high-to-low transition while SC is high */
9310 static unsigned short
9311 SiS_SetStart(struct SiS_Private *SiS_Pr)
9312 {
9313   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                     /* (SC->low)  */
9314   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9315                   SiS_Pr->SiS_DDC_Index,
9316                   SiS_Pr->SiS_DDC_NData,
9317                   SiS_Pr->SiS_DDC_Data);                        /* SD->high */
9318   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* SC->high */
9319   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9320                   SiS_Pr->SiS_DDC_Index,
9321                   SiS_Pr->SiS_DDC_NData,
9322                   0x00);                                        /* SD->low = start condition */
9323   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* (SC->low) */
9324   return 0;
9325 }
9326
9327 /* Set I2C stop condition */
9328 /* This is done by a SD low-to-high transition while SC is high */
9329 static unsigned short
9330 SiS_SetStop(struct SiS_Private *SiS_Pr)
9331 {
9332   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                     /* (SC->low) */
9333   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9334                   SiS_Pr->SiS_DDC_Index,
9335                   SiS_Pr->SiS_DDC_NData,
9336                   0x00);                                        /* SD->low   */
9337   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* SC->high  */
9338   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9339                   SiS_Pr->SiS_DDC_Index,
9340                   SiS_Pr->SiS_DDC_NData,
9341                   SiS_Pr->SiS_DDC_Data);                        /* SD->high = stop condition */
9342   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                    /* (SC->high) */
9343   return 0;
9344 }
9345
9346 /* Write 8 bits of data */
9347 static unsigned short
9348 SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
9349 {
9350   unsigned short i,flag,temp;
9351
9352   flag = 0x80;
9353   for(i = 0; i < 8; i++) {
9354     SiS_SetSCLKLow(SiS_Pr);                                     /* SC->low */
9355     if(tempax & flag) {
9356       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9357                       SiS_Pr->SiS_DDC_Index,
9358                       SiS_Pr->SiS_DDC_NData,
9359                       SiS_Pr->SiS_DDC_Data);                    /* Write bit (1) to SD */
9360     } else {
9361       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9362                       SiS_Pr->SiS_DDC_Index,
9363                       SiS_Pr->SiS_DDC_NData,
9364                       0x00);                                    /* Write bit (0) to SD */
9365     }
9366     SiS_SetSCLKHigh(SiS_Pr);                                    /* SC->high */
9367     flag >>= 1;
9368   }
9369   temp = SiS_CheckACK(SiS_Pr);                                  /* Check acknowledge */
9370   return temp;
9371 }
9372
9373 static unsigned short
9374 SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
9375 {
9376   unsigned short i, temp, getdata;
9377
9378   getdata = 0;
9379   for(i = 0; i < 8; i++) {
9380     getdata <<= 1;
9381     SiS_SetSCLKLow(SiS_Pr);
9382     SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9383                     SiS_Pr->SiS_DDC_Index,
9384                     SiS_Pr->SiS_DDC_NData,
9385                     SiS_Pr->SiS_DDC_Data);
9386     SiS_SetSCLKHigh(SiS_Pr);
9387     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9388     if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
9389   }
9390   return getdata;
9391 }
9392
9393 static unsigned short
9394 SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
9395 {
9396   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9397                   SiS_Pr->SiS_DDC_Index,
9398                   SiS_Pr->SiS_DDC_NClk,
9399                   0x00);                                        /* SetSCLKLow()  */
9400   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9401   return 0;
9402 }
9403
9404 static unsigned short
9405 SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
9406 {
9407   unsigned short temp, watchdog=1000;
9408
9409   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9410                   SiS_Pr->SiS_DDC_Index,
9411                   SiS_Pr->SiS_DDC_NClk,
9412                   SiS_Pr->SiS_DDC_Clk);                         /* SetSCLKHigh()  */
9413   do {
9414     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
9415   } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
9416   if (!watchdog) {
9417         return 0xFFFF;
9418   }
9419   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9420   return 0;
9421 }
9422
9423 /* Check I2C acknowledge */
9424 /* Returns 0 if ack ok, non-0 if ack not ok */
9425 static unsigned short
9426 SiS_CheckACK(struct SiS_Private *SiS_Pr)
9427 {
9428   unsigned short tempah;
9429
9430   SiS_SetSCLKLow(SiS_Pr);                                          /* (SC->low) */
9431   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9432                   SiS_Pr->SiS_DDC_Index,
9433                   SiS_Pr->SiS_DDC_NData,
9434                   SiS_Pr->SiS_DDC_Data);                           /* (SD->high) */
9435   SiS_SetSCLKHigh(SiS_Pr);                                         /* SC->high = clock impulse for ack */
9436   tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
9437   SiS_SetSCLKLow(SiS_Pr);                                          /* SC->low = end of clock impulse */
9438   if(tempah & SiS_Pr->SiS_DDC_Data) return 1;                      /* Ack OK if bit = 0 */
9439   return 0;
9440 }
9441
9442 /* End of I2C functions ----------------------- */
9443
9444
9445 /* =============== SiS 315/330 O.E.M. ================= */
9446
9447 #ifdef CONFIG_FB_SIS_315
9448
9449 static unsigned short
9450 GetRAMDACromptr(struct SiS_Private *SiS_Pr)
9451 {
9452   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9453   unsigned short romptr;
9454
9455   if(SiS_Pr->ChipType < SIS_330) {
9456      romptr = SISGETROMW(0x128);
9457      if(SiS_Pr->SiS_VBType & VB_SIS30xB)
9458         romptr = SISGETROMW(0x12a);
9459   } else {
9460      romptr = SISGETROMW(0x1a8);
9461      if(SiS_Pr->SiS_VBType & VB_SIS30xB)
9462         romptr = SISGETROMW(0x1aa);
9463   }
9464   return romptr;
9465 }
9466
9467 static unsigned short
9468 GetLCDromptr(struct SiS_Private *SiS_Pr)
9469 {
9470   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9471   unsigned short romptr;
9472
9473   if(SiS_Pr->ChipType < SIS_330) {
9474      romptr = SISGETROMW(0x120);
9475      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9476         romptr = SISGETROMW(0x122);
9477   } else {
9478      romptr = SISGETROMW(0x1a0);
9479      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9480         romptr = SISGETROMW(0x1a2);
9481   }
9482   return romptr;
9483 }
9484
9485 static unsigned short
9486 GetTVromptr(struct SiS_Private *SiS_Pr)
9487 {
9488   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9489   unsigned short romptr;
9490
9491   if(SiS_Pr->ChipType < SIS_330) {
9492      romptr = SISGETROMW(0x114);
9493      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9494         romptr = SISGETROMW(0x11a);
9495   } else {
9496      romptr = SISGETROMW(0x194);
9497      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
9498         romptr = SISGETROMW(0x19a);
9499   }
9500   return romptr;
9501 }
9502
9503 static unsigned short
9504 GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
9505 {
9506   unsigned short index;
9507
9508   if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9509      if(!(SiS_IsNotM650orLater(SiS_Pr))) {
9510         if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
9511            index >>= 4;
9512            index *= 3;
9513            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9514            else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9515            return index;
9516         }
9517      }
9518   }
9519
9520   index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
9521   if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
9522   if(SiS_Pr->SiS_VBType & VB_SIS301C) {  /* 1.15.20 and later (not VB specific) */
9523      if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
9524      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
9525   } else {
9526      if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
9527   }
9528   index--;
9529   index *= 3;
9530   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
9531   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9532   return index;
9533 }
9534
9535 static unsigned short
9536 GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
9537 {
9538   unsigned short index;
9539
9540   index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
9541   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
9542   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
9543   return index;
9544 }
9545
9546 static unsigned short
9547 GetTVPtrIndex(struct SiS_Private *SiS_Pr)
9548 {
9549   unsigned short index;
9550
9551   index = 0;
9552   if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
9553   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
9554
9555   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
9556
9557   index <<= 1;
9558
9559   if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
9560      (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9561      index++;
9562   }
9563
9564   return index;
9565 }
9566
9567 static unsigned int
9568 GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
9569 {
9570    unsigned short index = 0, temp = 0;
9571
9572    if(SiS_Pr->SiS_TVMode & TVSetPAL)   index = 1;
9573    if(SiS_Pr->SiS_TVMode & TVSetPALM)  index = 2;
9574    if(SiS_Pr->SiS_TVMode & TVSetPALN)  index = 3;
9575    if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
9576    if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
9577       index = 4;
9578       if(SiS_Pr->SiS_TVMode & TVSetPALM)  index++;
9579       if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
9580    }
9581
9582    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
9583       if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
9584          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
9585          index += addme;
9586          temp++;
9587       }
9588       temp += 0x0100;
9589    }
9590    return (unsigned int)(index | (temp << 16));
9591 }
9592
9593 static unsigned int
9594 GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
9595 {
9596    return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
9597 }
9598
9599 #if 0
9600 static unsigned int
9601 GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
9602 {
9603    return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
9604 }
9605 #endif
9606
9607 static int
9608 GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
9609 {
9610    int index = 0;
9611
9612    if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
9613    if(SiS_Pr->SiS_ROMNew) {
9614       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
9615       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
9616       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
9617       if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
9618    } else {
9619       if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
9620       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
9621       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
9622       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
9623    }
9624
9625    if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
9626
9627    return index;
9628 }
9629
9630 static void
9631 SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
9632 {
9633   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9634   unsigned short delay=0,index,myindex,temp,romptr=0;
9635   bool dochiptest = true;
9636
9637   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9638      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
9639   } else {
9640      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
9641   }
9642
9643   /* Find delay (from ROM, internal tables, PCI subsystem) */
9644
9645   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {                    /* ------------ VGA */
9646
9647      if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9648         romptr = GetRAMDACromptr(SiS_Pr);
9649      }
9650      if(romptr) delay = ROMAddr[romptr];
9651      else {
9652         delay = 0x04;
9653         if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
9654            if(IS_SIS650) {
9655               delay = 0x0a;
9656            } else if(IS_SIS740) {
9657               delay = 0x00;
9658            } else if(SiS_Pr->ChipType < SIS_330) {
9659               delay = 0x0c;
9660            } else {
9661               delay = 0x0c;
9662            }
9663         } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9664            delay = 0x00;
9665         }
9666      }
9667
9668   } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {  /* ---------- LCD/LCDA */
9669
9670      bool gotitfrompci = false;
9671
9672      /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
9673
9674      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
9675         if(SiS_Pr->PDC != -1) {
9676            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
9677            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
9678            return;
9679         }
9680      } else {
9681         if(SiS_Pr->PDCA != -1) {
9682            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
9683            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
9684            return;
9685         }
9686      }
9687
9688      /* Custom Panel? */
9689
9690      if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
9691         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9692            delay = 0x00;
9693            if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
9694               delay = 0x20;
9695            }
9696            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
9697         } else {
9698            delay = 0x0c;
9699            if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9700               delay = 0x03;
9701               if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
9702                  delay = 0x00;
9703               }
9704            } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
9705               if(IS_SIS740) delay = 0x01;
9706               else          delay = 0x03;
9707            }
9708            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
9709         }
9710         return;
9711      }
9712
9713      /* This is a piece of typical SiS crap: They code the OEM LCD
9714       * delay into the code, at no defined place in the BIOS.
9715       * We now have to start doing a PCI subsystem check here.
9716       */
9717
9718      switch(SiS_Pr->SiS_CustomT) {
9719      case CUT_COMPAQ1280:
9720      case CUT_COMPAQ12802:
9721         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
9722            gotitfrompci = true;
9723            dochiptest = false;
9724            delay = 0x03;
9725         }
9726         break;
9727      case CUT_CLEVO1400:
9728      case CUT_CLEVO14002:
9729         gotitfrompci = true;
9730         dochiptest = false;
9731         delay = 0x02;
9732         break;
9733      case CUT_CLEVO1024:
9734      case CUT_CLEVO10242:
9735         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
9736            gotitfrompci = true;
9737            dochiptest = false;
9738            delay = 0x33;
9739            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9740            delay &= 0x0f;
9741         }
9742         break;
9743      }
9744
9745      /* Could we find it through the PCI ID? If no, use ROM or table */
9746
9747      if(!gotitfrompci) {
9748
9749         index = GetLCDPtrIndexBIOS(SiS_Pr);
9750         myindex = GetLCDPtrIndex(SiS_Pr);
9751
9752         if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9753
9754            if(SiS_IsNotM650orLater(SiS_Pr)) {
9755
9756               if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9757                  /* Always use the second pointer on 650; some BIOSes */
9758                  /* still carry old 301 data at the first location    */
9759                  /* romptr = SISGETROMW(0x120);                       */
9760                  /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
9761                  romptr = SISGETROMW(0x122);
9762                  if(!romptr) return;
9763                  delay = ROMAddr[(romptr + index)];
9764               } else {
9765                  delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9766               }
9767
9768           } else {
9769
9770              delay = SiS310_LCDDelayCompensation_651301LV[myindex];
9771              if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
9772                 delay = SiS310_LCDDelayCompensation_651302LV[myindex];
9773
9774           }
9775
9776         } else if(SiS_Pr->SiS_UseROM                          &&
9777                   (!(SiS_Pr->SiS_ROMNew))                     &&
9778                   (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
9779                   (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
9780                   (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)  &&
9781                   (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)  &&
9782                   ((romptr = GetLCDromptr(SiS_Pr)))) {
9783
9784            /* Data for 1280x1024 wrong in 301B BIOS */
9785            /* Data for 1600x1200 wrong in 301C BIOS */
9786            delay = ROMAddr[(romptr + index)];
9787
9788         } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9789
9790            if(IS_SIS740) delay = 0x03;
9791            else          delay = 0x00;
9792
9793         } else {
9794
9795            delay = SiS310_LCDDelayCompensation_301[myindex];
9796            if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
9797               if(IS_SIS740) delay = 0x01;
9798               else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
9799               else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
9800            } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
9801               if(IS_SIS740) delay = 0x01;  /* ? */
9802               else          delay = 0x03;
9803               if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
9804            } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
9805               if(IS_SIS740) delay = 0x01;
9806               else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
9807            }
9808
9809         }
9810
9811      }  /* got it from PCI */
9812
9813      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
9814         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
9815         dochiptest = false;
9816      }
9817
9818   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 /* ------------ TV */
9819
9820      index = GetTVPtrIndex(SiS_Pr);
9821
9822      if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
9823
9824         if(SiS_IsNotM650orLater(SiS_Pr)) {
9825
9826            if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9827               /* Always use the second pointer on 650; some BIOSes */
9828               /* still carry old 301 data at the first location    */
9829               /* romptr = SISGETROMW(0x114);                       */
9830               /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
9831               romptr = SISGETROMW(0x11a);
9832               if(!romptr) return;
9833               delay = ROMAddr[romptr + index];
9834
9835            } else {
9836
9837               delay = SiS310_TVDelayCompensation_301B[index];
9838
9839            }
9840
9841         } else {
9842
9843            switch(SiS_Pr->SiS_CustomT) {
9844            case CUT_COMPAQ1280:
9845            case CUT_COMPAQ12802:
9846            case CUT_CLEVO1400:
9847            case CUT_CLEVO14002:
9848               delay = 0x02;
9849               dochiptest = false;
9850               break;
9851            case CUT_CLEVO1024:
9852            case CUT_CLEVO10242:
9853               delay = 0x03;
9854               dochiptest = false;
9855               break;
9856            default:
9857               delay = SiS310_TVDelayCompensation_651301LV[index];
9858               if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
9859                  delay = SiS310_TVDelayCompensation_651302LV[index];
9860               }
9861            }
9862         }
9863
9864      } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
9865
9866         romptr = GetTVromptr(SiS_Pr);
9867         if(!romptr) return;
9868         delay = ROMAddr[romptr + index];
9869
9870      } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
9871
9872         delay = SiS310_TVDelayCompensation_LVDS[index];
9873
9874      } else {
9875
9876         delay = SiS310_TVDelayCompensation_301[index];
9877         if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
9878            if(IS_SIS740) {
9879               delay = SiS310_TVDelayCompensation_740301B[index];
9880               /* LV: use 301 data? BIOS bug? */
9881            } else {
9882               delay = SiS310_TVDelayCompensation_301B[index];
9883               if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
9884            }
9885         }
9886
9887      }
9888
9889      if(SiS_LCDAEnabled(SiS_Pr)) {
9890         delay &= 0x0f;
9891         dochiptest = false;
9892      }
9893
9894   } else return;
9895
9896   /* Write delay */
9897
9898   if(SiS_Pr->SiS_VBType & VB_SISVB) {
9899
9900      if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
9901
9902         temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
9903         if(temp == 8) {         /* 1400x1050 BIOS (COMPAL) */
9904            delay &= 0x0f;
9905            delay |= 0xb0;
9906         } else if(temp == 6) {
9907            delay &= 0x0f;
9908            delay |= 0xc0;
9909         } else if(temp > 7) {   /* 1280x1024 BIOS (which one?) */
9910            delay = 0x35;
9911         }
9912         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
9913
9914      } else {
9915
9916         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9917
9918      }
9919
9920   } else {  /* LVDS */
9921
9922      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
9923         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9924      } else {
9925         if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
9926            delay <<= 4;
9927            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
9928         } else {
9929            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
9930         }
9931      }
9932
9933   }
9934
9935 }
9936
9937 static void
9938 SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
9939 {
9940   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9941   unsigned short index,temp,temp1,romptr=0;
9942
9943   if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
9944
9945   if(ModeNo<=0x13)
9946      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
9947   else
9948      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
9949
9950   temp = GetTVPtrIndex(SiS_Pr);
9951   temp >>= 1;     /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9952   temp1 = temp;
9953
9954   if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
9955      if(SiS_Pr->ChipType >= SIS_661) {
9956         temp1 = GetOEMTVPtr661(SiS_Pr);
9957         temp1 >>= 1;
9958         romptr = SISGETROMW(0x260);
9959         if(SiS_Pr->ChipType >= SIS_760) {
9960            romptr = SISGETROMW(0x360);
9961         }
9962      } else if(SiS_Pr->ChipType >= SIS_330) {
9963         romptr = SISGETROMW(0x192);
9964      } else {
9965         romptr = SISGETROMW(0x112);
9966      }
9967   }
9968
9969   if(romptr) {
9970      temp1 <<= 1;
9971      temp = ROMAddr[romptr + temp1 + index];
9972   } else {
9973      temp = SiS310_TVAntiFlick1[temp][index];
9974   }
9975   temp <<= 4;
9976
9977   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp);  /* index 0A D[6:4] */
9978 }
9979
9980 static void
9981 SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
9982 {
9983   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
9984   unsigned short index,temp,temp1,romptr=0;
9985
9986   temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1;    /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
9987
9988   if(ModeNo <= 0x13)
9989      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
9990   else
9991      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
9992
9993   if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
9994      if(SiS_Pr->ChipType >= SIS_661) {
9995         romptr = SISGETROMW(0x26c);
9996         if(SiS_Pr->ChipType >= SIS_760) {
9997            romptr = SISGETROMW(0x36c);
9998         }
9999         temp1 = GetOEMTVPtr661(SiS_Pr);
10000         temp1 >>= 1;
10001      } else if(SiS_Pr->ChipType >= SIS_330) {
10002         romptr = SISGETROMW(0x1a4);
10003      } else {
10004         romptr = SISGETROMW(0x124);
10005      }
10006   }
10007
10008   if(romptr) {
10009      temp1 <<= 1;
10010      temp = ROMAddr[romptr + temp1 + index];
10011   } else {
10012      temp = SiS310_TVEdge1[temp][index];
10013   }
10014   temp <<= 5;
10015   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp);  /* index 0A D[7:5] */
10016 }
10017
10018 static void
10019 SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
10020 {
10021   unsigned short index, temp, i, j;
10022
10023   if(ModeNo <= 0x13) {
10024      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
10025   } else {
10026      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
10027   }
10028
10029   temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
10030
10031   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)        temp = 1;  /* NTSC-J uses PAL */
10032   else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
10033   else if(SiS_Pr->SiS_TVMode & TVSetPALN)    temp = 4;  /* PAL-N */
10034   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1;  /* HiVision uses PAL */
10035
10036   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10037      for(i=0x35, j=0; i<=0x38; i++, j++) {
10038         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10039      }
10040      for(i=0x48; i<=0x4A; i++, j++) {
10041         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
10042      }
10043   } else {
10044      for(i=0x35, j=0; i<=0x38; i++, j++) {
10045         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
10046      }
10047   }
10048 }
10049
10050 static void
10051 SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10052 {
10053   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10054   unsigned short index,temp,i,j,resinfo,romptr=0;
10055   unsigned int  lindex;
10056
10057   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
10058
10059   /* NTSC-J data not in BIOS, and already set in SetGroup2 */
10060   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
10061
10062   if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
10063      lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
10064      lindex <<= 2;
10065      for(j=0, i=0x31; i<=0x34; i++, j++) {
10066         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
10067      }
10068      return;
10069   }
10070
10071   /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
10072   if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
10073
10074   if(ModeNo<=0x13) {
10075      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10076   } else {
10077      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10078   }
10079
10080   temp = GetTVPtrIndex(SiS_Pr);
10081   /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
10082    * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
10083    */
10084   if(SiS_Pr->SiS_UseROM) {
10085      romptr = SISGETROMW(0x116);
10086      if(SiS_Pr->ChipType >= SIS_330) {
10087         romptr = SISGETROMW(0x196);
10088      }
10089      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10090         romptr = SISGETROMW(0x11c);
10091         if(SiS_Pr->ChipType >= SIS_330) {
10092            romptr = SISGETROMW(0x19c);
10093         }
10094         if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
10095            romptr = SISGETROMW(0x116);
10096            if(SiS_Pr->ChipType >= SIS_330) {
10097               romptr = SISGETROMW(0x196);
10098            }
10099         }
10100      }
10101   }
10102   if(romptr) {
10103      romptr += (temp << 2);
10104      for(j=0, i=0x31; i<=0x34; i++, j++) {
10105         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10106      }
10107   } else {
10108      index = temp % 2;
10109      temp >>= 1;          /* 0:NTSC, 1:PAL, 2:HiTV */
10110      for(j=0, i=0x31; i<=0x34; i++, j++) {
10111         if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
10112            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10113         else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
10114            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
10115         else
10116            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
10117      }
10118   }
10119
10120   if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
10121      if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
10122         if((resinfo == SIS_RI_640x480) ||
10123            (resinfo == SIS_RI_800x600)) {
10124            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
10125            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
10126            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
10127            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
10128         } else if(resinfo == SIS_RI_1024x768) {
10129            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
10130            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
10131            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
10132            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
10133         }
10134      }
10135   }
10136 }
10137
10138 static void
10139 SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10140                 unsigned short ModeIdIndex, unsigned short RTI)
10141 {
10142    unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
10143    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10144
10145    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
10146       return;
10147
10148    /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
10149    /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
10150
10151    if(SiS_Pr->SiS_ROMNew) {
10152       if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)                         ||
10153          ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
10154           (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
10155          index = 25;
10156          if(SiS_Pr->UseCustomMode) {
10157             index = SiS_Pr->CSRClock;
10158          } else if(ModeNo > 0x13) {
10159             index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
10160             index = SiS_Pr->SiS_VCLKData[index].CLOCK;
10161          }
10162          if(index < 25) index = 25;
10163          index = ((index / 25) - 1) << 1;
10164          if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
10165             index++;
10166          }
10167          romptr = SISGETROMW(0x104);
10168          delay = ROMAddr[romptr + index];
10169          if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
10170             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10171             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10172          } else {
10173             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10174             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10175          }
10176          return;
10177       }
10178    }
10179
10180    /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
10181
10182    if(SiS_Pr->UseCustomMode) delay = 0x04;
10183    else if(ModeNo <= 0x13)   delay = 0x04;
10184    else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
10185    delay |= (delay << 8);
10186
10187    if(SiS_Pr->ChipType >= XGI_20) {
10188
10189       delay = 0x0606;
10190       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10191
10192          delay = 0x0404;
10193          if(SiS_Pr->SiS_XGIROM) {
10194              index = GetTVPtrIndex(SiS_Pr);
10195              if((romptr = SISGETROMW(0x35e))) {
10196                 delay = (ROMAddr[romptr + index] & 0x0f) << 1;
10197                 delay |= (delay << 8);
10198              }
10199          }
10200
10201          if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
10202             if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
10203                delay -= 0x0404;
10204             }
10205          }
10206       }
10207
10208    } else if(SiS_Pr->ChipType >= SIS_340) {
10209
10210       delay = 0x0606;
10211       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10212          delay = 0x0404;
10213       }
10214       /* TODO (eventually) */
10215
10216    } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10217
10218       /* 3. TV */
10219
10220       index = GetOEMTVPtr661(SiS_Pr);
10221       if(SiS_Pr->SiS_ROMNew) {
10222          romptr = SISGETROMW(0x106);
10223          if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
10224          delay = ROMAddr[romptr + index];
10225       } else {
10226          delay = 0x04;
10227          if(index > 3) delay = 0;
10228       }
10229
10230    } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10231
10232       /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
10233
10234       if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
10235           ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
10236
10237          lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
10238
10239          /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
10240          delay = ROMAddr[romptr + lcdpdcindex + 1];     /* LCD  */
10241          delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
10242
10243       } else {
10244
10245          /* TMDS: Set our own, since BIOS has no idea */
10246          /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
10247          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10248             switch(SiS_Pr->SiS_LCDResInfo) {
10249             case Panel_1024x768:  delay = 0x0008; break;
10250             case Panel_1280x720:  delay = 0x0004; break;
10251             case Panel_1280x768:
10252             case Panel_1280x768_2:delay = 0x0004; break;
10253             case Panel_1280x800:
10254             case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
10255             case Panel_1280x854:  delay = 0x0004; break; /* FIXME */
10256             case Panel_1280x1024: delay = 0x1e04; break;
10257             case Panel_1400x1050: delay = 0x0004; break;
10258             case Panel_1600x1200: delay = 0x0400; break;
10259             case Panel_1680x1050: delay = 0x0e04; break;
10260             default:
10261                if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
10262                   delay = 0x0008;
10263                } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
10264                   delay = 0x1e04;
10265                } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
10266                   delay = 0x0004;
10267                } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
10268                   delay = 0x0400;
10269                } else
10270                   delay = 0x0e04;
10271                break;
10272             }
10273          }
10274
10275          /* Override by detected or user-set values */
10276          /* (but only if, for some reason, we can't read value from BIOS) */
10277          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
10278             delay = SiS_Pr->PDC & 0x1f;
10279          }
10280          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
10281             delay = (SiS_Pr->PDCA & 0x1f) << 8;
10282          }
10283
10284       }
10285
10286    }
10287
10288    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10289       delay >>= 8;
10290       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
10291       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
10292    } else {
10293       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
10294       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
10295    }
10296 }
10297
10298 static void
10299 SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
10300 {
10301    unsigned short infoflag;
10302    unsigned char  temp;
10303
10304    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10305
10306       if(ModeNo <= 0x13) {
10307          infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
10308       } else if(SiS_Pr->UseCustomMode) {
10309          infoflag = SiS_Pr->CInfoFlag;
10310       } else {
10311          infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
10312       }
10313
10314       if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
10315          infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
10316       }
10317
10318       infoflag &= 0xc0;
10319
10320       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10321          temp = (infoflag >> 6) | 0x0c;
10322          if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10323             temp ^= 0x04;
10324             if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
10325          }
10326          SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
10327       } else {
10328          temp = 0x30;
10329          if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
10330          temp |= infoflag;
10331          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
10332          temp = 0;
10333          if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
10334             if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
10335          }
10336          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
10337       }
10338
10339    }
10340 }
10341
10342 static void
10343 SetPanelParms661(struct SiS_Private *SiS_Pr)
10344 {
10345    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10346    unsigned short romptr, temp1, temp2;
10347
10348    if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
10349       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
10350    }
10351
10352    if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
10353       if(SiS_Pr->LVDSHL != -1) {
10354          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10355       }
10356    }
10357
10358    if(SiS_Pr->SiS_ROMNew) {
10359
10360       if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
10361          if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
10362             temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
10363             temp2 = 0xfc;
10364             if(SiS_Pr->LVDSHL != -1) {
10365               temp1 &= 0xfc;
10366               temp2 = 0xf3;
10367             }
10368             SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
10369          }
10370          if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10371             temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
10372             SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
10373          }
10374       }
10375
10376    }
10377 }
10378
10379 static void
10380 SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
10381 {
10382    if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
10383       SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
10384       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10385          SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10386          SetPanelParms661(SiS_Pr);
10387       }
10388    } else {
10389       SetDelayComp(SiS_Pr,ModeNo);
10390    }
10391
10392    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
10393       SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
10394       SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
10395       SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
10396       if(SiS_Pr->SiS_VBType & VB_SIS301) {
10397          SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
10398       }
10399    }
10400 }
10401
10402 static void
10403 SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
10404                         unsigned short ModeIdIndex, unsigned short RRTI)
10405 {
10406    if(SiS_Pr->SiS_VBType & VB_SISVB) {
10407
10408       SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
10409
10410       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10411          SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
10412          SetPanelParms661(SiS_Pr);
10413       }
10414
10415       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
10416          SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
10417          SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
10418          SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
10419          if(SiS_Pr->SiS_VBType & VB_SIS301) {
10420             SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
10421          }
10422       }
10423    }
10424 }
10425
10426 /* FinalizeLCD
10427  * This finalizes some CRT2 registers for the very panel used.
10428  * If we have a backup if these registers, we use it; otherwise
10429  * we set the register according to most BIOSes. However, this
10430  * function looks quite different in every BIOS, so you better
10431  * pray that we have a backup...
10432  */
10433 static void
10434 SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10435 {
10436   unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
10437   unsigned short resinfo,modeflag;
10438
10439   if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
10440   if(SiS_Pr->SiS_ROMNew) return;
10441
10442   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10443      if(SiS_Pr->LVDSHL != -1) {
10444         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
10445      }
10446   }
10447
10448   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10449   if(SiS_Pr->UseCustomMode) return;
10450
10451   switch(SiS_Pr->SiS_CustomT) {
10452   case CUT_COMPAQ1280:
10453   case CUT_COMPAQ12802:
10454   case CUT_CLEVO1400:
10455   case CUT_CLEVO14002:
10456      return;
10457   }
10458
10459   if(ModeNo <= 0x13) {
10460      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
10461      modeflag =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10462   } else {
10463      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
10464      modeflag =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10465   }
10466
10467   if(IS_SIS650) {
10468      if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
10469         if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10470            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
10471         } else {
10472            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
10473         }
10474      }
10475   }
10476
10477   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
10478      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10479         /* Maybe all panels? */
10480         if(SiS_Pr->LVDSHL == -1) {
10481            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10482         }
10483         return;
10484      }
10485   }
10486
10487   if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
10488      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10489         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10490            if(SiS_Pr->LVDSHL == -1) {
10491               /* Maybe all panels? */
10492               SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10493            }
10494            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10495               tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10496               if(tempch == 3) {
10497                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10498                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10499                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10500                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10501               }
10502            }
10503            return;
10504         }
10505      }
10506   }
10507
10508   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
10509      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10510         if(SiS_Pr->SiS_VBType & VB_SISEMI) {
10511            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
10512 #ifdef SET_EMI
10513            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
10514 #endif
10515            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
10516         }
10517      } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10518         if(SiS_Pr->LVDSHL == -1) {
10519            /* Maybe ACER only? */
10520            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
10521         }
10522      }
10523      tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
10524      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10525         if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
10526            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
10527         } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10528            if(tempch == 0x03) {
10529               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10530               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
10531               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
10532               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
10533            }
10534            if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
10535               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
10536               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
10537               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
10538               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
10539               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
10540               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
10541               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
10542               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
10543               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
10544               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
10545            } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {  /* 1.10.8w */
10546               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
10547               if(ModeNo <= 0x13) {
10548                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
10549                  if((resinfo == 0) || (resinfo == 2)) return;
10550                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
10551                  if((resinfo == 1) || (resinfo == 3)) return;
10552               }
10553               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
10554               if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
10555                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);  /* 1.10.7u */
10556 #if 0
10557                  tempbx = 806;  /* 0x326 */                      /* other older BIOSes */
10558                  tempbx--;
10559                  temp = tempbx & 0xff;
10560                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
10561                  temp = (tempbx >> 8) & 0x03;
10562                  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
10563 #endif
10564               }
10565            } else if(ModeNo <= 0x13) {
10566               if(ModeNo <= 1) {
10567                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
10568                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
10569                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10570                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10571               }
10572               if(!(modeflag & HalfDCLK)) {
10573                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
10574                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
10575                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
10576                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
10577                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
10578                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10579                  if(ModeNo == 0x12) {
10580                     switch(tempch) {
10581                        case 0:
10582                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10583                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
10584                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
10585                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10586                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
10587                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
10588                           break;
10589                        case 2:
10590                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
10591                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
10592                           break;
10593                        case 3:
10594                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
10595                           break;
10596                     }
10597                  }
10598               }
10599            }
10600         }
10601      } else {
10602         tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
10603         tempcl &= 0x0f;
10604         tempbh &= 0x70;
10605         tempbh >>= 4;
10606         tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
10607         tempbx = (tempbh << 8) | tempbl;
10608         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10609            if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
10610               if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
10611                  tempbx = 770;
10612               } else {
10613                  if(tempbx > 770) tempbx = 770;
10614                  if(SiS_Pr->SiS_VGAVDE < 600) {
10615                     tempax = 768 - SiS_Pr->SiS_VGAVDE;
10616                     tempax >>= 4;                                /* 1.10.7w; 1.10.6s: 3;  */
10617                     if(SiS_Pr->SiS_VGAVDE <= 480)  tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
10618                     tempbx -= tempax;
10619                  }
10620               }
10621            } else return;
10622         }
10623         temp = tempbx & 0xff;
10624         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
10625         temp = ((tempbx & 0xff00) >> 4) | tempcl;
10626         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
10627      }
10628   }
10629 }
10630
10631 #endif
10632
10633 /*  =================  SiS 300 O.E.M. ================== */
10634
10635 #ifdef CONFIG_FB_SIS_300
10636
10637 static void
10638 SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
10639                 unsigned short RefTabIndex)
10640 {
10641   unsigned short crt2crtc=0, modeflag, myindex=0;
10642   unsigned char  temp;
10643   int i;
10644
10645   if(ModeNo <= 0x13) {
10646      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
10647      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
10648   } else {
10649      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
10650      crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
10651   }
10652
10653   crt2crtc &= 0x3f;
10654
10655   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
10656      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
10657   }
10658
10659   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
10660      if(modeflag & HalfDCLK) myindex = 1;
10661
10662      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
10663         for(i=0; i<7; i++) {
10664            if(barco_p1[myindex][crt2crtc][i][0]) {
10665               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
10666                               barco_p1[myindex][crt2crtc][i][0],
10667                               barco_p1[myindex][crt2crtc][i][2],
10668                               barco_p1[myindex][crt2crtc][i][1]);
10669            }
10670         }
10671      }
10672      temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
10673      if(temp & 0x80) {
10674         temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
10675         temp++;
10676         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
10677      }
10678   }
10679 }
10680
10681 static unsigned short
10682 GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
10683 {
10684   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10685   unsigned short tempbx=0,romptr=0;
10686   static const unsigned char customtable300[] = {
10687         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
10688         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10689   };
10690   static const unsigned char customtable630[] = {
10691         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
10692         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10693   };
10694
10695   if(SiS_Pr->ChipType == SIS_300) {
10696
10697     tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
10698     if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
10699     tempbx -= 2;
10700     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
10701     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10702        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
10703     }
10704     if(SiS_Pr->SiS_UseROM) {
10705        if(ROMAddr[0x235] & 0x80) {
10706           tempbx = SiS_Pr->SiS_LCDTypeInfo;
10707           if(Flag) {
10708              romptr = SISGETROMW(0x255);
10709              if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10710              else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
10711              if(tempbx == 0xFF) return 0xFFFF;
10712           }
10713           tempbx <<= 1;
10714           if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
10715        }
10716     }
10717
10718   } else {
10719
10720     if(Flag) {
10721        if(SiS_Pr->SiS_UseROM) {
10722           romptr = SISGETROMW(0x255);
10723           if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
10724           else       tempbx = 0xff;
10725        } else {
10726           tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
10727        }
10728        if(tempbx == 0xFF) return 0xFFFF;
10729        tempbx <<= 2;
10730        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10731        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10732        return tempbx;
10733     }
10734     tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
10735     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
10736     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
10737
10738   }
10739
10740   return tempbx;
10741 }
10742
10743 static void
10744 SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
10745 {
10746   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10747   unsigned short index,temp,romptr=0;
10748
10749   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
10750
10751   if(SiS_Pr->SiS_UseROM) {
10752      if(!(ROMAddr[0x237] & 0x01)) return;
10753      if(!(ROMAddr[0x237] & 0x02)) return;
10754      romptr = SISGETROMW(0x24b);
10755   }
10756
10757   /* The Panel Compensation Delay should be set according to tables
10758    * here. Unfortunately, various BIOS versions don't care about
10759    * a uniform way using eg. ROM byte 0x220, but use different
10760    * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
10761    * Thus we don't set this if the user selected a custom pdc or if
10762    * we otherwise detected a valid pdc.
10763    */
10764   if(SiS_Pr->PDC != -1) return;
10765
10766   temp = GetOEMLCDPtr(SiS_Pr, 0);
10767
10768   if(SiS_Pr->UseCustomMode)
10769      index = 0;
10770   else
10771      index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
10772
10773   if(SiS_Pr->ChipType != SIS_300) {
10774      if(romptr) {
10775         romptr += (temp * 2);
10776         romptr = SISGETROMW(romptr);
10777         romptr += index;
10778         temp = ROMAddr[romptr];
10779      } else {
10780         if(SiS_Pr->SiS_VBType & VB_SISVB) {
10781            temp = SiS300_OEMLCDDelay2[temp][index];
10782         } else {
10783            temp = SiS300_OEMLCDDelay3[temp][index];
10784         }
10785      }
10786   } else {
10787      if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
10788         if(romptr) {
10789            romptr += (temp * 2);
10790            romptr = SISGETROMW(romptr);
10791            romptr += index;
10792            temp = ROMAddr[romptr];
10793         } else {
10794            temp = SiS300_OEMLCDDelay5[temp][index];
10795         }
10796      } else {
10797         if(SiS_Pr->SiS_UseROM) {
10798            romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
10799            if(romptr) {
10800               romptr += (temp * 2);
10801               romptr = SISGETROMW(romptr);
10802               romptr += index;
10803               temp = ROMAddr[romptr];
10804            } else {
10805               temp = SiS300_OEMLCDDelay4[temp][index];
10806            }
10807         } else {
10808            temp = SiS300_OEMLCDDelay4[temp][index];
10809         }
10810      }
10811   }
10812   temp &= 0x3c;
10813   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
10814 }
10815
10816 static void
10817 SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10818 {
10819 #if 0  /* Unfinished; Data table missing */
10820   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10821   unsigned short index,temp;
10822
10823   if((SiS_Pr->SiS_UseROM) {
10824      if(!(ROMAddr[0x237] & 0x01)) return;
10825      if(!(ROMAddr[0x237] & 0x04)) return;
10826      /* No rom pointer in BIOS header! */
10827   }
10828
10829   temp = GetOEMLCDPtr(SiS_Pr, 1);
10830   if(temp == 0xFFFF) return;
10831
10832   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
10833   for(i=0x14, j=0; i<=0x17; i++, j++) {
10834       SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
10835   }
10836   SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
10837
10838   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
10839   SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
10840   SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
10841   SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
10842   for(i=0x1b, j=3; i<=0x1d; i++, j++) {
10843       SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
10844   }
10845 #endif
10846 }
10847
10848 static unsigned short
10849 GetOEMTVPtr(struct SiS_Private *SiS_Pr)
10850 {
10851   unsigned short index;
10852
10853   index = 0;
10854   if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  index += 4;
10855   if(SiS_Pr->SiS_VBType & VB_SISVB) {
10856      if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)  index += 2;
10857      else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
10858      else if(SiS_Pr->SiS_TVMode & TVSetPAL)   index += 1;
10859   } else {
10860      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
10861      if(SiS_Pr->SiS_TVMode & TVSetPAL)        index += 1;
10862   }
10863   return index;
10864 }
10865
10866 static void
10867 SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10868 {
10869   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10870   unsigned short index,temp,romptr=0;
10871
10872   if(SiS_Pr->SiS_UseROM) {
10873      if(!(ROMAddr[0x238] & 0x01)) return;
10874      if(!(ROMAddr[0x238] & 0x02)) return;
10875      romptr = SISGETROMW(0x241);
10876   }
10877
10878   temp = GetOEMTVPtr(SiS_Pr);
10879
10880   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
10881
10882   if(romptr) {
10883      romptr += (temp * 2);
10884      romptr = SISGETROMW(romptr);
10885      romptr += index;
10886      temp = ROMAddr[romptr];
10887   } else {
10888      if(SiS_Pr->SiS_VBType & VB_SISVB) {
10889         temp = SiS300_OEMTVDelay301[temp][index];
10890      } else {
10891         temp = SiS300_OEMTVDelayLVDS[temp][index];
10892      }
10893   }
10894   temp &= 0x3c;
10895   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
10896 }
10897
10898 static void
10899 SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10900 {
10901   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10902   unsigned short index,temp,romptr=0;
10903
10904   if(SiS_Pr->SiS_UseROM) {
10905      if(!(ROMAddr[0x238] & 0x01)) return;
10906      if(!(ROMAddr[0x238] & 0x04)) return;
10907      romptr = SISGETROMW(0x243);
10908   }
10909
10910   temp = GetOEMTVPtr(SiS_Pr);
10911
10912   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
10913
10914   if(romptr) {
10915      romptr += (temp * 2);
10916      romptr = SISGETROMW(romptr);
10917      romptr += index;
10918      temp = ROMAddr[romptr];
10919   } else {
10920      temp = SiS300_OEMTVFlicker[temp][index];
10921   }
10922   temp &= 0x70;
10923   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
10924 }
10925
10926 static void
10927 SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
10928 {
10929   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10930   unsigned short index,i,j,temp,romptr=0;
10931
10932   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
10933
10934   if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
10935
10936   if(SiS_Pr->SiS_UseROM) {
10937      if(!(ROMAddr[0x238] & 0x01)) return;
10938      if(!(ROMAddr[0x238] & 0x08)) return;
10939      romptr = SISGETROMW(0x245);
10940   }
10941
10942   temp = GetOEMTVPtr(SiS_Pr);
10943
10944   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
10945
10946   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10947      for(i=0x31, j=0; i<=0x34; i++, j++) {
10948         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
10949      }
10950   } else {
10951      if(romptr) {
10952         romptr += (temp * 2);
10953         romptr = SISGETROMW(romptr);
10954         romptr += (index * 4);
10955         for(i=0x31, j=0; i<=0x34; i++, j++) {
10956            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
10957         }
10958      } else {
10959         for(i=0x31, j=0; i<=0x34; i++, j++) {
10960            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
10961         }
10962      }
10963   }
10964 }
10965
10966 static void
10967 SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
10968 {
10969   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
10970   unsigned short index,temp,i,j,romptr=0;
10971
10972   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
10973
10974   if(SiS_Pr->SiS_UseROM) {
10975      if(!(ROMAddr[0x238] & 0x01)) return;
10976      if(!(ROMAddr[0x238] & 0x10)) return;
10977      romptr = SISGETROMW(0x247);
10978   }
10979
10980   temp = GetOEMTVPtr(SiS_Pr);
10981
10982   if(SiS_Pr->SiS_TVMode & TVSetPALM)      temp = 8;
10983   else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
10984   /* NTSCJ uses NTSC filters */
10985
10986   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
10987
10988   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
10989       for(i=0x35, j=0; i<=0x38; i++, j++) {
10990         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
10991       }
10992       for(i=0x48; i<=0x4A; i++, j++) {
10993         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
10994       }
10995   } else {
10996       if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
10997          romptr += (temp * 2);
10998          romptr = SISGETROMW(romptr);
10999          romptr += (index * 4);
11000          for(i=0x35, j=0; i<=0x38; i++, j++) {
11001             SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11002          }
11003       } else {
11004          for(i=0x35, j=0; i<=0x38; i++, j++) {
11005             SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
11006          }
11007       }
11008   }
11009 }
11010
11011 static unsigned short
11012 SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
11013 {
11014    unsigned short ModeIdIndex;
11015    unsigned char  VGAINFO = SiS_Pr->SiS_VGAINFO;
11016
11017    if(*ModeNo <= 5) *ModeNo |= 1;
11018
11019    for(ModeIdIndex=0; ; ModeIdIndex++) {
11020       if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
11021       if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF)    return 0;
11022    }
11023
11024    if(*ModeNo != 0x07) {
11025       if(*ModeNo > 0x03) return ModeIdIndex;
11026       if(VGAINFO & 0x80) return ModeIdIndex;
11027       ModeIdIndex++;
11028    }
11029
11030    if(VGAINFO & 0x10) ModeIdIndex++;   /* 400 lines */
11031                                        /* else 350 lines */
11032    return ModeIdIndex;
11033 }
11034
11035 static void
11036 SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
11037                   unsigned short RefTableIndex)
11038 {
11039   unsigned short OEMModeIdIndex = 0;
11040
11041   if(!SiS_Pr->UseCustomMode) {
11042      OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
11043      if(!(OEMModeIdIndex)) return;
11044   }
11045
11046   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
11047      SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
11048      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
11049         SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
11050      }
11051   }
11052   if(SiS_Pr->UseCustomMode) return;
11053   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
11054      SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
11055      if(SiS_Pr->SiS_VBType & VB_SISVB) {
11056         SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
11057         SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
11058         SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
11059      }
11060   }
11061 }
11062 #endif
11063