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