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