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