vserver 1.9.5.x5
[linux-2.6.git] / drivers / video / sis / init301.c
1 /* $XFree86$ */
2 /* $XdotOrg$ */
3 /*
4  * Mode initializing code (CRT2 section)
5  * for SiS 300/305/540/630/730 and
6  *     SiS 315/550/650/M650/651/661FX/M661xX/740/741(GX)/M741/330/660/M660/760/M760
7  * (Universal module for Linux kernel framebuffer and XFree86/X.org 4.x)
8  *
9  * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
10  *
11  * If distributed as part of the Linux kernel, the following license terms
12  * apply:
13  *
14  * * This program is free software; you can redistribute it and/or modify
15  * * it under the terms of the GNU General Public License as published by
16  * * the Free Software Foundation; either version 2 of the named License,
17  * * or any later version.
18  * *
19  * * This program is distributed in the hope that it will be useful,
20  * * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * * GNU General Public License for more details.
23  * *
24  * * You should have received a copy of the GNU General Public License
25  * * along with this program; if not, write to the Free Software
26  * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
27  *
28  * Otherwise, the following license terms apply:
29  *
30  * * Redistribution and use in source and binary forms, with or without
31  * * modification, are permitted provided that the following conditions
32  * * are met:
33  * * 1) Redistributions of source code must retain the above copyright
34  * *    notice, this list of conditions and the following disclaimer.
35  * * 2) Redistributions in binary form must reproduce the above copyright
36  * *    notice, this list of conditions and the following disclaimer in the
37  * *    documentation and/or other materials provided with the distribution.
38  * * 3) The name of the author may not be used to endorse or promote products
39  * *    derived from this software without specific prior written permission.
40  * *
41  * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
42  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
45  * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47  * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48  * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49  * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
50  * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51  *
52  * Author:      Thomas Winischhofer <thomas@winischhofer.net>
53  *
54  * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
55  * Used by permission.
56  *
57  * TW says: This code looks awful, I know. But please don't do anything about
58  * this otherwise debugging will be hell.
59  * The code is extremely fragile as regards the different chipsets, different
60  * video bridges and combinations thereof. If anything is changed, extreme
61  * care has to be taken that that change doesn't break it for other chipsets,
62  * bridges or combinations thereof.
63  * All comments in this file are by me, regardless if marked TW or not.
64  *
65  */
66
67 #if 1
68 #define SET_EMI         /* 302LV/ELV: Set EMI values */
69 #endif
70
71 #define COMPAL_HACK     /* Needed for Compal 1400x1050 (EMI) */
72 #define COMPAQ_HACK     /* Needed for Inventec/Compaq 1280x1024 (EMI) */
73 #define ASUS_HACK       /* Needed for Asus A2H 1024x768 (EMI) */
74
75 #include "init301.h"
76
77 #ifdef SIS300
78 #include "oem300.h"
79 #endif
80
81 #ifdef SIS315H
82 #include "oem310.h"
83 #endif
84
85 #define SiS_I2CDELAY      1000
86 #define SiS_I2CDELAYSHORT  150
87
88 static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr);
89
90 /*********************************************/
91 /*         HELPER: Lock/Unlock CRT2          */
92 /*********************************************/
93
94 void
95 SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
96 {
97    if(HwInfo->jChipType >= SIS_315H)
98       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
99    else
100       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
101 }
102
103 void
104 SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
105 {
106    if(HwInfo->jChipType >= SIS_315H)
107       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
108    else
109       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
110 }
111
112 /*********************************************/
113 /*            HELPER: Write SR11             */
114 /*********************************************/
115
116 static void
117 SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
118 {
119    if(HwInfo->jChipType >= SIS_661) {
120       DataAND &= 0x0f;
121       DataOR  &= 0x0f;
122    }
123    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
124 }
125
126 /*********************************************/
127 /*    HELPER: Get Pointer to LCD structure   */
128 /*********************************************/
129
130 #ifdef SIS315H
131 static UCHAR *
132 GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
133 {
134    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
135    UCHAR  *myptr = NULL;
136    USHORT romindex = 0, reg = 0, idx = 0;
137
138    /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
139     * due to the variaty of panels the BIOS doesn't know about.
140     * Exception: If the BIOS has better knowledge (such as in case
141     * of machines with a 301C and a panel that does not support DDC)
142     * use the BIOS data as well.
143     */
144
145    if((SiS_Pr->SiS_ROMNew) &&
146       ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
147
148       if(HwInfo->jChipType < SIS_661) reg = 0x3c;
149       else                            reg = 0x7d;
150
151       idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
152
153       if(idx < (8*26)) {
154          myptr = (UCHAR *)&SiS_LCDStruct661[idx];
155       }
156       romindex = SISGETROMW(0x100);
157       if(romindex) {
158          romindex += idx;
159          myptr = &ROMAddr[romindex];
160       }
161    }
162    return myptr;
163 }
164
165 static USHORT
166 GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
167 {
168    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
169    USHORT romptr = 0;
170
171    /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
172     * due to the variaty of panels the BIOS doesn't know about.
173     * Exception: If the BIOS has better knowledge (such as in case
174     * of machines with a 301C and a panel that does not support DDC)
175     * use the BIOS data as well.
176     */
177
178    if((SiS_Pr->SiS_ROMNew) &&
179       ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
180       romptr = SISGETROMW(0x102);
181       romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
182    }
183
184    return(romptr);
185 }
186 #endif
187
188 /*********************************************/
189 /*           Adjust Rate for CRT2            */
190 /*********************************************/
191
192 static BOOLEAN
193 SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
194                    USHORT RRTI, USHORT *i, PSIS_HW_INFO HwInfo)
195 {
196   USHORT checkmask=0,modeid,infoflag;
197
198   modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
199
200   if(SiS_Pr->SiS_VBType & VB_SISVB) {
201
202      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
203
204         checkmask |= SupportRAMDAC2;
205         if(HwInfo->jChipType >= SIS_315H) {
206            checkmask |= SupportRAMDAC2_135;
207            if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
208               checkmask |= SupportRAMDAC2_162;
209               if(SiS_Pr->SiS_VBType & VB_SIS301C) {
210                  checkmask |= SupportRAMDAC2_202;
211               }
212            }
213         }
214
215      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
216
217         checkmask |= SupportLCD;
218         if(HwInfo->jChipType >= SIS_315H) {
219            if(SiS_Pr->SiS_VBType & VB_SISVB) {
220               if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
221                  if(modeid == 0x2e) checkmask |= Support64048060Hz;
222               }
223            }
224         }
225
226      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
227
228         checkmask |= SupportHiVision;
229
230      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
231
232         checkmask |= SupportTV;
233         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
234            checkmask |= SupportTV1024;
235            if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
236               if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
237                  checkmask |= SupportYPbPr750p;
238               }
239            }
240         }
241
242      }
243
244   } else {      /* LVDS */
245
246      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
247         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
248            checkmask |= SupportCHTV;
249         }
250      }
251
252      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
253         checkmask |= SupportLCD;
254      }
255
256   }
257
258   /* Look backwards in table for matching CRT2 mode */
259   for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
260      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
261      if(infoflag & checkmask) return TRUE;
262      if((*i) == 0) break;
263   }
264
265   /* Look through the whole mode-section of the table from the beginning
266    * for a matching CRT2 mode if no mode was found yet.
267    */
268   for((*i) = 0; ; (*i)++) {
269      if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
270      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
271      if(infoflag & checkmask) return TRUE;
272   }
273   return FALSE;
274 }
275
276 /*********************************************/
277 /*              Get rate index               */
278 /*********************************************/
279
280 USHORT
281 SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
282                PSIS_HW_INFO HwInfo)
283 {
284   SHORT  LCDRefreshIndex[] = { 0x00, 0x00, 0x01, 0x01,
285                                0x01, 0x01, 0x01, 0x01,
286                                0x01, 0x01, 0x01, 0x01,
287                                0x01, 0x01, 0x01, 0x01,
288                                0x00, 0x00, 0x00, 0x00 };
289   USHORT RRTI,i,backup_i;
290   USHORT modeflag,index,temp,backupindex;
291
292   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
293   if(ModeNo == 0xfe) return 0;
294
295   if(ModeNo <= 0x13) {
296      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
297   } else {
298      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
299   }
300
301   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
302      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
303         if(modeflag & HalfDCLK) return 0;
304      }
305   }
306
307   if(ModeNo < 0x14) return 0xFFFF;
308
309   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
310   backupindex = index;
311
312   if(index > 0) index--;
313
314   if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
315      if(SiS_Pr->SiS_VBType & VB_SISVB) {
316         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
317            if(SiS_Pr->SiS_VBType & VB_NoLCD)            index = 0;
318            else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
319         }
320         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
321            if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
322               temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
323               if(index > temp) index = temp;
324            }
325         }
326      } else {
327         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
328         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
329            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
330         }
331      }
332   }
333
334   RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
335   ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
336
337   if(HwInfo->jChipType >= SIS_315H) {
338      if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
339         if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
340             (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
341            if(backupindex <= 1) RRTI++;
342         }
343      }
344   }
345
346   i = 0;
347   do {
348      if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
349      temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
350      temp &= ModeTypeMask;
351      if(temp < SiS_Pr->SiS_ModeType) break;
352      i++;
353      index--;
354   } while(index != 0xFFFF);
355
356   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
357      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
358         temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
359         if(temp & InterlaceMode) i++;
360      }
361   }
362
363   i--;
364
365   if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
366      backup_i = i;
367      if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i, HwInfo))) {
368         i = backup_i;
369      }
370   }
371
372   return(RRTI + i);
373 }
374
375 /*********************************************/
376 /*            STORE CRT2 INFO in CR34        */
377 /*********************************************/
378
379 static void
380 SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo)
381 {
382   USHORT temp1,temp2;
383
384   /* Store CRT1 ModeNo in CR34 */
385   SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
386   temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
387   temp2 = ~(SetInSlaveMode >> 8);
388   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
389 }
390
391 /*********************************************/
392 /*    HELPER: GET SOME DATA FROM BIOS ROM    */
393 /*********************************************/
394
395 #ifdef SIS300
396 static BOOLEAN
397 SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
398 {
399   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
400   USHORT temp,temp1;
401
402   if(SiS_Pr->SiS_UseROM) {
403      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
404         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
405         temp1 = SISGETROMW(0x23b);
406         if(temp1 & temp) return TRUE;
407      }
408   }
409   return FALSE;
410 }
411
412 static BOOLEAN
413 SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
414 {
415   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
416   USHORT temp,temp1;
417
418   if(SiS_Pr->SiS_UseROM) {
419      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
420         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
421         temp1 = SISGETROMW(0x23d);
422         if(temp1 & temp) return TRUE;
423      }
424   }
425   return FALSE;
426 }
427 #endif
428
429 /*********************************************/
430 /*          HELPER: DELAY FUNCTIONS          */
431 /*********************************************/
432
433 void
434 SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime)
435 {
436   USHORT i, j;
437
438   for(i=0; i<delaytime; i++) {
439      j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
440   }
441 }
442
443 #if defined(SIS300) || defined(SIS315H)
444 static void
445 SiS_GenericDelay(SiS_Private *SiS_Pr, USHORT delay)
446 {
447   USHORT temp,flag;
448
449   flag = SiS_GetRegByte(0x61) & 0x10;
450
451   while(delay) {
452      temp = SiS_GetRegByte(0x61) & 0x10;
453      if(temp == flag) continue;
454      flag = temp;
455      delay--;
456   }
457 }
458 #endif
459
460 #ifdef SIS315H
461 static void
462 SiS_LongDelay(SiS_Private *SiS_Pr, USHORT delay)
463 {
464   while(delay--) {
465      SiS_GenericDelay(SiS_Pr,0x19df);
466   }
467 }
468 #endif
469
470 #if defined(SIS300) || defined(SIS315H)
471 static void
472 SiS_ShortDelay(SiS_Private *SiS_Pr, USHORT delay)
473 {
474   while(delay--) {
475      SiS_GenericDelay(SiS_Pr,0x42);
476   }
477 }
478 #endif
479
480 static void
481 SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
482 {
483 #if defined(SIS300) || defined(SIS315H)
484   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
485   USHORT PanelID, DelayIndex, Delay=0;
486 #endif
487
488   if(HwInfo->jChipType < SIS_315H) {
489
490 #ifdef SIS300
491
492       PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
493       if(SiS_Pr->SiS_VBType & VB_SISVB) {
494          if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
495          if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
496       }
497       DelayIndex = PanelID >> 4;
498       if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
499          Delay = 3;
500       } else {
501          if(DelayTime >= 2) DelayTime -= 2;
502          if(!(DelayTime & 0x01)) {
503             Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
504          } else {
505             Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
506          }
507          if(SiS_Pr->SiS_UseROM) {
508             if(ROMAddr[0x220] & 0x40) {
509                if(!(DelayTime & 0x01)) Delay = (USHORT)ROMAddr[0x225];
510                else                    Delay = (USHORT)ROMAddr[0x226];
511             }
512          }
513       }
514       SiS_ShortDelay(SiS_Pr, Delay);
515
516 #endif  /* SIS300 */
517
518    } else {
519
520 #ifdef SIS315H
521
522       if((HwInfo->jChipType >= SIS_661)    ||
523          (HwInfo->jChipType <= SIS_315PRO) ||
524          (HwInfo->jChipType == SIS_330)    ||
525          (SiS_Pr->SiS_ROMNew)) {
526
527          if(!(DelayTime & 0x01)) {
528             SiS_DDC2Delay(SiS_Pr, 0x1000);
529          } else {
530             SiS_DDC2Delay(SiS_Pr, 0x4000);
531          }
532
533       } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
534          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
535          (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) {                  /* 315 series, LVDS; Special */
536
537          if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
538             PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
539             if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
540                if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
541             }
542             if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
543                DelayIndex = PanelID & 0x0f;
544             } else {
545                DelayIndex = PanelID >> 4;
546             }
547             if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
548                Delay = 3;
549             } else {
550                if(DelayTime >= 2) DelayTime -= 2;
551                if(!(DelayTime & 0x01)) {
552                   Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
553                } else {
554                   Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
555                }
556                if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
557                   if(ROMAddr[0x13c] & 0x40) {
558                      if(!(DelayTime & 0x01)) {
559                         Delay = (USHORT)ROMAddr[0x17e];
560                      } else {
561                         Delay = (USHORT)ROMAddr[0x17f];
562                      }
563                   }
564                }
565             }
566             SiS_ShortDelay(SiS_Pr, Delay);
567          }
568
569       } else if(SiS_Pr->SiS_VBType & VB_SISVB) {                        /* 315 series, all bridges */
570
571          DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
572          if(!(DelayTime & 0x01)) {
573             Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
574          } else {
575             Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
576          }
577          Delay <<= 8;
578          SiS_DDC2Delay(SiS_Pr, Delay);
579
580       }
581
582 #endif /* SIS315H */
583
584    }
585 }
586
587 #ifdef SIS315H
588 static void
589 SiS_PanelDelayLoop(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
590                       USHORT DelayTime, USHORT DelayLoop)
591 {
592    int i;
593    for(i=0; i<DelayLoop; i++) {
594       SiS_PanelDelay(SiS_Pr, HwInfo, DelayTime);
595    }
596 }
597 #endif
598
599 /*********************************************/
600 /*    HELPER: WAIT-FOR-RETRACE FUNCTIONS     */
601 /*********************************************/
602
603 void
604 SiS_WaitRetrace1(SiS_Private *SiS_Pr)
605 {
606   USHORT watchdog;
607
608   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
609   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
610
611   watchdog = 65535;
612   while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
613   watchdog = 65535;
614   while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
615 }
616
617 #if defined(SIS300) || defined(SIS315H)
618 static void
619 SiS_WaitRetrace2(SiS_Private *SiS_Pr, USHORT reg)
620 {
621   USHORT watchdog;
622
623   watchdog = 65535;
624   while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
625   watchdog = 65535;
626   while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
627 }
628 #endif
629
630 static void
631 SiS_WaitVBRetrace(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
632 {
633   if(HwInfo->jChipType < SIS_315H) {
634 #ifdef SIS300
635      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
636         if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
637      }
638      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
639         SiS_WaitRetrace1(SiS_Pr);
640      } else {
641         SiS_WaitRetrace2(SiS_Pr, 0x25);
642      }
643 #endif
644   } else {
645 #ifdef SIS315H
646      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
647         SiS_WaitRetrace1(SiS_Pr);
648      } else {
649         SiS_WaitRetrace2(SiS_Pr, 0x30);
650      }
651 #endif
652   }
653 }
654
655 static void
656 SiS_VBWait(SiS_Private *SiS_Pr)
657 {
658   USHORT tempal,temp,i,j;
659
660   temp = 0;
661   for(i=0; i<3; i++) {
662     for(j=0; j<100; j++) {
663        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
664        if(temp & 0x01) {
665           if((tempal & 0x08))  continue;
666           else break;
667        } else {
668           if(!(tempal & 0x08)) continue;
669           else break;
670        }
671     }
672     temp ^= 0x01;
673   }
674 }
675
676 static void
677 SiS_VBLongWait(SiS_Private *SiS_Pr)
678 {
679   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
680      SiS_VBWait(SiS_Pr);
681   } else {
682      SiS_WaitRetrace1(SiS_Pr);
683   }
684 }
685
686 /*********************************************/
687 /*               HELPER: MISC                */
688 /*********************************************/
689
690 #ifdef SIS300
691 static BOOLEAN
692 SiS_Is301B(SiS_Private *SiS_Pr)
693 {
694   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
695   return FALSE;
696 }
697 #endif
698
699 static BOOLEAN
700 SiS_CRT2IsLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
701 {
702   USHORT flag;
703
704   if(HwInfo->jChipType == SIS_730) {
705      flag = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13);
706      if(flag & 0x20) return TRUE;
707   }
708   flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
709   if(flag & 0x20) return TRUE;
710   return FALSE;
711 }
712
713 BOOLEAN
714 SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
715 {
716 #ifdef SIS315H
717   USHORT flag;
718
719   if(HwInfo->jChipType >= SIS_315H) {
720      if((HwInfo->jChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
721         flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
722         if(flag & EnableDualEdge) return TRUE;
723      }
724   }
725 #endif
726   return FALSE;
727 }
728
729 BOOLEAN
730 SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
731 {
732 #ifdef SIS315H
733   USHORT flag;
734
735   if(HwInfo->jChipType >= SIS_315H) {
736      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
737      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
738   }
739 #endif
740   return FALSE;
741 }
742
743 #ifdef SIS315H
744 static BOOLEAN
745 SiS_IsVAorLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
746 {
747   if(SiS_IsVAMode(SiS_Pr,HwInfo))   return TRUE;
748   if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) return TRUE;
749   return FALSE;
750 }
751 #endif
752
753 static BOOLEAN
754 SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
755 {
756 #ifdef SIS315H
757   if(HwInfo->jChipType >= SIS_315H) {
758      if((SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ||
759         (SiS_IsVAMode(SiS_Pr, HwInfo))) {
760         if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
761      }
762   }
763 #endif
764   return FALSE;
765 }
766
767 #ifdef SIS315H
768 static BOOLEAN
769 SiS_TVEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
770 {
771   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
772   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV302LV)) {
773      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
774   }
775   return FALSE;
776 }
777 #endif
778
779 #ifdef SIS315H
780 static BOOLEAN
781 SiS_LCDAEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
782 {
783   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
784   return FALSE;
785 }
786 #endif
787
788 #ifdef SIS315H
789 static BOOLEAN
790 SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
791 {
792   if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
793      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
794   }
795   return FALSE;
796 }
797 #endif
798
799 #ifdef SIS315H
800 static BOOLEAN
801 SiS_IsNotM650orLater(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
802 {
803   USHORT flag;
804
805   if(HwInfo->jChipType == SIS_650) {
806      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f);
807      flag &= 0xF0;
808      /* Check for revision != A0 only */
809      if((flag == 0xe0) || (flag == 0xc0) ||
810         (flag == 0xb0) || (flag == 0x90)) return FALSE;
811   } else if(HwInfo->jChipType >= SIS_661) return FALSE;
812   return TRUE;
813 }
814 #endif
815
816 #ifdef SIS315H
817 static BOOLEAN
818 SiS_IsYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
819 {
820   USHORT flag;
821
822   if(HwInfo->jChipType >= SIS_315H) {
823      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
824      if(flag & EnableCHYPbPr) return TRUE;  /* = YPrPb = 0x08 */
825   }
826   return FALSE;
827 }
828 #endif
829
830 #ifdef SIS315H
831 static BOOLEAN
832 SiS_IsChScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
833 {
834   USHORT flag;
835
836   if(HwInfo->jChipType >= SIS_315H) {
837      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
838      if(flag & EnableCHScart) return TRUE;  /* = Scart = 0x04 */
839   }
840   return FALSE;
841 }
842 #endif
843
844 #ifdef SIS315H
845 static BOOLEAN
846 SiS_IsTVOrYPbPrOrScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
847 {
848   USHORT flag;
849
850   if(HwInfo->jChipType >= SIS_315H) {
851      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
852      if(flag & SetCRT2ToTV)        return TRUE;
853      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
854      if(flag & EnableCHYPbPr)      return TRUE;  /* = YPrPb = 0x08 */
855      if(flag & EnableCHScart)      return TRUE;  /* = Scart = 0x04 - TW */
856   } else {
857      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
858      if(flag & SetCRT2ToTV)        return TRUE;
859   }
860   return FALSE;
861 }
862 #endif
863
864 #ifdef SIS315H
865 static BOOLEAN
866 SiS_IsLCDOrLCDA(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
867 {
868   USHORT flag;
869
870   if(HwInfo->jChipType >= SIS_315H) {
871      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
872      if(flag & SetCRT2ToLCD) return TRUE;
873      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
874      if(flag & SetToLCDA)    return TRUE;
875   } else {
876      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
877      if(flag & SetCRT2ToLCD) return TRUE;
878   }
879   return FALSE;
880 }
881 #endif
882
883 static BOOLEAN
884 SiS_BridgeIsOn(SiS_Private *SiS_Pr)
885 {
886   USHORT flag;
887
888   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
889      return TRUE;
890   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
891      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
892      if((flag == 1) || (flag == 2)) return TRUE;
893   }
894   return FALSE;
895 }
896
897 static BOOLEAN
898 SiS_BridgeIsEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
899 {
900   USHORT flag;
901
902   if(SiS_BridgeIsOn(SiS_Pr)) {
903      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
904      if(HwInfo->jChipType < SIS_315H) {
905        flag &= 0xa0;
906        if((flag == 0x80) || (flag == 0x20)) return TRUE;
907      } else {
908        flag &= 0x50;
909        if((flag == 0x40) || (flag == 0x10)) return TRUE;
910      }
911   }
912   return FALSE;
913 }
914
915 static BOOLEAN
916 SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
917 {
918   USHORT flag1;
919
920   flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
921   if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
922   return FALSE;
923 }
924
925 /*********************************************/
926 /*       GET VIDEO BRIDGE CONFIG INFO        */
927 /*********************************************/
928
929 /* Setup general purpose IO for Chrontel communication */
930 void
931 SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo)
932 {
933    unsigned long  acpibase;
934    unsigned short temp;
935
936    if(!(SiS_Pr->SiS_ChSW)) return;
937
938 #ifdef LINUX_KERNEL
939    SiS_SetRegLong(0xcf8,0x80000874);                   /* get ACPI base */
940    acpibase = SiS_GetRegLong(0xcfc);
941 #else
942    acpibase = pciReadLong(0x00000800, 0x74);
943 #endif
944    acpibase &= 0xFFFF;
945    temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c));  /* ACPI register 0x3c: GP Event 1 I/O mode select */
946    temp &= 0xFEFF;
947    SiS_SetRegShort((USHORT)(acpibase + 0x3c), temp);
948    temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c));
949    temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a));  /* ACPI register 0x3a: GP Pin Level (low/high) */
950    temp &= 0xFEFF;
951    if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
952    SiS_SetRegShort((USHORT)(acpibase + 0x3a), temp);
953    temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a));
954 }
955
956 void
957 SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
958               PSIS_HW_INFO HwInfo, int checkcrt2mode)
959 {
960   USHORT tempax,tempbx,temp;
961   USHORT modeflag, resinfo=0;
962
963   if(ModeNo <= 0x13) {
964      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
965   } else if(SiS_Pr->UseCustomMode) {
966      modeflag = SiS_Pr->CModeFlag;
967   } else {
968      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
969      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
970   }
971
972   SiS_Pr->SiS_SetFlag = 0;
973
974   SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
975
976   tempbx = 0;
977   if(SiS_BridgeIsOn(SiS_Pr)) {
978         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
979 #if 0
980         if(HwInfo->jChipType < SIS_661) {
981            /* NO - YPbPr not set yet ! */
982            if(SiS_Pr->SiS_YPbPr & <all ypbpr except 525i>) {
983               temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode);       /* 0x83 */
984               temp |= SetCRT2ToHiVision;                                        /* 0x80 */
985            }
986            if(SiS_Pr->SiS_YPbPr & <ypbpr525i>) {
987               temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode);       /* 0x83 */
988               temp |= SetCRT2ToSVIDEO;                                          /* 0x08 */
989            }
990         }
991 #endif
992         tempbx |= temp;
993         tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
994         tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
995         tempbx |= tempax;
996
997 #ifdef SIS315H
998         if(HwInfo->jChipType >= SIS_315H) {
999            if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
1000               if(ModeNo == 0x03) {
1001                  /* Mode 0x03 is never in driver mode */
1002                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
1003               }
1004               if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
1005                  /* Reset LCDA setting if not driver mode */
1006                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
1007               }
1008               if(IS_SIS650) {
1009                  if(SiS_Pr->SiS_UseLCDA) {
1010                     if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
1011                        if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
1012                           SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
1013                        }
1014                     }
1015                  }
1016               }
1017               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1018               if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
1019                  tempbx |= SetCRT2ToLCDA;
1020               }
1021            }
1022
1023            if(SiS_Pr->SiS_VBType & (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
1024               tempbx &= ~(SetCRT2ToRAMDAC);
1025            }
1026
1027            if(HwInfo->jChipType >= SIS_661) {
1028               tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
1029               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1030               if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1031                  if(temp & 0x04) {
1032                     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
1033                     if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
1034                     else             tempbx |= SetCRT2ToYPbPr525750;
1035                  }
1036               } else if(SiS_Pr->SiS_VBType & VB_SISHIVISION) {
1037                  if(temp & 0x04) {
1038                     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
1039                     if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
1040                  }
1041               }
1042            }
1043
1044            if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1045               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1046               if(temp & SetToLCDA) {
1047                  tempbx |= SetCRT2ToLCDA;
1048               }
1049               if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1050                  if(temp & EnableCHYPbPr) {
1051                     tempbx |= SetCRT2ToCHYPbPr;
1052                  }
1053               }
1054            }
1055         }
1056
1057 #endif  /* SIS315H */
1058
1059         if(SiS_Pr->SiS_VBType & VB_SISVB) {
1060            temp = SetCRT2ToSVIDEO   |
1061                   SetCRT2ToAVIDEO   |
1062                   SetCRT2ToSCART    |
1063                   SetCRT2ToLCDA     |
1064                   SetCRT2ToLCD      |
1065                   SetCRT2ToRAMDAC   |
1066                   SetCRT2ToHiVision |
1067                   SetCRT2ToYPbPr525750;
1068         } else {
1069            if(HwInfo->jChipType >= SIS_315H) {
1070               if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1071                  temp = SetCRT2ToAVIDEO |
1072                         SetCRT2ToSVIDEO |
1073                         SetCRT2ToSCART  |
1074                         SetCRT2ToLCDA   |
1075                         SetCRT2ToLCD    |
1076                         SetCRT2ToCHYPbPr;
1077               } else {
1078                  temp = SetCRT2ToLCDA   |
1079                         SetCRT2ToLCD;
1080               }
1081            } else {
1082               if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1083                  temp = SetCRT2ToTV | SetCRT2ToLCD;
1084               } else {
1085                  temp = SetCRT2ToLCD;
1086               }
1087            }
1088         }
1089
1090         if(!(tempbx & temp)) {
1091            tempax = DisableCRT2Display;
1092            tempbx = 0;
1093         }
1094
1095         if(SiS_Pr->SiS_VBType & VB_SISVB) {
1096            USHORT clearmask = ( DriverMode         |
1097                                 DisableCRT2Display |
1098                                 LoadDACFlag        |
1099                                 SetNotSimuMode     |
1100                                 SetInSlaveMode     |
1101                                 SetPALTV           |
1102                                 SwitchCRT2         |
1103                                 SetSimuScanMode );
1104            if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
1105            if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
1106            if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
1107            if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
1108            if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
1109            if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
1110         } else {
1111            if(HwInfo->jChipType >= SIS_315H) {
1112               if(tempbx & SetCRT2ToLCDA) {
1113                  tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
1114               }
1115            }
1116            if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1117               if(tempbx & SetCRT2ToTV) {
1118                  tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
1119               }
1120            }
1121            if(tempbx & SetCRT2ToLCD) {
1122               tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
1123            }
1124            if(HwInfo->jChipType >= SIS_315H) {
1125               if(tempbx & SetCRT2ToLCDA) {
1126                  tempbx |= SetCRT2ToLCD;
1127               }
1128            }
1129         }
1130
1131         if(tempax & DisableCRT2Display) {
1132            if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1133               tempbx = SetSimuScanMode | DisableCRT2Display;
1134            }
1135         }
1136
1137         if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
1138
1139         /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
1140         if(SiS_Pr->SiS_ModeType <= ModeVGA) {
1141            if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
1142                ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
1143                modeflag &= (~CRT2Mode);
1144            }
1145         }
1146
1147         if(!(tempbx & SetSimuScanMode)) {
1148            if(tempbx & SwitchCRT2) {
1149               if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1150                  if( (HwInfo->jChipType >= SIS_315H) &&
1151                      (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
1152                     if(resinfo != SIS_RI_1600x1200) {
1153                        tempbx |= SetSimuScanMode;
1154                     }
1155                  } else {
1156                     tempbx |= SetSimuScanMode;
1157                  }
1158               }
1159            } else {
1160               if(SiS_BridgeIsEnabled(SiS_Pr,HwInfo)) {
1161                  if(!(tempbx & DriverMode)) {
1162                     if(SiS_BridgeInSlavemode(SiS_Pr)) {
1163                        tempbx |= SetSimuScanMode;
1164                     }
1165                  }
1166               }
1167            }
1168         }
1169
1170         if(!(tempbx & DisableCRT2Display)) {
1171            if(tempbx & DriverMode) {
1172               if(tempbx & SetSimuScanMode) {
1173                  if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1174                     if( (HwInfo->jChipType >= SIS_315H) &&
1175                         (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
1176                        if(resinfo != SIS_RI_1600x1200) {
1177                           tempbx |= SetInSlaveMode;
1178                        }
1179                     } else {
1180                        tempbx |= SetInSlaveMode;
1181                     }
1182                  }
1183               }
1184            } else {
1185               tempbx |= SetInSlaveMode;
1186            }
1187         }
1188
1189   }
1190
1191   SiS_Pr->SiS_VBInfo = tempbx;
1192
1193   if(HwInfo->jChipType == SIS_630) {
1194      SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1195   }
1196
1197 #ifdef TWDEBUG
1198 #ifdef LINUX_KERNEL
1199   printk(KERN_DEBUG "sisfb: (VBInfo= 0x%04x, SetFlag=0x%04x)\n",
1200       SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1201 #endif
1202 #ifdef LINUX_XF86
1203   xf86DrvMsgVerb(0, X_PROBED, 3, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
1204       SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1205 #endif
1206 #endif
1207 }
1208
1209 /*********************************************/
1210 /*           DETERMINE YPbPr MODE            */
1211 /*********************************************/
1212
1213 void
1214 SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
1215 {
1216
1217   UCHAR temp;
1218
1219   /* Note: This variable is only used on 30xLV systems.
1220    * CR38 has a different meaning on LVDS/CH7019 systems.
1221    * On 661 and later, these bits moved to CR35.
1222    *
1223    * On 301, 301B, only HiVision 1080i is supported.
1224    * On 30xLV, 301C, only YPbPr 1080i is supported.
1225    */
1226
1227   SiS_Pr->SiS_YPbPr = 0;
1228   if(HwInfo->jChipType >= SIS_661) return;
1229
1230   if(SiS_Pr->SiS_VBType) {
1231      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1232         SiS_Pr->SiS_YPbPr = YPbPrHiVision;
1233      }
1234   }
1235
1236   if(HwInfo->jChipType >= SIS_315H) {
1237      if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_SIS301C)) {
1238         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1239         if(temp & 0x08) {
1240            switch((temp >> 4)) {
1241            case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
1242            case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
1243            case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
1244            case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
1245            }
1246         }
1247      }
1248   }
1249
1250 }
1251
1252 /*********************************************/
1253 /*           DETERMINE TVMode flag           */
1254 /*********************************************/
1255
1256 void
1257 SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo)
1258 {
1259   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
1260   USHORT temp, temp1, resinfo = 0, romindex = 0;
1261   UCHAR  OutputSelect = *SiS_Pr->pSiS_OutputSelect;
1262
1263   SiS_Pr->SiS_TVMode = 0;
1264
1265   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
1266   if(SiS_Pr->UseCustomMode) return;
1267
1268   if(ModeNo > 0x13) {
1269      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1270   }
1271
1272   if(HwInfo->jChipType < SIS_661) {
1273
1274      if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
1275
1276      if(SiS_Pr->SiS_VBType & VB_SISVB) {
1277         temp = 0;
1278         if((HwInfo->jChipType == SIS_630) ||
1279            (HwInfo->jChipType == SIS_730)) {
1280            temp = 0x35;
1281            romindex = 0xfe;
1282         } else if(HwInfo->jChipType >= SIS_315H) {
1283            temp = 0x38;
1284            romindex = 0xf3;
1285            if(HwInfo->jChipType >= SIS_330) romindex = 0x11b;
1286         }
1287         if(temp) {
1288            if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
1289               OutputSelect = ROMAddr[romindex];
1290               if(!(OutputSelect & EnablePALMN)) {
1291                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
1292               }
1293            }
1294            temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
1295            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1296               if(temp1 & EnablePALM) {          /* 0x40 */
1297                  SiS_Pr->SiS_TVMode |= TVSetPALM;
1298                  SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1299               } else if(temp1 & EnablePALN) {   /* 0x80 */
1300                  SiS_Pr->SiS_TVMode |= TVSetPALN;
1301               }
1302            } else {
1303               if(temp1 & EnableNTSCJ) {         /* 0x40 */
1304                  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1305               }
1306            }
1307         }
1308         /* Translate HiVision/YPbPr to our new flags */
1309         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1310            if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1311            else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1312            else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
1313            else                                        SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1314            if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
1315               SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
1316               SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
1317            } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
1318               SiS_Pr->SiS_TVMode |= TVSetPAL;
1319            }
1320         }
1321      } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1322         if(SiS_Pr->SiS_CHOverScan) {
1323            if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
1324               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1325               if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
1326                  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1327               }
1328            } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1329               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
1330               if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
1331                  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1332               }
1333            }
1334            if(SiS_Pr->SiS_CHSOverScan) {
1335               SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1336            }
1337         }
1338         if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1339            temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1340            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1341               if(temp & EnablePALM)      SiS_Pr->SiS_TVMode |= TVSetPALM;
1342               else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
1343            } else {
1344               if(temp & EnableNTSCJ) {
1345                  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1346               }
1347            }
1348         }
1349      }
1350
1351   } else {  /* 661 and later */
1352
1353      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1354      if(temp1 & 0x01) {
1355         SiS_Pr->SiS_TVMode |= TVSetPAL;
1356         if(temp1 & 0x08) {
1357            SiS_Pr->SiS_TVMode |= TVSetPALN;
1358         } else if(temp1 & 0x04) {
1359            if(SiS_Pr->SiS_VBType & VB_SISVB) {
1360               SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1361            }
1362            SiS_Pr->SiS_TVMode |= TVSetPALM;
1363         }
1364      } else {
1365         if(temp1 & 0x02) {
1366            SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1367         }
1368      }
1369      if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1370         if(SiS_Pr->SiS_CHOverScan) {
1371            if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
1372               SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1373            }
1374         }
1375      }
1376      if(SiS_Pr->SiS_VBType & VB_SISVB) {
1377         if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1378            temp1 &= 0xe0;
1379            if(temp1 == 0x00)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1380            else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1381            else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1382         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1383            SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
1384         }
1385         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
1386            if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
1387               SiS_Pr->SiS_TVMode |= TVAspect169;
1388            } else {
1389               temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
1390               if(temp1 & 0x02) {
1391                  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
1392                     SiS_Pr->SiS_TVMode |= TVAspect169;
1393                  } else {
1394                     SiS_Pr->SiS_TVMode |= TVAspect43LB;
1395                  }
1396               } else {
1397                  SiS_Pr->SiS_TVMode |= TVAspect43;
1398               }
1399            }
1400         }
1401      }
1402   }
1403
1404   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
1405
1406   if(SiS_Pr->SiS_VBType & VB_SISVB) {
1407
1408      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1409         SiS_Pr->SiS_TVMode |= TVSetPAL;
1410         SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
1411      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1412         if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
1413            SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
1414         }
1415      }
1416
1417      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1418         if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
1419            SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1420         }
1421      }
1422
1423      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
1424         /* BIOS sets TVNTSC1024 without checking 525p here. Wrong? */
1425         if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr525p | TVSetYPbPr750p))) {
1426            if(resinfo == SIS_RI_1024x768) {
1427               SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
1428            }
1429         }
1430      }
1431
1432      SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
1433      if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
1434         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
1435         SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1436      } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
1437         SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1438      } else if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
1439         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
1440            SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1441         }
1442      }
1443
1444   }
1445
1446   SiS_Pr->SiS_VBInfo &= ~SetPALTV;
1447
1448 #ifdef TWDEBUG
1449   xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
1450 #endif
1451 }
1452
1453 /*********************************************/
1454 /*               GET LCD INFO                */
1455 /*********************************************/
1456
1457 static USHORT
1458 SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr)
1459 {
1460    USHORT temp = SiS_Pr->SiS_LCDResInfo;
1461    /* Translate my LCDResInfo to BIOS value */
1462    if(temp == Panel_1280x768_2)  temp = Panel_1280x768;
1463    if(temp == Panel_1280x800_2)  temp = Panel_1280x800;
1464    return temp;
1465 }
1466
1467 static void
1468 SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
1469 {
1470 #ifdef SIS315H
1471    UCHAR  *ROMAddr;
1472    USHORT temp;
1473
1474 #ifdef TWDEBUG
1475    xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
1476         SiS_Pr->PanelHT, SiS_Pr->PanelVT,
1477         SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1478         SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1479         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1480         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1481         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1482 #endif
1483
1484    if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
1485       if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
1486          SiS_Pr->SiS_NeedRomModeData = TRUE;
1487          SiS_Pr->PanelHT  = temp;
1488       }
1489       if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
1490          SiS_Pr->SiS_NeedRomModeData = TRUE;
1491          SiS_Pr->PanelVT  = temp;
1492       }
1493       SiS_Pr->PanelHRS = SISGETROMW(10);
1494       SiS_Pr->PanelHRE = SISGETROMW(12);
1495       SiS_Pr->PanelVRS = SISGETROMW(14);
1496       SiS_Pr->PanelVRE = SISGETROMW(16);
1497       SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1498       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
1499          SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)((UCHAR)ROMAddr[18]);
1500       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
1501          SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
1502       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
1503          SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
1504
1505 #ifdef TWDEBUG
1506       xf86DrvMsg(0, X_INFO, "Paneldata BIOS:  [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
1507         SiS_Pr->PanelHT, SiS_Pr->PanelVT,
1508         SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1509         SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1510         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1511         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1512         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1513 #endif
1514
1515    }
1516 #endif
1517 }
1518
1519 static void
1520 SiS_CheckScaling(SiS_Private *SiS_Pr, USHORT resinfo, const UCHAR *nonscalingmodes)
1521 {
1522     int i = 0;
1523     while(nonscalingmodes[i] != 0xff) {
1524         if(nonscalingmodes[i++] == resinfo) {
1525            if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
1526               (SiS_Pr->UsePanelScaler == -1)) {
1527               SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1528            }
1529            break;
1530         }
1531     }
1532 }
1533
1534 void
1535 SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
1536                   PSIS_HW_INFO HwInfo)
1537 {
1538 #ifdef SIS300
1539   UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
1540   const unsigned char SiS300SeriesLCDRes[] =
1541           { 0,  1,  2,  3,  7,  4,  5,  8,
1542             0,  0, 10,  0,  0,  0,  0, 15 };
1543 #endif
1544 #ifdef SIS315H
1545   UCHAR   *myptr = NULL;
1546 #endif
1547   USHORT  temp,modeflag,resinfo=0,modexres=0,modeyres=0;
1548   BOOLEAN panelcanscale = FALSE;
1549
1550   SiS_Pr->SiS_LCDResInfo  = 0;
1551   SiS_Pr->SiS_LCDTypeInfo = 0;
1552   SiS_Pr->SiS_LCDInfo     = 0;
1553   SiS_Pr->PanelHRS        = 999; /* HSync start */
1554   SiS_Pr->PanelHRE        = 999; /* HSync end */
1555   SiS_Pr->PanelVRS        = 999; /* VSync start */
1556   SiS_Pr->PanelVRE        = 999; /* VSync end */
1557   SiS_Pr->SiS_NeedRomModeData = FALSE;
1558
1559   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
1560
1561   if(ModeNo <= 0x13) {
1562      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
1563   } else if(SiS_Pr->UseCustomMode) {
1564      modeflag = SiS_Pr->CModeFlag;
1565   } else {
1566      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1567      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1568      modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
1569      modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
1570   }
1571
1572   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
1573
1574   /* For broken BIOSes: Assume 1024x768 */
1575   if(temp == 0) temp = 0x02;
1576
1577   if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
1578      SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
1579   } else if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
1580      SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
1581   } else {
1582      SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1583   }
1584   temp &= 0x0f;
1585 #ifdef SIS300
1586   if(HwInfo->jChipType < SIS_315H) {
1587      /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
1588      if(SiS_Pr->SiS_VBType & VB_SIS301) {
1589         if(temp < 0x0f) temp &= 0x07;
1590      }
1591      /* Translate 300 series LCDRes to 315 series for unified usage */
1592      temp = SiS300SeriesLCDRes[temp];
1593   }
1594 #endif
1595
1596   /* Translate to our internal types */
1597   if(HwInfo->jChipType == SIS_550) {
1598      if(temp == Panel310_640x480_2) temp = Panel_640x480_2;
1599      if(temp == Panel310_640x480_3) temp = Panel_640x480_3;
1600   }
1601
1602   if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
1603      if(temp == Panel310_1280x768) {
1604         temp = Panel_1280x768_2;
1605      }
1606      if(SiS_Pr->SiS_ROMNew) {
1607         if(temp == Panel661_1280x800) {
1608            temp = Panel_1280x800_2;
1609         }
1610      }
1611   }
1612
1613   SiS_Pr->SiS_LCDResInfo = temp;
1614
1615   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1616      if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
1617         SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
1618      } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
1619         SiS_Pr->SiS_LCDResInfo = Panel_848x480;
1620      }
1621   }
1622
1623   if(SiS_Pr->SiS_VBType & VB_SISVB) {
1624      if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
1625         SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
1626   } else {
1627      if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
1628         SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
1629   }
1630
1631   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
1632   SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
1633   /* Need temp below! */
1634
1635   /* These can't scale no matter what */
1636   switch(SiS_Pr->SiS_LCDResInfo) {
1637   case Panel_1280x960:
1638       SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1639   }
1640
1641   panelcanscale = (SiS_Pr->SiS_LCDInfo & DontExpandLCD) ? TRUE : FALSE;
1642
1643   if(!SiS_Pr->UsePanelScaler)          SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1644   else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1645
1646   /* Dual link, Pass 1:1 BIOS default, etc. */
1647 #ifdef SIS315H
1648   if(HwInfo->jChipType >= SIS_661) {
1649      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1650         if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1651      }
1652      if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
1653         if(SiS_Pr->SiS_ROMNew) {
1654            if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1655         } else if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
1656            if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1657         }
1658      }
1659   } else if(HwInfo->jChipType >= SIS_315H) {
1660      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1661         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1662      }
1663      if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
1664         SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
1665         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1666         if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
1667         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
1668            if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1669         }
1670      } else if(!(SiS_Pr->SiS_ROMNew)) {
1671         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
1672            if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
1673               (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
1674               SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1675            }
1676            if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
1677               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
1678               (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
1679               (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
1680               SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1681            }
1682         }
1683      }
1684   }
1685 #endif
1686
1687   /* Pass 1:1 */
1688   if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
1689      /* Always center screen on LVDS (if scaling is disabled) */
1690      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1691   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1692      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1693         /* Always center screen on SiS LVDS (if scaling is disabled) */
1694         SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1695      } else {
1696         /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
1697         if(panelcanscale)             SiS_Pr->SiS_LCDInfo |= LCDPass11;
1698         if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1699      }
1700   }
1701
1702   SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1703   SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1704
1705   switch(SiS_Pr->SiS_LCDResInfo) {
1706      case Panel_320x480:    SiS_Pr->PanelXRes =  320; SiS_Pr->PanelYRes =  480;
1707                             SiS_Pr->PanelHT   =  400; SiS_Pr->PanelVT   =  525;
1708                             SiS_Pr->PanelVCLKIdx300 = VCLK28;
1709                             SiS_Pr->PanelVCLKIdx315 = VCLK28;
1710                             break;
1711      case Panel_640x480_2:
1712      case Panel_640x480_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
1713                             SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
1714                             SiS_Pr->PanelVCLKIdx300 = VCLK28;
1715                             SiS_Pr->PanelVCLKIdx315 = VCLK28;
1716                             break;
1717      case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
1718                                                       SiS_Pr->PanelVRE  =    3;
1719                             SiS_Pr->PanelVCLKIdx300 = VCLK28;
1720                             SiS_Pr->PanelVCLKIdx315 = VCLK28;
1721                             break;
1722      case Panel_800x600:    SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600;
1723                             SiS_Pr->PanelHT   = 1056; SiS_Pr->PanelVT   =  628;
1724                             SiS_Pr->PanelHRS  =   40; SiS_Pr->PanelHRE  =  128;
1725                             SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    4;
1726                             SiS_Pr->PanelVCLKIdx300 = VCLK40;
1727                             SiS_Pr->PanelVCLKIdx315 = VCLK40;
1728                             break;
1729      case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
1730                             SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
1731                             SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
1732                             SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
1733                             SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1734                             SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
1735                             break;
1736      case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
1737                             SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
1738                             SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
1739                             SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1740                             if(HwInfo->jChipType < SIS_315H) {
1741                                SiS_Pr->PanelHRS = 23;
1742                                                       SiS_Pr->PanelVRE  =    5;
1743                             }
1744                             SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1745                             SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
1746                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1747                             break;
1748      case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
1749                             SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
1750                             SiS_Pr->PanelHRS  =   24;
1751                             SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1752                             if(HwInfo->jChipType < SIS_315H) {
1753                                SiS_Pr->PanelHRS = 23;
1754                                                       SiS_Pr->PanelVRE  =    5;
1755                             }
1756                             SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1757                             SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
1758                             break;
1759      case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
1760                             break;
1761      case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
1762                             SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
1763                             SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
1764                             SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
1765                             SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
1766                             /* Data above for TMDS (projector); get from BIOS for LVDS */
1767                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1768                             break;
1769      case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
1770                             if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1771                                SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
1772                                SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
1773                                SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
1774                             } else {
1775                                SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
1776                                SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRS  =  112;
1777                                SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1778                                SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
1779                                SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
1780                             }
1781                             break;
1782      case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
1783                             SiS_Pr->PanelHT   = 1660; SiS_Pr->PanelVT   =  806;
1784                             SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
1785                             SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1786                             SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
1787                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1788                             break;
1789      case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
1790                             SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
1791                             SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
1792                             SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
1793                             SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
1794                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1795                             break;
1796      case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
1797                             SiS_Pr->PanelHT   = 1552; SiS_Pr->PanelVT   =  812;
1798                             SiS_Pr->PanelHRS   =  48; SiS_Pr->PanelHRE  =  112;
1799                             SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
1800                             SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
1801                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1802                             break;
1803      case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
1804                             SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
1805                             SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1806                             SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
1807                             if(resinfo == SIS_RI_1280x1024) {
1808                                SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
1809                                SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
1810                             }
1811                             break;
1812      case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
1813                             SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
1814                             SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
1815                             SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
1816                             SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1817                             SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1818                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1819                             break;
1820      case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
1821                             SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
1822                             SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112; /* HRE OK for LVDS, not for LCDA */
1823                             SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
1824                             SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1825                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1826                             break;
1827      case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
1828                             SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
1829                             SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
1830                             SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
1831                             SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
1832                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1833                             break;
1834      case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
1835                             SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
1836                             SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
1837                             SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1838                             SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
1839                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1840                             break;
1841      case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
1842                             SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
1843                             break;
1844      case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
1845                             SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
1846                             break;
1847      case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
1848                             SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
1849                             SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
1850                             SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
1851                             if(SiS_Pr->CP_PreferredIndex != -1) {
1852                                SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
1853                                SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
1854                                SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
1855                                SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
1856                                SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
1857                                SiS_Pr->PanelHRE  = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
1858                                SiS_Pr->PanelVRS  = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
1859                                SiS_Pr->PanelVRE  = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
1860                                SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
1861                                SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
1862                                SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
1863                                SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
1864                                if(SiS_Pr->CP_PrefClock) {
1865                                   int idx;
1866                                   SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1867                                   SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
1868                                   if(HwInfo->jChipType < SIS_315H) idx = VCLK_CUSTOM_300;
1869                                   else                             idx = VCLK_CUSTOM_315;
1870                                   SiS_Pr->SiS_VCLKData[idx].CLOCK =
1871                                      SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
1872                                   SiS_Pr->SiS_VCLKData[idx].SR2B =
1873                                      SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
1874                                   SiS_Pr->SiS_VCLKData[idx].SR2C =
1875                                      SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
1876                                }
1877                             }
1878                             break;
1879      default:               SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
1880                             SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
1881                             break;
1882   }
1883
1884   /* Special cases */
1885   if( (SiS_Pr->SiS_IF_DEF_FSTN)              ||
1886       (SiS_Pr->SiS_IF_DEF_DSTN)              ||
1887       (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1888       (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
1889       (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
1890      SiS_Pr->PanelHRS = 999;
1891      SiS_Pr->PanelHRE = 999;
1892   }
1893
1894   if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1895       (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
1896       (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
1897      SiS_Pr->PanelVRS = 999;
1898      SiS_Pr->PanelVRE = 999;
1899   }
1900
1901   /* DontExpand overrule */
1902   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
1903
1904      if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
1905         /* No scaling for this mode on any panel (LCD=CRT2)*/
1906         SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1907      }
1908
1909      switch(SiS_Pr->SiS_LCDResInfo) {
1910
1911      case Panel_Custom:
1912      case Panel_1152x864:
1913      case Panel_1280x768:       /* TMDS only */
1914         SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1915         break;
1916
1917      case Panel_800x600: {
1918         static const UCHAR nonscalingmodes[] = {
1919            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
1920         };
1921         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1922         break;
1923      }
1924      case Panel_1024x768: {
1925         static const UCHAR nonscalingmodes[] = {
1926            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1927            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1928            0xff
1929         };
1930         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1931         break;
1932      }
1933      case Panel_1280x720: {
1934         static const UCHAR nonscalingmodes[] = {
1935            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1936            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1937            0xff
1938         };
1939         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1940         if(SiS_Pr->PanelHT == 1650) {
1941            SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1942         }
1943         break;
1944      }
1945      case Panel_1280x768_2: {  /* LVDS only */
1946         static const UCHAR nonscalingmodes[] = {
1947            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1948            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1949            SIS_RI_1152x768,0xff
1950         };
1951         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1952         switch(resinfo) {
1953         case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
1954                                   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1955                                }
1956                                break;
1957         }
1958         break;
1959      }
1960      case Panel_1280x800: {     /* SiS TMDS special (Averatec 6200 series) */
1961         static const UCHAR nonscalingmodes[] = {
1962            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1963            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1964            SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
1965         };
1966         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1967         break;
1968      }
1969      case Panel_1280x800_2:  {  /* SiS LVDS */
1970         static const UCHAR nonscalingmodes[] = {
1971            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1972            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1973            SIS_RI_1152x768,0xff
1974         };
1975         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1976         switch(resinfo) {
1977         case SIS_RI_1280x720:
1978         case SIS_RI_1280x768:  if(SiS_Pr->UsePanelScaler == -1) {
1979                                   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1980                                }
1981                                break;
1982         }
1983         break;
1984      }
1985      case Panel_1280x960: {
1986         static const UCHAR nonscalingmodes[] = {
1987            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1988            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1989            SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
1990            0xff
1991         };
1992         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1993         break;
1994      }
1995      case Panel_1280x1024: {
1996         static const UCHAR nonscalingmodes[] = {
1997            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1998            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1999            SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2000            SIS_RI_1280x960,0xff
2001         };
2002         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2003         break;
2004      }
2005      case Panel_1400x1050: {
2006         static const UCHAR nonscalingmodes[] = {
2007              SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2008              SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2009              SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x960,
2010              0xff
2011         };
2012         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2013         switch(resinfo) {
2014         case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
2015                                   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2016                                }
2017                                break;
2018         case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2019                                break;
2020         }
2021         break;
2022      }
2023      case Panel_1600x1200: {
2024         static const UCHAR nonscalingmodes[] = {
2025              SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2026              SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2027              SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2028              SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
2029         };
2030         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2031         break;
2032      }
2033      case Panel_1680x1050: {
2034         static const UCHAR 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,SIS_RI_1152x864,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,
2038              0xff
2039         };
2040         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2041         break;
2042      }
2043      }
2044   }
2045
2046   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2047      if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
2048         SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
2049      }
2050   }
2051
2052 #ifdef SIS300
2053   if(HwInfo->jChipType < SIS_315H) {
2054      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2055         if(SiS_Pr->SiS_UseROM) {
2056            if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
2057               if(!(ROMAddr[0x235] & 0x02)) {
2058                  SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2059               }
2060            }
2061         }
2062      } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
2063         if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
2064            SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2065         }
2066      }
2067   }
2068 #endif
2069
2070   /* Special cases */
2071
2072   if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
2073      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2074   }
2075
2076   if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
2077      SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2078   }
2079
2080   switch(SiS_Pr->SiS_LCDResInfo) {
2081   case Panel_640x480:
2082      SiS_Pr->SiS_LCDInfo |= LCDPass11;
2083      break;
2084   case Panel_1280x800:
2085      /* Don't pass 1:1 by default (TMDS special) */
2086      if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2087      break;
2088   case Panel_1280x960:
2089      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2090      break;
2091   case Panel_Custom:
2092      if((!SiS_Pr->CP_PrefClock) ||
2093         (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
2094         SiS_Pr->SiS_LCDInfo |= LCDPass11;
2095      }
2096      break;
2097   }
2098
2099   if(SiS_Pr->UseCustomMode) {
2100      SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2101   }
2102
2103   /* (In)validate LCDPass11 flag */
2104   if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2105      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2106   }
2107
2108   /* LVDS DDA */
2109   if(!((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
2110
2111      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
2112         if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
2113            if(ModeNo == 0x12) {
2114               if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
2115                  SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2116               }
2117            } else if(ModeNo > 0x13) {
2118               if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
2119                  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2120                     if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
2121                        SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2122                     }
2123                  }
2124               }
2125            }
2126         }
2127      }
2128
2129      if(modeflag & HalfDCLK) {
2130         if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
2131            SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2132         } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
2133            SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2134         } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
2135            SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2136         } else if(ModeNo > 0x13) {
2137            if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
2138               if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2139            } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
2140               if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2141            }
2142         }
2143      }
2144
2145   }
2146
2147   /* VESA timing */
2148   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2149      if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
2150         SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2151      }
2152   } else {
2153      SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2154   }
2155
2156 #ifdef LINUX_KERNEL
2157 #ifdef TWDEBUG
2158   printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
2159         SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
2160 #endif
2161 #endif
2162 #ifdef LINUX_XF86
2163   xf86DrvMsgVerb(0, X_PROBED, 4,
2164         "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
2165         SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
2166 #endif
2167 }
2168
2169 /*********************************************/
2170 /*                 GET VCLK                  */
2171 /*********************************************/
2172
2173 USHORT
2174 SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
2175                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
2176 {
2177   USHORT CRT2Index,VCLKIndex=0,VCLKIndexGEN=0;
2178   USHORT modeflag,resinfo,tempbx;
2179   const UCHAR *CHTVVCLKPtr = NULL;
2180
2181   if(ModeNo <= 0x13) {
2182      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2183      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
2184      CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2185      VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
2186   } else {
2187      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2188      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2189      CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2190      VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
2191      if(HwInfo->jChipType < SIS_315H) VCLKIndexGEN &= 0x3f;
2192   }
2193
2194   if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
2195
2196      if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2197
2198         CRT2Index >>= 6;
2199         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {       /*  LCD */
2200
2201            if(HwInfo->jChipType < SIS_315H) {
2202               VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2203               if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2204                  VCLKIndex = VCLKIndexGEN;
2205               }
2206            } else {
2207               VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2208               if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2209                  switch(resinfo) {
2210                  /* Only those whose IndexGEN doesn't match VBVCLK array */
2211                  case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
2212                  case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
2213                  case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
2214                  case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
2215                  case SIS_RI_848x480:  VCLKIndex = VCLK_848x480;  break;
2216                  case SIS_RI_856x480:  VCLKIndex = VCLK_856x480;  break;
2217                  case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
2218                  case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
2219                  case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
2220                  case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
2221                  default:              VCLKIndex = VCLKIndexGEN;
2222                  }
2223
2224                  if(ModeNo <= 0x13) {
2225                     if(HwInfo->jChipType <= SIS_315PRO) {
2226                        if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
2227                     } else {
2228                        if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
2229                     }
2230                  }
2231                  if(HwInfo->jChipType <= SIS_315PRO) {
2232                     if(VCLKIndex == 0) VCLKIndex = 0x41;
2233                     if(VCLKIndex == 1) VCLKIndex = 0x43;
2234                     if(VCLKIndex == 4) VCLKIndex = 0x44;
2235                  }
2236               }
2237            }
2238
2239         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                   /*  TV */
2240
2241            if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2242               if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)             VCLKIndex = HiTVVCLKDIV2;
2243               else                                              VCLKIndex = HiTVVCLK;
2244               if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
2245                  if(modeflag & Charx8Dot)                       VCLKIndex = HiTVSimuVCLK;
2246                  else                                           VCLKIndex = HiTVTextVCLK;
2247               }
2248            } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)       VCLKIndex = YPbPr750pVCLK;
2249            else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)         VCLKIndex = TVVCLKDIV2;
2250            else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)           VCLKIndex = TVVCLKDIV2;
2251            else                                                 VCLKIndex = TVVCLK;
2252
2253            if(HwInfo->jChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
2254            else                             VCLKIndex += TVCLKBASE_315;
2255
2256         } else {                                                        /* VGA2 */
2257
2258            VCLKIndex = VCLKIndexGEN;
2259            if(HwInfo->jChipType < SIS_315H) {
2260               if(ModeNo > 0x13) {
2261                  if( (HwInfo->jChipType == SIS_630) &&
2262                      (HwInfo->jChipRevision >= 0x30)) {
2263                     if(VCLKIndex == 0x14) VCLKIndex = 0x34;
2264                  }
2265                  /* Better VGA2 clock for 1280x1024@75 */
2266                  if(VCLKIndex == 0x17) VCLKIndex = 0x45;
2267               }
2268            }
2269         }
2270
2271      } else {   /* If not programming CRT2 */
2272
2273         VCLKIndex = VCLKIndexGEN;
2274         if(HwInfo->jChipType < SIS_315H) {
2275            if(ModeNo > 0x13) {
2276               if( (HwInfo->jChipType != SIS_630) &&
2277                   (HwInfo->jChipType != SIS_300) ) {
2278                  if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2279               }
2280            }
2281         }
2282      }
2283
2284   } else {       /*   LVDS  */
2285
2286      VCLKIndex = CRT2Index;
2287
2288      if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2289
2290         if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
2291
2292            VCLKIndex &= 0x1f;
2293            tempbx = 0;
2294            if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2295            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2296               tempbx += 2;
2297               if(SiS_Pr->SiS_ModeType > ModeVGA) {
2298                  if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
2299               }
2300               if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2301                  tempbx = 4;
2302                  if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2303               } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2304                  tempbx = 6;
2305                  if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2306               }
2307            }
2308            switch(tempbx) {
2309              case  0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC;  break;
2310              case  1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC;  break;
2311              case  2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL;   break;
2312              case  3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
2313              case  4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM;  break;
2314              case  5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM;  break;
2315              case  6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN;  break;
2316              case  7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN;  break;
2317              case  8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL;  break;
2318              default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
2319            }
2320            VCLKIndex = CHTVVCLKPtr[VCLKIndex];
2321
2322         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2323
2324            if(HwInfo->jChipType < SIS_315H) {
2325               VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2326            } else {
2327               VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2328            }
2329
2330            /* Special Timing: Barco iQ Pro R series */
2331            if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2332
2333            /* Special Timing: 848x480 parallel lvds */
2334            if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
2335               if(HwInfo->jChipType < SIS_315H) {
2336                  VCLKIndex = VCLK34_300;
2337                  /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2338               } else {
2339                  VCLKIndex = VCLK34_315;
2340                  /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2341               }
2342            }
2343
2344         } else {
2345
2346            VCLKIndex = VCLKIndexGEN;
2347            if(HwInfo->jChipType < SIS_315H) {
2348               if(ModeNo > 0x13) {
2349                  if( (HwInfo->jChipType == SIS_630) &&
2350                      (HwInfo->jChipRevision >= 0x30) ) {
2351                     if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
2352                  }
2353               }
2354            }
2355         }
2356
2357      } else {  /* if not programming CRT2 */
2358
2359         VCLKIndex = VCLKIndexGEN;
2360         if(HwInfo->jChipType < SIS_315H) {
2361            if(ModeNo > 0x13) {
2362               if( (HwInfo->jChipType != SIS_630) &&
2363                   (HwInfo->jChipType != SIS_300) ) {
2364                  if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2365               }
2366 #if 0
2367               if(HwInfo->jChipType == SIS_730) {
2368                  if(VCLKIndex == 0x0b) VCLKIndex = 0x40;   /* 1024x768-70 */
2369                  if(VCLKIndex == 0x0d) VCLKIndex = 0x41;   /* 1024x768-75 */
2370               }
2371 #endif
2372            }
2373         }
2374
2375      }
2376
2377   }
2378
2379 #ifdef TWDEBUG
2380   xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
2381 #endif
2382
2383   return(VCLKIndex);
2384 }
2385
2386 /*********************************************/
2387 /*        SET CRT2 MODE TYPE REGISTERS       */
2388 /*********************************************/
2389
2390 static void
2391 SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
2392                     PSIS_HW_INFO HwInfo)
2393 {
2394   USHORT i,j,modeflag;
2395   USHORT tempcl,tempah=0;
2396 #if defined(SIS300) || defined(SIS315H)
2397   USHORT tempbl;
2398 #endif
2399 #ifdef SIS315H
2400   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
2401   USHORT tempah2, tempbl2;
2402 #endif
2403
2404   if(ModeNo <= 0x13) {
2405      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2406   } else if(SiS_Pr->UseCustomMode) {
2407      modeflag = SiS_Pr->CModeFlag;
2408   } else {
2409      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2410   }
2411
2412   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2413
2414      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
2415      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
2416
2417   } else {
2418
2419      for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
2420      if(HwInfo->jChipType >= SIS_315H) {
2421         SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
2422      }
2423
2424      tempcl = SiS_Pr->SiS_ModeType;
2425
2426      if(HwInfo->jChipType < SIS_315H) {
2427
2428 #ifdef SIS300    /* ---- 300 series ---- */
2429
2430         /* For 301BDH: (with LCD via LVDS) */
2431         if(SiS_Pr->SiS_VBType & VB_NoLCD) {
2432            tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
2433            tempbl &= 0xef;
2434            tempbl |= 0x02;
2435            if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2436               tempbl |= 0x10;
2437               tempbl &= 0xfd;
2438            }
2439            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
2440         }
2441
2442         if(ModeNo > 0x13) {
2443            tempcl -= ModeVGA;
2444            if((tempcl > 0) || (tempcl == 0)) {      /* tempcl is USHORT -> always true! */
2445               tempah = ((0x10 >> tempcl) | 0x80);
2446            }
2447         } else tempah = 0x80;
2448
2449         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  tempah ^= 0xA0;
2450
2451 #endif  /* SIS300 */
2452
2453      } else {
2454
2455 #ifdef SIS315H    /* ------- 315/330 series ------ */
2456
2457         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
2458            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2459               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x08);
2460            }
2461         }
2462
2463         if(ModeNo > 0x13) {
2464            tempcl -= ModeVGA;
2465            if((tempcl > 0) || (tempcl == 0)) {  /* tempcl is USHORT -> always true! */
2466               tempah = (0x08 >> tempcl);
2467               if (tempah == 0) tempah = 1;
2468               tempah |= 0x40;
2469            }
2470         } else tempah = 0x40;
2471
2472         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
2473
2474 #endif  /* SIS315H */
2475
2476      }
2477
2478      if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2479
2480      if(HwInfo->jChipType < SIS_315H) {
2481         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2482      } else {
2483         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2484            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2485         } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2486            if(IS_SIS740) {
2487               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2488            } else {
2489               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2490            }
2491         }
2492      }
2493
2494      if(SiS_Pr->SiS_VBType & VB_SISVB) {
2495
2496         tempah = 0x01;
2497         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2498            tempah |= 0x02;
2499         }
2500         if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2501            tempah ^= 0x05;
2502            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
2503               tempah ^= 0x01;
2504            }
2505         }
2506
2507         if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
2508
2509         if(HwInfo->jChipType < SIS_315H) {
2510
2511            tempah = (tempah << 5) & 0xFF;
2512            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2513            tempah = (tempah >> 5) & 0xFF;
2514
2515         } else {
2516
2517            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF8,tempah);
2518
2519         }
2520
2521         if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
2522            tempah |= 0x10;
2523         }
2524
2525         tempah |= 0x80;
2526         if(SiS_Pr->SiS_VBType & VB_SIS301) {
2527            if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
2528         }
2529
2530         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2531            if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
2532               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2533                  tempah |= 0x20;
2534               }
2535            }
2536         }
2537
2538         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
2539
2540         tempah = 0x80;
2541         if(SiS_Pr->SiS_VBType & VB_SIS301) {
2542            if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
2543         }
2544
2545         if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempah |= 0x40;
2546
2547         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2548            if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
2549               tempah |= 0x40;
2550            }
2551         }
2552
2553         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
2554
2555      } else {  /* LVDS */
2556
2557         if(HwInfo->jChipType >= SIS_315H) {
2558
2559 #ifdef SIS315H
2560            /* LVDS can only be slave in 8bpp modes */
2561            tempah = 0x80;
2562            if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
2563               if(SiS_Pr->SiS_VBInfo & DriverMode) {
2564                  tempah |= 0x02;
2565               }
2566            }
2567
2568            if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2569               tempah |= 0x02;
2570            }
2571
2572            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2573               tempah ^= 0x01;
2574            }
2575
2576            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2577               tempah = 1;
2578            }
2579
2580            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
2581 #endif
2582
2583         } else {
2584
2585 #ifdef SIS300
2586            tempah = 0;
2587            if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
2588               tempah |= 0x02;
2589            }
2590            tempah <<= 5;
2591
2592            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
2593
2594            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2595 #endif
2596
2597         }
2598
2599      }
2600
2601   }  /* LCDA */
2602
2603   if(SiS_Pr->SiS_VBType & VB_SISVB) {
2604
2605      if(HwInfo->jChipType >= SIS_315H) {
2606
2607 #ifdef SIS315H
2608         unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
2609
2610         /* The following is nearly unpreditable and varies from machine
2611          * to machine. Especially the 301DH seems to be a real trouble
2612          * maker. Some BIOSes simply set the registers (like in the
2613          * NoLCD-if-statements here), some set them according to the
2614          * LCDA stuff. It is very likely that some machines are not
2615          * treated correctly in the following, very case-orientated
2616          * code. What do I do then...?
2617          */
2618
2619         /* 740 variants match for 30xB, 301B-DH, 30xLV */
2620
2621         if(!(IS_SIS740)) {
2622            tempah = 0x04;                                                  /* For all bridges */
2623            tempbl = 0xfb;
2624            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2625               tempah = 0x00;
2626               if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
2627                  tempbl = 0xff;
2628               }
2629            }
2630            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2631         }
2632
2633         /* The following two are responsible for eventually wrong colors
2634          * in TV output. The DH (VB_NoLCD) conditions are unknown; the
2635          * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
2636          * in a 650 box (Jake). What is the criteria?
2637          */
2638
2639         if((IS_SIS740) || (HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
2640            tempah = 0x30;
2641            tempbl = 0xc0;
2642            if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2643               ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
2644               tempah = 0x00;
2645               tempbl = 0x00;
2646            }
2647            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
2648            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
2649         } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
2650            /* Fixes "TV-blue-bug" on 315+301 */
2651            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf);     /* For 301   */
2652            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
2653         } else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
2654            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);      /* For 30xLV */
2655            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
2656         } else if((SiS_Pr->SiS_VBType & VB_NoLCD) && (bridgerev == 0xb0)) {
2657            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);      /* For 30xB-DH rev b0 (or "DH on 651"?) */
2658            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
2659         } else {
2660            tempah = 0x30; tempah2 = 0xc0;                      /* For 30xB (and 301BDH rev b1) */
2661            tempbl = 0xcf; tempbl2 = 0x3f;
2662            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2663               tempah = tempah2 = 0x00;
2664               if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
2665                  tempbl = tempbl2 = 0xff;
2666               }
2667            }
2668            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2669            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2670         }
2671
2672         if(IS_SIS740) {
2673            tempah = 0x80;
2674            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
2675            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
2676         } else {
2677            tempah = 0x00;
2678            tempbl = 0x7f;
2679            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2680               tempbl = 0xff;
2681               if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) tempah = 0x80;
2682            }
2683            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
2684         }
2685
2686 #endif /* SIS315H */
2687
2688      } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
2689
2690 #ifdef SIS300
2691         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
2692
2693         if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2694            ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
2695             (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
2696            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
2697         } else {
2698            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
2699         }
2700 #endif
2701
2702      }
2703
2704      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
2705         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
2706         if(SiS_Pr->SiS_VBType & VB_SIS301C) {
2707            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
2708         }
2709      }
2710
2711   } else {  /* LVDS */
2712
2713 #ifdef SIS315H
2714      if(HwInfo->jChipType >= SIS_315H) {
2715
2716         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
2717
2718            tempah = 0x04;
2719            tempbl = 0xfb;
2720            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2721               tempah = 0x00;
2722               if(SiS_IsDualEdge(SiS_Pr, HwInfo)) tempbl = 0xff;
2723            }
2724            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2725
2726            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2727               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2728            }
2729
2730            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2731
2732         } else if(HwInfo->jChipType == SIS_550) {
2733
2734            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2735            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2736
2737         }
2738
2739      }
2740 #endif
2741
2742   }
2743
2744 }
2745
2746 /*********************************************/
2747 /*            GET RESOLUTION DATA            */
2748 /*********************************************/
2749
2750 USHORT
2751 SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
2752 {
2753   if(ModeNo <= 0x13) return((USHORT)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
2754   else               return((USHORT)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
2755 }
2756
2757 static void
2758 SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
2759                    PSIS_HW_INFO HwInfo)
2760 {
2761   USHORT xres,yres,modeflag=0,resindex;
2762
2763   if(SiS_Pr->UseCustomMode) {
2764      xres = SiS_Pr->CHDisplay;
2765      if(SiS_Pr->CModeFlag & HalfDCLK) xres *= 2;
2766      SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2767      yres = SiS_Pr->CVDisplay;
2768      if(SiS_Pr->CModeFlag & DoubleScanMode) yres *= 2;
2769      SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
2770      return;
2771   }
2772
2773   resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
2774
2775   if(ModeNo <= 0x13) {
2776      xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
2777      yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
2778   } else {
2779      xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
2780      yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
2781      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2782   }
2783
2784   if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
2785
2786      if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
2787         if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
2788            if(yres == 350) yres = 400;
2789         }
2790         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
2791            if(ModeNo == 0x12) yres = 400;
2792         }
2793      }
2794
2795      if(modeflag & HalfDCLK)       xres *= 2;
2796      if(modeflag & DoubleScanMode) yres *= 2;
2797
2798   }
2799
2800   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
2801
2802 #if 0
2803         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
2804            if(xres == 720) xres = 640;
2805         }
2806 #endif
2807
2808         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2809            switch(SiS_Pr->SiS_LCDResInfo) {
2810            case Panel_1024x768:
2811               if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
2812                  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2813                     if(yres == 350) yres = 357;
2814                     if(yres == 400) yres = 420;
2815                     if(yres == 480) yres = 525;
2816                  }
2817               }
2818               break;
2819            case Panel_1280x1024:
2820               if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2821                  /* BIOS bug - does this regardless of scaling */
2822                  if(yres == 400) yres = 405;
2823               }
2824               if(yres == 350) yres = 360;
2825               if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
2826                  if(yres == 360) yres = 375;
2827               }
2828               break;
2829            case Panel_1600x1200:
2830               if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
2831                  if(yres == 1024) yres = 1056;
2832               }
2833               break;
2834            }
2835         }
2836
2837   } else {
2838
2839      if(SiS_Pr->SiS_VBType & VB_SISVB) {
2840         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
2841            if(xres == 720) xres = 640;
2842         }
2843      } else if(xres == 720) xres = 640;
2844
2845      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
2846         yres = 400;
2847         if(HwInfo->jChipType >= SIS_315H) {
2848            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
2849         } else {
2850            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
2851         }
2852         if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN)  yres = 480;
2853      }
2854
2855   }
2856   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2857   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
2858 }
2859
2860 /*********************************************/
2861 /*           GET CRT2 TIMING DATA            */
2862 /*********************************************/
2863
2864 static BOOLEAN
2865 SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
2866                    USHORT RefreshRateTableIndex, USHORT *ResIndex,
2867                    USHORT *DisplayType)
2868  {
2869   USHORT modeflag=0;
2870
2871   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2872      if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2873         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
2874      }
2875   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2876      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))    return FALSE;
2877   } else
2878      return FALSE;
2879
2880   if(ModeNo <= 0x13) {
2881      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2882      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2883   } else {
2884      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2885      (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2886   }
2887
2888   (*ResIndex) &= 0x3F;
2889
2890   if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
2891      (*DisplayType) = 18;
2892      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
2893      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2894         (*DisplayType) += 2;
2895         if(SiS_Pr->SiS_ModeType > ModeVGA) {
2896            if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 99;
2897         }
2898         if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2899            (*DisplayType) = 18;  /* PALM uses NTSC data */
2900            if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
2901         } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2902            (*DisplayType) = 20;  /* PALN uses PAL data  */
2903            if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
2904         }
2905      }
2906   } else {
2907      switch(SiS_Pr->SiS_LCDResInfo) {
2908      case Panel_640x480:   (*DisplayType) = 50; break;
2909      case Panel_640x480_2: (*DisplayType) = 52; break;
2910      case Panel_640x480_3: (*DisplayType) = 54; break;
2911      case Panel_800x600:   (*DisplayType) =  0; break;
2912      case Panel_1024x600:  (*DisplayType) = 23; break;
2913      case Panel_1024x768:  (*DisplayType) =  4; break;
2914      case Panel_1152x768:  (*DisplayType) = 27; break;
2915      case Panel_1280x768:  (*DisplayType) = 40; break;
2916      case Panel_1280x1024: (*DisplayType) =  8; break;
2917      case Panel_1400x1050: (*DisplayType) = 14; break;
2918      case Panel_1600x1200: (*DisplayType) = 36; break;
2919      default: return FALSE;
2920      }
2921
2922      if(modeflag & HalfDCLK) (*DisplayType)++;
2923
2924      switch(SiS_Pr->SiS_LCDResInfo) {
2925      case Panel_640x480:
2926      case Panel_640x480_2:
2927      case Panel_640x480_3:
2928         break;
2929      default:
2930         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
2931      }
2932
2933      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
2934         (*DisplayType) = 12;
2935         if(modeflag & HalfDCLK) (*DisplayType)++;
2936      }
2937   }
2938
2939 #if 0
2940   if(SiS_Pr->SiS_IF_DEF_FSTN) {
2941      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
2942         (*DisplayType) = 22;
2943      }
2944   }
2945 #endif
2946
2947   return TRUE;
2948 }
2949
2950 static void
2951 SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
2952                USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex,
2953                PSIS_HW_INFO HwInfo)
2954 {
2955   USHORT tempbx=0,tempal=0,resinfo=0;
2956
2957   if(ModeNo <= 0x13) {
2958      tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2959   } else {
2960      tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2961      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2962   }
2963
2964   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
2965
2966      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
2967
2968         tempbx = SiS_Pr->SiS_LCDResInfo;
2969         if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
2970
2971         if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
2972            if     (resinfo == SIS_RI_1280x800)  tempal =  9;
2973            else if(resinfo == SIS_RI_1400x1050) tempal = 11;
2974         } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
2975                   (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2)) {
2976            if     (resinfo == SIS_RI_1280x768)  tempal =  9;
2977         }
2978
2979         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
2980            /* Pass 1:1 only (center-screen handled outside) */
2981            /* This is never called for the panel's native resolution */
2982            /* since Pass1:1 will not be set in this case */
2983            tempbx = 100;
2984            if(ModeNo >= 0x13) {
2985               tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
2986            }
2987         }
2988
2989 #ifdef SIS315H
2990         if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
2991            if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
2992               if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2993                  tempbx = 200;
2994                  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
2995               }
2996            }
2997         }
2998 #endif
2999
3000      } else {                                                   /* TV */
3001
3002         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3003            /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
3004            tempbx = 2;
3005            if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3006               tempbx = 13;
3007               if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
3008            }
3009         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3010            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      tempbx = 7;
3011            else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
3012            else                                         tempbx = 5;
3013            if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
3014         } else {
3015            if(SiS_Pr->SiS_TVMode & TVSetPAL)            tempbx = 3;
3016            else                                         tempbx = 4;
3017            if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
3018         }
3019
3020      }
3021
3022      tempal &= 0x3F;
3023
3024      if(ModeNo > 0x13) {
3025         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
3026            if(tempal == 6) tempal = 7;
3027            if((resinfo == SIS_RI_720x480) ||
3028               (resinfo == SIS_RI_720x576) ||
3029               (resinfo == SIS_RI_768x576)) {
3030               tempal = 6;
3031               if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) {
3032                  if(resinfo == SIS_RI_720x480) tempal = 9;
3033               }
3034            }
3035            if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3036               if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3037                  if(resinfo == SIS_RI_1024x768) tempal = 8;
3038               }
3039               if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3040                  if((resinfo == SIS_RI_720x576) ||
3041                     (resinfo == SIS_RI_768x576)) {
3042                     tempal = 8;
3043                  }
3044                  if(resinfo == SIS_RI_1280x720) tempal = 9;
3045               }
3046            }
3047         }
3048      }
3049
3050      *CRT2Index = tempbx;
3051      *ResIndex = tempal;
3052
3053   } else {   /* LVDS, 301B-DH (if running on LCD) */
3054
3055      tempbx = 0;
3056      if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
3057
3058         tempbx = 10;
3059         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
3060         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
3061            tempbx += 2;
3062            if(SiS_Pr->SiS_ModeType > ModeVGA) {
3063               if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
3064            }
3065            if(SiS_Pr->SiS_TVMode & TVSetPALM) {
3066               tempbx = 90;
3067               if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
3068            } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
3069               tempbx = 92;
3070               if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
3071            }
3072         }
3073
3074      } else {
3075
3076         switch(SiS_Pr->SiS_LCDResInfo) {
3077         case Panel_640x480:   tempbx = 6;  break;
3078         case Panel_640x480_2:
3079         case Panel_640x480_3: tempbx = 30; break;
3080         case Panel_800x600:   tempbx = 0;  break;
3081         case Panel_1024x600:  tempbx = 15; break;
3082         case Panel_1024x768:  tempbx = 2;  break;
3083         case Panel_1152x768:  tempbx = 17; break;
3084         case Panel_1280x768:  tempbx = 18; break;
3085         case Panel_1280x1024: tempbx = 4;  break;
3086         case Panel_1400x1050: tempbx = 8;  break;
3087         case Panel_1600x1200: tempbx = 21; break;
3088         case Panel_Barco1366: tempbx = 80; break;
3089         }
3090
3091         switch(SiS_Pr->SiS_LCDResInfo) {
3092         case Panel_640x480:
3093         case Panel_640x480_2:
3094         case Panel_640x480_3:
3095            break;
3096         default:
3097            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3098         }
3099
3100         if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 7;
3101
3102         if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3103            tempbx = 82;
3104            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3105         } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
3106            tempbx = 84;
3107            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3108         }
3109
3110         if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
3111            (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
3112            if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
3113               (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
3114               tempal = 0;
3115            }
3116         }
3117
3118      }
3119
3120      (*CRT2Index) = tempbx;
3121      (*ResIndex) = tempal & 0x1F;
3122   }
3123 }
3124
3125 static void
3126 SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
3127                    USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
3128 {
3129   USHORT tempax=0,tempbx=0;
3130   USHORT temp1=0,modeflag=0,tempcx=0;
3131   USHORT index;
3132
3133   SiS_Pr->SiS_RVBHCMAX  = 1;
3134   SiS_Pr->SiS_RVBHCFACT = 1;
3135
3136   if(ModeNo <= 0x13) {
3137
3138      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3139      index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
3140
3141      tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
3142      tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
3143      temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
3144
3145   } else {
3146
3147      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3148      index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
3149
3150      tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
3151      tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
3152      tempax &= 0x03FF;
3153      tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
3154      tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
3155      tempcx &= 0x0100;
3156      tempcx <<= 2;
3157      tempbx |= tempcx;
3158      temp1  = SiS_Pr->SiS_CRT1Table[index].CR[7];
3159
3160   }
3161
3162   if(temp1 & 0x01) tempbx |= 0x0100;
3163   if(temp1 & 0x20) tempbx |= 0x0200;
3164
3165   tempax += 5;
3166
3167   /* Charx8Dot is no more used (and assumed), so we set it */
3168   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
3169      modeflag |= Charx8Dot;
3170   }
3171
3172   if(modeflag & Charx8Dot) tempax *= 8;
3173   else                     tempax *= 9;
3174
3175   if(modeflag & HalfDCLK)  tempax <<= 1;
3176
3177   tempbx++;
3178
3179   SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3180   SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
3181 }
3182
3183 static void
3184 SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
3185                     USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
3186 {
3187    USHORT CRT2Index, ResIndex;
3188    const SiS_LVDSDataStruct *LVDSData = NULL;
3189
3190    SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
3191
3192    if(SiS_Pr->SiS_VBType & VB_SISVB) {
3193       SiS_Pr->SiS_RVBHCMAX  = 1;
3194       SiS_Pr->SiS_RVBHCFACT = 1;
3195       SiS_Pr->SiS_NewFlickerMode = 0;
3196       SiS_Pr->SiS_RVBHRS = 50;
3197       SiS_Pr->SiS_RY1COE = 0;
3198       SiS_Pr->SiS_RY2COE = 0;
3199       SiS_Pr->SiS_RY3COE = 0;
3200       SiS_Pr->SiS_RY4COE = 0;
3201    }
3202
3203    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3204
3205 #ifdef SIS315H
3206       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3207          if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3208             if(SiS_Pr->UseCustomMode) {
3209                SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
3210                SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3211             } else {
3212                if(ModeNo < 0x13) {
3213                   ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3214                } else {
3215                   ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3216                }
3217                SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
3218                SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
3219                SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
3220                SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
3221             }
3222          } else {
3223             SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3224             SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3225          }
3226       } else {
3227          /* This handles custom modes and custom panels */
3228          SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3229          SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3230          SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
3231          SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
3232          SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
3233          SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
3234       }
3235
3236       SiS_CalcLCDACRT1Timing(SiS_Pr,ModeNo,ModeIdIndex);
3237
3238 #endif
3239
3240    } else {
3241
3242       /* 301BDH needs LVDS Data */
3243       if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3244          SiS_Pr->SiS_IF_DEF_LVDS = 1;
3245       }
3246
3247       SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
3248                                 &CRT2Index, &ResIndex, HwInfo);
3249
3250       /* 301BDH needs LVDS Data */
3251       if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3252          SiS_Pr->SiS_IF_DEF_LVDS = 0;
3253       }
3254
3255       switch (CRT2Index) {
3256          case  0: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
3257          case  1: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2;    break;
3258          case  2: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
3259          case  3: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2;   break;
3260          case  4: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1;  break;
3261          case  5: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2;  break;
3262          case  6: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
3263          case  7: LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1;    break;
3264          case  8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1;  break;
3265          case  9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2;  break;
3266          case 10: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
3267          case 11: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
3268          case 12: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
3269          case 13: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
3270          case 14: LVDSData = SiS_Pr->SiS_LVDS320x480Data_1;    break;
3271          case 15: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
3272          case 16: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2;   break;
3273          case 17: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1;   break;
3274          case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2;   break;
3275          case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1;   break;
3276          case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2;   break;
3277          case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1;  break;
3278          case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2;  break;
3279          case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2;    break;
3280          case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
3281          case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
3282          case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
3283          case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2;  break;
3284          case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
3285          case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
3286          case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
3287          case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
3288          case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
3289          case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
3290          case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;        break;  /* Super Overscan */
3291          default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
3292       }
3293
3294       SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
3295       SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
3296       SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
3297       SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
3298
3299       if(!(SiS_Pr->SiS_VBType & VB_SISVB)) {
3300          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
3301             if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3302                SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3303                SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3304                if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3305                   if(ResIndex < 0x08) {
3306                      SiS_Pr->SiS_HDE = 1280;
3307                      SiS_Pr->SiS_VDE = 1024;
3308                   }
3309                }
3310             }
3311          }
3312       }
3313    }
3314 }
3315
3316 static void
3317 SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
3318                    USHORT RefreshRateTableIndex,
3319                    PSIS_HW_INFO HwInfo)
3320 {
3321   UCHAR  *ROMAddr = NULL;
3322   USHORT tempax,tempbx,modeflag,romptr=0;
3323   USHORT resinfo,CRT2Index,ResIndex;
3324   const SiS_LCDDataStruct *LCDPtr = NULL;
3325   const SiS_TVDataStruct  *TVPtr  = NULL;
3326 #ifdef SIS315H
3327   SHORT  resinfo661;
3328 #endif
3329
3330   if(ModeNo <= 0x13) {
3331      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3332      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
3333   } else if(SiS_Pr->UseCustomMode) {
3334      modeflag = SiS_Pr->CModeFlag;
3335      resinfo = 0;
3336   } else {
3337      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3338      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
3339 #ifdef SIS315H
3340      resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3341      if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
3342          (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
3343          (resinfo661 >= 0)                     &&
3344          (SiS_Pr->SiS_NeedRomModeData) ) {
3345         if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
3346            if((romptr = (SISGETROMW(21)))) {
3347               romptr += (resinfo661 * 10);
3348               ROMAddr = HwInfo->pjVirtualRomBase;
3349            }
3350         }
3351      }
3352 #endif
3353   }
3354   
3355   SiS_Pr->SiS_NewFlickerMode = 0;
3356   SiS_Pr->SiS_RVBHRS = 50;
3357   SiS_Pr->SiS_RY1COE = 0;
3358   SiS_Pr->SiS_RY2COE = 0;
3359   SiS_Pr->SiS_RY3COE = 0;
3360   SiS_Pr->SiS_RY4COE = 0;
3361
3362   SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex,HwInfo);
3363
3364   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){
3365
3366      if(SiS_Pr->UseCustomMode) {
3367
3368         SiS_Pr->SiS_RVBHCMAX  = 1;
3369         SiS_Pr->SiS_RVBHCFACT = 1;
3370         SiS_Pr->SiS_VGAHT     = SiS_Pr->CHTotal;
3371         SiS_Pr->SiS_VGAVT     = SiS_Pr->CVTotal;
3372         SiS_Pr->SiS_HT        = SiS_Pr->CHTotal;
3373         SiS_Pr->SiS_VT        = SiS_Pr->CVTotal;
3374         SiS_Pr->SiS_HDE       = SiS_Pr->SiS_VGAHDE;
3375         SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
3376
3377      } else {
3378
3379         SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3380
3381      }
3382
3383   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3384
3385      SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3386                     &CRT2Index,&ResIndex,HwInfo);
3387
3388      switch(CRT2Index) {
3389         case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
3390         case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
3391         case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
3392         case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
3393         case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
3394         case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
3395         case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
3396         case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
3397         case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
3398         case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
3399         case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
3400         case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
3401         case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
3402         default: TVPtr = SiS_Pr->SiS_StPALData;     break;
3403      }
3404
3405      SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
3406      SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
3407      SiS_Pr->SiS_VGAHT     = (TVPtr+ResIndex)->VGAHT;
3408      SiS_Pr->SiS_VGAVT     = (TVPtr+ResIndex)->VGAVT;
3409      SiS_Pr->SiS_HDE       = (TVPtr+ResIndex)->TVHDE;
3410      SiS_Pr->SiS_VDE       = (TVPtr+ResIndex)->TVVDE;
3411      SiS_Pr->SiS_RVBHRS    = (TVPtr+ResIndex)->RVBHRS;
3412      SiS_Pr->SiS_NewFlickerMode = (TVPtr+ResIndex)->FlickerMode;
3413      if(modeflag & HalfDCLK) {
3414         SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
3415      }
3416
3417      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3418
3419         if((resinfo == SIS_RI_1024x768)  ||
3420            (resinfo == SIS_RI_1280x1024) ||
3421            (resinfo == SIS_RI_1280x720)) {
3422            SiS_Pr->SiS_NewFlickerMode = 0x40;
3423         }
3424
3425         if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
3426
3427         SiS_Pr->SiS_HT = ExtHiTVHT;
3428         SiS_Pr->SiS_VT = ExtHiTVVT;
3429         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3430            if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
3431               SiS_Pr->SiS_HT = StHiTVHT;
3432               SiS_Pr->SiS_VT = StHiTVVT;
3433 #if 0
3434               if(!(modeflag & Charx8Dot)) {
3435                  SiS_Pr->SiS_HT = StHiTextTVHT;
3436                  SiS_Pr->SiS_VT = StHiTextTVVT;
3437               }
3438 #endif
3439            }
3440         }
3441
3442      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3443
3444         if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3445            SiS_Pr->SiS_HT = 1650;
3446            SiS_Pr->SiS_VT = 750;
3447         } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3448            SiS_Pr->SiS_HT = NTSCHT;
3449            SiS_Pr->SiS_VT = NTSCVT;
3450         } else {
3451            SiS_Pr->SiS_HT = NTSCHT;
3452            if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
3453            SiS_Pr->SiS_VT = NTSCVT;
3454         }
3455
3456      } else {
3457
3458         SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
3459         SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
3460         SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
3461         SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
3462
3463         if(modeflag & HalfDCLK) {
3464            SiS_Pr->SiS_RY1COE = 0x00;
3465            SiS_Pr->SiS_RY2COE = 0xf4;
3466            SiS_Pr->SiS_RY3COE = 0x10;
3467            SiS_Pr->SiS_RY4COE = 0x38;
3468         }
3469
3470         if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
3471            SiS_Pr->SiS_HT = NTSCHT;
3472            if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
3473            SiS_Pr->SiS_VT = NTSCVT;
3474         } else {
3475            SiS_Pr->SiS_HT = PALHT;
3476            SiS_Pr->SiS_VT = PALVT;
3477         }
3478
3479      }
3480
3481   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3482
3483      SiS_Pr->SiS_RVBHCMAX  = 1;
3484      SiS_Pr->SiS_RVBHCFACT = 1;
3485
3486      if(SiS_Pr->UseCustomMode) {
3487
3488         SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal;
3489         SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal;
3490         SiS_Pr->SiS_HT    = SiS_Pr->CHTotal;
3491         SiS_Pr->SiS_VT    = SiS_Pr->CVTotal;
3492         SiS_Pr->SiS_HDE   = SiS_Pr->SiS_VGAHDE;
3493         SiS_Pr->SiS_VDE   = SiS_Pr->SiS_VGAVDE;
3494
3495      } else {
3496
3497         BOOLEAN gotit = FALSE;
3498
3499         if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
3500
3501            SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
3502            SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3503            SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
3504            SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
3505            gotit = TRUE;
3506
3507         } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3508
3509 #ifdef SIS315H
3510            SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
3511            SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3512            SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
3513            SiS_Pr->SiS_VGAVT     = ROMAddr[romptr+4] | ((ROMAddr[romptr+3] & 0xf0) << 4);
3514            SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
3515            SiS_Pr->SiS_VT        = ROMAddr[romptr+7] | ((ROMAddr[romptr+6] & 0xf0) << 4);
3516            if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
3517            else {
3518               SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
3519               SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
3520               SiS_Pr->SiS_VGAHT   = SiS_Pr->PanelHT;
3521               SiS_Pr->SiS_VGAVT   = SiS_Pr->PanelVT;
3522               SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
3523               SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
3524               gotit = TRUE;
3525            }
3526 #endif
3527
3528         }
3529
3530         if(!gotit) {
3531
3532            SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3533                           &CRT2Index,&ResIndex,HwInfo);
3534
3535            switch(CRT2Index) {
3536               case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
3537               case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
3538               case Panel_1280x720      :
3539               case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
3540               case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
3541               case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
3542               case Panel_1280x800      :
3543               case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
3544               case Panel_1280x800_2    :
3545               case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data;    break;
3546               case Panel_1280x960      :
3547               case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
3548               case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
3549               case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
3550               case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
3551               case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
3552               case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
3553               case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
3554               case Panel_1680x1050     :
3555               case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
3556               case 100                 : LCDPtr = SiS_Pr->SiS_NoScaleData;          break;
3557 #ifdef SIS315H
3558               case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
3559               case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
3560 #endif
3561               default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
3562            }
3563
3564 #ifdef TWDEBUG
3565            xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
3566 #endif
3567
3568            SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
3569            SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3570            SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
3571            SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
3572            SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
3573            SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
3574
3575         }
3576
3577         tempax = SiS_Pr->PanelXRes;
3578         tempbx = SiS_Pr->PanelYRes;
3579
3580         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3581            if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3582               if(HwInfo->jChipType < SIS_315H) {
3583                  if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3584                  else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3585               }
3586            } else {
3587               if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
3588               else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
3589               else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
3590               else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
3591               else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3592               else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3593            }
3594         } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) {
3595            if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
3596            else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
3597            else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
3598         } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
3599            if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
3600            else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
3601            else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
3602         } else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) {
3603            if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
3604               if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
3605               else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
3606            }
3607         }
3608
3609         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3610            tempax = SiS_Pr->SiS_VGAHDE;
3611            tempbx = SiS_Pr->SiS_VGAVDE;
3612         }
3613
3614         SiS_Pr->SiS_HDE = tempax;
3615         SiS_Pr->SiS_VDE = tempbx;
3616      }
3617   }
3618 }
3619
3620 static void
3621 SiS_GetCRT2Data(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
3622                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
3623 {
3624
3625   if(SiS_Pr->SiS_VBType & VB_SISVB) {
3626
3627      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3628         SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3629      } else {
3630         if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3631            /* Need LVDS Data for LCD on 301B-DH */
3632            SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3633         } else {
3634            SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3635         }
3636      }
3637
3638   } else {
3639
3640      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3641
3642   }
3643 }
3644
3645 /*********************************************/
3646 /*         GET LVDS DES (SKEW) DATA          */
3647 /*********************************************/
3648
3649 static void
3650 SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
3651                   USHORT RefreshRateTableIndex, USHORT *PanelIndex,
3652                   USHORT *ResIndex, PSIS_HW_INFO HwInfo)
3653 {
3654   USHORT modeflag;
3655
3656   if(ModeNo <= 0x13) {
3657      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3658      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3659   } else {
3660      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3661      (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3662   }
3663
3664   (*ResIndex) &= 0x1F;
3665   (*PanelIndex) = 0;
3666
3667   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
3668      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3669         (*PanelIndex) = 50;
3670         if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) (*PanelIndex) += 2;
3671         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*PanelIndex) += 1;
3672         /* Nothing special needed for SOverscan    */
3673         /* PALM uses NTSC data, PALN uses PAL data */
3674      }
3675   }
3676
3677   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3678      *PanelIndex = SiS_Pr->SiS_LCDTypeInfo;
3679      if(HwInfo->jChipType >= SIS_661) {
3680         /* As long as we don's use the BIOS tables, we
3681          * need to convert the TypeInfo as for 315 series
3682          */
3683         (*PanelIndex) = SiS_Pr->SiS_LCDResInfo - 1;
3684      }
3685      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3686         (*PanelIndex) += 16;
3687         if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3688            (*PanelIndex) = 32;
3689            if(modeflag & HalfDCLK) (*PanelIndex)++;
3690         }
3691      }
3692   }
3693
3694   if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
3695      if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
3696         (*ResIndex) = 7;
3697         if(HwInfo->jChipType < SIS_315H) {
3698            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) (*ResIndex)++;
3699         }
3700      }
3701   }
3702 }
3703
3704 static void
3705 SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
3706                    USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
3707 {
3708   USHORT modeflag;
3709   USHORT PanelIndex,ResIndex;
3710   const  SiS_LVDSDesStruct *PanelDesPtr = NULL;
3711
3712   SiS_Pr->SiS_LCDHDES = 0;
3713   SiS_Pr->SiS_LCDVDES = 0;
3714
3715   if( (SiS_Pr->UseCustomMode)                    ||
3716       (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
3717       (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
3718       ((SiS_Pr->SiS_VBType & VB_SISVB) &&
3719        (SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
3720        (SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
3721      return;
3722   }
3723
3724   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3725
3726 #ifdef SIS315H
3727      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3728         /* non-pass 1:1 only, see above */
3729         if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3730            SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3731         }
3732         if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3733            SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3734         }
3735      }
3736      if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3737         switch(SiS_Pr->SiS_CustomT) {
3738         case CUT_UNIWILL1024:
3739         case CUT_UNIWILL10242:
3740         case CUT_CLEVO1400:
3741            if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3742               SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3743            }
3744            break;
3745         }
3746         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
3747            if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
3748               SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3749            }
3750         }
3751      }
3752 #endif
3753
3754   } else {
3755
3756      SiS_GetLVDSDesPtr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
3757                        &PanelIndex, &ResIndex, HwInfo);
3758
3759      switch(PanelIndex) {
3760         case  0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1;    break;   /* ---  */
3761         case  1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1;    break;
3762         case  2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1;    break;
3763         case  3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1;    break;
3764         case  4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1;    break;
3765         case  5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1;    break;
3766         case  6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1;    break;
3767         case  7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1;    break;
3768         case  8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1;    break;
3769         case  9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1;    break;
3770         case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1;    break;
3771         case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1;    break;
3772         case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1;    break;
3773         case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1;    break;
3774         case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;    break;
3775         case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1;    break;
3776         case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2;    break;    /* --- */
3777         case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2;    break;
3778         case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2;    break;
3779         case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2;    break;
3780         case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2;    break;
3781         case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2;    break;
3782         case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2;    break;
3783         case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2;    break;
3784         case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2;    break;
3785         case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2;    break;
3786         case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2;    break;
3787         case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2;    break;
3788         case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2;    break;
3789         case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2;    break;
3790         case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2;    break;
3791         case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2;    break;
3792         case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1;    break;    /* pass 1:1 */
3793         case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2;    break;
3794         case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData; break;    /* TV */
3795         case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break;
3796         case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData;  break;
3797         case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData;  break;
3798         default: return;
3799      }
3800
3801      SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
3802      SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
3803
3804      if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
3805         modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3806         if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3807            if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
3808         } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3809            if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
3810               if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
3811                  if(HwInfo->jChipType < SIS_315H) {
3812                     if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
3813                  } else {
3814                     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
3815                     if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
3816                     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
3817                     if(!(modeflag & HalfDCLK)) {
3818                        SiS_Pr->SiS_LCDHDES = 320;
3819                        if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
3820                        if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
3821                     }
3822                  }
3823               }
3824            }
3825         }
3826      }
3827   }
3828 }
3829
3830 /*********************************************/
3831 /*           DISABLE VIDEO BRIDGE            */
3832 /*********************************************/
3833
3834 /* NEVER use any variables (VBInfo), this will be called
3835  * from outside the context of modeswitch!
3836  * MUST call getVBType before calling this
3837  */
3838 void
3839 SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
3840 {
3841 #ifdef SIS315H
3842   USHORT tempah,pushax=0,modenum;
3843 #endif
3844   USHORT temp=0;
3845
3846   if(SiS_Pr->SiS_VBType & VB_SISVB) {
3847
3848      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
3849
3850         if(HwInfo->jChipType < SIS_315H) {
3851
3852 #ifdef SIS300      /* 300 series */
3853
3854            if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
3855               if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3856                  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
3857               } else {
3858                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
3859               }
3860               SiS_PanelDelay(SiS_Pr, HwInfo, 3);
3861            }
3862            if(SiS_Is301B(SiS_Pr)) {
3863               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
3864               SiS_ShortDelay(SiS_Pr,1);
3865            }
3866            SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
3867            SiS_DisplayOff(SiS_Pr);
3868            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3869            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
3870            SiS_UnLockCRT2(SiS_Pr,HwInfo);
3871            if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
3872               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
3873               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
3874            }
3875            if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
3876                (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
3877               SiS_PanelDelay(SiS_Pr, HwInfo, 2);
3878               if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3879                  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
3880               } else {
3881                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
3882               }
3883            }
3884
3885 #endif  /* SIS300 */
3886
3887         } else {
3888
3889 #ifdef SIS315H     /* 315 series */
3890
3891            BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
3892                               (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
3893
3894            modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
3895
3896            if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3897
3898 #ifdef SET_EMI
3899               if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
3900                  if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
3901                     SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
3902                  }
3903               }
3904 #endif
3905               if( (modenum <= 0x13)                  ||
3906                   (SiS_IsVAMode(SiS_Pr,HwInfo))      ||
3907                   (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
3908                  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
3909                  if(custom1) SiS_PanelDelay(SiS_Pr, HwInfo, 3);
3910               }
3911
3912               if(!custom1) {
3913                  SiS_DDC2Delay(SiS_Pr,0xff00);
3914                  SiS_DDC2Delay(SiS_Pr,0xe000);
3915                  SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
3916                  pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
3917                  if(IS_SIS740) {
3918                     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
3919                  }
3920                  SiS_PanelDelay(SiS_Pr, HwInfo, 3);
3921               }
3922
3923            }
3924
3925            if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
3926               if(HwInfo->jChipType < SIS_340) {
3927                  tempah = 0xef;
3928                  if(SiS_IsVAMode(SiS_Pr,HwInfo)) tempah = 0xf7;
3929                  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
3930               }
3931            }
3932
3933            if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3934               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
3935            }
3936
3937            tempah = 0x3f;
3938            if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
3939               tempah = 0x7f;
3940               if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) tempah = 0xbf;
3941            }
3942            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
3943
3944            if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
3945               ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
3946
3947               SiS_DisplayOff(SiS_Pr);
3948               if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3949                  SiS_PanelDelay(SiS_Pr, HwInfo, 2);
3950               }
3951               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3952               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
3953
3954            }
3955
3956            if((!(SiS_IsVAMode(SiS_Pr,HwInfo))) ||
3957               ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
3958
3959               if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
3960                  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
3961                  SiS_DisplayOff(SiS_Pr);
3962               }
3963               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
3964
3965               if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3966                  SiS_PanelDelay(SiS_Pr, HwInfo, 2);
3967               }
3968
3969               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3970               temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
3971               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
3972               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
3973               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
3974
3975            }
3976
3977            if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
3978               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
3979            }
3980
3981            if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3982
3983               if(!custom1) {
3984
3985                  if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
3986                     if(!(SiS_CRT2IsLCD(SiS_Pr,HwInfo))) {
3987                        if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
3988                           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
3989                        }
3990                     }
3991                  }
3992
3993                  SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
3994
3995                  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
3996                     if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
3997                        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 20);
3998                     }
3999                  }
4000
4001               } else {
4002
4003                  if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
4004                     (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
4005                     if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
4006                        (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
4007                        SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4008                        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
4009                        SiS_PanelDelay(SiS_Pr, HwInfo, 4);
4010                     }
4011                  }
4012
4013               }
4014            }
4015
4016 #endif /* SIS315H */
4017
4018         }
4019
4020      } else {     /* ============ For 301 ================ */
4021
4022         if(HwInfo->jChipType < SIS_315H) {
4023 #ifdef SIS300
4024            if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4025               SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
4026               SiS_PanelDelay(SiS_Pr, HwInfo, 3);
4027            }
4028 #endif
4029         }
4030
4031         SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
4032         SiS_DisplayOff(SiS_Pr);
4033
4034         if(HwInfo->jChipType >= SIS_315H) {
4035            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4036         }
4037
4038         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);                /* disable lock mode */
4039
4040         if(HwInfo->jChipType >= SIS_315H) {
4041             temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4042             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
4043             SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4044             SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4045         } else {
4046 #ifdef SIS300
4047             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
4048             if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
4049                 (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
4050                 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4051                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
4052             }
4053 #endif
4054         }
4055
4056       }
4057
4058   } else {     /* ============ For LVDS =============*/
4059
4060     if(HwInfo->jChipType < SIS_315H) {
4061
4062 #ifdef SIS300   /* 300 series */
4063
4064         if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
4065            SiS_SetCH700x(SiS_Pr,0x090E);
4066         }
4067
4068         if(HwInfo->jChipType == SIS_730) {
4069            if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4070               SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4071            }
4072            if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4073               SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
4074               SiS_PanelDelay(SiS_Pr, HwInfo, 3);
4075            }
4076         } else {
4077            if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4078               if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4079                  if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4080                     SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4081                     if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
4082                        SiS_DisplayOff(SiS_Pr);
4083                     }
4084                     SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
4085                     SiS_PanelDelay(SiS_Pr, HwInfo, 3);
4086                  }
4087               }
4088            }
4089         }
4090
4091         SiS_DisplayOff(SiS_Pr);
4092
4093         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4094
4095         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4096         SiS_UnLockCRT2(SiS_Pr,HwInfo);
4097         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4098         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4099
4100         if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
4101             (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
4102            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4103            SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
4104         }
4105
4106 #endif  /* SIS300 */
4107
4108     } else {
4109
4110 #ifdef SIS315H  /* 315 series */
4111
4112         if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
4113            if(HwInfo->jChipType < SIS_340) {
4114               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
4115            }
4116         }
4117
4118         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4119
4120            if(HwInfo->jChipType == SIS_740) {
4121               temp = SiS_GetCH701x(SiS_Pr,0x61);
4122               if(temp < 1) {
4123                  SiS_SetCH701x(SiS_Pr,0xac76);
4124                  SiS_SetCH701x(SiS_Pr,0x0066);
4125               }
4126
4127               if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4128                   (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
4129                  SiS_SetCH701x(SiS_Pr,0x3e49);
4130               }
4131            }
4132
4133            if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4134                (SiS_IsVAMode(SiS_Pr,HwInfo)) ) {
4135               SiS_Chrontel701xBLOff(SiS_Pr);
4136               SiS_Chrontel701xOff(SiS_Pr,HwInfo);
4137            }
4138
4139            if(HwInfo->jChipType != SIS_740) {
4140               if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4141                   (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
4142                  SiS_SetCH701x(SiS_Pr,0x0149);
4143               }
4144            }
4145
4146         }
4147
4148         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4149            SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
4150            SiS_PanelDelay(SiS_Pr, HwInfo, 3);
4151         }
4152
4153         if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4154             (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4155             (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo))) ) {
4156            SiS_DisplayOff(SiS_Pr);
4157         }
4158
4159         if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4160             (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4161             (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
4162            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4163         }
4164
4165         if(HwInfo->jChipType == SIS_740) {
4166            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4167         }
4168
4169         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4170
4171         if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4172             (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4173             (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
4174            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4175         }
4176
4177         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4178            if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4179               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4180               if(HwInfo->jChipType == SIS_550) {
4181                  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
4182                  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
4183               }
4184            }
4185         } else {
4186            if(HwInfo->jChipType == SIS_740) {
4187               if(SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) {
4188                  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4189               }
4190            } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
4191               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4192            }
4193         }
4194
4195         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4196            if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
4197               /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
4198            } else {
4199               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
4200            }
4201         }
4202
4203         SiS_UnLockCRT2(SiS_Pr,HwInfo);
4204
4205         if(HwInfo->jChipType == SIS_550) {
4206            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
4207            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
4208         } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4209                    (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4210                    (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
4211            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4212         }
4213
4214         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4215            if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4216               if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4217                  SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4218                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
4219               }
4220            }
4221         }
4222
4223 #endif  /* SIS315H */
4224
4225     }  /* 315 series */
4226
4227   }  /* LVDS */
4228
4229 }
4230
4231 /*********************************************/
4232 /*            ENABLE VIDEO BRIDGE            */
4233 /*********************************************/
4234
4235 /* NEVER use any variables (VBInfo), this will be called
4236  * from outside the context of a mode switch!
4237  * MUST call getVBType before calling this
4238  */
4239 void
4240 SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
4241 {
4242   USHORT temp=0,tempah;
4243 #ifdef SIS315H
4244   USHORT temp1,pushax=0;
4245   BOOLEAN delaylong = FALSE;
4246 #endif
4247
4248   if(SiS_Pr->SiS_VBType & VB_SISVB) {
4249
4250     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ====== For 301B et al  ====== */
4251
4252       if(HwInfo->jChipType < SIS_315H) {
4253
4254 #ifdef SIS300     /* 300 series */
4255
4256          if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4257             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4258                SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4259             } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4260                SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
4261             }
4262             if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_NoLCD)) {
4263                if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
4264                   SiS_PanelDelay(SiS_Pr, HwInfo, 0);
4265                }
4266             }
4267          }
4268
4269          if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
4270             (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
4271
4272             SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* Enable CRT2 */
4273             SiS_DisplayOn(SiS_Pr);
4274             SiS_UnLockCRT2(SiS_Pr,HwInfo);
4275             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4276             if(SiS_BridgeInSlavemode(SiS_Pr)) {
4277                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4278             } else {
4279                SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4280             }
4281             if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4282                if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4283                   if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4284                      SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4285                   }
4286                   SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4287                   SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
4288                }
4289             }
4290
4291          } else {
4292
4293             temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
4294             if(SiS_BridgeInSlavemode(SiS_Pr)) {
4295                tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4296                if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4297             }
4298             SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4299             SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4300             SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
4301             SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
4302             SiS_DisplayOn(SiS_Pr);
4303             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4304                if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4305                   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4306                      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4307                         SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4308                      }
4309                      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4310                   }
4311                }
4312             }
4313
4314          }
4315
4316
4317 #endif /* SIS300 */
4318
4319       } else {
4320
4321 #ifdef SIS315H    /* 315 series */
4322
4323 #ifdef SET_EMI
4324          UCHAR   r30=0, r31=0, r32=0, r33=0, cr36=0;
4325          /* USHORT  emidelay=0; */
4326 #endif
4327
4328          if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4329             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
4330 #ifdef SET_EMI
4331             if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4332                SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4333             }
4334 #endif
4335          }
4336
4337          if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
4338             if(HwInfo->jChipType < SIS_340) {
4339                tempah = 0x10;
4340                if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
4341                   if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
4342                   else                              tempah = 0x08;
4343                }
4344                SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
4345             }
4346          }
4347
4348          if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4349
4350             SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4351             SiS_DisplayOff(SiS_Pr);
4352             pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4353             if(IS_SIS740) {
4354                SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4355             }
4356
4357             if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
4358                if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
4359                   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
4360                   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4361                   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
4362                   if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4363                      SiS_GenericDelay(SiS_Pr, 0x4500);
4364                   }
4365                }
4366             }
4367
4368             if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
4369                SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
4370                delaylong = TRUE;
4371             }
4372
4373          }
4374
4375          if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
4376
4377             temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
4378             if(SiS_BridgeInSlavemode(SiS_Pr)) {
4379                tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4380                if(!(tempah & SetCRT2ToRAMDAC)) {
4381                   if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
4382                }
4383             }
4384             SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4385
4386             SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
4387
4388             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4389             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4390
4391             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4392                SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4393             }
4394
4395          } else {
4396
4397             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
4398
4399          }
4400
4401          SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
4402          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4403
4404          tempah = 0xc0;
4405          if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
4406             tempah = 0x80;
4407             if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) tempah = 0x40;
4408          }
4409          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
4410
4411          if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4412
4413             SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4414
4415             SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
4416             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4417
4418             if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4419 #ifdef SET_EMI
4420                if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4421                   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4422                   SiS_GenericDelay(SiS_Pr, 0x500);
4423                }
4424 #endif
4425                SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
4426
4427                if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4428 #ifdef SET_EMI
4429                   cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
4430
4431                   if(SiS_Pr->SiS_ROMNew) {
4432                      UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
4433                      USHORT romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo);
4434                      if(romptr) {
4435                         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
4436                         SiS_Pr->EMI_30 = 0;
4437                         SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
4438                         SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
4439                         SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
4440                         if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
4441                         /* emidelay = SISGETROMW((romptr + 0x22)); */
4442                         SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = TRUE;
4443                      }
4444                   }
4445
4446                   /*                                              (P4_30|0x40)  */
4447                   /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
4448                   /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
4449                   /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
4450                   /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
4451                   /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
4452                   /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
4453                   /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
4454                   /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
4455                   /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
4456
4457                   if(SiS_Pr->HaveEMI) {
4458                      r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
4459                      r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
4460                   } else {
4461                      r30 = 0;
4462                   }
4463
4464                   /* EMI_30 is read at driver start; however, the BIOS sets this
4465                    * (if it is used) only if the LCD is in use. In case we caught
4466                    * the machine while on TV output, this bit is not set and we
4467                    * don't know if it should be set - hence our detection is wrong.
4468                    * Work-around this here:
4469                    */
4470
4471                   if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
4472                      switch((cr36 & 0x0f)) {
4473                      case 2:
4474                         r30 |= 0x40;
4475                         if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
4476                         if(!SiS_Pr->HaveEMI) {
4477                            r31 = 0x05; r32 = 0x60; r33 = 0x33;
4478                            if((cr36 & 0xf0) == 0x30) {
4479                               r31 = 0x0d; r32 = 0x70; r33 = 0x40;
4480                            }
4481                         }
4482                         break;
4483                      case 3:  /* 1280x1024 */
4484                         if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
4485                         if(!SiS_Pr->HaveEMI) {
4486                            r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4487                            if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4488                               r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
4489                            }
4490                         }
4491                         break;
4492                      case 9:  /* 1400x1050 */
4493                         r30 |= 0x40;
4494                         if(!SiS_Pr->HaveEMI) {
4495                            r31 = 0x05; r32 = 0x60; r33 = 0x00;
4496                            if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4497                               r31 = 0x0d; r32 = 0x70; r33 = 0x40;  /* BIOS values */
4498                            }
4499                         }
4500                         break;
4501                      case 11: /* 1600x1200 - unknown */
4502                         r30 |= 0x40;
4503                         if(!SiS_Pr->HaveEMI) {
4504                            r31 = 0x05; r32 = 0x60; r33 = 0x00;
4505                         }
4506                      }
4507                   }
4508
4509                   /* BIOS values don't work so well sometimes */
4510                   if(!SiS_Pr->OverruleEMI) {
4511 #ifdef COMPAL_HACK
4512                      if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4513                         if((cr36 & 0x0f) == 0x09) {
4514                            r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
4515                         }
4516                      }
4517 #endif
4518 #ifdef COMPAQ_HACK
4519                      if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4520                         if((cr36 & 0x0f) == 0x03) {
4521                            r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4522                         }
4523                      }
4524 #endif
4525 #ifdef ASUS_HACK
4526                      if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
4527                         if((cr36 & 0x0f) == 0x02) {
4528                            /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
4529                            /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
4530                            /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
4531                            /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
4532                         }
4533                      }
4534 #endif
4535                   }
4536
4537                   if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
4538                      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
4539                      SiS_GenericDelay(SiS_Pr, 0x500);
4540                   }
4541                   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
4542                   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
4543                   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
4544 #endif  /* SET_EMI */
4545
4546                   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
4547
4548 #ifdef SET_EMI
4549                   if( (SiS_LCDAEnabled(SiS_Pr, HwInfo)) ||
4550                       (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
4551                      if(r30 & 0x40) {
4552                         SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
4553                         if(delaylong) {
4554                            SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
4555                            delaylong = FALSE;
4556                         }
4557                         SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4558                         if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
4559                            SiS_GenericDelay(SiS_Pr, 0x500);
4560                         }
4561                         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   /* Enable */
4562                      }
4563                   }
4564 #endif
4565                }
4566             }
4567
4568             if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4569                if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
4570                   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
4571                   if(delaylong) {
4572                      SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
4573                   }
4574                   SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4575                   if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4576                      SiS_GenericDelay(SiS_Pr, 0x500);
4577                   }
4578                   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4579                }
4580             }
4581
4582             SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4583             SiS_DisplayOn(SiS_Pr);
4584             SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
4585
4586          }
4587
4588          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4589             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4590          }
4591
4592 #endif /* SIS315H */
4593
4594       }
4595
4596     } else {    /* ============  For 301 ================ */
4597
4598        if(HwInfo->jChipType < SIS_315H) {
4599           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4600              SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
4601              SiS_PanelDelay(SiS_Pr, HwInfo, 0);
4602           }
4603        }
4604
4605        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
4606        if(SiS_BridgeInSlavemode(SiS_Pr)) {
4607           tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4608           if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4609        }
4610        SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4611
4612        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                  /* enable CRT2 */
4613
4614        if(HwInfo->jChipType >= SIS_315H) {
4615           temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4616           if(!(temp & 0x80)) {
4617              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);         /* BVBDOENABLE=1 */
4618           }
4619        }
4620
4621        SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);     /* enable VB processor */
4622
4623        SiS_VBLongWait(SiS_Pr);
4624        SiS_DisplayOn(SiS_Pr);
4625        if(HwInfo->jChipType >= SIS_315H) {
4626           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4627        }
4628        SiS_VBLongWait(SiS_Pr);
4629
4630        if(HwInfo->jChipType < SIS_315H) {
4631           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4632              SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4633              SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
4634           }
4635        }
4636
4637     }
4638
4639   } else {   /* =================== For LVDS ================== */
4640
4641     if(HwInfo->jChipType < SIS_315H) {
4642
4643 #ifdef SIS300    /* 300 series */
4644
4645        if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4646           if(HwInfo->jChipType == SIS_730) {
4647              SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4648              SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4649              SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4650           }
4651           SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
4652           if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
4653              SiS_PanelDelay(SiS_Pr, HwInfo, 0);
4654           }
4655        }
4656
4657        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4658        SiS_DisplayOn(SiS_Pr);
4659        SiS_UnLockCRT2(SiS_Pr,HwInfo);
4660        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4661        if(SiS_BridgeInSlavemode(SiS_Pr)) {
4662           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4663        } else {
4664           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4665        }
4666
4667        if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
4668           if(!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
4669              SiS_WaitVBRetrace(SiS_Pr, HwInfo);
4670              SiS_SetCH700x(SiS_Pr,0x0B0E);
4671           }
4672        }
4673
4674        if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4675           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4676              if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4677                 if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4678                    SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4679                    SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4680                 }
4681                 SiS_WaitVBRetrace(SiS_Pr, HwInfo);
4682                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
4683              }
4684           }
4685        }
4686
4687 #endif  /* SIS300 */
4688
4689     } else {
4690
4691 #ifdef SIS315H    /* 315 series */
4692
4693        if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
4694           if(HwInfo->jChipType < SIS_340) {
4695              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
4696           }
4697        }
4698
4699        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4700           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4701              SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
4702              SiS_PanelDelay(SiS_Pr, HwInfo, 0);
4703           }
4704        }
4705
4706        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4707        SiS_UnLockCRT2(SiS_Pr,HwInfo);
4708
4709        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4710
4711        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4712           temp = SiS_GetCH701x(SiS_Pr,0x66);
4713           temp &= 0x20;
4714           SiS_Chrontel701xBLOff(SiS_Pr);
4715        }
4716
4717        if(HwInfo->jChipType != SIS_550) {
4718           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4719        }
4720
4721        if(HwInfo->jChipType == SIS_740) {
4722           if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4723              if(SiS_IsLCDOrLCDA(SiS_Pr, HwInfo)) {
4724                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
4725              }
4726           }
4727        }
4728
4729        temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4730        if(!(temp1 & 0x80)) {
4731           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
4732        }
4733
4734        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4735           if(temp) {
4736              SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
4737           }
4738        }
4739
4740        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4741           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4742              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
4743              if(HwInfo->jChipType == SIS_550) {
4744                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
4745                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
4746              }
4747           }
4748        } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
4749           if(HwInfo->jChipType != SIS_740) {
4750              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
4751           }
4752        }
4753
4754        if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4755           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4756        }
4757
4758        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4759           if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) {
4760              SiS_Chrontel701xOn(SiS_Pr,HwInfo);
4761           }
4762           if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
4763               (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
4764              SiS_ChrontelDoSomething1(SiS_Pr,HwInfo);
4765           }
4766        }
4767
4768        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4769           if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4770              if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
4771                  (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
4772                 SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
4773                 SiS_ChrontelInitTVVSync(SiS_Pr,HwInfo);
4774              }
4775           }
4776        } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4777           if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4778              if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4779                 SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4780                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
4781              }
4782           }
4783        }
4784
4785 #endif  /* SIS315H */
4786
4787     } /* 310 series */
4788
4789   }  /* LVDS */
4790
4791 }
4792
4793 /*********************************************/
4794 /*         SET PART 1 REGISTER GROUP         */
4795 /*********************************************/
4796
4797 /* Set CRT2 OFFSET / PITCH */
4798 static void
4799 SiS_SetCRT2Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
4800                   USHORT RRTI, PSIS_HW_INFO HwInfo)
4801 {
4802   USHORT offset;
4803   UCHAR temp;
4804
4805   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
4806
4807   offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI,HwInfo);
4808
4809   if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
4810      (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
4811      offset >>= 1;
4812   }
4813
4814   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
4815   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
4816   temp = (UCHAR)(((offset >> 3) & 0xFF) + 1);
4817   if(offset % 8) temp++;
4818   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
4819 }
4820
4821 /* Set CRT2 sync and PanelLink mode */
4822 static void
4823 SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT RefreshRateTableIndex,
4824                 PSIS_HW_INFO HwInfo)
4825 {
4826   USHORT tempah=0,tempbl,infoflag;
4827
4828   tempbl = 0xC0;
4829
4830   if(SiS_Pr->UseCustomMode) {
4831      infoflag = SiS_Pr->CInfoFlag;
4832   } else {
4833      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
4834   }
4835
4836   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {                                    /* LVDS */
4837
4838      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4839         tempah = 0;
4840      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
4841         tempah = SiS_Pr->SiS_LCDInfo;
4842      } else tempah = infoflag >> 8;
4843      tempah &= 0xC0;
4844      tempah |= 0x20;
4845      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4846      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4847         if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
4848            (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
4849            tempah |= 0xf0;
4850         }
4851         if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4852             (SiS_Pr->SiS_IF_DEF_DSTN) ||
4853             (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
4854             (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
4855            tempah |= 0x30;
4856         }
4857      }
4858      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4859         if(HwInfo->jChipType >= SIS_315H) {
4860            tempah >>= 3;
4861            tempah &= 0x18;
4862            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
4863            /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
4864         } else {
4865            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
4866         }
4867      } else {
4868         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4869      }
4870
4871   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
4872
4873      if(HwInfo->jChipType < SIS_315H) {
4874
4875 #ifdef SIS300  /* ---- 300 series --- */
4876
4877         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {                   /* 630 - 301B(-DH) */
4878
4879            tempah = infoflag >> 8;
4880            tempbl = 0;
4881            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4882               if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4883                  tempah = SiS_Pr->SiS_LCDInfo;
4884                  tempbl = (tempah >> 6) & 0x03;
4885               }
4886            }
4887            tempah &= 0xC0;
4888            tempah |= 0x20;
4889            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4890            tempah |= 0xc0;
4891            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4892            if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
4893               SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4894            }
4895
4896         } else {                                                        /* 630 - 301 */
4897
4898            tempah = infoflag >> 8;
4899            tempah &= 0xC0;
4900            tempah |= 0x20;
4901            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4902            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4903
4904         }
4905
4906 #endif /* SIS300 */
4907
4908      } else {
4909
4910 #ifdef SIS315H  /* ------- 315 series ------ */
4911
4912         if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {                     /* 315 - LVDS */
4913
4914            tempbl = 0;
4915            if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
4916               (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
4917               tempah = infoflag >> 8;
4918               if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4919                 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
4920               }
4921            } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
4922                      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
4923               tempah = infoflag >> 8;
4924               tempbl = 0x03;
4925            } else {
4926               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
4927               tempbl = (tempah >> 6) & 0x03;
4928               tempbl |= 0x08;
4929               if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
4930            }
4931            tempah &= 0xC0;
4932            tempah |= 0x20;
4933            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4934            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
4935            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4936            if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
4937               if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4938                  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4939               }
4940            }
4941
4942         } else {                                                        /* 315 - TMDS */
4943
4944            tempah = tempbl = infoflag >> 8;
4945            if(!SiS_Pr->UseCustomMode) {
4946               tempbl = 0;
4947               if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4948                  if(ModeNo <= 0x13) {
4949                     tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
4950                  }
4951               }
4952               if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
4953                  if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
4954                     if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4955                        tempah = SiS_Pr->SiS_LCDInfo;
4956                        tempbl = (tempah >> 6) & 0x03;
4957                     }
4958                  }
4959               }
4960            }
4961            tempah &= 0xC0;
4962            tempah |= 0x20;
4963            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4964            if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4965               /* Imitate BIOS bug */
4966               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
4967            }
4968            if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4969               tempah >>= 3;
4970               tempah &= 0x18;
4971               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
4972            } else {
4973               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4974               if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
4975                  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4976                     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4977                  }
4978               }
4979            }
4980
4981         }
4982 #endif  /* SIS315H */
4983       }
4984    }
4985 }
4986
4987 /* Set CRT2 FIFO on 300/630/730 */
4988 #ifdef SIS300
4989 static void
4990 SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
4991                     PSIS_HW_INFO HwInfo)
4992 {
4993   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
4994   USHORT temp,index;
4995   USHORT modeidindex,refreshratetableindex;
4996   USHORT VCLK=0,MCLK,colorth=0,data2=0;
4997   USHORT tempal, tempah, tempbx, tempcl, tempax;
4998   USHORT CRT1ModeNo,CRT2ModeNo;
4999   USHORT SelectRate_backup;
5000   ULONG  data,eax;
5001   const UCHAR  LatencyFactor[] = {
5002         97, 88, 86, 79, 77, 00,       /*; 64  bit    BQ=2   */
5003         00, 87, 85, 78, 76, 54,       /*; 64  bit    BQ=1   */
5004         97, 88, 86, 79, 77, 00,       /*; 128 bit    BQ=2   */
5005         00, 79, 77, 70, 68, 48,       /*; 128 bit    BQ=1   */
5006         80, 72, 69, 63, 61, 00,       /*; 64  bit    BQ=2   */
5007         00, 70, 68, 61, 59, 37,       /*; 64  bit    BQ=1   */
5008         86, 77, 75, 68, 66, 00,       /*; 128 bit    BQ=2   */
5009         00, 68, 66, 59, 57, 37        /*; 128 bit    BQ=1   */
5010   };
5011   const UCHAR  LatencyFactor730[] = {
5012          69, 63, 61,
5013          86, 79, 77,
5014         103, 96, 94,
5015         120,113,111,
5016         137,130,128,    /* <-- last entry, data below */
5017         137,130,128,    /* to avoid using illegal values */
5018         137,130,128,
5019         137,130,128,
5020         137,130,128,
5021         137,130,128,
5022         137,130,128,
5023         137,130,128,
5024         137,130,128,
5025         137,130,128,
5026         137,130,128,
5027         137,130,128,
5028   };
5029   const UCHAR ThLowB[]   = {
5030         81, 4, 72, 6, 88, 8,120,12,
5031         55, 4, 54, 6, 66, 8, 90,12,
5032         42, 4, 45, 6, 55, 8, 75,12
5033   };
5034   const UCHAR ThTiming[] = {
5035         1, 2, 2, 3, 0, 1, 1, 2
5036   };
5037
5038   SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
5039
5040   if(!SiS_Pr->CRT1UsesCustomMode) {
5041
5042      CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 /* get CRT1 ModeNo */
5043      SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
5044      SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
5045      SiS_Pr->SiS_SelectCRT2Rate = 0;
5046      refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex, HwInfo);
5047
5048      if(CRT1ModeNo >= 0x13) {
5049         index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
5050         index &= 0x3F;
5051         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                       /* Get VCLK */
5052
5053         colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex);     /* Get colordepth */
5054         colorth >>= 1;
5055         if(!colorth) colorth++;
5056      }
5057
5058   } else {
5059
5060      CRT1ModeNo = 0xfe;
5061      VCLK = SiS_Pr->CSRClock_CRT1;                                      /* Get VCLK */
5062      data2 = (SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2;
5063      switch(data2) {                                                    /* Get color depth */
5064         case 0 : colorth = 1; break;
5065         case 1 : colorth = 1; break;
5066         case 2 : colorth = 2; break;
5067         case 3 : colorth = 2; break;
5068         case 4 : colorth = 3; break;
5069         case 5 : colorth = 4; break;
5070         default: colorth = 2;
5071      }
5072
5073   }
5074
5075   if(CRT1ModeNo >= 0x13) {
5076     if(HwInfo->jChipType == SIS_300) {
5077        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
5078     } else {
5079        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
5080     }
5081     index &= 0x07;
5082     MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;                         /* Get MCLK */
5083
5084     data2 = (colorth * VCLK) / MCLK;
5085
5086     temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5087     temp = ((temp & 0x00FF) >> 6) << 1;
5088     if(temp == 0) temp = 1;
5089     temp <<= 2;
5090     temp &= 0xff;
5091
5092     data2 = temp - data2;
5093
5094     if((28 * 16) % data2) {
5095         data2 = (28 * 16) / data2;
5096         data2++;
5097     } else {
5098         data2 = (28 * 16) / data2;
5099     }
5100
5101     if(HwInfo->jChipType == SIS_300) {
5102
5103         tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
5104         tempah &= 0x62;
5105         tempah >>= 1;
5106         tempal = tempah;
5107         tempah >>= 3;
5108         tempal |= tempah;
5109         tempal &= 0x07;
5110         tempcl = ThTiming[tempal];
5111         tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
5112         tempbx >>= 6;
5113         tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5114         tempah >>= 4;
5115         tempah &= 0x0c;
5116         tempbx |= tempah;
5117         tempbx <<= 1;
5118         tempal = ThLowB[tempbx + 1];
5119         tempal *= tempcl;
5120         tempal += ThLowB[tempbx];
5121         data = tempal;
5122
5123     } else if(HwInfo->jChipType == SIS_730) {
5124
5125 #ifdef LINUX_KERNEL
5126        SiS_SetRegLong(0xcf8,0x80000050);
5127        eax = SiS_GetRegLong(0xcfc);
5128 #else
5129        eax = pciReadLong(0x00000000, 0x50);
5130 #endif
5131        tempal = (USHORT)(eax >> 8);
5132        tempal &= 0x06;
5133        tempal <<= 5;
5134
5135 #ifdef LINUX_KERNEL
5136        SiS_SetRegLong(0xcf8,0x800000A0);
5137        eax = SiS_GetRegLong(0xcfc);
5138 #else
5139        eax = pciReadLong(0x00000000, 0xA0);
5140 #endif
5141        temp = (USHORT)(eax >> 28);
5142        temp &= 0x0F;
5143        tempal |= temp;
5144
5145        tempbx = tempal;   /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
5146        tempbx = 0;        /* -- do it like the BIOS anyway... */
5147        tempax = tempbx;
5148        tempbx &= 0xc0;
5149        tempbx >>= 6;
5150        tempax &= 0x0f;
5151        tempax *= 3;
5152        tempbx += tempax;
5153
5154        data = LatencyFactor730[tempbx];
5155        data += 15;
5156        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5157        if(!(temp & 0x80)) data += 5;
5158
5159     } else {
5160
5161        index = 0;
5162        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5163        if(temp & 0x0080) index += 12;
5164
5165 #ifdef LINUX_KERNEL
5166        SiS_SetRegLong(0xcf8,0x800000A0);
5167        eax = SiS_GetRegLong(0xcfc);
5168 #else
5169        /* We use pci functions X offers. We use tag 0, because
5170         * we want to read/write to the host bridge (which is always
5171         * 00:00.0 on 630, 730 and 540), not the VGA device.
5172         */
5173        eax = pciReadLong(0x00000000, 0xA0);
5174 #endif
5175        temp = (USHORT)(eax >> 24);
5176        if(!(temp&0x01)) index += 24;
5177
5178 #ifdef LINUX_KERNEL
5179        SiS_SetRegLong(0xcf8,0x80000050);
5180        eax = SiS_GetRegLong(0xcfc);
5181 #else
5182        eax = pciReadLong(0x00000000, 0x50);
5183 #endif
5184        temp=(USHORT)(eax >> 24);
5185        if(temp & 0x01) index += 6;
5186
5187        temp = (temp & 0x0F) >> 1;
5188        index += temp;
5189
5190        data = LatencyFactor[index];
5191        data += 15;
5192        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5193        if(!(temp & 0x80)) data += 5;
5194     }
5195
5196     data += data2;                              /* CRT1 Request Period */
5197
5198     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5199     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
5200
5201     if(!SiS_Pr->UseCustomMode) {
5202
5203        CRT2ModeNo = ModeNo;
5204        SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
5205
5206        refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex, HwInfo);
5207
5208        index = SiS_GetVCLK2Ptr(SiS_Pr,CRT2ModeNo,modeidindex,
5209                                refreshratetableindex,HwInfo);
5210        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                /* Get VCLK  */
5211
5212        if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5213           if(SiS_Pr->SiS_UseROM) {
5214              if(ROMAddr[0x220] & 0x01) {
5215                 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
5216              }
5217           }
5218        }
5219
5220     } else {
5221
5222        CRT2ModeNo = 0xfe;
5223        VCLK = SiS_Pr->CSRClock;                                 /* Get VCLK */
5224
5225     }
5226
5227     colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex); /* Get colordepth */
5228     colorth >>= 1;
5229     if(!colorth) colorth++;
5230
5231     data = data * VCLK * colorth;
5232     if(data % (MCLK << 4)) {
5233         data = data / (MCLK << 4);
5234         data++;
5235     } else {
5236         data = data / (MCLK << 4);
5237     }
5238
5239     if(data <= 6) data = 6;
5240     if(data > 0x14) data = 0x14;
5241
5242     temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x01);
5243     if(HwInfo->jChipType == SIS_300) {
5244        if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13;
5245        else             temp = (temp & (~0x1F)) | 0x16;
5246        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
5247           temp = (temp & (~0x1F)) | 0x13;
5248        }
5249     } else {
5250        if( ( (HwInfo->jChipType == SIS_630) ||
5251              (HwInfo->jChipType == SIS_730) )  &&
5252            (HwInfo->jChipRevision >= 0x30) ) /* 630s or 730(s?) */
5253       {
5254           temp = (temp & (~0x1F)) | 0x1b;
5255       } else {
5256           temp = (temp & (~0x1F)) | 0x16;
5257       }
5258     }
5259     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
5260
5261     if( (HwInfo->jChipType == SIS_630) &&
5262         (HwInfo->jChipRevision >= 0x30) ) /* 630s, NOT 730 */
5263     {
5264         if(data > 0x13) data = 0x13;
5265     }
5266     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
5267
5268   } else {  /* If mode <= 0x13, we just restore everything */
5269
5270     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5271     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
5272
5273   }
5274 }
5275 #endif
5276
5277 /* Set CRT2 FIFO on 315/330 series */
5278 #ifdef SIS315H
5279 static void
5280 SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
5281 {
5282   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
5283   if( (HwInfo->jChipType == SIS_760)      &&
5284       (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
5285       (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
5286       (SiS_Pr->SiS_VGAHDE >= 1280)        &&
5287       (SiS_Pr->SiS_VGAVDE >= 1024) ) {
5288      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
5289      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
5290      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5291      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
5292      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5293      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
5294   } else {
5295      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
5296   }
5297
5298 }
5299 #endif
5300
5301 static USHORT
5302 SiS_GetVGAHT2(SiS_Private *SiS_Pr)
5303 {
5304   ULONG tempax,tempbx;
5305
5306   tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
5307   tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
5308   tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
5309   return((USHORT)tempax);
5310 }
5311
5312 /* Set Part 1 / SiS bridge slave mode */
5313 static void
5314 SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
5315                   PSIS_HW_INFO HwInfo,USHORT RefreshRateTableIndex)
5316 {
5317   USHORT  push1,push2;
5318   USHORT  tempax,tempbx,tempcx,temp;
5319   USHORT  resinfo,modeflag,xres=0;
5320   unsigned char p1_7, p1_8;
5321
5322   if(ModeNo <= 0x13) {
5323      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5324      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
5325   } else if(SiS_Pr->UseCustomMode) {
5326      modeflag = SiS_Pr->CModeFlag;
5327      resinfo = 0;
5328      xres = SiS_Pr->CHDisplay;
5329   } else {
5330      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5331      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5332      xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
5333   }
5334
5335   /* The following is only done if bridge is in slave mode: */
5336
5337   if((HwInfo->jChipType >= SIS_661) && (ModeNo > 0x13)) {
5338      if(xres >= 1600) {
5339         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
5340      }
5341   }
5342
5343   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0xff);                  /* set MAX HT */
5344
5345   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)  modeflag |= Charx8Dot;
5346
5347   if(modeflag & Charx8Dot) tempcx = 0x08;
5348   else                     tempcx = 0x09;
5349
5350   tempax = SiS_Pr->SiS_VGAHDE;                                  /* 0x04 Horizontal Display End */
5351   if(modeflag & HalfDCLK) tempax >>= 1;
5352   tempax = ((tempax / tempcx) - 1) & 0xff;
5353   tempbx = tempax;
5354
5355   temp = tempax;
5356   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,temp);
5357
5358   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5359      if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
5360         temp += 2;
5361      }
5362   }
5363   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
5364      if(resinfo == SIS_RI_800x600) temp -= 2;
5365   }
5366   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x05,temp);                 /* 0x05 Horizontal Display Start */
5367
5368   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x06,0x03);                 /* 0x06 Horizontal Blank end     */
5369
5370   tempax = 0xFFFF;
5371   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempax = SiS_GetVGAHT2(SiS_Pr);
5372   if(tempax >= SiS_Pr->SiS_VGAHT) tempax = SiS_Pr->SiS_VGAHT;
5373   if(modeflag & HalfDCLK)         tempax >>= 1;
5374   tempax = (tempax / tempcx) - 5;
5375   tempcx = tempax;
5376
5377   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
5378      temp = tempcx - 1;
5379      if(!(modeflag & HalfDCLK)) {
5380         temp -= 6;
5381         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
5382            temp -= 2;
5383            if(ModeNo > 0x13) temp -= 10;
5384         }
5385      }
5386   } else {
5387      tempcx = (tempcx + tempbx) >> 1;
5388      temp = (tempcx & 0x00FF) + 2;
5389      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5390         temp--;
5391         if(!(modeflag & HalfDCLK)) {
5392            if((modeflag & Charx8Dot)) {
5393               temp += 4;
5394               if(SiS_Pr->SiS_VGAHDE >= 800) temp -= 6;
5395               if(HwInfo->jChipType >= SIS_315H) {
5396                  if(SiS_Pr->SiS_VGAHDE == 800) temp += 2;
5397               }
5398            }
5399         }
5400      } else {
5401         if(!(modeflag & HalfDCLK)) {
5402            temp -= 4;
5403            if((SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
5404               (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)) {
5405               if(SiS_Pr->SiS_VGAHDE >= 800) {
5406                  temp -= 7;
5407                  if(HwInfo->jChipType < SIS_315H) {
5408                     if(SiS_Pr->SiS_ModeType == ModeEGA) {
5409                        if(SiS_Pr->SiS_VGAVDE == 1024) {
5410                           temp += 15;
5411                           if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
5412                              temp += 7;
5413                        }
5414                     }
5415                  }
5416                  if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
5417                     if(SiS_Pr->SiS_VGAHDE >= 1280) {
5418                        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
5419                     }
5420                  }
5421               }
5422            }
5423         }
5424      }
5425   }
5426
5427   p1_7 = temp;
5428   p1_8 = 0x00;
5429
5430   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5431      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
5432         if(ModeNo <= 0x01) {
5433            p1_7 = 0x2a;
5434            if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_8 = 0x61;
5435            else                                 p1_8 = 0x41;
5436         } else if(SiS_Pr->SiS_ModeType == ModeText) {
5437            if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_7 = 0x54;
5438            else                                 p1_7 = 0x55;
5439            p1_8 = 0x00;
5440         } else if(ModeNo <= 0x13) {
5441            if(modeflag & HalfDCLK) {
5442               if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
5443                  p1_7 = 0x30;
5444                  p1_8 = 0x03;
5445               } else {
5446                  p1_7 = 0x2f;
5447                  p1_8 = 0x02;
5448               }
5449            } else {
5450               p1_7 = 0x5b;
5451               p1_8 = 0x03;
5452            }
5453         } else if( ((HwInfo->jChipType >= SIS_315H) &&
5454                     ((ModeNo == 0x50) || (ModeNo == 0x56) || (ModeNo == 0x53))) ||
5455                    ((HwInfo->jChipType < SIS_315H) &&
5456                     (resinfo == SIS_RI_320x200 || resinfo == SIS_RI_320x240)) ) {
5457            if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
5458               p1_7 = 0x30,
5459               p1_8 = 0x03;
5460            } else {
5461               p1_7 = 0x2f;
5462               p1_8 = 0x03;
5463            }
5464         }
5465      }
5466   }
5467
5468   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
5469      if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p)) {
5470         p1_7 = 0x63;
5471         if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) p1_7 = 0x55;
5472      }
5473      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
5474         if(!(modeflag & HalfDCLK)) {
5475            p1_7 = 0xb2;
5476            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
5477               p1_7 = 0xab;
5478            }
5479         }
5480      } else {
5481         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
5482            if(modeflag & HalfDCLK) p1_7 = 0x30;
5483         }
5484      }
5485   }
5486
5487   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,p1_7);                  /* 0x07 Horizontal Retrace Start */
5488   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,p1_8);                  /* 0x08 Horizontal Retrace End   */
5489
5490   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x03);                  /* 0x18 SR08 (FIFO Threshold?)   */
5491
5492   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x19,0xF0);
5493
5494   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,0xFF);                  /* 0x09 Set Max VT    */
5495
5496   tempcx = 0x121;
5497   tempbx = SiS_Pr->SiS_VGAVDE;                                  /* 0x0E Vertical Display End */
5498   if     (tempbx == 357) tempbx = 350;
5499   else if(tempbx == 360) tempbx = 350;
5500   else if(tempbx == 375) tempbx = 350;
5501   else if(tempbx == 405) tempbx = 400;
5502   else if(tempbx == 420) tempbx = 400;
5503   else if(tempbx == 525) tempbx = 480;
5504   push2 = tempbx;
5505   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5506      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5507         if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
5508            if     (tempbx == 350) tempbx += 5;
5509            else if(tempbx == 480) tempbx += 5;
5510         }
5511      }
5512   }
5513   tempbx -= 2;
5514   temp = tempbx & 0x00FF;
5515   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);                  /* 0x10 vertical Blank Start */
5516
5517   tempbx = push2;
5518   tempbx--;
5519   temp = tempbx & 0x00FF;
5520 #if 0
5521   /* Missing code from 630/301B 2.04.5a and 650/302LV 1.10.6s (calles int 2f) */
5522   if(xxx()) {
5523       if(temp == 0xdf) temp = 0xda;
5524   }
5525 #endif
5526   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);
5527
5528   temp = 0;
5529   if(modeflag & DoubleScanMode) temp |= 0x80;
5530   if(HwInfo->jChipType >= SIS_661) {
5531      if(tempbx & 0x0200)        temp |= 0x20;
5532      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x0B,0x5F,temp);
5533      if(tempbx & 0x0100)  tempcx |= 0x000a;
5534      if(tempbx & 0x0400)  tempcx |= 0x1200;
5535   } else {
5536      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);
5537      if(tempbx & 0x0100)  tempcx |= 0x0002;
5538      if(tempbx & 0x0400)  tempcx |= 0x0600;
5539   }
5540
5541   if(tempbx & 0x0200)  tempcx |= 0x0040;
5542
5543   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,0x00);                  /* 0x11 Vertical Blank End */
5544
5545   tempax = (SiS_Pr->SiS_VGAVT - tempbx) >> 2;
5546
5547   if((ModeNo > 0x13) || (HwInfo->jChipType < SIS_315H)) {
5548      if(resinfo != SIS_RI_1280x1024) {
5549         tempbx += (tempax << 1);
5550      }
5551   } else if(HwInfo->jChipType >= SIS_315H) {
5552      if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
5553         tempbx += (tempax << 1);
5554      }
5555   }
5556
5557   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
5558      tempbx -= 10;
5559   } else {
5560      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
5561         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
5562            tempbx += 40;
5563            if(HwInfo->jChipType >= SIS_315H) {
5564               if(SiS_Pr->SiS_VGAHDE == 800) tempbx += 10;
5565            }
5566         }
5567      }
5568   }
5569   tempax >>= 2;
5570   tempax++;
5571   tempax += tempbx;
5572   push1 = tempax;
5573   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
5574      if(tempbx <= 513)  {
5575         if(tempax >= 513) tempbx = 513;
5576      }
5577   }
5578   temp = tempbx & 0x00FF;
5579   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                  /* 0x0C Vertical Retrace Start */
5580
5581   tempbx--;
5582   temp = tempbx & 0x00FF;
5583   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);
5584
5585   if(tempbx & 0x0100) tempcx |= 0x0008;
5586
5587   if(tempbx & 0x0200) {
5588      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x0B,0x20);
5589   }
5590   tempbx++;
5591
5592   if(tempbx & 0x0100) tempcx |= 0x0004;
5593   if(tempbx & 0x0200) tempcx |= 0x0080;
5594   if(tempbx & 0x0400) {
5595      if(HwInfo->jChipType >= SIS_661)        tempcx |= 0x0800;
5596      else if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x0800;
5597      else                                    tempcx |= 0x0C00;
5598   }
5599
5600   tempbx = push1;
5601   temp = tempbx & 0x000F;
5602   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                  /* 0x0D vertical Retrace End */
5603
5604   if(tempbx & 0x0010) tempcx |= 0x2000;
5605
5606   temp = tempcx & 0x00FF;
5607   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);                  /* 0x0A CR07 */
5608
5609   temp = (tempcx & 0xFF00) >> 8;
5610   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                  /* 0x17 SR0A */
5611
5612   tempax = modeflag;
5613   temp = (tempax & 0xFF00) >> 8;
5614   temp = (temp >> 1) & 0x09;
5615   if(!(SiS_Pr->SiS_VBType & VB_SIS301)) temp |= 0x01;           /* Always 8 dotclock */
5616   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                  /* 0x16 SR01 */
5617
5618   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00);                  /* 0x0F CR14 */
5619
5620   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00);                  /* 0x12 CR17 */
5621
5622   temp = 0x00;
5623   if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5624      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
5625         temp = 0x80;
5626      }
5627   }
5628   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                  /* 0x1A SR0E */
5629
5630   temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
5631   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
5632 }
5633
5634 /* Setup panel link
5635  * This is used for LVDS, LCDA and Chrontel TV output
5636  * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
5637  */
5638 static void
5639 SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
5640                    PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
5641 {
5642   USHORT modeflag,resinfo;
5643   USHORT push2,tempax,tempbx,tempcx,temp;
5644   ULONG tempeax=0,tempebx,tempecx,tempvcfact=0;
5645   BOOLEAN islvds = FALSE, issis  = FALSE, chkdclkfirst = FALSE;
5646 #ifdef SIS300
5647   USHORT crt2crtc;
5648 #endif
5649 #ifdef SIS315H
5650   USHORT pushcx;
5651 #endif
5652
5653   if(ModeNo <= 0x13) {
5654      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5655      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
5656 #ifdef SIS300
5657      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5658 #endif
5659   } else if(SiS_Pr->UseCustomMode) {
5660      modeflag = SiS_Pr->CModeFlag;
5661      resinfo = 0;
5662 #ifdef SIS300
5663      crt2crtc = 0;
5664 #endif
5665   } else {
5666      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5667      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5668 #ifdef SIS300
5669      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5670 #endif
5671   }
5672
5673   /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
5674   if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
5675      islvds = TRUE;
5676   }
5677
5678   /* is really sis if sis bridge, but not 301B-DH */
5679   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
5680      issis = TRUE;
5681   }
5682
5683   if((HwInfo->jChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
5684      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
5685         chkdclkfirst = TRUE;
5686      }
5687   }
5688
5689 #ifdef SIS315H
5690   if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
5691      if(IS_SIS330) {
5692         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5693      } else if(IS_SIS740) {
5694         if(islvds) {
5695            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5696            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
5697         } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5698            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5699         }
5700      } else {
5701         if(islvds) {
5702            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5703            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
5704         } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5705            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
5706            if(SiS_Pr->SiS_VBType & VB_SIS301C) {
5707               if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
5708                  (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5709                  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
5710               }
5711            }
5712         }
5713      }
5714   }
5715 #endif
5716
5717   /* Horizontal */
5718
5719   tempax = SiS_Pr->SiS_LCDHDES;
5720   if(islvds) {
5721      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5722         if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
5723            if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
5724               (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
5725               tempax -= 8;
5726            }
5727         }
5728      }
5729   }
5730
5731   temp = (tempax & 0x0007);
5732   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                  /* BPLHDESKEW[2:0]   */
5733   temp = (tempax >> 3) & 0x00FF;
5734   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                  /* BPLHDESKEW[10:3]  */
5735
5736   tempbx = SiS_Pr->SiS_HDE;
5737   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5738      if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
5739         (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
5740         tempbx >>= 1;
5741      }
5742      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5743         tempbx = SiS_Pr->PanelXRes;
5744      }
5745   }
5746
5747   tempax += tempbx;
5748   if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
5749
5750   temp = tempax;
5751   if(temp & 0x07) temp += 8;
5752   temp >>= 3;
5753   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                  /* BPLHDEE  */
5754
5755   tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
5756
5757   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5758      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5759         if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
5760      }
5761   }
5762
5763   tempcx += tempax;
5764   if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
5765
5766   temp = (tempcx >> 3) & 0x00FF;
5767   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5768      if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5769         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5770            switch(ModeNo) {
5771            case 0x04:
5772            case 0x05:
5773            case 0x0d: temp = 0x56; break;
5774            case 0x10: temp = 0x60; break;
5775            case 0x13: temp = 0x5f; break;
5776            case 0x40:
5777            case 0x41:
5778            case 0x4f:
5779            case 0x43:
5780            case 0x44:
5781            case 0x62:
5782            case 0x56:
5783            case 0x53:
5784            case 0x5d:
5785            case 0x5e: temp = 0x54; break;
5786            }
5787         }
5788      }
5789   }
5790   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);                  /* BPLHRS */
5791
5792   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5793      temp += 2;
5794      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5795         temp += 8;
5796         if(SiS_Pr->PanelHRE != 999) {
5797            temp = tempcx + SiS_Pr->PanelHRE;
5798            if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
5799            temp >>= 3;
5800         }
5801      }
5802   } else {
5803      temp += 10;
5804   }
5805
5806   temp &= 0x1F;
5807   temp |= ((tempcx & 0x07) << 5);
5808 #if 0
5809   if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;                      /* WRONG? BIOS loads cl, not ah */
5810 #endif
5811   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);                  /* BPLHRE */
5812
5813   /* Vertical */
5814
5815   tempax = SiS_Pr->SiS_VGAVDE;
5816   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5817      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5818         tempax = SiS_Pr->PanelYRes;
5819      }
5820   }
5821
5822   tempbx = SiS_Pr->SiS_LCDVDES + tempax;
5823   if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5824
5825   push2 = tempbx;
5826
5827   tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
5828   if(HwInfo->jChipType < SIS_315H) {
5829      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5830         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5831            tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
5832         }
5833      }
5834   }
5835   if(islvds) tempcx >>= 1;
5836   else       tempcx >>= 2;
5837
5838   if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
5839       (!(SiS_Pr->SiS_LCDInfo & LCDPass11))                  &&
5840       (SiS_Pr->PanelVRS != 999) ) {
5841      tempcx = SiS_Pr->PanelVRS;
5842      tempbx += tempcx;
5843      if(issis) tempbx++;
5844   } else {
5845      tempbx += tempcx;
5846      if(HwInfo->jChipType < SIS_315H) tempbx++;
5847      else if(issis)                   tempbx++;
5848   }
5849
5850   if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;        /* BPLVRS  */
5851
5852   temp = tempbx & 0x00FF;
5853   if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5854      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5855         if(ModeNo == 0x10) temp = 0xa9;
5856      }
5857   }
5858   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
5859
5860   tempcx >>= 3;
5861   tempcx++;
5862
5863   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5864      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5865         if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
5866      }
5867   }
5868
5869   tempcx += tempbx;
5870   temp = tempcx & 0x000F;
5871   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);        /* BPLVRE  */
5872
5873   temp = ((tempbx >> 8) & 0x07) << 3;
5874   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5875      if(SiS_Pr->SiS_HDE != 640) {
5876         if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
5877      }
5878   } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5879   if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
5880   tempbx = 0x87;
5881   if((HwInfo->jChipType >= SIS_315H) ||
5882      (HwInfo->jChipRevision >= 0x30)) {
5883      tempbx = 0x07;
5884      if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
5885         if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
5886      }
5887      /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit mutliplexed) via VGA2 */
5888      if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5889         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5890            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
5891         } else {
5892            if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
5893         }
5894      }
5895   }
5896   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
5897
5898   tempbx = push2;                                               /* BPLVDEE */
5899
5900   tempcx = SiS_Pr->SiS_LCDVDES;                                 /* BPLVDES */
5901
5902   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5903      switch(SiS_Pr->SiS_LCDResInfo) {
5904      case Panel_640x480:
5905         tempbx = SiS_Pr->SiS_VGAVDE - 1;
5906         tempcx = SiS_Pr->SiS_VGAVDE;
5907         break;
5908      case Panel_800x600:
5909         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5910            if(resinfo == SIS_RI_800x600) tempcx++;
5911         }
5912         break;
5913      case Panel_1024x600:
5914         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5915            if(resinfo == SIS_RI_1024x600) tempcx++;
5916            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
5917               if(resinfo == SIS_RI_800x600) tempcx++;
5918            }
5919         }
5920         break;
5921      case Panel_1024x768:
5922         if(HwInfo->jChipType < SIS_315H) {
5923            if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5924               if(resinfo == SIS_RI_1024x768) tempcx++;
5925            }
5926         }
5927         break;
5928      }
5929   }
5930
5931   temp = ((tempbx >> 8) & 0x07) << 3;
5932   temp = temp | ((tempcx >> 8) & 0x07);
5933   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
5934   /* if(SiS_Pr->SiS_IF_DEF_FSTN) tempbx++;  */
5935   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
5936   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
5937
5938   /* Vertical scaling */
5939
5940   if(HwInfo->jChipType < SIS_315H) {
5941
5942 #ifdef SIS300      /* 300 series */
5943      tempeax = SiS_Pr->SiS_VGAVDE << 6;
5944      temp = (tempeax % (ULONG)SiS_Pr->SiS_VDE);
5945      tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
5946      if(temp) tempeax++;
5947
5948      if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
5949
5950      temp = (USHORT)(tempeax & 0x00FF);
5951      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);       /* BPLVCFACT */
5952      tempvcfact = temp;
5953 #endif /* SIS300 */
5954
5955   } else {
5956
5957 #ifdef SIS315H  /* 315 series */
5958      tempeax = SiS_Pr->SiS_VGAVDE << 18;
5959      tempebx = SiS_Pr->SiS_VDE;
5960      temp = (tempeax % tempebx);
5961      tempeax = tempeax / tempebx;
5962      if(temp) tempeax++;
5963      tempvcfact = tempeax;
5964
5965      temp = (USHORT)(tempeax & 0x00FF);
5966      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
5967      temp = (USHORT)((tempeax & 0x00FF00) >> 8);
5968      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
5969      temp = (USHORT)((tempeax & 0x00030000) >> 16);
5970      if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
5971      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
5972
5973      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
5974         temp = (USHORT)(tempeax & 0x00FF);
5975         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
5976         temp = (USHORT)((tempeax & 0x00FF00) >> 8);
5977         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
5978         temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
5979         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
5980         temp = 0;
5981         if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
5982         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
5983      }
5984 #endif
5985
5986   }
5987
5988   /* Horizontal scaling */
5989
5990   tempeax = SiS_Pr->SiS_VGAHDE;         /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
5991   if(chkdclkfirst) {
5992      if(modeflag & HalfDCLK) tempeax >>= 1;
5993   }
5994   tempebx = tempeax << 16;
5995   if(SiS_Pr->SiS_HDE == tempeax) {
5996      tempecx = 0xFFFF;
5997   } else {
5998      tempecx = tempebx / SiS_Pr->SiS_HDE;
5999      if(HwInfo->jChipType >= SIS_315H) {
6000         if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
6001      }
6002   }
6003
6004   if(HwInfo->jChipType >= SIS_315H) {
6005      tempeax = (tempebx / tempecx) - 1;
6006   } else {
6007      tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
6008   }
6009   tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
6010   temp = (USHORT)(tempecx & 0x00FF);
6011   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
6012
6013   if(HwInfo->jChipType >= SIS_315H) {
6014      tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
6015      tempbx = (USHORT)(tempeax & 0xFFFF);
6016   } else {
6017      tempeax = SiS_Pr->SiS_VGAVDE << 6;
6018      tempbx = tempvcfact & 0x3f;
6019      if(tempbx == 0) tempbx = 64;
6020      tempeax /= tempbx;
6021      tempbx = (USHORT)(tempeax & 0xFFFF);
6022   }
6023   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
6024   if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
6025      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
6026      else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480)             tempbx = 1;
6027   }
6028
6029   temp = ((tempbx >> 8) & 0x07) << 3;
6030   temp = temp | ((tempecx >> 8) & 0x07);
6031   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
6032   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
6033
6034   tempecx >>= 16;                                               /* BPLHCFACT  */
6035   if(!chkdclkfirst) {
6036      if(modeflag & HalfDCLK) tempecx >>= 1;
6037   }
6038   temp = (USHORT)((tempecx & 0xFF00) >> 8);
6039   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
6040   temp = (USHORT)(tempecx & 0x00FF);
6041   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
6042
6043 #ifdef SIS315H
6044   if(HwInfo->jChipType >= SIS_315H) {
6045      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
6046         if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
6047            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
6048         }
6049      } else {
6050         if(islvds) {
6051            if(HwInfo->jChipType == SIS_740) {
6052               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
6053            } else {
6054               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
6055            }
6056         }
6057      }
6058   }
6059 #endif
6060
6061 #ifdef SIS300
6062   if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
6063      int i;
6064      UCHAR TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
6065      UCHAR TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
6066      UCHAR TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
6067
6068      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
6069      for(i=0; i<5; i++) {
6070         SiS_SetTrumpionBlock(SiS_Pr, &SiS300_TrumpionData[crt2crtc][0]);
6071      }
6072      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6073         if(ModeNo == 0x13) {
6074            for(i=0; i<4; i++) {
6075               SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
6076            }
6077         } else if(ModeNo == 0x10) {
6078            for(i=0; i<4; i++) {
6079               SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
6080               SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
6081            }
6082         }
6083      }
6084      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
6085   }
6086 #endif
6087
6088 #ifdef SIS315H
6089   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
6090      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
6091      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
6092      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
6093      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
6094      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
6095      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
6096      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
6097      tempax = SiS_Pr->SiS_HDE;                                  /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
6098      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6099         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
6100      tempax += 64;
6101      temp = tempax & 0x00FF;
6102      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,temp);
6103      temp = ((tempax & 0xFF00) >> 8) << 3;
6104      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
6105      tempax += 32;                                              /* Blpe=lBlps+32 */
6106      temp = tempax & 0x00FF;
6107      if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0;
6108      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,temp);
6109      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00);               /* Bflml=0 */
6110      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
6111
6112      tempax = SiS_Pr->SiS_VDE;
6113      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6114         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
6115      tempax >>= 1;
6116      temp = tempax & 0x00FF;
6117      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,temp);
6118      temp = ((tempax & 0xFF00) >> 8) << 3;
6119      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
6120
6121      tempeax = SiS_Pr->SiS_HDE;
6122      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6123         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempeax >>= 1;
6124      tempeax <<= 2;                                             /* BDxFIFOSTOP = (HDE*4)/128 */
6125      tempebx = 128;
6126      temp = (USHORT)(tempeax % tempebx);
6127      tempeax = tempeax / tempebx;
6128      if(temp) tempeax++;
6129      temp = (USHORT)(tempeax & 0x003F);
6130      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x45,~0x0FF,temp);
6131      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00);               /* BDxWadrst0 */
6132      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
6133      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
6134      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
6135
6136      tempax = SiS_Pr->SiS_HDE;
6137      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6138         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
6139      tempax >>= 4;                                              /* BDxWadroff = HDE*4/8/8 */
6140      pushcx = tempax;
6141      temp = tempax & 0x00FF;
6142      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
6143      temp = ((tempax & 0xFF00) >> 8) << 3;
6144      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
6145
6146      tempax = SiS_Pr->SiS_VDE;                                  /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
6147      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6148         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
6149      tempeax = (tempax * pushcx);
6150      tempebx = 0x00100000 + tempeax;
6151      temp = (USHORT)tempebx & 0x000000FF;
6152      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
6153      temp = (USHORT)((tempebx & 0x0000FF00) >> 8);
6154      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
6155      temp = (USHORT)((tempebx & 0x00FF0000) >> 16);
6156      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
6157      temp = (USHORT)(((tempebx & 0x01000000) >> 24) << 7);
6158      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
6159
6160      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
6161      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
6162      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
6163      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
6164      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
6165
6166      if(SiS_Pr->SiS_IF_DEF_FSTN) {
6167         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
6168         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
6169         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
6170         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
6171         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
6172         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
6173         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
6174         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
6175         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
6176         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
6177         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
6178         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
6179         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
6180         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
6181         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
6182         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
6183         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
6184         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
6185         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
6186         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
6187      }
6188   }
6189 #endif  /* SIS315H */
6190 }
6191
6192 /* Set Part 1 */
6193 static void
6194 SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
6195               PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
6196 {
6197 #if defined(SIS300) || defined(SIS315H)
6198   UCHAR   *ROMAddr = HwInfo->pjVirtualRomBase;
6199 #endif
6200   USHORT  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
6201   USHORT  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
6202 #ifdef SIS315H
6203   USHORT  tempbl=0;
6204 #endif
6205
6206   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
6207      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
6208      return;
6209   }
6210
6211   if(ModeNo <= 0x13) {
6212      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6213   } else if(SiS_Pr->UseCustomMode) {
6214      modeflag = SiS_Pr->CModeFlag;
6215   } else {
6216      CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
6217      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
6218      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6219   }
6220
6221   SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
6222
6223   if( ! ((HwInfo->jChipType >= SIS_315H) &&
6224          (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
6225          (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
6226
6227      if(HwInfo->jChipType < SIS_315H ) {
6228 #ifdef SIS300
6229         SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
6230 #endif
6231      } else {
6232 #ifdef SIS315H
6233         SiS_SetCRT2FIFO_310(SiS_Pr, HwInfo);
6234 #endif
6235      }
6236
6237      /* 1. Horizontal setup */
6238
6239      if(HwInfo->jChipType < SIS_315H ) {
6240
6241 #ifdef SIS300   /* ------------- 300 series --------------*/
6242
6243         temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;                   /* BTVGA2HT 0x08,0x09 */
6244         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
6245
6246         temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
6247         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
6248
6249         temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
6250         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
6251
6252         pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
6253         tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
6254         tempbx = pushbx + tempcx;
6255         tempcx <<= 1;
6256         tempcx += tempbx;
6257
6258         bridgeadd = 12;
6259
6260 #endif /* SIS300 */
6261
6262      } else {
6263
6264 #ifdef SIS315H  /* ------------------- 315/330 series --------------- */
6265
6266         tempcx = SiS_Pr->SiS_VGAHT;                               /* BTVGA2HT 0x08,0x09 */
6267         if(modeflag & HalfDCLK) {
6268            if(SiS_Pr->SiS_VBType & VB_SISVB) {
6269               tempcx >>= 1;
6270            } else {
6271               tempax = SiS_Pr->SiS_VGAHDE >> 1;
6272               tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
6273               if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
6274                  tempcx = SiS_Pr->SiS_HT - tempax;
6275               }
6276            }
6277         }
6278         tempcx--;
6279         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx);            /* CRT2 Horizontal Total */
6280         temp = (tempcx >> 4) & 0xF0;
6281         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
6282
6283         tempcx = SiS_Pr->SiS_VGAHT;                               /* BTVGA2HDEE 0x0A,0x0C */
6284         tempbx = SiS_Pr->SiS_VGAHDE;
6285         tempcx -= tempbx;
6286         tempcx >>= 2;
6287         if(modeflag & HalfDCLK) {
6288            tempbx >>= 1;
6289            tempcx >>= 1;
6290         }
6291         tempbx += 16;
6292
6293         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx);            /* CRT2 Horizontal Display Enable End */
6294
6295         pushbx = tempbx;
6296         tempcx >>= 1;
6297         tempbx += tempcx;
6298         tempcx += tempbx;
6299
6300         bridgeadd = 16;
6301
6302         if(SiS_Pr->SiS_VBType & VB_SISVB) {
6303            if(HwInfo->jChipType >= SIS_661) {
6304               if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
6305                  (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
6306                  if(resinfo == SIS_RI_1280x1024) {
6307                     tempcx = (tempcx & 0xff00) | 0x30;
6308                  } else if(resinfo == SIS_RI_1600x1200) {
6309                     tempcx = (tempcx & 0xff00) | 0xff;
6310                  }
6311               }
6312            }
6313         }
6314
6315 #endif  /* SIS315H */
6316
6317      }  /* 315/330 series */
6318
6319      if(SiS_Pr->SiS_VBType & VB_SISVB) {
6320
6321         if(SiS_Pr->UseCustomMode) {
6322            tempbx = SiS_Pr->CHSyncStart + bridgeadd;
6323            tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
6324            tempax = SiS_Pr->SiS_VGAHT;
6325            if(modeflag & HalfDCLK) tempax >>= 1;
6326            tempax--;
6327            if(tempcx > tempax) tempcx = tempax;
6328         }
6329
6330         if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6331            unsigned char cr4, cr14, cr5, cr15;
6332            if(SiS_Pr->UseCustomMode) {
6333               cr4  = SiS_Pr->CCRT1CRTC[4];
6334               cr14 = SiS_Pr->CCRT1CRTC[14];
6335               cr5  = SiS_Pr->CCRT1CRTC[5];
6336               cr15 = SiS_Pr->CCRT1CRTC[15];
6337            } else {
6338               cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
6339               cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
6340               cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
6341               cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
6342            }
6343            tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3;                /* (VGAHRS-3)*8 */
6344            tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
6345            tempcx &= 0x00FF;
6346            tempcx |= (tempbx & 0xFF00);
6347            tempbx += bridgeadd;
6348            tempcx += bridgeadd;
6349            tempax = SiS_Pr->SiS_VGAHT;
6350            if(modeflag & HalfDCLK) tempax >>= 1;
6351            tempax--;
6352            if(tempcx > tempax) tempcx = tempax;
6353         }
6354
6355         if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6356            tempbx = 1040;
6357            tempcx = 1044;   /* HWCursor bug! */
6358         }
6359
6360      }
6361
6362      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx);               /* CRT2 Horizontal Retrace Start */
6363
6364      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx);               /* CRT2 Horizontal Retrace End */
6365
6366      temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
6367      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                 /* Overflow */
6368
6369      /* 2. Vertical setup */
6370
6371      tempcx = SiS_Pr->SiS_VGAVT - 1;
6372      temp = tempcx & 0x00FF;
6373
6374      if(HwInfo->jChipType < SIS_661) {
6375         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6376            if(HwInfo->jChipType < SIS_315H) {
6377               if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6378                  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6379                     temp--;
6380                  }
6381               }
6382            } else {
6383               temp--;
6384            }
6385         } else if(HwInfo->jChipType >= SIS_315H) {
6386            temp--;
6387         }
6388      }
6389      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
6390
6391      tempbx = SiS_Pr->SiS_VGAVDE - 1;
6392      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx);               /* CRT2 Vertical Display Enable End */
6393
6394      temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
6395      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
6396
6397      if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
6398         tempbx++;
6399         tempax = tempbx;
6400         tempcx++;
6401         tempcx -= tempax;
6402         tempcx >>= 2;
6403         tempbx += tempcx;
6404         if(tempcx < 4) tempcx = 4;
6405         tempcx >>= 2;
6406         tempcx += tempbx;
6407         tempcx++;
6408      } else {
6409         tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
6410         tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
6411      }
6412
6413      if(SiS_Pr->SiS_VBType & VB_SISVB) {
6414         if(SiS_Pr->UseCustomMode) {
6415            tempbx = SiS_Pr->CVSyncStart;
6416            tempcx = SiS_Pr->CVSyncEnd;
6417         }
6418         if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6419            unsigned char cr8, cr7, cr13;
6420            if(SiS_Pr->UseCustomMode) {
6421               cr8    = SiS_Pr->CCRT1CRTC[8];
6422               cr7    = SiS_Pr->CCRT1CRTC[7];
6423               cr13   = SiS_Pr->CCRT1CRTC[13];
6424               tempcx = SiS_Pr->CCRT1CRTC[9];
6425            } else {
6426               cr8    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
6427               cr7    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
6428               cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
6429               tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
6430            }
6431            tempbx = cr8;
6432            if(cr7  & 0x04) tempbx |= 0x0100;
6433            if(cr7  & 0x80) tempbx |= 0x0200;
6434            if(cr13 & 0x08) tempbx |= 0x0400;
6435         }
6436      }
6437      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
6438
6439      temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
6440      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow */
6441
6442      /* 3. Panel delay compensation */
6443
6444      if(HwInfo->jChipType < SIS_315H) {
6445
6446 #ifdef SIS300  /* ---------- 300 series -------------- */
6447
6448         if(SiS_Pr->SiS_VBType & VB_SISVB) {
6449            temp = 0x20;
6450            if(HwInfo->jChipType == SIS_300) {
6451               temp = 0x10;
6452               if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
6453               if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6454            }
6455            if(SiS_Pr->SiS_VBType & VB_SIS301) {
6456               if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6457            }
6458            if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
6459            if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
6460            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)             temp = 0x08;
6461            if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6462               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)       temp = 0x2c;
6463               else                                          temp = 0x20;
6464            }
6465            if(SiS_Pr->SiS_UseROM) {
6466               if(ROMAddr[0x220] & 0x80) {
6467                  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
6468                     temp = ROMAddr[0x221];
6469                  else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
6470                     temp = ROMAddr[0x222];
6471                  else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
6472                     temp = ROMAddr[0x223];
6473                  else
6474                     temp = ROMAddr[0x224];
6475                  temp &= 0x3c;
6476               }
6477            }
6478            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6479               if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC & 0x3c;
6480            }
6481
6482         } else {
6483            temp = 0x20;
6484            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6485               if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
6486            }
6487            if(SiS_Pr->SiS_UseROM) {
6488               if(ROMAddr[0x220] & 0x80) {
6489                  temp = ROMAddr[0x220] & 0x3c;
6490               }
6491            }
6492            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6493               if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
6494            }
6495         }
6496
6497         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
6498
6499 #endif  /* SIS300 */
6500
6501      } else {
6502
6503 #ifdef SIS315H   /* --------------- 315/330 series ---------------*/
6504
6505         if(HwInfo->jChipType < SIS_661) {
6506
6507            if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6508
6509               if(HwInfo->jChipType == SIS_740) temp = 0x03;
6510               else                             temp = 0x00;
6511
6512               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
6513               tempbl = 0xF0;
6514               if(HwInfo->jChipType == SIS_650) {
6515                  if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6516                     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
6517                  }
6518               }
6519
6520               if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
6521                  temp = 0x08;
6522                  tempbl = 0;
6523                  if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
6524                     if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
6525                  }
6526               }
6527
6528               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp);      /* Panel Link Delay Compensation */
6529            }
6530
6531         } /* < 661 */
6532
6533         tempax = 0;
6534         if(modeflag & DoubleScanMode) tempax |= 0x80;
6535         if(modeflag & HalfDCLK)       tempax |= 0x40;
6536         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
6537
6538 #endif  /* SIS315H */
6539
6540      }
6541
6542   }  /* Slavemode */
6543
6544   if(SiS_Pr->SiS_VBType & VB_SISVB) {
6545      if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
6546         /* For 301BDH with LCD, we set up the Panel Link */
6547         SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
6548      } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6549         SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
6550      }
6551   } else {
6552      if(HwInfo->jChipType < SIS_315H) {
6553         SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
6554      } else {
6555         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6556            if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6557               SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
6558            }
6559         } else {
6560            SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
6561         }
6562      }
6563   }
6564 }
6565
6566 /*********************************************/
6567 /*         SET PART 2 REGISTER GROUP         */
6568 /*********************************************/
6569
6570 #ifdef SIS315H
6571 static UCHAR *
6572 SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
6573 {
6574    const UCHAR  *tableptr = NULL;
6575    USHORT       a, b, p = 0;
6576
6577    a = SiS_Pr->SiS_VGAHDE;
6578    b = SiS_Pr->SiS_HDE;
6579    if(tabletype) {
6580       a = SiS_Pr->SiS_VGAVDE;
6581       b = SiS_Pr->SiS_VDE;
6582    }
6583
6584    if(a < b) {
6585       tableptr = SiS_Part2CLVX_1;
6586    } else if(a == b) {
6587       tableptr = SiS_Part2CLVX_2;
6588    } else {
6589       if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6590          tableptr = SiS_Part2CLVX_4;
6591       } else {
6592          tableptr = SiS_Part2CLVX_3;
6593       }
6594       if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6595          if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)        tableptr = SiS_Part2CLVX_3;
6596          else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   tableptr = SiS_Part2CLVX_3;
6597          else                                           tableptr = SiS_Part2CLVX_5;
6598       } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6599          tableptr = SiS_Part2CLVX_6;
6600       }
6601       do {
6602          if((tableptr[p] | tableptr[p+1] << 8) == a) break;
6603          p += 0x42;
6604       } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
6605       if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
6606    }
6607    p += 2;
6608    return((UCHAR *)&tableptr[p]);
6609 }
6610
6611 static void
6612 SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
6613                     USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
6614 {
6615    UCHAR *tableptr;
6616    int i, j;
6617    UCHAR temp;
6618
6619    if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
6620
6621    tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0, HwInfo);
6622    for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
6623       SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6624    }
6625    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6626       tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1, HwInfo);
6627       for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
6628          SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6629       }
6630    }
6631    temp = 0x10;
6632    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
6633    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
6634 }
6635
6636 static BOOLEAN
6637 SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
6638                     USHORT RefreshRateTableIndex,USHORT *CRT2Index,
6639                     USHORT *ResIndex,PSIS_HW_INFO HwInfo)
6640 {
6641
6642   if(HwInfo->jChipType < SIS_315H) return FALSE;
6643
6644   if(ModeNo <= 0x13)
6645      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6646   else
6647      (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6648
6649   (*ResIndex) &= 0x3f;
6650   (*CRT2Index) = 0;
6651
6652   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6653      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6654         (*CRT2Index) = 200;
6655      }
6656   }
6657
6658   if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
6659      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6660         if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
6661      }
6662   }
6663   return(((*CRT2Index) != 0));
6664 }
6665 #endif
6666
6667 #ifdef SIS300
6668 static void
6669 SiS_Group2LCDSpecial(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT crt2crtc)
6670 {
6671    USHORT tempcx;
6672    const UCHAR atable[] = {
6673        0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
6674        0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
6675    };
6676
6677    if(!SiS_Pr->UseCustomMode) {
6678       if( ( ( (HwInfo->jChipType == SIS_630) ||
6679               (HwInfo->jChipType == SIS_730) ) &&
6680             (HwInfo->jChipRevision > 2) )  &&
6681           (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
6682           (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
6683           (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
6684          if(ModeNo == 0x13) {
6685             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
6686             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
6687             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
6688          } else {
6689             if((crt2crtc & 0x3F) == 4) {
6690                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
6691                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
6692                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
6693                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
6694                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
6695             }
6696          }
6697       }
6698
6699       if(HwInfo->jChipType < SIS_315H) {
6700          if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
6701             crt2crtc &= 0x1f;
6702             tempcx = 0;
6703             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6704                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6705                   tempcx += 7;
6706                }
6707             }
6708             tempcx += crt2crtc;
6709             if(crt2crtc >= 4) {
6710                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
6711             }
6712
6713             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6714                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6715                   if(crt2crtc == 4) {
6716                      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
6717                   }
6718                }
6719             }
6720             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
6721             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
6722          }
6723       }
6724    }
6725 }
6726
6727 /* For ECS A907. Highly preliminary. */
6728 static void
6729 SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
6730                     USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
6731                     USHORT ModeNo)
6732 {
6733   USHORT crt2crtc, resindex;
6734   int    i,j;
6735   const  SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
6736
6737   if(HwInfo->jChipType != SIS_300) return;
6738   if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
6739   if(SiS_Pr->UseCustomMode) return;
6740
6741   if(ModeNo <= 0x13) {
6742      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6743   } else {
6744      crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6745   }
6746
6747   resindex = crt2crtc & 0x3F;
6748   if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6749   else                                    CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
6750
6751   /* The BIOS code (1.16.51,56) is obviously a fragment! */
6752   if(ModeNo > 0x13) {
6753      CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6754      resindex = 4;
6755   }
6756
6757   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6758   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6759   for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
6760         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6761   }
6762   for(j = 0x1c; j <= 0x1d; i++, j++ ) {
6763         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6764   }
6765   for(j = 0x1f; j <= 0x21; i++, j++ ) {
6766         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6767   }
6768   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6769   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6770 }
6771 #endif
6772
6773 static void
6774 SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo)
6775 {
6776   if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
6777   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
6778   if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
6779
6780   if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6781      if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6782         const UCHAR specialtv[] = {
6783                 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
6784                 0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
6785                 0x58,0xe4,0x73,0xda,0x13
6786         };
6787         int i, j;
6788         for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
6789            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
6790         }
6791         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
6792         if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
6793            if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6794               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
6795               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
6796            } else {
6797               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);  /* 15 */
6798               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a);  /* 1b */
6799            }
6800         }
6801      }
6802   } else {
6803      if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
6804         (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
6805         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 21 */
6806         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 5a */
6807      } else {
6808         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a);  /* 21 */
6809         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53);  /* 5a */
6810      }
6811   }
6812 }
6813
6814 static void
6815 SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
6816 {
6817   USHORT temp;
6818
6819   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6820      if(SiS_Pr->SiS_VGAVDE == 525) {
6821         temp = 0xc3;
6822         if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6823            temp++;
6824            if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
6825         }
6826         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6827         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
6828      } else if(SiS_Pr->SiS_VGAVDE == 420) {
6829         temp = 0x4d;
6830         if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6831            temp++;
6832            if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
6833         }
6834         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6835      }
6836   }
6837
6838   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6839      if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
6840         if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
6841            SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
6842            /* Not always for LV, see SetGrp2 */
6843         }
6844         temp = 1;
6845         if(ModeNo <= 0x13) temp = 3;
6846         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
6847      }
6848 #if 0
6849      /* 651+301C, for 1280x768 - do I really need that? */
6850      if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
6851         if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
6852            if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
6853               ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
6854               SiS_SetReg(SiS_Part2Port,0x01,0x2b);
6855               SiS_SetReg(SiS_Part2Port,0x02,0x13);
6856               SiS_SetReg(SiS_Part2Port,0x04,0xe5);
6857               SiS_SetReg(SiS_Part2Port,0x05,0x08);
6858               SiS_SetReg(SiS_Part2Port,0x06,0xe2);
6859               SiS_SetReg(SiS_Part2Port,0x1c,0x21);
6860               SiS_SetReg(SiS_Part2Port,0x1d,0x45);
6861               SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
6862               SiS_SetReg(SiS_Part2Port,0x20,0x00);
6863               SiS_SetReg(SiS_Part2Port,0x21,0xa9);
6864               SiS_SetReg(SiS_Part2Port,0x23,0x0b);
6865               SiS_SetReg(SiS_Part2Port,0x25,0x04);
6866            }
6867         }
6868      }
6869 #endif
6870   }
6871 }
6872
6873 static void
6874 SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
6875               PSIS_HW_INFO HwInfo)
6876 {
6877   USHORT      i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
6878   USHORT      push2, modeflag, crt2crtc, bridgeoffset;
6879   ULONG       longtemp;
6880   const       UCHAR *PhasePoint;
6881   const       UCHAR *TimingPoint;
6882 #ifdef SIS315H
6883   USHORT      resindex, CRT2Index;
6884   const       SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
6885
6886   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
6887 #endif
6888
6889   if(ModeNo <= 0x13) {
6890      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6891      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6892   } else if(SiS_Pr->UseCustomMode) {
6893      modeflag = SiS_Pr->CModeFlag;
6894      crt2crtc = 0;
6895   } else {
6896      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6897      crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6898   }
6899
6900   temp = 0;
6901   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
6902   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
6903   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)     temp |= 0x02;
6904   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)  temp |= 0x01;
6905
6906   if(!(SiS_Pr->SiS_TVMode & TVSetPAL))        temp |= 0x10;
6907
6908   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
6909
6910   PhasePoint  = SiS_Pr->SiS_PALPhase;
6911   TimingPoint = SiS_Pr->SiS_PALTiming;
6912
6913   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6914
6915      TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
6916      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6917         TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
6918         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6919            TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
6920 #if 0
6921            if(!(modeflag & Charx8Dot))  TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
6922 #endif
6923         }
6924      }
6925
6926   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6927
6928      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      TimingPoint = &SiS_YPbPrTable[2][0];
6929      else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) TimingPoint = &SiS_YPbPrTable[1][0];
6930      else                                         TimingPoint = &SiS_YPbPrTable[0][0];
6931
6932      PhasePoint = SiS_Pr->SiS_NTSCPhase;
6933
6934   } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6935
6936      if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
6937          ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6938            (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6939         PhasePoint = SiS_Pr->SiS_PALPhase2;
6940      }
6941
6942   } else {
6943
6944      TimingPoint = SiS_Pr->SiS_NTSCTiming;
6945      PhasePoint  = SiS_Pr->SiS_NTSCPhase;
6946      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
6947         PhasePoint = SiS_Pr->SiS_PALPhase;
6948      }
6949
6950      if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
6951          ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6952            (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6953         PhasePoint = SiS_Pr->SiS_NTSCPhase2;
6954         if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
6955            PhasePoint = SiS_Pr->SiS_PALPhase2;
6956         }
6957      }
6958
6959   }
6960
6961   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6962      PhasePoint = SiS_Pr->SiS_PALMPhase;
6963      if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
6964          ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6965            (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6966         PhasePoint = SiS_Pr->SiS_PALMPhase2;
6967      }
6968   }
6969
6970   if(SiS_Pr->SiS_TVMode & TVSetPALN) {
6971      PhasePoint = SiS_Pr->SiS_PALNPhase;
6972      if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
6973          ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6974            (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6975         PhasePoint = SiS_Pr->SiS_PALNPhase2;
6976      }
6977   }
6978
6979   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6980      PhasePoint = SiS_Pr->SiS_SpecialPhase;
6981      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6982         PhasePoint = SiS_Pr->SiS_SpecialPhaseM;
6983      } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
6984         PhasePoint = SiS_Pr->SiS_SpecialPhaseJ;
6985      }
6986   }
6987
6988   for(i=0x31, j=0; i<=0x34; i++, j++) {
6989      SiS_SetReg(SiS_Pr->SiS_Part2Port,i,PhasePoint[j]);
6990   }
6991
6992   for(i=0x01, j=0; i<=0x2D; i++, j++) {
6993      SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6994   }
6995   for(i=0x39; i<=0x45; i++, j++) {
6996      SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6997   }
6998
6999   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7000      if(SiS_Pr->SiS_ModeType != ModeText) {
7001         SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
7002      }
7003   }
7004
7005   SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
7006
7007   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
7008   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
7009   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
7010   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
7011
7012   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)    tempax = 950;
7013   else if(SiS_Pr->SiS_TVMode & TVSetPAL)        tempax = 520;
7014   else                                          tempax = 440; /* NTSC, YPbPr 525, 750 */
7015
7016   if( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) && (SiS_Pr->SiS_VDE <= tempax) ) ||
7017       ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
7018         ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
7019
7020      tempax -= SiS_Pr->SiS_VDE;
7021      tempax >>= 2;
7022      tempax &= 0x00ff;
7023
7024      temp = tempax + (USHORT)TimingPoint[0];
7025      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7026
7027      temp = tempax + (USHORT)TimingPoint[1];
7028      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7029
7030      if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
7031         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7032            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 19 */
7033            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 52 */
7034         } else {
7035            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
7036            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
7037         }
7038      }
7039
7040   }
7041
7042   tempcx = SiS_Pr->SiS_HT;
7043   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
7044   tempcx--;
7045   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
7046   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
7047   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
7048
7049   tempcx = SiS_Pr->SiS_HT >> 1;
7050   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
7051   tempcx += 7;
7052   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
7053   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
7054
7055   tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
7056   tempbx += tempcx;
7057   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
7058   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
7059
7060   tempbx += 8;
7061   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7062      tempbx -= 4;
7063      tempcx = tempbx;
7064   }
7065   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
7066
7067   j += 2;
7068   tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
7069   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
7070   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
7071
7072   tempcx += 8;
7073   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
7074   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
7075
7076   tempcx = SiS_Pr->SiS_HT >> 1;
7077   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
7078   j += 2;
7079   tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
7080   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
7081
7082   tempcx -= 11;
7083   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7084      tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
7085   }
7086   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
7087
7088   tempbx = SiS_Pr->SiS_VDE;
7089   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7090      if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
7091      if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
7092      if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
7093   } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
7094              (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
7095      tempbx >>= 1;
7096      if(HwInfo->jChipType >= SIS_315H) {
7097         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7098            if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
7099         } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7100            if(SiS_Pr->SiS_ModeType <= ModeVGA) {
7101               if(crt2crtc == 4) tempbx++;
7102            }
7103         }
7104      }
7105      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7106         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7107            if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
7108         }
7109         if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
7110            if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
7111         }
7112      }
7113   }
7114   tempbx -= 2;
7115   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
7116
7117   temp = (tempcx >> 8) & 0x0F;
7118   temp |= ((tempbx >> 2) & 0xC0);
7119   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
7120      temp |= 0x10;
7121      if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
7122   }
7123   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
7124
7125   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
7126      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
7127   }
7128
7129 #if 0
7130   /* TEST qqqq */
7131   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7132      for(i=0x01, j=0; i<=0x2D; i++, j++) {
7133         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
7134      }
7135      for(i=0x39; i<=0x45; i++, j++) {
7136         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
7137      }
7138   }
7139 #endif
7140
7141   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
7142      tempbx = SiS_Pr->SiS_VDE;
7143      if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
7144          (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
7145         tempbx >>= 1;
7146      }
7147      tempbx -= 3;
7148      temp = ((tempbx >> 3) & 0x60) | 0x18;
7149      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
7150      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
7151
7152      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
7153         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
7154      }
7155   }
7156
7157   tempbx = 0;
7158   if(!(modeflag & HalfDCLK)) {
7159      if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
7160         tempax = 0;
7161         tempbx |= 0x20;
7162      }
7163   }
7164
7165   tempch = tempcl = 0x01;
7166   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7167      if(SiS_Pr->SiS_VGAHDE >= 1024) {
7168         if((!(modeflag & HalfDCLK)) || (HwInfo->jChipType < SIS_315H)) {
7169            tempch = 0x19;
7170            tempcl = 0x20;
7171            if(SiS_Pr->SiS_VGAHDE >= 1280) {
7172               tempch = 0x14;
7173               tempbx &= ~0x20;
7174            }
7175         }
7176      }
7177   }
7178
7179   if(!(tempbx & 0x20)) {
7180      if(modeflag & HalfDCLK) tempcl <<= 1;
7181      longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
7182      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) longtemp <<= 3;
7183      tempax = longtemp / SiS_Pr->SiS_HDE;
7184      if(longtemp % SiS_Pr->SiS_HDE) tempax++;
7185      tempbx |= ((tempax >> 8) & 0x1F);
7186      tempcx = tempax >> 13;
7187   }
7188
7189   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
7190   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
7191
7192   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
7193
7194      tempcx &= 0x07;
7195      if(tempbx & 0x20) tempcx = 0;
7196      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
7197
7198      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7199         tempbx = 0x0382;
7200         tempcx = 0x007e;
7201      } else {
7202         tempbx = 0x0369;
7203         tempcx = 0x0061;
7204      }
7205      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
7206      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
7207      temp = (tempcx & 0x0300) >> 6;
7208      temp |= ((tempbx >> 8) & 0x03);
7209      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7210         temp |= 0x10;
7211         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)      temp |= 0x20;
7212         else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
7213      }
7214      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
7215
7216      temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7217      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
7218
7219      SiS_SetTVSpecial(SiS_Pr, ModeNo);
7220
7221      if(SiS_Pr->SiS_VBType & VB_SIS301C) {
7222         temp = 0;
7223         if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
7224         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
7225      }
7226
7227   }
7228
7229   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7230      if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
7231         temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
7232         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
7233      }
7234      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
7235   }
7236
7237   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7238      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
7239         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
7240      }
7241   }
7242
7243   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
7244
7245   /* From here: Part2 LCD setup */
7246
7247   tempbx = SiS_Pr->SiS_HDE;
7248   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7249   tempbx--;                                     /* RHACTE = HDE - 1 */
7250   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
7251   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
7252
7253   temp = 0x01;
7254   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7255      if(SiS_Pr->SiS_ModeType == ModeEGA) {
7256         if(SiS_Pr->SiS_VGAHDE >= 1024) {
7257            temp = 0x02;
7258            if(HwInfo->jChipType >= SIS_315H) {
7259               if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7260                  temp = 0x01;
7261               }
7262            }
7263         }
7264      }
7265   }
7266   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
7267
7268   tempbx = SiS_Pr->SiS_VDE - 1;
7269   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
7270   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
7271
7272   tempcx = SiS_Pr->SiS_VT - 1;
7273   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
7274   temp = (tempcx >> 3) & 0xE0;
7275   if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
7276      /* Enable dithering; only do this for 32bpp mode */
7277      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
7278         temp |= 0x10;
7279      }
7280   }
7281   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
7282
7283   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
7284   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
7285
7286   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
7287   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
7288
7289 #ifdef SIS315H
7290   if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7291                                                 &CRT2Index, &resindex, HwInfo)) {
7292       switch(CRT2Index) {
7293         case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
7294         case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
7295         default:  CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;   break;
7296       }
7297
7298       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
7299       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
7300       for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
7301         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7302       }
7303       for(j = 0x1c; j <= 0x1d; i++, j++ ) {
7304         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7305       }
7306       for(j = 0x1f; j <= 0x21; i++, j++ ) {
7307         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7308       }
7309       SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
7310       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
7311
7312       SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7313
7314
7315   } else {
7316 #endif
7317
7318     /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
7319     /*             Clevo dual-link 1024x768 */
7320     /*             Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
7321     /*             Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
7322
7323     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7324        if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7325           tempbx = SiS_Pr->SiS_VDE - 1;
7326           tempcx = SiS_Pr->SiS_VT - 1;
7327        } else {
7328           tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7329           tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7330        }
7331     } else {
7332        tempbx = SiS_Pr->PanelYRes;
7333        tempcx = SiS_Pr->SiS_VT;
7334        tempax = 1;
7335        if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7336           tempax = SiS_Pr->PanelYRes;
7337           /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
7338           if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7339              tempax = tempcx = 0;
7340           } else {
7341              tempax -= SiS_Pr->SiS_VDE;
7342           }
7343           tempax >>= 1;
7344        }
7345        tempcx -= tempax; /* lcdvdes */
7346        tempbx -= tempax; /* lcdvdee */
7347     }
7348
7349     /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7350
7351 #ifdef TWDEBUG
7352     xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
7353 #endif
7354
7355     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);      /* lcdvdes  */
7356     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);      /* lcdvdee  */
7357
7358     temp = (tempbx >> 5) & 0x38;
7359     temp |= ((tempcx >> 8) & 0x07);
7360     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7361
7362     tempax = SiS_Pr->SiS_VDE;
7363     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7364        tempax = SiS_Pr->PanelYRes;
7365     }
7366     tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7367     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7368        if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7369           tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7370        }
7371     }
7372
7373     tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7374     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7375        if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7376           if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7377              tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7378              if(tempax % 4) { tempax >>= 2; tempax++; }
7379              else           { tempax >>= 2;           }
7380              tempbx -= (tempax - 1);
7381           } else {
7382              tempbx -= 10;
7383              if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7384           }
7385        }
7386     }
7387     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7388        tempbx++;
7389        if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7390           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7391              tempbx = 770;
7392              tempcx = 3;
7393           }
7394        }
7395     }
7396
7397     /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7398
7399     if(SiS_Pr->UseCustomMode) {
7400        tempbx = SiS_Pr->CVSyncStart;
7401     }
7402
7403 #ifdef TWDEBUG
7404     xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
7405 #endif
7406
7407     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);          /* lcdvrs */
7408
7409     temp = (tempbx >> 4) & 0xF0;
7410     tempbx += (tempcx + 1);
7411     temp |= (tempbx & 0x0F);
7412
7413     if(SiS_Pr->UseCustomMode) {
7414        temp &= 0xf0;
7415        temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7416     }
7417
7418 #ifdef TWDEBUG
7419     xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
7420 #endif
7421
7422     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7423
7424 #ifdef SIS300
7425     SiS_Group2LCDSpecial(SiS_Pr, HwInfo, ModeNo, crt2crtc);
7426 #endif
7427
7428     bridgeoffset = 7;
7429     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)          bridgeoffset += 2;
7430     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) bridgeoffset++;
7431     if(SiS_IsDualLink(SiS_Pr, HwInfo))                   bridgeoffset++;
7432
7433     temp = 0;
7434     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7435        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7436           temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7437           if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp >>= 1;
7438        }
7439     }
7440     temp += bridgeoffset;
7441     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);             /* lcdhdes */
7442     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7443
7444     tempcx = SiS_Pr->SiS_HT;
7445     tempax = tempbx = SiS_Pr->SiS_HDE;
7446     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7447        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7448           tempax = SiS_Pr->PanelXRes;
7449           tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7450        }
7451     }
7452     if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
7453        tempcx >>= 1;
7454        tempbx >>= 1;
7455        tempax >>= 1;
7456     }
7457
7458 #ifdef TWDEBUG
7459     xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
7460 #endif
7461
7462     tempbx += bridgeoffset;
7463
7464     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);          /* lcdhdee */
7465     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7466
7467     tempcx = (tempcx - tempax) >> 2;
7468
7469     tempbx += tempcx;
7470     push2 = tempbx;
7471
7472     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7473        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7474           if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7475              if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7476           }
7477        }
7478     }
7479
7480     if(SiS_Pr->UseCustomMode) {
7481        tempbx = SiS_Pr->CHSyncStart;
7482        if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7483        tempbx += bridgeoffset;
7484     }
7485
7486 #ifdef TWDEBUG
7487     xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
7488 #endif
7489
7490     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);          /* lcdhrs */
7491     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7492
7493     tempbx = push2;
7494
7495     tempcx <<= 1;
7496     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7497        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7498     }
7499     tempbx += tempcx;
7500
7501     if(SiS_Pr->UseCustomMode) {
7502        tempbx = SiS_Pr->CHSyncEnd;
7503        if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7504        tempbx += bridgeoffset;
7505     }
7506
7507 #ifdef TWDEBUG
7508     xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
7509 #endif
7510
7511     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);          /* lcdhre */
7512
7513     SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7514
7515 #ifdef SIS300
7516     SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex, RefreshRateTableIndex, ModeNo);
7517 #endif
7518 #ifdef SIS315H
7519   } /* CRT2-LCD from table */
7520 #endif
7521 }
7522
7523 /*********************************************/
7524 /*         SET PART 3 REGISTER GROUP         */
7525 /*********************************************/
7526
7527 static void
7528 SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7529               PSIS_HW_INFO HwInfo)
7530 {
7531   USHORT        i;
7532   const UCHAR   *tempdi;
7533
7534   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7535
7536 #ifndef SIS_CP
7537   SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7538 #else
7539   SIS_CP_INIT301_CP
7540 #endif
7541
7542   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7543      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7544      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7545   } else {
7546      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7547      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7548   }
7549
7550   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7551      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7552      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7553      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7554   }
7555
7556   tempdi = NULL;
7557   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7558      tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7559      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7560         tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7561      }
7562   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7563      if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7564         tempdi = SiS_HiTVGroup3_1;
7565         if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7566      }
7567   }
7568   if(tempdi) {
7569      for(i=0; i<=0x3E; i++) {
7570         SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7571      }
7572      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
7573         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7574            SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7575         }
7576      }
7577   }
7578
7579 #ifdef SIS_CP
7580   SIS_CP_INIT301_CP2
7581 #endif
7582 }
7583
7584 /*********************************************/
7585 /*         SET PART 4 REGISTER GROUP         */
7586 /*********************************************/
7587
7588 #ifdef SIS315H
7589 static void
7590 SiS_ShiftXPos(SiS_Private *SiS_Pr, int shift)
7591 {
7592    USHORT temp, temp1, temp2;
7593
7594    temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7595    temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
7596    temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7597    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7598    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7599    temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
7600    temp = (USHORT)((int)(temp) + shift);
7601    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7602    temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7603    temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
7604    temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7605    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7606    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7607 }
7608
7609 static void
7610 SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
7611                     USHORT ModeNo, USHORT ModeIdIndex)
7612 {
7613    USHORT temp, temp1, resinfo = 0;
7614
7615    if(!(SiS_Pr->SiS_VBType & VB_SIS301C)) return;
7616    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7617
7618    if(ModeNo > 0x13) {
7619       resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7620    }
7621
7622    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7623    temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7624    if(!(temp & 0x01)) {
7625       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7626       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
7627       if((HwInfo->jChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
7628          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7629       }
7630       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7631       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
7632       else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7633       else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
7634       else                                         temp = 0x0402;
7635       if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
7636          temp1 = 0;
7637          if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7638          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7639          if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7640          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
7641       } else {
7642          temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7643          if(temp1 == 0x01) temp |= 0x01;
7644          if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
7645          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
7646       }
7647       SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7648       if(ModeNo > 0x13) {
7649          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7650       }
7651
7652       if(HwInfo->jChipType >= SIS_661) {                /* ? */
7653          if(SiS_Pr->SiS_TVMode & TVAspect43) {
7654             if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7655                if(resinfo == SIS_RI_1024x768) {
7656                   SiS_ShiftXPos(SiS_Pr, 97);
7657                } else {
7658                   SiS_ShiftXPos(SiS_Pr, 111);
7659                }
7660             } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7661                SiS_ShiftXPos(SiS_Pr, 136);
7662             }
7663          }
7664       }
7665    }
7666 }
7667 #endif
7668
7669 static void
7670 SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7671                  USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
7672 {
7673   USHORT vclkindex;
7674   USHORT temp, reg1, reg2;
7675
7676   if(SiS_Pr->UseCustomMode) {
7677      reg1 = SiS_Pr->CSR2B;
7678      reg2 = SiS_Pr->CSR2C;
7679   } else {
7680      vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7681                                  HwInfo);
7682      reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7683      reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7684   }
7685
7686   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
7687      if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
7688         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7689         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7690         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7691      } else {
7692         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7693         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7694      }
7695   } else {
7696      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7697      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7698      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7699   }
7700   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7701   temp = 0x08;
7702   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7703   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7704 }
7705
7706 static void
7707 SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7708               USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
7709 {
7710   USHORT tempax,tempcx,tempbx,modeflag,temp,resinfo;
7711   ULONG tempebx,tempeax,templong;
7712
7713   if(ModeNo <= 0x13) {
7714      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7715      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7716   } else if(SiS_Pr->UseCustomMode) {
7717      modeflag = SiS_Pr->CModeFlag;
7718      resinfo = 0;
7719   } else {
7720      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7721      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7722   }
7723
7724   if(HwInfo->jChipType >= SIS_315H) {
7725      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
7726         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7727            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7728         }
7729      }
7730   }
7731
7732   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV)) {
7733      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7734         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
7735      }
7736   }
7737
7738   if(HwInfo->jChipType >= SIS_315H) {
7739      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7740         if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
7741            if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
7742               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7743            } else {
7744               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7745            }
7746
7747            if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
7748               SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7749 #ifdef SET_EMI
7750               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7751 #endif
7752               SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7753            }
7754         }
7755         return;
7756      }
7757   }
7758
7759   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7760
7761   tempbx = SiS_Pr->SiS_RVBHCMAX;
7762   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7763
7764   temp = (tempbx >> 1) & 0x80;
7765
7766   tempcx = SiS_Pr->SiS_VGAHT - 1;
7767   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7768
7769   temp |= ((tempcx >> 5) & 0x78);
7770
7771   tempcx = SiS_Pr->SiS_VGAVT - 1;
7772   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7773   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7774
7775   temp |= ((tempcx >> 8) & 0x07);
7776   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7777
7778   tempbx = SiS_Pr->SiS_VGAHDE;
7779   if(modeflag & HalfDCLK)            tempbx >>= 1;
7780   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7781
7782   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7783      temp = 0;
7784      if(tempbx > 800)        temp = 0x60;
7785   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7786      temp = 0;
7787      if(tempbx == 1024)      temp = 0xA0;
7788      else if(tempbx > 1024)  temp = 0xC0;
7789   } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7790      temp = 0;
7791      if(tempbx >= 1280)      temp = 0x40;
7792      else if(tempbx >= 1024) temp = 0x20;
7793   } else {
7794      temp = 0x80;
7795      if(tempbx >= 1024)      temp = 0xA0;
7796   }
7797
7798   if(SiS_Pr->SiS_VBType & VB_SIS301) {
7799      if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) temp |= 0x0A;
7800   }
7801
7802   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7803
7804   tempeax = SiS_Pr->SiS_VGAVDE;
7805   tempebx = SiS_Pr->SiS_VDE;
7806   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7807      if(!(temp & 0xE0)) tempebx >>=1;
7808   }
7809
7810   tempcx = SiS_Pr->SiS_RVBHRS;
7811   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7812   tempcx >>= 8;
7813   tempcx |= 0x40;
7814
7815   if(tempeax <= tempebx) {
7816      tempcx ^= 0x40;
7817   } else {
7818      tempeax -= tempebx;
7819   }
7820
7821   tempeax *= (256 * 1024);
7822   templong = tempeax % tempebx;
7823   tempeax /= tempebx;
7824   if(templong) tempeax++;
7825
7826   temp = (USHORT)(tempeax & 0x000000FF);
7827   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
7828   temp = (USHORT)((tempeax & 0x0000FF00) >> 8);
7829   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
7830   temp = (USHORT)((tempeax >> 12) & 0x70); /* sic! */
7831   temp |= (tempcx & 0x4F);
7832   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7833
7834   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
7835
7836      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7837
7838      /* Calc Linebuffer max address and set/clear decimode */
7839      tempbx = 0;
7840      if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7841      tempax = SiS_Pr->SiS_VGAHDE;
7842      if(modeflag & HalfDCLK)            tempax >>= 1;
7843      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
7844      if(tempax > 800) {
7845         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7846            tempax -= 800;
7847         } else {  /* 651+301C: Only if TVNoHiviNoYPbPr */
7848            tempbx = 0x08;
7849            if(tempax == 1024) tempax *= 25;
7850            else               tempax *= 20;
7851            temp = tempax % 32;
7852            tempax /= 32;
7853            if(temp) tempax++;
7854            tempax++;
7855            if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) ||
7856               (SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7857               if(resinfo == SIS_RI_1024x768) {
7858                  /* Otherwise white line at right edge */
7859                  tempax = (tempax & 0xff00) | 0x20;
7860               }
7861            }
7862         }
7863      }
7864      tempax--;
7865      temp = ((tempax >> 4) & 0x30) | tempbx;
7866      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7867      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7868
7869      temp = 0x0036; tempbx = 0xD0;
7870      if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
7871         temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7872      }
7873      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7874         if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7875            temp |= 0x01;
7876            if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7877               if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7878                  temp &= ~0x01;
7879               }
7880            }
7881         }
7882      }
7883      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7884
7885      tempbx = SiS_Pr->SiS_HT >> 1;
7886      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7887      tempbx -= 2;
7888      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7889      temp = (tempbx >> 5) & 0x38;
7890      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7891
7892      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
7893         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7894            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7895            /* LCD-too-dark-error-source, see FinalizeLCD() */
7896         }
7897         if(HwInfo->jChipType >= SIS_315H) {
7898            if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
7899               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7900            } else {
7901               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7902            }
7903         }
7904         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
7905            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7906 #ifdef SET_EMI
7907            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7908 #endif
7909            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7910         }
7911      }
7912
7913   }  /* 301B */
7914
7915   SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
7916 }
7917
7918 /*********************************************/
7919 /*         SET PART 5 REGISTER GROUP         */
7920 /*********************************************/
7921
7922 static void
7923 SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7924               PSIS_HW_INFO HwInfo)
7925 {
7926
7927   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)  return;
7928
7929   if(SiS_Pr->SiS_ModeType == ModeVGA) {
7930      if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7931         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
7932         SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
7933      }
7934   }
7935 }
7936
7937 /*********************************************/
7938 /*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
7939 /*********************************************/
7940
7941 static void
7942 SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7943                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
7944 {
7945   USHORT tempah,i,modeflag,j;
7946   USHORT ResIndex,DisplayType;
7947   const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL;
7948
7949   if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7950   else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7951
7952   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
7953      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
7954      (SiS_Pr->SiS_CustomT == CUT_PANEL848))
7955      return;
7956
7957   if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7958                           &ResIndex, &DisplayType))) {
7959      return;
7960   }
7961
7962   if(HwInfo->jChipType < SIS_315H) {
7963      if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
7964   }
7965
7966   switch(DisplayType) {
7967     case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1;           break;
7968     case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H;         break;
7969     case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2;           break;
7970     case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H;         break;
7971     case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
7972     case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H;        break;
7973     case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2;          break;
7974     case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H;        break;
7975     case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1;         break;
7976     case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H;       break;
7977     case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2;         break;
7978     case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2_H;       break;
7979     case 12: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1;           break;
7980     case 13: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H;         break;
7981     case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1;         break;
7982     case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1_H;       break;
7983     case 16: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2;         break;
7984     case 17: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2_H;       break;
7985     case 18: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC;               break;
7986     case 19: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC;               break;
7987     case 20: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL;                break;
7988     case 21: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL;                break;
7989     case 22: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x480_1;           break; /* FSTN */
7990     case 23: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1;          break;
7991     case 24: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H;        break;
7992     case 25: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2;          break;
7993     case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H;        break;
7994     case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1;          break;
7995     case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1_H;        break;
7996     case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2;          break;
7997     case 30: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2_H;        break;
7998     case 36: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1;         break;
7999     case 37: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1_H;       break;
8000     case 38: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2;         break;
8001     case 39: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2_H;       break;
8002     case 40: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1;          break;
8003     case 41: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1_H;        break;
8004     case 42: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2;          break;
8005     case 43: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2_H;        break;
8006     case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1;           break;
8007     case 51: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H;         break;
8008     case 52: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2;           break;
8009     case 53: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2_H;         break;
8010     case 54: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3;           break;
8011     case 55: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3_H;         break;
8012     case 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL;               break;
8013     default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
8014   }
8015
8016   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
8017
8018   tempah = (LVDSCRT1Ptr + ResIndex)->CR[0];
8019   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,tempah);
8020
8021   for(i=0x02,j=1;i<=0x05;i++,j++){
8022     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8023     SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
8024   }
8025   for(i=0x06,j=5;i<=0x07;i++,j++){
8026     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8027     SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
8028   }
8029   for(i=0x10,j=7;i<=0x11;i++,j++){
8030     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8031     SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
8032   }
8033   for(i=0x15,j=9;i<=0x16;i++,j++){
8034     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8035     SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
8036   }
8037   for(i=0x0A,j=11;i<=0x0C;i++,j++){
8038     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8039     SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
8040   }
8041
8042   tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
8043   tempah &= 0xE0;
8044   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
8045
8046   tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
8047   tempah &= 0x01;
8048   tempah <<= 5;
8049   if(modeflag & DoubleScanMode)  tempah |= 0x080;
8050   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
8051 }
8052
8053 /*********************************************/
8054 /*              SET CRT2 ECLK                */
8055 /*********************************************/
8056
8057 static void
8058 SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
8059            USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
8060 {
8061   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
8062   USHORT clkbase, vclkindex=0;
8063   UCHAR  sr2b, sr2c;
8064
8065   if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) || (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
8066         SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
8067         if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) {
8068            RefreshRateTableIndex--;
8069         }
8070         vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
8071                                     RefreshRateTableIndex, HwInfo);
8072         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8073   } else {
8074         vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
8075                                     RefreshRateTableIndex, HwInfo);
8076   }
8077
8078   sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
8079   sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
8080
8081   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
8082      if(SiS_Pr->SiS_UseROM) {
8083         if(ROMAddr[0x220] & 0x01) {
8084            sr2b = ROMAddr[0x227];
8085            sr2c = ROMAddr[0x228];
8086         }
8087      }
8088   }
8089
8090   clkbase = 0x02B;
8091   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
8092      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
8093         clkbase += 3;
8094      }
8095   }
8096
8097   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
8098   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
8099   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
8100   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
8101   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
8102   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
8103   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
8104   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
8105   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
8106 }
8107
8108 /*********************************************/
8109 /*           SET UP CHRONTEL CHIPS           */
8110 /*********************************************/
8111
8112 static void
8113 SiS_SetCHTVReg(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
8114                USHORT RefreshRateTableIndex)
8115 {
8116 #if defined(SIS300) || defined(SIS315H)
8117   USHORT temp, tempbx;
8118 #endif
8119   USHORT tempcl;
8120   USHORT TVType, resindex;
8121   const SiS_CHTVRegDataStruct *CHTVRegData = NULL;
8122
8123   if(ModeNo <= 0x13)
8124      tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
8125   else
8126      tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
8127
8128   TVType = 0;
8129   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
8130   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
8131         TVType += 2;
8132         if(SiS_Pr->SiS_ModeType > ModeVGA) {
8133            if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
8134         }
8135         if(SiS_Pr->SiS_TVMode & TVSetPALM) {
8136                 TVType = 4;
8137                 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
8138         } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
8139                 TVType = 6;
8140                 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
8141         }
8142   }
8143   switch(TVType) {
8144      case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
8145      case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
8146      case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
8147      case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
8148      case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
8149      case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
8150      case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
8151      case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
8152      case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
8153      default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
8154   }
8155   resindex = tempcl & 0x3F;
8156
8157   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8158
8159 #ifdef SIS300
8160
8161      /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
8162
8163      /* We don't support modes >800x600 */
8164      if (resindex > 5) return;
8165
8166      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
8167         SiS_SetCH700x(SiS_Pr,0x4304);   /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
8168         SiS_SetCH700x(SiS_Pr,0x6909);   /* Black level for PAL (105)*/
8169      } else {
8170         SiS_SetCH700x(SiS_Pr,0x0304);   /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
8171         SiS_SetCH700x(SiS_Pr,0x7109);   /* Black level for NTSC (113)*/
8172      }
8173
8174      temp = CHTVRegData[resindex].Reg[0];
8175      tempbx=((temp&0x00FF)<<8)|0x00;    /* Mode register */
8176      SiS_SetCH700x(SiS_Pr,tempbx);
8177      temp = CHTVRegData[resindex].Reg[1];
8178      tempbx=((temp&0x00FF)<<8)|0x07;    /* Start active video register */
8179      SiS_SetCH700x(SiS_Pr,tempbx);
8180      temp = CHTVRegData[resindex].Reg[2];
8181      tempbx=((temp&0x00FF)<<8)|0x08;    /* Position overflow register */
8182      SiS_SetCH700x(SiS_Pr,tempbx);
8183      temp = CHTVRegData[resindex].Reg[3];
8184      tempbx=((temp&0x00FF)<<8)|0x0A;    /* Horiz Position register */
8185      SiS_SetCH700x(SiS_Pr,tempbx);
8186      temp = CHTVRegData[resindex].Reg[4];
8187      tempbx=((temp&0x00FF)<<8)|0x0B;    /* Vertical Position register */
8188      SiS_SetCH700x(SiS_Pr,tempbx);
8189
8190      /* Set minimum flicker filter for Luma channel (SR1-0=00),
8191                 minimum text enhancement (S3-2=10),
8192                 maximum flicker filter for Chroma channel (S5-4=10)
8193                 =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
8194       */
8195      SiS_SetCH700x(SiS_Pr,0x2801);
8196
8197      /* Set video bandwidth
8198             High bandwith Luma composite video filter(S0=1)
8199             low bandwith Luma S-video filter (S2-1=00)
8200             disable peak filter in S-video channel (S3=0)
8201             high bandwidth Chroma Filter (S5-4=11)
8202             =00110001=0x31
8203      */
8204      SiS_SetCH700x(SiS_Pr,0xb103);       /* old: 3103 */
8205
8206      /* Register 0x3D does not exist in non-macrovision register map
8207             (Maybe this is a macrovision register?)
8208       */
8209 #ifndef SIS_CP
8210      SiS_SetCH70xx(SiS_Pr,0x003D);
8211 #endif
8212
8213      /* Register 0x10 only contains 1 writable bit (S0) for sensing,
8214             all other bits a read-only. Macrovision?
8215       */
8216      SiS_SetCH70xxANDOR(SiS_Pr,0x0010,0x1F);
8217
8218      /* Register 0x11 only contains 3 writable bits (S0-S2) for
8219             contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
8220       */
8221      SiS_SetCH70xxANDOR(SiS_Pr,0x0211,0xF8);
8222
8223      /* Clear DSEN
8224       */
8225      SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xEF);
8226
8227      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {             /* ---- NTSC ---- */
8228        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
8229          if(resindex == 0x04) {                         /* 640x480 overscan: Mode 16 */
8230            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);      /* loop filter off */
8231            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);      /* ACIV on, no need to set FSCI */
8232          } else if(resindex == 0x05) {                  /* 800x600 overscan: Mode 23 */
8233            SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0);      /* 0x18-0x1f: FSCI 469,762,048 */
8234            SiS_SetCH70xxANDOR(SiS_Pr,0x0C19,0xF0);
8235            SiS_SetCH70xxANDOR(SiS_Pr,0x001A,0xF0);
8236            SiS_SetCH70xxANDOR(SiS_Pr,0x001B,0xF0);
8237            SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xF0);
8238            SiS_SetCH70xxANDOR(SiS_Pr,0x001D,0xF0);
8239            SiS_SetCH70xxANDOR(SiS_Pr,0x001E,0xF0);
8240            SiS_SetCH70xxANDOR(SiS_Pr,0x001F,0xF0);
8241            SiS_SetCH70xxANDOR(SiS_Pr,0x0120,0xEF);       /* Loop filter on for mode 23 */
8242            SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE);       /* ACIV off, need to set FSCI */
8243          }
8244        } else {
8245          if(resindex == 0x04) {                          /* ----- 640x480 underscan; Mode 17 */
8246            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);       /* loop filter off */
8247            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
8248          } else if(resindex == 0x05) {                   /* ----- 800x600 underscan: Mode 24 */
8249 #if 0
8250            SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0);       /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
8251            SiS_SetCH70xxANDOR(SiS_Pr,0x0919,0xF0);       /* FSCI for mode 24 is 428,554,851 */
8252            SiS_SetCH70xxANDOR(SiS_Pr,0x081A,0xF0);       /* 198b3a63 */
8253            SiS_SetCH70xxANDOR(SiS_Pr,0x0b1B,0xF0);
8254            SiS_SetCH70xxANDOR(SiS_Pr,0x041C,0xF0);
8255            SiS_SetCH70xxANDOR(SiS_Pr,0x011D,0xF0);
8256            SiS_SetCH70xxANDOR(SiS_Pr,0x061E,0xF0);
8257            SiS_SetCH70xxANDOR(SiS_Pr,0x051F,0xF0);
8258            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);       /* loop filter off for mode 24 */
8259            SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE);       /* ACIV off, need to set FSCI */
8260 #endif     /* All alternatives wrong (datasheet wrong?), don't use FSCI */
8261            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);       /* loop filter off */
8262            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
8263          }
8264        }
8265      } else {                                           /* ---- PAL ---- */
8266            /* We don't play around with FSCI in PAL mode */
8267          if(resindex == 0x04) {
8268            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);      /* loop filter off */
8269            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);      /* ACIV on */
8270          } else {
8271            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);      /* loop filter off */
8272            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);      /* ACIV on */
8273          }
8274      }
8275      
8276 #endif  /* 300 */
8277
8278   } else {
8279
8280      /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
8281
8282 #ifdef SIS315H
8283
8284      /* We don't support modes >1024x768 */
8285      if (resindex > 6) return;
8286
8287      temp = CHTVRegData[resindex].Reg[0];
8288      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
8289         temp |= 0x10;
8290      }
8291      tempbx=((temp & 0x00FF) << 8) | 0x00;
8292      SiS_SetCH701x(SiS_Pr,tempbx);
8293
8294      temp = CHTVRegData[resindex].Reg[1];
8295      tempbx=((temp & 0x00FF) << 8) | 0x01;
8296      SiS_SetCH701x(SiS_Pr,tempbx);
8297
8298      temp = CHTVRegData[resindex].Reg[2];
8299      tempbx=((temp & 0x00FF) << 8) | 0x02;
8300      SiS_SetCH701x(SiS_Pr,tempbx);
8301
8302      temp = CHTVRegData[resindex].Reg[3];
8303      tempbx=((temp & 0x00FF) << 8) | 0x04;
8304      SiS_SetCH701x(SiS_Pr,tempbx);
8305
8306      temp = CHTVRegData[resindex].Reg[4];
8307      tempbx=((temp & 0x00FF) << 8) | 0x03;
8308      SiS_SetCH701x(SiS_Pr,tempbx);
8309
8310      temp = CHTVRegData[resindex].Reg[5];
8311      tempbx=((temp & 0x00FF) << 8) | 0x05;
8312      SiS_SetCH701x(SiS_Pr,tempbx);
8313
8314      temp = CHTVRegData[resindex].Reg[6];
8315      tempbx=((temp & 0x00FF) << 8) | 0x06;
8316      SiS_SetCH701x(SiS_Pr,tempbx);
8317
8318      temp = CHTVRegData[resindex].Reg[7];
8319      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
8320         temp = 0x66;
8321      }
8322      tempbx=((temp & 0x00FF) << 8) | 0x07;
8323      SiS_SetCH701x(SiS_Pr,tempbx);
8324
8325      temp = CHTVRegData[resindex].Reg[8];
8326      tempbx=((temp & 0x00FF) << 8) | 0x08;
8327      SiS_SetCH701x(SiS_Pr,tempbx);
8328
8329      temp = CHTVRegData[resindex].Reg[9];
8330      tempbx=((temp & 0x00FF) << 8) | 0x15;
8331      SiS_SetCH701x(SiS_Pr,tempbx);
8332
8333      temp = CHTVRegData[resindex].Reg[10];
8334      tempbx=((temp & 0x00FF) << 8) | 0x1f;
8335      SiS_SetCH701x(SiS_Pr,tempbx);
8336
8337      temp = CHTVRegData[resindex].Reg[11];
8338      tempbx=((temp & 0x00FF) << 8) | 0x0c;
8339      SiS_SetCH701x(SiS_Pr,tempbx);
8340
8341      temp = CHTVRegData[resindex].Reg[12];
8342      tempbx=((temp & 0x00FF) << 8) | 0x0d;
8343      SiS_SetCH701x(SiS_Pr,tempbx);
8344
8345      temp = CHTVRegData[resindex].Reg[13];
8346      tempbx=((temp & 0x00FF) << 8) | 0x0e;
8347      SiS_SetCH701x(SiS_Pr,tempbx);
8348
8349      temp = CHTVRegData[resindex].Reg[14];
8350      tempbx=((temp & 0x00FF) << 8) | 0x0f;
8351      SiS_SetCH701x(SiS_Pr,tempbx);
8352
8353      temp = CHTVRegData[resindex].Reg[15];
8354      tempbx=((temp & 0x00FF) << 8) | 0x10;
8355      SiS_SetCH701x(SiS_Pr,tempbx);
8356
8357      temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8358      /* D1 should be set for PAL, PAL-N and NTSC-J,
8359         but I won't do that for PAL unless somebody
8360         tells me to do so. Since the BIOS uses
8361         non-default CIV values and blacklevels,
8362         this might be compensated anyway.
8363       */
8364      if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8365      SiS_SetCH701x(SiS_Pr,((temp << 8) | 0x21));
8366
8367 #endif  /* 315 */
8368
8369   }
8370
8371 #ifdef SIS_CP
8372   SIS_CP_INIT301_CP3
8373 #endif
8374
8375 }
8376
8377 void
8378 SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8379 {
8380   USHORT temp;
8381
8382   /* Enable Chrontel 7019 LCD panel backlight */
8383   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8384      if(HwInfo->jChipType == SIS_740) {
8385         SiS_SetCH701x(SiS_Pr,0x6566);
8386      } else {
8387         temp = SiS_GetCH701x(SiS_Pr,0x66);
8388         temp |= 0x20;
8389         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
8390      }
8391   }
8392 }
8393
8394 void
8395 SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr)
8396 {
8397   USHORT temp;
8398
8399   /* Disable Chrontel 7019 LCD panel backlight */
8400   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8401      temp = SiS_GetCH701x(SiS_Pr,0x66);
8402      temp &= 0xDF;
8403      SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
8404   }
8405 }
8406
8407 #ifdef SIS315H  /* ----------- 315 series only ---------- */
8408
8409 static void
8410 SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8411 {
8412   UCHAR regtable[]      = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8413   UCHAR table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8414   UCHAR table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8415   UCHAR asus1024_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8416   UCHAR asus1400_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8417   UCHAR table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8418   UCHAR table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8419   UCHAR *tableptr = NULL;
8420   int i;
8421
8422   /* Set up Power up/down timing */
8423
8424   if(HwInfo->jChipType == SIS_740) {
8425      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8426         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8427         else                                      tableptr = table1024_740;
8428      } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8429                (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8430                (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8431         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8432         else                                      tableptr = table1400_740;
8433      } else return;
8434   } else {
8435      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8436         tableptr = table1024_650;
8437      } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8438                (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8439                (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8440         tableptr = table1400_650;
8441      } else return;
8442   }
8443
8444   for(i=0; i<5; i++) {
8445      SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
8446   }
8447 }
8448
8449 static void
8450 SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8451 {
8452   UCHAR regtable[]      = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8453                             0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66 };
8454   UCHAR table1024_740[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8455                             0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44 };
8456   UCHAR table1280_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8457                             0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
8458   UCHAR table1400_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8459                             0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
8460   UCHAR table1600_740[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8461                             0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44 };
8462   UCHAR table1024_650[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8463                             0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02 };
8464   UCHAR table1280_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8465                             0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02 };
8466   UCHAR table1400_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8467                             0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02 };
8468   UCHAR table1600_650[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8469                             0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a };
8470   UCHAR *tableptr = NULL;
8471   USHORT tempbh;
8472   int i;
8473
8474   if(HwInfo->jChipType == SIS_740) {
8475      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
8476      else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8477      else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8478      else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8479      else return;
8480   } else {
8481      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
8482      else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8483      else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8484      else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8485      else return;
8486   }
8487
8488   tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8489   if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8490      tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8491      if(tempbh == 0xc8) {
8492         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8493      } else if(tempbh == 0xdb) {
8494         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8495         if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8496      } else if(tempbh == 0xde) {
8497         if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8498      }
8499   }
8500
8501   if(HwInfo->jChipType == SIS_740) tempbh = 0x0d;
8502   else                             tempbh = 0x0c;
8503
8504   for(i = 0; i < tempbh; i++) {
8505      SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
8506   }
8507   SiS_ChrontelPowerSequencing(SiS_Pr,HwInfo);
8508   tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8509   tempbh |= 0xc0;
8510   SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1e);
8511
8512   if(HwInfo->jChipType == SIS_740) {
8513      tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8514      tempbh &= 0xfb;
8515      SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1c);
8516      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8517      tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8518      tempbh |= 0x40;
8519      SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x64);
8520      tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8521      tempbh &= 0x3f;
8522      SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x03);
8523   }
8524 }
8525
8526 static void
8527 SiS_ChrontelResetVSync(SiS_Private *SiS_Pr)
8528 {
8529   unsigned char temp, temp1;
8530
8531   temp1 = SiS_GetCH701x(SiS_Pr,0x49);
8532   SiS_SetCH701x(SiS_Pr,0x3e49);
8533   temp = SiS_GetCH701x(SiS_Pr,0x47);
8534   temp &= 0x7f; /* Use external VSYNC */
8535   SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
8536   SiS_LongDelay(SiS_Pr,3);
8537   temp = SiS_GetCH701x(SiS_Pr,0x47);
8538   temp |= 0x80; /* Use internal VSYNC */
8539   SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
8540   SiS_SetCH701x(SiS_Pr,(temp1 << 8) | 0x49);
8541 }
8542
8543 static void
8544 SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8545 {
8546   USHORT temp;
8547
8548   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8549      if(HwInfo->jChipType == SIS_740) {
8550         temp = SiS_GetCH701x(SiS_Pr,0x1c);
8551         temp |= 0x04;   /* Invert XCLK phase */
8552         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
8553      }
8554      if(SiS_IsYPbPr(SiS_Pr, HwInfo)) {
8555         temp = SiS_GetCH701x(SiS_Pr,0x01);
8556         temp &= 0x3f;
8557         temp |= 0x80;   /* Enable YPrPb (HDTV) */
8558         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
8559      }
8560      if(SiS_IsChScart(SiS_Pr, HwInfo)) {
8561         temp = SiS_GetCH701x(SiS_Pr,0x01);
8562         temp &= 0x3f;
8563         temp |= 0xc0;   /* Enable SCART + CVBS */
8564         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
8565      }
8566      if(HwInfo->jChipType == SIS_740) {
8567         SiS_ChrontelResetVSync(SiS_Pr);
8568         SiS_SetCH701x(SiS_Pr,0x2049);   /* Enable TV path */
8569      } else {
8570         SiS_SetCH701x(SiS_Pr,0x2049);   /* Enable TV path */
8571         temp = SiS_GetCH701x(SiS_Pr,0x49);
8572         if(SiS_IsYPbPr(SiS_Pr,HwInfo)) {
8573            temp = SiS_GetCH701x(SiS_Pr,0x73);
8574            temp |= 0x60;
8575            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x73);
8576         }
8577         temp = SiS_GetCH701x(SiS_Pr,0x47);
8578         temp &= 0x7f;
8579         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
8580         SiS_LongDelay(SiS_Pr,2);
8581         temp = SiS_GetCH701x(SiS_Pr,0x47);
8582         temp |= 0x80;
8583         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
8584      }
8585   }
8586 }
8587
8588 static void
8589 SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8590 {
8591   USHORT temp;
8592
8593   /* Complete power down of LVDS */
8594   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8595      if(HwInfo->jChipType == SIS_740) {
8596         SiS_LongDelay(SiS_Pr,1);
8597         SiS_GenericDelay(SiS_Pr,0x16ff);
8598         SiS_SetCH701x(SiS_Pr,0xac76);
8599         SiS_SetCH701x(SiS_Pr,0x0066);
8600      } else {
8601         SiS_LongDelay(SiS_Pr,2);
8602         temp = SiS_GetCH701x(SiS_Pr,0x76);
8603         temp &= 0xfc;
8604         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
8605         SiS_SetCH701x(SiS_Pr,0x0066);
8606      }
8607   }
8608 }
8609
8610 static void
8611 SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8612 {
8613      USHORT temp;
8614
8615      if(HwInfo->jChipType == SIS_740) {
8616
8617         temp = SiS_GetCH701x(SiS_Pr,0x4a);  /* Version ID */
8618         temp &= 0x01;
8619         if(!temp) {
8620
8621            if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
8622               temp = SiS_GetCH701x(SiS_Pr,0x49);
8623               SiS_SetCH701x(SiS_Pr,0x3e49);
8624            }
8625            /* Reset Chrontel 7019 datapath */
8626            SiS_SetCH701x(SiS_Pr,0x1048);
8627            SiS_LongDelay(SiS_Pr,1);
8628            SiS_SetCH701x(SiS_Pr,0x1848);
8629
8630            if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
8631               SiS_ChrontelResetVSync(SiS_Pr);
8632               SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x49);
8633            }
8634
8635         } else {
8636
8637            /* Clear/set/clear GPIO */
8638            temp = SiS_GetCH701x(SiS_Pr,0x5c);
8639            temp &= 0xef;
8640            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
8641            temp = SiS_GetCH701x(SiS_Pr,0x5c);
8642            temp |= 0x10;
8643            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
8644            temp = SiS_GetCH701x(SiS_Pr,0x5c);
8645            temp &= 0xef;
8646            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
8647            temp = SiS_GetCH701x(SiS_Pr,0x61);
8648            if(!temp) {
8649               SiS_SetCH701xForLCD(SiS_Pr, HwInfo);
8650            }
8651         }
8652
8653      } else { /* 650 */
8654         /* Reset Chrontel 7019 datapath */
8655         SiS_SetCH701x(SiS_Pr,0x1048);
8656         SiS_LongDelay(SiS_Pr,1);
8657         SiS_SetCH701x(SiS_Pr,0x1848);
8658      }
8659 }
8660
8661 static void
8662 SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8663 {
8664      USHORT temp;
8665
8666      if(HwInfo->jChipType == SIS_740) {
8667
8668         if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
8669            SiS_ChrontelResetVSync(SiS_Pr);
8670         }
8671
8672      } else {
8673
8674         SiS_SetCH701x(SiS_Pr,0xaf76);  /* Power up LVDS block */
8675         temp = SiS_GetCH701x(SiS_Pr,0x49);
8676         temp &= 1;
8677         if(temp != 1) {  /* TV block powered? (0 = yes, 1 = no) */
8678            temp = SiS_GetCH701x(SiS_Pr,0x47);
8679            temp &= 0x70;
8680            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);  /* enable VSYNC */
8681            SiS_LongDelay(SiS_Pr,3);
8682            temp = SiS_GetCH701x(SiS_Pr,0x47);
8683            temp |= 0x80;
8684            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);  /* disable VSYNC */
8685         }
8686
8687      }
8688 }
8689
8690 static void
8691 SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
8692 {
8693      USHORT temp,temp1;
8694
8695      if(HwInfo->jChipType == SIS_740) {
8696
8697         temp = SiS_GetCH701x(SiS_Pr,0x61);
8698         if(temp < 1) {
8699            temp++;
8700            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
8701         }
8702         SiS_SetCH701x(SiS_Pr,0x4566);  /* Panel power on */
8703         SiS_SetCH701x(SiS_Pr,0xaf76);  /* All power on */
8704         SiS_LongDelay(SiS_Pr,1);
8705         SiS_GenericDelay(SiS_Pr,0x16ff);
8706
8707      } else {  /* 650 */
8708
8709         temp1 = 0;
8710         temp = SiS_GetCH701x(SiS_Pr,0x61);
8711         if(temp < 2) {
8712            temp++;
8713            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
8714            temp1 = 1;
8715         }
8716         SiS_SetCH701x(SiS_Pr,0xac76);
8717         temp = SiS_GetCH701x(SiS_Pr,0x66);
8718         temp |= 0x5f;
8719         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
8720         if(ModeNo > 0x13) {
8721            if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
8722               SiS_GenericDelay(SiS_Pr,0x3ff);
8723            } else {
8724               SiS_GenericDelay(SiS_Pr,0x2ff);
8725            }
8726         } else {
8727            if(!temp1)
8728               SiS_GenericDelay(SiS_Pr,0x2ff);
8729         }
8730         temp = SiS_GetCH701x(SiS_Pr,0x76);
8731         temp |= 0x03;
8732         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
8733         temp = SiS_GetCH701x(SiS_Pr,0x66);
8734         temp &= 0x7f;
8735         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
8736         SiS_LongDelay(SiS_Pr,1);
8737
8738      }
8739 }
8740
8741 static void
8742 SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8743 {
8744      USHORT temp,tempcl,tempch;
8745
8746      SiS_LongDelay(SiS_Pr, 1);
8747      tempcl = 3;
8748      tempch = 0;
8749
8750      do {
8751        temp = SiS_GetCH701x(SiS_Pr,0x66);
8752        temp &= 0x04;  /* PLL stable? -> bail out */
8753        if(temp == 0x04) break;
8754
8755        if(HwInfo->jChipType == SIS_740) {
8756           /* Power down LVDS output, PLL normal operation */
8757           SiS_SetCH701x(SiS_Pr,0xac76);
8758        }
8759
8760        SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
8761
8762        if(tempcl == 0) {
8763            if(tempch == 3) break;
8764            SiS_ChrontelResetDB(SiS_Pr,HwInfo);
8765            tempcl = 3;
8766            tempch++;
8767        }
8768        tempcl--;
8769        temp = SiS_GetCH701x(SiS_Pr,0x76);
8770        temp &= 0xfb;  /* Reset PLL */
8771        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
8772        SiS_LongDelay(SiS_Pr,2);
8773        temp = SiS_GetCH701x(SiS_Pr,0x76);
8774        temp |= 0x04;  /* PLL normal operation */
8775        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
8776        if(HwInfo->jChipType == SIS_740) {
8777           SiS_SetCH701x(SiS_Pr,0xe078); /* PLL loop filter */
8778        } else {
8779           SiS_SetCH701x(SiS_Pr,0x6078);
8780        }
8781        SiS_LongDelay(SiS_Pr,2);
8782     } while(0);
8783
8784     SiS_SetCH701x(SiS_Pr,0x0077);  /* MV? */
8785 }
8786
8787 static void
8788 SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8789 {
8790      USHORT temp;
8791
8792      temp = SiS_GetCH701x(SiS_Pr,0x03);
8793      temp |= 0x80;      /* Set datapath 1 to TV   */
8794      temp &= 0xbf;      /* Set datapath 2 to LVDS */
8795      SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
8796
8797      if(HwInfo->jChipType == SIS_740) {
8798
8799         temp = SiS_GetCH701x(SiS_Pr,0x1c);
8800         temp &= 0xfb;   /* Normal XCLK phase */
8801         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
8802
8803         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8804
8805         temp = SiS_GetCH701x(SiS_Pr,0x64);
8806         temp |= 0x40;   /* ? Bit not defined */
8807         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x64);
8808
8809         temp = SiS_GetCH701x(SiS_Pr,0x03);
8810         temp &= 0x3f;   /* D1 input to both LVDS and TV */
8811         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
8812
8813         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
8814            SiS_SetCH701x(SiS_Pr,0x4063); /* LVDS off */
8815            SiS_LongDelay(SiS_Pr, 1);
8816            SiS_SetCH701x(SiS_Pr,0x0063); /* LVDS on */
8817            SiS_ChrontelResetDB(SiS_Pr, HwInfo);
8818            SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
8819            SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
8820         } else {
8821            temp = SiS_GetCH701x(SiS_Pr,0x66);
8822            if(temp != 0x45) {
8823               SiS_ChrontelResetDB(SiS_Pr, HwInfo);
8824               SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
8825               SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
8826            }
8827         }
8828
8829      } else { /* 650 */
8830
8831         SiS_ChrontelResetDB(SiS_Pr,HwInfo);
8832         SiS_ChrontelDoSomething2(SiS_Pr,HwInfo);
8833         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
8834         SiS_ChrontelDoSomething3(SiS_Pr,temp,HwInfo);
8835         SiS_SetCH701x(SiS_Pr,0xaf76);  /* All power on, LVDS normal operation */
8836
8837      }
8838
8839 }
8840 #endif  /* 315 series  */
8841
8842 /*********************************************/
8843 /*      MAIN: SET CRT2 REGISTER GROUP        */
8844 /*********************************************/
8845
8846 BOOLEAN
8847 SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
8848 {
8849 #ifdef SIS300
8850    UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
8851 #endif
8852    USHORT ModeIdIndex, RefreshRateTableIndex;
8853 #if 0
8854    USHORT temp;
8855 #endif
8856
8857    SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8858
8859    if(!SiS_Pr->UseCustomMode) {
8860       SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8861    } else {
8862       ModeIdIndex = 0;
8863    }
8864
8865    /* Used for shifting CR33 */
8866    SiS_Pr->SiS_SelectCRT2Rate = 4;
8867
8868    SiS_UnLockCRT2(SiS_Pr, HwInfo);
8869
8870    RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
8871
8872    SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8873
8874    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8875       SiS_DisableBridge(SiS_Pr,HwInfo);
8876       if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (HwInfo->jChipType == SIS_730)) {
8877          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8878       }
8879       SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
8880    }
8881
8882    if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
8883       SiS_LockCRT2(SiS_Pr, HwInfo);
8884       SiS_DisplayOn(SiS_Pr);
8885       return TRUE;
8886    }
8887
8888    SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8889
8890    /* Set up Panel Link for LVDS and LCDA */
8891    SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8892    if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8893        ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
8894        ((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
8895       SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8896    }
8897
8898 #ifdef LINUX_XF86
8899 #ifdef TWDEBUG
8900   xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES);
8901   xf86DrvMsg(0, X_INFO, "(init301: HDE     0x%03x VDE     0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE);
8902   xf86DrvMsg(0, X_INFO, "(init301: VGAHDE  0x%03x VGAVDE  0x%03x)\n", SiS_Pr->SiS_VGAHDE, SiS_Pr->SiS_VGAVDE);
8903   xf86DrvMsg(0, X_INFO, "(init301: HT      0x%03x VT      0x%03x)\n", SiS_Pr->SiS_HT, SiS_Pr->SiS_VT);
8904   xf86DrvMsg(0, X_INFO, "(init301: VGAHT   0x%03x VGAVT   0x%03x)\n", SiS_Pr->SiS_VGAHT, SiS_Pr->SiS_VGAVT);
8905 #endif
8906 #endif
8907
8908    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8909       SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
8910    }
8911
8912    if(SiS_Pr->SiS_VBType & VB_SISVB) {
8913
8914         if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8915
8916            SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8917 #ifdef SIS315H
8918            SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8919 #endif
8920            SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
8921            SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8922 #ifdef SIS315H
8923            SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
8924 #endif
8925            SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
8926
8927            SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
8928
8929            /* For 301BDH (Panel link initialization): */
8930            if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8931               if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
8932                  if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8933                     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8934                        SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
8935                                        RefreshRateTableIndex,HwInfo);
8936                     }
8937                  }
8938               }
8939               SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,
8940                               RefreshRateTableIndex,HwInfo);
8941            }
8942         }
8943
8944    } else {
8945
8946         SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
8947
8948         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
8949            SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
8950         }
8951
8952         SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
8953
8954         if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8955            if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8956               if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8957                  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8958 #ifdef SIS315H
8959                     SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
8960 #endif
8961                  }
8962               }
8963               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8964                  SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8965               }
8966            }
8967         }
8968
8969    }
8970
8971 #ifdef SIS300
8972    if(HwInfo->jChipType < SIS_315H) {
8973       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8974          if(SiS_Pr->SiS_UseOEM) {
8975             if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8976                if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
8977                   SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
8978                                     RefreshRateTableIndex);
8979                }
8980             } else {
8981                SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
8982                                  RefreshRateTableIndex);
8983             }
8984          }
8985          if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
8986             if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
8987                (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
8988                SetOEMLCDData2(SiS_Pr, HwInfo, ModeNo, ModeIdIndex,RefreshRateTableIndex);
8989             }
8990             SiS_DisplayOn(SiS_Pr);
8991          }
8992       }
8993    }
8994 #endif
8995
8996 #ifdef SIS315H
8997    if(HwInfo->jChipType >= SIS_315H) {
8998       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8999          if(HwInfo->jChipType < SIS_661) {
9000             SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
9001             SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
9002          } else {
9003             SiS_OEM661Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
9004          }
9005          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
9006       }
9007    }
9008 #endif
9009
9010    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
9011       SiS_EnableBridge(SiS_Pr, HwInfo);
9012    }
9013
9014    SiS_DisplayOn(SiS_Pr);
9015
9016    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
9017       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
9018          /* Disable LCD panel when using TV */
9019          SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFF,0x0C);
9020       } else {
9021          /* Disable TV when using LCD */
9022          SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8);
9023       }
9024    }
9025
9026    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
9027       SiS_LockCRT2(SiS_Pr,HwInfo);
9028    }
9029
9030    return TRUE;
9031 }
9032
9033
9034 /*********************************************/
9035 /*     ENABLE/DISABLE LCD BACKLIGHT (SIS)    */
9036 /*********************************************/
9037
9038 void
9039 SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
9040 {
9041   /* Switch on LCD backlight on SiS30xLV */
9042   SiS_DDC2Delay(SiS_Pr,0xff00);
9043   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
9044      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
9045      SiS_WaitVBRetrace(SiS_Pr,HwInfo);
9046   }
9047   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
9048      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
9049   }
9050 }
9051
9052 void
9053 SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
9054 {
9055   /* Switch off LCD backlight on SiS30xLV */
9056   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
9057   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
9058   SiS_DDC2Delay(SiS_Pr,0xe000);
9059 }
9060
9061 /*********************************************/
9062 /*          DDC RELATED FUNCTIONS            */
9063 /*********************************************/
9064
9065 static void
9066 SiS_SetupDDCN(SiS_Private *SiS_Pr)
9067 {
9068   SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
9069   SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
9070   if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
9071      SiS_Pr->SiS_DDC_NData &= 0x0f;
9072      SiS_Pr->SiS_DDC_NClk  &= 0x0f;
9073   }
9074 }
9075
9076 #ifdef SIS300
9077 static UCHAR *
9078 SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
9079 {
9080   int i, j, num;
9081   USHORT tempah,temp;
9082   UCHAR *mydataptr;
9083
9084   for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
9085      mydataptr = dataptr;
9086      num = *mydataptr++;
9087      if(!num) return mydataptr;
9088      if(i) {
9089         SiS_SetStop(SiS_Pr);
9090         SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT*2);
9091      }
9092      if(SiS_SetStart(SiS_Pr)) continue;         /* Set start condition */
9093      tempah = SiS_Pr->SiS_DDC_DeviceAddr;
9094      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write DAB (S0=0=write) */
9095      if(temp) continue;                         /*    (ERROR: no ack) */
9096      tempah = *mydataptr++;
9097      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write register number */
9098      if(temp) continue;                         /*    (ERROR: no ack) */
9099      for(j=0; j<num; j++) {
9100         tempah = *mydataptr++;
9101         temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
9102         if(temp) break;
9103      }
9104      if(temp) continue;
9105      if(SiS_SetStop(SiS_Pr)) continue;
9106      return mydataptr;
9107   }
9108   return NULL;
9109 }
9110
9111 static BOOLEAN
9112 SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
9113 {
9114   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;            /* DAB (Device Address Byte) */
9115   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9116   SiS_Pr->SiS_DDC_Data  = 0x02;                 /* Bitmask in IndexReg for Data */
9117   SiS_Pr->SiS_DDC_Clk   = 0x01;                 /* Bitmask in IndexReg for Clk */
9118   SiS_SetupDDCN(SiS_Pr);
9119
9120   SiS_SetSwitchDDC2(SiS_Pr);
9121
9122   while(*dataptr) {
9123      dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
9124      if(!dataptr) return FALSE;
9125   }
9126 #ifdef TWDEBUG
9127   xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
9128 #endif
9129   return TRUE;
9130 }
9131 #endif
9132
9133 /* The Chrontel 700x is connected to the 630/730 via
9134  * the 630/730's DDC/I2C port.
9135  *
9136  * On 630(S)T chipset, the index changed from 0x11 to
9137  * 0x0a, possibly for working around the DDC problems
9138  */
9139
9140 static BOOLEAN
9141 SiS_SetChReg(SiS_Private *SiS_Pr, USHORT tempbx, USHORT myor)
9142 {
9143   USHORT tempah,temp,i;
9144
9145   for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
9146      if(i) {
9147         SiS_SetStop(SiS_Pr);
9148         SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9149      }
9150      if(SiS_SetStart(SiS_Pr)) continue;         /* Set start condition */
9151      tempah = SiS_Pr->SiS_DDC_DeviceAddr;
9152      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write DAB (S0=0=write) */
9153      if(temp) continue;                         /*    (ERROR: no ack) */
9154      tempah = tempbx & 0x00FF;                  /* Write RAB */
9155      tempah |= myor;                            /* (700x: set bit 7, see datasheet) */
9156      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
9157      if(temp) continue;                         /*    (ERROR: no ack) */
9158      tempah = (tempbx & 0xFF00) >> 8;
9159      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write data */
9160      if(temp) continue;                         /*    (ERROR: no ack) */
9161      if(SiS_SetStop(SiS_Pr)) continue;          /* Set stop condition */
9162      SiS_Pr->SiS_ChrontelInit = 1;
9163      return TRUE;
9164   }
9165   return FALSE;
9166 }
9167
9168 #if 0
9169 #ifdef SIS300
9170 /* Write Trumpion register */
9171 static void
9172 SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
9173 {
9174   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;            /* DAB (Device Address Byte) */
9175   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9176   SiS_Pr->SiS_DDC_Data  = 0x02;                 /* Bitmask in IndexReg for Data */
9177   SiS_Pr->SiS_DDC_Clk   = 0x01;                 /* Bitmask in IndexReg for Clk */
9178   SiS_SetupDDCN(SiS_Pr);
9179   SiS_SetChReg(SiS_Pr, tempbx, 0);
9180 }
9181 #endif
9182 #endif
9183
9184 /* Write to Chrontel 700x */
9185 /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
9186 void
9187 SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
9188 {
9189   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
9190
9191   if(!(SiS_Pr->SiS_ChrontelInit)) {
9192      SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
9193      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
9194      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
9195      SiS_SetupDDCN(SiS_Pr);
9196   }
9197
9198   if( (!(SiS_SetChReg(SiS_Pr, tempbx, 0x80))) &&
9199       (!(SiS_Pr->SiS_ChrontelInit)) ) {
9200      SiS_Pr->SiS_DDC_Index = 0x0a;              /* Bit 7 = SC;  Bit 6 = SD */
9201      SiS_Pr->SiS_DDC_Data  = 0x80;              /* Bitmask in IndexReg for Data */
9202      SiS_Pr->SiS_DDC_Clk   = 0x40;              /* Bitmask in IndexReg for Clk */
9203      SiS_SetupDDCN(SiS_Pr);
9204
9205      SiS_SetChReg(SiS_Pr, tempbx, 0x80);
9206   }
9207 }
9208
9209 /* Write to Chrontel 701x */
9210 /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
9211 void
9212 SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
9213 {
9214   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9215   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
9216   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
9217   SiS_SetupDDCN(SiS_Pr);
9218   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
9219   SiS_SetChReg(SiS_Pr, tempbx, 0);
9220 }
9221
9222 void
9223 SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
9224 {
9225   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
9226      SiS_SetCH700x(SiS_Pr,tempbx);
9227   else
9228      SiS_SetCH701x(SiS_Pr,tempbx);
9229 }
9230
9231 static USHORT
9232 SiS_GetChReg(SiS_Private *SiS_Pr, USHORT myor)
9233 {
9234   USHORT tempah,temp,i;
9235
9236   for(i=0; i<20; i++) {                         /* Do 20 attempts to read */
9237      if(i) {
9238         SiS_SetStop(SiS_Pr);
9239         SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9240      }
9241      if(SiS_SetStart(SiS_Pr)) continue;         /* Set start condition */
9242      tempah = SiS_Pr->SiS_DDC_DeviceAddr;
9243      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write DAB (S0=0=write) */
9244      if(temp) continue;                         /*        (ERROR: no ack) */
9245      tempah = SiS_Pr->SiS_DDC_ReadAddr | myor;  /* Write RAB (700x: | 0x80) */
9246      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
9247      if(temp) continue;                         /*        (ERROR: no ack) */
9248      if (SiS_SetStart(SiS_Pr)) continue;        /* Re-start */
9249      tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01;/* DAB | 0x01 = Read */
9250      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* DAB (S0=1=read) */
9251      if(temp) continue;                         /*        (ERROR: no ack) */
9252      tempah = SiS_ReadDDC2Data(SiS_Pr,tempah);  /* Read byte */
9253      if(SiS_SetStop(SiS_Pr)) continue;          /* Stop condition */
9254      SiS_Pr->SiS_ChrontelInit = 1;
9255      return(tempah);
9256   }
9257   return 0xFFFF;
9258 }
9259
9260 #if 0
9261 #ifdef SIS300
9262 /* Read from Trumpion */
9263 static USHORT
9264 SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
9265 {
9266   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;    /* DAB */
9267   SiS_Pr->SiS_DDC_Index = 0x11;         /* Bit 0 = SC;  Bit 1 = SD */
9268   SiS_Pr->SiS_DDC_Data  = 0x02;         /* Bitmask in IndexReg for Data */
9269   SiS_Pr->SiS_DDC_Clk   = 0x01;         /* Bitmask in IndexReg for Clk */
9270   SiS_SetupDDCN(SiS_Pr);
9271   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9272   return(SiS_GetChReg(SiS_Pr,0));
9273 }
9274 #endif
9275 #endif
9276
9277 /* Read from Chrontel 700x */
9278 /* Parameter is [Register no (S7-S0)] */
9279 USHORT
9280 SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
9281 {
9282   USHORT result;
9283
9284   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
9285
9286   if(!(SiS_Pr->SiS_ChrontelInit)) {
9287      SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
9288      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
9289      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
9290      SiS_SetupDDCN(SiS_Pr);
9291   }
9292
9293   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9294
9295   if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
9296       (!SiS_Pr->SiS_ChrontelInit) ) {
9297
9298      SiS_Pr->SiS_DDC_Index = 0x0a;
9299      SiS_Pr->SiS_DDC_Data  = 0x80;
9300      SiS_Pr->SiS_DDC_Clk   = 0x40;
9301      SiS_SetupDDCN(SiS_Pr);
9302
9303      result = SiS_GetChReg(SiS_Pr,0x80);
9304   }
9305   return(result);
9306 }
9307
9308 /* Read from Chrontel 701x */
9309 /* Parameter is [Register no (S7-S0)] */
9310 USHORT
9311 SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
9312 {
9313   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9314   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
9315   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
9316   SiS_SetupDDCN(SiS_Pr);
9317   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
9318
9319   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9320
9321   return(SiS_GetChReg(SiS_Pr,0));
9322 }
9323
9324 /* Read from Chrontel 70xx */
9325 /* Parameter is [Register no (S7-S0)] */
9326 USHORT
9327 SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
9328 {
9329   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
9330      return(SiS_GetCH700x(SiS_Pr, tempbx));
9331   else
9332      return(SiS_GetCH701x(SiS_Pr, tempbx));
9333 }
9334
9335 /* Our own DDC functions */
9336 static USHORT
9337 SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
9338                 USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32)
9339 {
9340      unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
9341      unsigned char flag, cr32;
9342      USHORT        temp = 0, myadaptnum = adaptnum;
9343
9344      if(adaptnum != 0) {
9345         if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0xFFFF;
9346         if((VBFlags & VB_30xBDH) && (adaptnum == 1)) return 0xFFFF;
9347      }  
9348      
9349      /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
9350      
9351      SiS_Pr->SiS_ChrontelInit = 0;   /* force re-detection! */
9352
9353      SiS_Pr->SiS_DDC_SecAddr = 0;
9354      SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
9355      SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
9356      SiS_Pr->SiS_DDC_Index = 0x11;
9357      flag = 0xff;
9358
9359      cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
9360
9361 #if 0
9362      if(VBFlags & VB_SISBRIDGE) {
9363         if(myadaptnum == 0) {
9364            if(!(cr32 & 0x20)) {
9365               myadaptnum = 2;
9366               if(!(cr32 & 0x10)) {
9367                  myadaptnum = 1;
9368                  if(!(cr32 & 0x08)) {
9369                     myadaptnum = 0;
9370                  }
9371               }
9372            }
9373         }
9374      }
9375 #endif
9376
9377      if(VGAEngine == SIS_300_VGA) {             /* 300 series */
9378         
9379         if(myadaptnum != 0) {
9380            flag = 0;
9381            if(VBFlags & VB_SISBRIDGE) {
9382               SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9383               SiS_Pr->SiS_DDC_Index = 0x0f;
9384            }
9385         }
9386
9387         if(!(VBFlags & VB_301)) {
9388            if((cr32 & 0x80) && (checkcr32)) {
9389               if(myadaptnum >= 1) {
9390                  if(!(cr32 & 0x08)) {
9391                      myadaptnum = 1;
9392                      if(!(cr32 & 0x10)) return 0xFFFF;
9393                  }
9394               }
9395            }
9396         }
9397
9398         temp = 4 - (myadaptnum * 2);
9399         if(flag) temp = 0;
9400
9401      } else {                                           /* 315/330 series */
9402
9403         /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
9404
9405         if(VBFlags & VB_SISBRIDGE) {
9406            if(myadaptnum == 2) {
9407               myadaptnum = 1;
9408            }
9409         }
9410
9411         if(myadaptnum == 1) {
9412            flag = 0;
9413            if(VBFlags & VB_SISBRIDGE) {
9414               SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9415               SiS_Pr->SiS_DDC_Index = 0x0f;
9416            }
9417         }
9418
9419         if((cr32 & 0x80) && (checkcr32)) {
9420            if(myadaptnum >= 1) {
9421               if(!(cr32 & 0x08)) {
9422                  myadaptnum = 1;
9423                  if(!(cr32 & 0x10)) return 0xFFFF;
9424               }
9425            }
9426         }
9427
9428         temp = myadaptnum;
9429         if(myadaptnum == 1) {
9430            temp = 0;
9431            if(VBFlags & VB_LVDS) flag = 0xff;
9432         }
9433
9434         if(flag) temp = 0;
9435     }
9436     
9437     SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9438     SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
9439
9440     SiS_SetupDDCN(SiS_Pr);
9441
9442 #ifdef TWDEBUG
9443     xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
9444                 SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
9445 #endif
9446     
9447     return 0;
9448 }
9449
9450 static USHORT
9451 SiS_WriteDABDDC(SiS_Private *SiS_Pr)
9452 {
9453    if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9454    if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
9455         return 0xFFFF;
9456    }
9457    if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
9458         return 0xFFFF;
9459    }
9460    return(0);
9461 }
9462
9463 static USHORT
9464 SiS_PrepareReadDDC(SiS_Private *SiS_Pr)
9465 {
9466    if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9467    if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
9468         return 0xFFFF;
9469    }
9470    return(0);
9471 }
9472
9473 static USHORT
9474 SiS_PrepareDDC(SiS_Private *SiS_Pr)
9475 {
9476    if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
9477    if(SiS_PrepareReadDDC(SiS_Pr)) return(SiS_PrepareReadDDC(SiS_Pr));
9478    return(0);
9479 }
9480
9481 static void
9482 SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno)
9483 {
9484    SiS_SetSCLKLow(SiS_Pr);
9485    if(yesno) {
9486       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9487                       SiS_Pr->SiS_DDC_Index,
9488                       SiS_Pr->SiS_DDC_NData,
9489                       SiS_Pr->SiS_DDC_Data);
9490    } else {
9491       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9492                       SiS_Pr->SiS_DDC_Index,
9493                       SiS_Pr->SiS_DDC_NData,
9494                       0);
9495    }
9496    SiS_SetSCLKHigh(SiS_Pr);
9497 }
9498
9499 static USHORT
9500 SiS_DoProbeDDC(SiS_Private *SiS_Pr)
9501 {
9502     unsigned char mask, value;
9503     USHORT  temp, ret=0;
9504     BOOLEAN failed = FALSE;
9505
9506     SiS_SetSwitchDDC2(SiS_Pr);
9507     if(SiS_PrepareDDC(SiS_Pr)) {
9508          SiS_SetStop(SiS_Pr);
9509 #ifdef TWDEBUG
9510          xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n");
9511 #endif
9512          return(0xFFFF);
9513     }
9514     mask = 0xf0;
9515     value = 0x20;
9516     if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9517        temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
9518        SiS_SendACK(SiS_Pr, 0);
9519        if(temp == 0) {
9520            mask = 0xff;
9521            value = 0xff;
9522        } else {
9523            failed = TRUE;
9524            ret = 0xFFFF;
9525 #ifdef TWDEBUG
9526            xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n");
9527 #endif
9528        }
9529     }
9530     if(failed == FALSE) {
9531        temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
9532        SiS_SendACK(SiS_Pr, 1);
9533        temp &= mask;
9534        if(temp == value) ret = 0;
9535        else {
9536           ret = 0xFFFF;
9537 #ifdef TWDEBUG
9538           xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n");
9539 #endif
9540           if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9541              if(temp == 0x30) ret = 0;
9542           }
9543        }
9544     }
9545     SiS_SetStop(SiS_Pr);
9546     return(ret);
9547 }
9548
9549 static USHORT
9550 SiS_ProbeDDC(SiS_Private *SiS_Pr)
9551 {
9552    USHORT flag;
9553
9554    flag = 0x180;
9555    SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9556    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9557    SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9558    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9559    SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9560    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9561    if(!(flag & 0x1a)) flag = 0;
9562    return(flag);
9563 }
9564
9565 static USHORT
9566 SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
9567 {
9568    USHORT flag, length, i;
9569    unsigned char chksum,gotcha;
9570
9571    if(DDCdatatype > 4) return 0xFFFF;  
9572
9573    flag = 0;
9574    SiS_SetSwitchDDC2(SiS_Pr);
9575    if(!(SiS_PrepareDDC(SiS_Pr))) {
9576       length = 127;
9577       if(DDCdatatype != 1) length = 255;
9578       chksum = 0;
9579       gotcha = 0;
9580       for(i=0; i<length; i++) {
9581          buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
9582          chksum += buffer[i];
9583          gotcha |= buffer[i];
9584          SiS_SendACK(SiS_Pr, 0);
9585       }
9586       buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
9587       chksum += buffer[i];
9588       SiS_SendACK(SiS_Pr, 1);
9589       if(gotcha) flag = (USHORT)chksum;
9590       else flag = 0xFFFF;
9591    } else {
9592       flag = 0xFFFF;
9593    }
9594    SiS_SetStop(SiS_Pr);
9595    return(flag);
9596 }
9597
9598 /* Our private DDC functions
9599
9600    It complies somewhat with the corresponding VESA function
9601    in arguments and return values.
9602
9603    Since this is probably called before the mode is changed,
9604    we use our pre-detected pSiS-values instead of SiS_Pr as
9605    regards chipset and video bridge type.
9606
9607    Arguments:
9608        adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9609                  CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9610                  LCDA is CRT1, but DDC is read from CRT2 port.
9611        DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9612        buffer: ptr to 256 data bytes which will be filled with read data.
9613
9614    Returns 0xFFFF if error, otherwise
9615        if DDCdatatype > 0:  Returns 0 if reading OK (included a correct checksum)
9616        if DDCdatatype = 0:  Returns supported DDC modes
9617
9618  */
9619 USHORT
9620 SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
9621               USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer)
9622 {
9623    unsigned char sr1f,cr17=1;
9624    USHORT result;
9625
9626    if(adaptnum > 2) return 0xFFFF;
9627    if(DDCdatatype > 4) return 0xFFFF;
9628    if((!(VBFlags & VB_VIDEOBRIDGE)) && (adaptnum > 0)) return 0xFFFF;
9629    if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE) == 0xFFFF) return 0xFFFF;
9630
9631    sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9632    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9633    if(VGAEngine == SIS_300_VGA) {
9634       cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9635       if(!cr17) {
9636          SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9637          SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9638          SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9639       }
9640    }
9641    if((sr1f) || (!cr17)) {
9642       SiS_WaitRetrace1(SiS_Pr);
9643       SiS_WaitRetrace1(SiS_Pr);
9644       SiS_WaitRetrace1(SiS_Pr);
9645       SiS_WaitRetrace1(SiS_Pr);
9646    }
9647
9648    if(DDCdatatype == 0) {
9649       result = SiS_ProbeDDC(SiS_Pr);
9650    } else {
9651       result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9652       if((!result) && (DDCdatatype == 1)) {
9653          if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9654             (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9655             (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9656             (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9657             (buffer[0x12] == 1)) {
9658             if(adaptnum == 1) {
9659                if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9660             } else {
9661                if(buffer[0x14] & 0x80)    result = 0xFFFE;
9662             }
9663          }
9664       }
9665    }
9666    SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9667    if(VGAEngine == SIS_300_VGA) {
9668       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9669    }
9670    return result;
9671 }
9672
9673 #ifdef LINUX_XF86
9674
9675 static BOOLEAN
9676 checkedid1(unsigned char *buffer)
9677 {
9678    /* Check header */
9679    if((buffer[0] != 0x00) ||
9680       (buffer[1] != 0xff) ||
9681       (buffer[2] != 0xff) ||
9682       (buffer[3] != 0xff) ||
9683       (buffer[4] != 0xff) ||
9684       (buffer[5] != 0xff) ||
9685       (buffer[6] != 0xff) ||
9686       (buffer[7] != 0x00))
9687       return FALSE;
9688
9689    /* Check EDID version and revision */
9690    if((buffer[0x12] != 1) || (buffer[0x13] > 4)) return FALSE;
9691
9692    /* Check week of manufacture for sanity */
9693    if(buffer[0x10] > 53) return FALSE;
9694
9695    /* Check year of manufacture for sanity */
9696    if(buffer[0x11] > 40) return FALSE;
9697
9698    return TRUE;
9699 }
9700
9701 static BOOLEAN
9702 checkedid2(unsigned char *buffer)
9703 {
9704    USHORT year = buffer[6] | (buffer[7] << 8);
9705
9706    /* Check EDID version */
9707    if((buffer[0] & 0xf0) != 0x20) return FALSE;
9708
9709    /* Check week of manufacture for sanity */
9710    if(buffer[5] > 53) return FALSE;
9711
9712    /* Check year of manufacture for sanity */
9713    if((year != 0) && ((year < 1990) || (year > 2030))) return FALSE;
9714
9715    return TRUE;
9716 }
9717
9718 /* Sense the LCD parameters (CR36, CR37) via DDC */
9719 /* SiS30x(B) only */
9720 USHORT
9721 SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS)
9722 {
9723    USHORT DDCdatatype, paneltype, flag, xres=0, yres=0;
9724    USHORT index, myindex, lumsize, numcodes, panelvendor, panelproduct;
9725    int maxx=0, maxy=0, prefx=0, prefy=0;
9726    unsigned char cr37=0, seekcode;
9727    BOOLEAN checkexpand = FALSE;
9728    BOOLEAN havesync = FALSE;
9729    BOOLEAN indb = FALSE;
9730    int retry, i;
9731    unsigned char buffer[256];
9732
9733    for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE;
9734    SiS_Pr->CP_HaveCustomData = FALSE;
9735    SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0;
9736    SiS_Pr->CP_PreferredX = SiS_Pr->CP_PreferredY = 0;
9737    SiS_Pr->CP_PreferredIndex = -1;
9738    SiS_Pr->CP_PrefClock = 0;
9739    SiS_Pr->PanelSelfDetected = FALSE;
9740
9741    if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
9742    if(pSiS->VBFlags & VB_30xBDH) return 0;
9743   
9744    if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 1, 0, FALSE) == 0xFFFF) return 0;
9745    
9746    SiS_Pr->SiS_DDC_SecAddr = 0x00;
9747    
9748    /* Probe supported DA's */
9749    flag = SiS_ProbeDDC(SiS_Pr);
9750 #ifdef TWDEBUG
9751    xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
9752         "CRT2 DDC capabilities 0x%x\n", flag);
9753 #endif  
9754    if(flag & 0x10) {
9755       SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;        /* EDID V2 (FP) */
9756       DDCdatatype = 4;
9757    } else if(flag & 0x08) {
9758       SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;        /* EDID V2 (P&D-D Monitor) */
9759       DDCdatatype = 3;
9760    } else if(flag & 0x02) {
9761       SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;        /* EDID V1 */
9762       DDCdatatype = 1;
9763    } else return 0;                             /* no DDC support (or no device attached) */
9764    
9765    /* Read the entire EDID */
9766    retry = 2;
9767    do {
9768       if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
9769          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9770                 "CRT2: DDC read failed (attempt %d), %s\n",
9771                 (3-retry), (retry == 1) ? "giving up" : "retrying");
9772          retry--;
9773          if(retry == 0) return 0xFFFF;
9774       } else break;
9775    } while(1);
9776
9777 #ifdef TWDEBUG
9778    for(i=0; i<256; i+=16) {
9779        xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9780         "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
9781         buffer[i],    buffer[i+1], buffer[i+2], buffer[i+3],
9782         buffer[i+4],  buffer[i+5], buffer[i+6], buffer[i+7],
9783         buffer[i+8],  buffer[i+9], buffer[i+10], buffer[i+11],
9784         buffer[i+12], buffer[i+13], buffer[i+14], buffer[i+15]);
9785    }
9786 #endif   
9787    
9788    /* Analyze EDID and retrieve LCD panel information */
9789    paneltype = 0;
9790    switch(DDCdatatype) {
9791    case 1:                                                      /* Analyze EDID V1 */
9792       /* Catch a few clear cases: */
9793       if(!(checkedid1(buffer))) {
9794          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9795                 "LCD sense: EDID corrupt\n");
9796          return 0;
9797       }
9798
9799       if(!(buffer[0x14] & 0x80)) {
9800          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9801                 "LCD sense: Attached display expects analog input (0x%02x)\n",
9802                 buffer[0x14]);
9803          return 0;
9804       }
9805
9806       if((buffer[0x18] & 0x18) != 0x08) {
9807          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9808                 "LCD sense: Warning: Attached display is not of RGB but of %s type (0x%02x)\n",
9809                 ((buffer[0x18] & 0x18) == 0x00) ? "monochrome/greyscale" :
9810                   ( ((buffer[0x18] & 0x18) == 0x10) ? "non-RGB multicolor" :
9811                      "undefined"),
9812                 buffer[0x18]);
9813       }
9814
9815       /* Now analyze the first Detailed Timing Block and see
9816        * if the preferred timing mode is stored there. If so,
9817        * check if this is a standard panel for which we already
9818        * know the timing.
9819        */
9820
9821       paneltype = Panel_Custom;
9822       checkexpand = FALSE;
9823
9824       panelvendor = buffer[9] | (buffer[8] << 8);
9825       panelproduct = buffer[10] | (buffer[11] << 8);
9826
9827       /* Overrule bogus preferred modes from database */
9828       if((indb = SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
9829          if(prefx) SiS_Pr->CP_PreferredX = xres = prefx;
9830          if(prefy) SiS_Pr->CP_PreferredY = yres = prefy;
9831       }
9832
9833       if(buffer[0x18] & 0x02) {
9834
9835          USHORT pclk = (buffer[0x36] | (buffer[0x37] << 8));
9836          USHORT phb  = (buffer[0x39] | ((buffer[0x3a] & 0x0f) << 8));
9837          USHORT pvb  = (buffer[0x3c] | ((buffer[0x3d] & 0x0f) << 8));
9838
9839          if(!xres) SiS_Pr->CP_PreferredX = xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
9840          if(!yres) SiS_Pr->CP_PreferredY = yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
9841
9842          switch(xres) {
9843 #if 0       /* Treat as custom */
9844             case 800:
9845                 if(yres == 600) {
9846                    paneltype = Panel_800x600;
9847                    checkexpand = TRUE;
9848                 }
9849                 break;
9850 #endif
9851             case 1024:
9852                 if(yres == 768) {
9853                    paneltype = Panel_1024x768;
9854                    checkexpand = TRUE;
9855                 }
9856                 break;
9857             case 1280:
9858                 if(yres == 1024) {
9859                    paneltype = Panel_1280x1024;
9860                    checkexpand = TRUE;
9861                 } else if(yres == 960) {
9862                    if(pSiS->VGAEngine == SIS_300_VGA) {
9863                       paneltype = Panel300_1280x960;
9864                    } else {
9865                       paneltype = Panel310_1280x960;
9866                    }
9867                 } else if(yres == 768) {
9868                    if( (pclk == 8100) &&
9869                        (phb == (1688 - 1280)) &&
9870                        (pvb == (802 - 768)) ) {
9871                       paneltype = Panel_1280x768;
9872                       checkexpand = FALSE;
9873                       cr37 |= 0x10;
9874                    }
9875                 } else if(yres == 800) {
9876                    if( (pclk == 6900) &&
9877                        (phb == (1408 - 1280)) &&
9878                        (pvb == (816 - 800)) ) {
9879                       paneltype = Panel_1280x800;
9880                    }
9881                 }
9882                 break;
9883             case 1400:
9884                 if(pSiS->VGAEngine == SIS_315_VGA) {
9885                    if(yres == 1050) {
9886                       paneltype = Panel310_1400x1050;
9887                       checkexpand = TRUE;
9888                    }
9889                 }
9890                 break;
9891             case 1600:
9892                 if(pSiS->VGAEngine == SIS_315_VGA) {
9893                    if(pSiS->VBFlags & VB_301C) {
9894                       if(yres == 1200) {
9895                          paneltype = Panel310_1600x1200;
9896                          checkexpand = TRUE;
9897                       }
9898                    }
9899                 }
9900                 break;
9901          }
9902
9903          /* Save sync: This is used if "Pass 1:1" is off; in this case
9904           * we always use the panel's native mode = this "preferred mode"
9905           * we just have been analysing. Hence, we also need its sync.
9906           */
9907          if((buffer[0x47] & 0x18) == 0x18) {
9908             cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
9909             havesync = TRUE;
9910          } else {
9911             /* What now? There is no digital separate output timing... */
9912             xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
9913                    "LCD sense: Unable to retrieve Sync polarity information\n");
9914             cr37 |= 0xc0;  /* Default */
9915          }
9916
9917       }
9918
9919       /* Check against our database; eg. Sanyo Z2 projector reports
9920        * 1024x768 as preferred mode, although it supports 1280x720
9921        * natively in non-HDCP mode. Treat such wrongly reporting
9922        * panels as custom and fixup actual maximum resolutions.
9923        */
9924       if(paneltype != Panel_Custom) {
9925          if(indb) {
9926             paneltype = Panel_Custom;
9927             SiS_Pr->CP_MaxX = maxx;
9928             SiS_Pr->CP_MaxY = maxy;
9929             /* Leave preferred unchanged (MUST contain a valid mode!) */
9930          }
9931       }
9932
9933       /* If we still don't know what panel this is, we take it
9934        * as a custom panel and derive the timing data from the
9935        * detailed timing blocks
9936        */
9937       if(paneltype == Panel_Custom) {
9938
9939          int i, temp, base = 0x36;
9940          unsigned long estpack;
9941          const unsigned short estx[] = {
9942                 720, 720, 640, 640, 640, 640, 800, 800,
9943                 800, 800, 832,1024,1024,1024,1024,1280,
9944                 1152
9945          };
9946          const unsigned short esty[] = {
9947                 400, 400, 480, 480, 480, 480, 600, 600,
9948                 600, 600, 624, 768, 768, 768, 768,1024,
9949                 870
9950          };
9951          const int estclk[] = {
9952                     0,     0, 25100,   0, 31500, 31500, 36100, 40000,
9953                 50100, 49500,     0,   0, 65100, 75200, 78700,135200,
9954                 0
9955          };
9956
9957          paneltype = 0;
9958          SiS_Pr->CP_Supports64048075 = TRUE;
9959
9960          /* Find the maximum resolution */
9961
9962          /* 1. From Established timings */
9963          estpack = (buffer[0x23] << 9) | (buffer[0x24] << 1) | ((buffer[0x25] >> 7) & 0x01);
9964          for(i=16; i>=0; i--) {
9965              if(estpack & (1 << i)) {
9966                 if(estx[16 - i] > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = estx[16 - i];
9967                 if(esty[16 - i] > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = esty[16 - i];
9968                 if(estclk[16 - i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = estclk[16 - i];
9969              }
9970          }
9971
9972          /* By default we drive the LCD at 75Hz in 640x480 mode; if
9973           * the panel does not provide this mode, use 60hz
9974           */
9975          if(!(buffer[0x23] & 0x04)) SiS_Pr->CP_Supports64048075 = FALSE;
9976
9977          /* 2. From Standard Timings */
9978          for(i=0x26; i < 0x36; i+=2) {
9979             if((buffer[i] != 0x01) && (buffer[i+1] != 0x01)) {
9980                temp = (buffer[i] + 31) * 8;
9981                if(temp > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = temp;
9982                switch((buffer[i+1] & 0xc0) >> 6) {
9983                case 0x03: temp = temp * 9 / 16; break;
9984                case 0x02: temp = temp * 4 / 5;  break;
9985                case 0x01: temp = temp * 3 / 4;  break;
9986                }
9987                if(temp > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = temp;
9988             }
9989          }
9990
9991          /* Now extract the Detailed Timings and convert them into modes */
9992
9993          for(i = 0; i < 4; i++, base += 18) {
9994
9995             /* Is this a detailed timing block or a monitor descriptor? */
9996             if(buffer[base] || buffer[base+1] || buffer[base+2]) {
9997
9998                xres = buffer[base+2] | ((buffer[base+4] & 0xf0) << 4);
9999                yres = buffer[base+5] | ((buffer[base+7] & 0xf0) << 4);
10000
10001                SiS_Pr->CP_HDisplay[i] = xres;
10002                SiS_Pr->CP_HSyncStart[i] = xres + (buffer[base+8] | ((buffer[base+11] & 0xc0) << 2));
10003                SiS_Pr->CP_HSyncEnd[i]   = SiS_Pr->CP_HSyncStart[i] + (buffer[base+9] | ((buffer[base+11] & 0x30) << 4));
10004                SiS_Pr->CP_HTotal[i] = xres + (buffer[base+3] | ((buffer[base+4] & 0x0f) << 8));
10005                SiS_Pr->CP_HBlankStart[i] = xres + 1;
10006                SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
10007
10008                SiS_Pr->CP_VDisplay[i] = yres;
10009                SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[base+10] & 0xf0) >> 4) | ((buffer[base+11] & 0x0c) << 2));
10010                SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[base+10] & 0x0f) | ((buffer[base+11] & 0x03) << 4));
10011                SiS_Pr->CP_VTotal[i] = yres + (buffer[base+6] | ((buffer[base+7] & 0x0f) << 8));
10012                SiS_Pr->CP_VBlankStart[i] = yres + 1;
10013                SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
10014
10015                SiS_Pr->CP_Clock[i] = (buffer[base] | (buffer[base+1] << 8)) * 10;
10016
10017                SiS_Pr->CP_DataValid[i] = TRUE;
10018
10019                /* Sort out invalid timings, interlace and too high clocks */
10020                if((SiS_Pr->CP_HDisplay[i] & 7)                                            ||
10021                   (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i])                     ||
10022                   (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i])                      ||
10023                   (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i])                        ||
10024                   (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i])                    ||
10025                   (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i])                       ||
10026                   (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i])                         ||
10027                   (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i])                     ||
10028                   (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i])                      ||
10029                   (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i])                        ||
10030                   (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i])                     ||
10031                   (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i])                       ||
10032                   (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i])                         ||
10033                   (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
10034                    ((!(pSiS->VBFlags & VB_301C)) &&
10035                     ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024) ||
10036                      (SiS_Pr->CP_HDisplay[i] > 1600))))                                   ||
10037                   (buffer[base+17] & 0x80)) {
10038
10039                   SiS_Pr->CP_DataValid[i] = FALSE;
10040
10041                } else {
10042
10043                   SiS_Pr->CP_HaveCustomData = TRUE;
10044
10045                   if(xres > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = xres;
10046                   if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres;
10047                   if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
10048
10049                   if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
10050                      SiS_Pr->CP_PreferredIndex = i;
10051                      SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
10052                      SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
10053                   }
10054
10055                   /* Extract the sync polarisation information. This only works
10056                    * if the Flags indicate a digital separate output.
10057                    */
10058                   if((buffer[base+17] & 0x18) == 0x18) {
10059                      SiS_Pr->CP_HSync_P[i] = (buffer[base+17] & 0x02) ? TRUE : FALSE;
10060                      SiS_Pr->CP_VSync_P[i] = (buffer[base+17] & 0x04) ? TRUE : FALSE;
10061                      SiS_Pr->CP_SyncValid[i] = TRUE;
10062                      if((i == SiS_Pr->CP_PreferredIndex) && (!havesync)) {
10063                         cr37 |= ((((buffer[base+17] & 0x06) ^ 0x06) << 5) | 0x20);
10064                         havesync = TRUE;
10065                      }
10066                   } else {
10067                      SiS_Pr->CP_SyncValid[i] = FALSE;
10068                   }
10069
10070                }
10071
10072             } else if((!buffer[base]) && (!buffer[base+1]) && (!buffer[base+2]) && (!buffer[base+4])) {
10073
10074                /* Maximum pixclock from Monitor Range Limits */
10075                if((buffer[base+3] == 0xfd) && (buffer[base+9] != 0xff)) {
10076                   int maxclk = buffer[base+9] * 10;
10077                   /* More than 170 is not supported anyway */
10078                   if(maxclk <= 170) SiS_Pr->CP_MaxClock = maxclk * 1000;
10079                }
10080
10081             }
10082
10083          }
10084
10085          if(SiS_Pr->CP_MaxX && SiS_Pr->CP_MaxY) {
10086             paneltype = Panel_Custom;
10087             checkexpand = FALSE;
10088             cr37 |= 0x10;
10089             SiS_Pr->CP_Vendor = panelvendor;
10090             SiS_Pr->CP_Product = panelproduct;
10091          }
10092
10093       }
10094
10095       if(paneltype && checkexpand) {
10096          /* If any of the Established low-res modes is supported, the
10097           * panel can scale automatically. For 800x600 panels, we only 
10098           * check the even lower ones.
10099           */
10100          if(paneltype == Panel_800x600) {
10101             if(buffer[0x23] & 0xfc) cr37 |= 0x10;
10102          } else {
10103             if(buffer[0x23])        cr37 |= 0x10;
10104          }
10105       }
10106        
10107       break;
10108       
10109    case 3:                                                      /* Analyze EDID V2 */
10110    case 4:
10111       index = 0;
10112
10113       if(!(checkedid2(buffer))) {
10114          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10115                 "LCD sense: EDID corrupt\n");
10116          return 0;
10117       }
10118
10119       if((buffer[0x41] & 0x0f) == 0x03) {
10120          index = 0x42 + 3;
10121          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10122                 "LCD sense: Display supports TMDS input on primary interface\n");
10123       } else if((buffer[0x41] & 0xf0) == 0x30) {
10124          index = 0x46 + 3;
10125          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10126                 "LCD sense: Display supports TMDS input on secondary interface\n");
10127       } else {
10128          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10129                 "LCD sense: Display does not support TMDS video interface (0x%02x)\n",
10130                 buffer[0x41]);
10131          return 0;
10132       }
10133
10134       SiS_Pr->CP_Vendor = panelvendor = buffer[2] | (buffer[1] << 8);
10135       SiS_Pr->CP_Product = panelproduct = buffer[3] | (buffer[4] << 8);
10136
10137       paneltype = Panel_Custom;
10138       SiS_Pr->CP_MaxX = SiS_Pr->CP_PreferredX = xres = buffer[0x76] | (buffer[0x77] << 8);
10139       SiS_Pr->CP_MaxY = SiS_Pr->CP_PreferredY = yres = buffer[0x78] | (buffer[0x79] << 8);
10140
10141       switch(xres) {
10142 #if 0
10143          case 800:
10144              if(yres == 600) {
10145                 paneltype = Panel_800x600;
10146                 checkexpand = TRUE;
10147              }
10148              break;
10149 #endif
10150          case 1024:
10151              if(yres == 768) {
10152                 paneltype = Panel_1024x768;
10153                 checkexpand = TRUE;
10154              }
10155              break;
10156          case 1280:
10157              if(yres == 960) {
10158                 if(pSiS->VGAEngine == SIS_315_VGA) {
10159                    paneltype = Panel310_1280x960;
10160                 } else {
10161                    paneltype = Panel300_1280x960;
10162                 }
10163              } else if(yres == 1024) {
10164                 paneltype = Panel_1280x1024;
10165                 checkexpand = TRUE;
10166              }
10167              /* 1280x768 treated as custom here */
10168              break;
10169          case 1400:
10170              if(pSiS->VGAEngine == SIS_315_VGA) {
10171                 if(yres == 1050) {
10172                    paneltype = Panel310_1400x1050;
10173                    checkexpand = TRUE;
10174                 }
10175              }
10176              break;
10177          case 1600:
10178              if(pSiS->VGAEngine == SIS_315_VGA) {
10179                 if(pSiS->VBFlags & VB_301C) {
10180                    if(yres == 1200) {
10181                       paneltype = Panel310_1600x1200;
10182                       checkexpand = TRUE;
10183                    }
10184                 }
10185              }
10186              break;
10187       }
10188
10189       /* Determine if RGB18 or RGB24 */
10190       if(index) {
10191          if((buffer[index] == 0x20) || (buffer[index] == 0x34)) {
10192             cr37 |= 0x01;
10193          }
10194       }
10195
10196       if(checkexpand) {
10197          /* TODO - for now, we let the panel scale */
10198          cr37 |= 0x10;
10199       }
10200
10201       /* Now seek 4-Byte Timing codes and extract sync pol info */
10202       index = 0x80;
10203       if(buffer[0x7e] & 0x20) {                     /* skip Luminance Table (if provided) */
10204          lumsize = buffer[0x80] & 0x1f;
10205          if(buffer[0x80] & 0x80) lumsize *= 3;
10206          lumsize++;  /* luminance header byte */
10207          index += lumsize;
10208       }
10209 #if 0 /* "pixel rate" = pixel clock? */
10210       if(buffer[0x7e] & 0x1c) {
10211          for(i=0; i<((buffer[0x7e] & 0x1c) >> 2); i++) {
10212             if(buffer[index + (i*8) + 6] && (buffer[index + (i*8) + 7] & 0x0f)) {
10213                int clk = (buffer[index + (i*8) + 6] | ((buffer[index + (i*8) + 7] & 0x0f) << 4)) * 1000;
10214                if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
10215             }
10216          }
10217       }
10218 #endif
10219       index += (((buffer[0x7e] & 0x1c) >> 2) * 8);   /* skip Frequency Ranges */
10220       if(buffer[0x7e] & 0x03) {
10221          for(i=0; i<(buffer[0x7e] & 0x03); i++) {
10222             if((buffer[index + (i*27) + 9]) || (buffer[index + (i*27) + 10])) {
10223                int clk = ((buffer[index + (i*27) + 9]) | ((buffer[index + (i*27) + 9]) << 8)) * 10;
10224                if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
10225             }
10226          }
10227       }
10228       index += ((buffer[0x7e] & 0x03) * 27);         /* skip Detailed Range Limits */
10229       numcodes = (buffer[0x7f] & 0xf8) >> 3;
10230       if(numcodes) {
10231          myindex = index;
10232          seekcode = (xres - 256) / 16;
10233          for(i=0; i<numcodes; i++) {
10234             if(buffer[myindex] == seekcode) break;
10235             myindex += 4;
10236          }
10237          if(buffer[myindex] == seekcode) {
10238             cr37 |= ((((buffer[myindex + 1] & 0x0c) ^ 0x0c) << 4) | 0x20);
10239             havesync = TRUE;
10240          } else {
10241             xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
10242                 "LCD sense: Unable to retrieve Sync polarity information\n");
10243          }
10244       } else {
10245          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
10246              "LCD sense: Unable to retrieve Sync polarity information\n");
10247       }
10248
10249       /* Check against our database; Eg. Sanyo projector reports
10250        * 1024x768 in non-HDPC mode, although it supports 1280x720.
10251        * Treat such wrongly reporting panels as custom.
10252        */
10253       if(paneltype != Panel_Custom) {
10254          int maxx, maxy, prefx, prefy;
10255          if((SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
10256             paneltype = Panel_Custom;
10257             SiS_Pr->CP_MaxX = maxx;
10258             SiS_Pr->CP_MaxY = maxy;
10259             cr37 |= 0x10;
10260             /* Leave preferred unchanged (MUST be a valid mode!) */
10261          }
10262       }
10263
10264       /* Now seek the detailed timing descriptions for custom panels */
10265       if(paneltype == Panel_Custom) {
10266
10267          SiS_Pr->CP_Supports64048075 = TRUE;
10268
10269          index += (numcodes * 4);
10270          numcodes = buffer[0x7f] & 0x07;
10271          for(i=0; i<numcodes; i++, index += 18) {
10272             xres = buffer[index+2] | ((buffer[index+4] & 0xf0) << 4);
10273             yres = buffer[index+5] | ((buffer[index+7] & 0xf0) << 4);
10274
10275             SiS_Pr->CP_HDisplay[i] = xres;
10276             SiS_Pr->CP_HSyncStart[i] = xres + (buffer[index+8] | ((buffer[index+11] & 0xc0) << 2));
10277             SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[index+9] | ((buffer[index+11] & 0x30) << 4));
10278             SiS_Pr->CP_HTotal[i] = xres + (buffer[index+3] | ((buffer[index+4] & 0x0f) << 8));
10279             SiS_Pr->CP_HBlankStart[i] = xres + 1;
10280             SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
10281
10282             SiS_Pr->CP_VDisplay[i] = yres;
10283             SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[index+10] & 0xf0) >> 4) | ((buffer[index+11] & 0x0c) << 2));
10284             SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[index+10] & 0x0f) | ((buffer[index+11] & 0x03) << 4));
10285             SiS_Pr->CP_VTotal[i] = yres + (buffer[index+6] | ((buffer[index+7] & 0x0f) << 8));
10286             SiS_Pr->CP_VBlankStart[i] = yres + 1;
10287             SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
10288
10289             SiS_Pr->CP_Clock[i] = (buffer[index] | (buffer[index+1] << 8)) * 10;
10290
10291             SiS_Pr->CP_DataValid[i] = TRUE;
10292
10293             if((SiS_Pr->CP_HDisplay[i] & 7)                                             ||
10294                (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i])                      ||
10295                (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i])                       ||
10296                (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i])                         ||
10297                (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i])                     ||
10298                (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i])                        ||
10299                (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i])                          ||
10300                (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i])                      ||
10301                (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i])                       ||
10302                (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i])                         ||
10303                (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i])                      ||
10304                (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i])                        ||
10305                (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i])                          ||
10306                (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
10307                 ((!(pSiS->VBFlags & VB_301C)) &&
10308                  ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024))))  ||
10309                (buffer[index + 17] & 0x80)) {
10310
10311                SiS_Pr->CP_DataValid[i] = FALSE;
10312
10313             } else {
10314
10315                SiS_Pr->CP_HaveCustomData = TRUE;
10316
10317                if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
10318
10319                if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
10320                   SiS_Pr->CP_PreferredIndex = i;
10321                   SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
10322                   SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
10323                   if(!havesync) {
10324                      cr37 |= ((((buffer[index + 17] & 0x06) ^ 0x06) << 5) | 0x20);
10325                      havesync = TRUE;
10326                   }
10327                }
10328
10329                SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE;
10330                SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE;
10331                SiS_Pr->CP_SyncValid[i] = TRUE;
10332
10333             }
10334          }
10335
10336          cr37 |= 0x10;
10337
10338       }
10339
10340       break;
10341
10342    }
10343
10344    /* 1280x960 panels are always RGB24, unable to scale and use
10345     * high active sync polarity
10346     */
10347    if(pSiS->VGAEngine == SIS_315_VGA) {
10348       if(paneltype == Panel310_1280x960) cr37 &= 0x0e;
10349    } else {
10350       if(paneltype == Panel300_1280x960) cr37 &= 0x0e;
10351    }
10352
10353    for(i = 0; i < 7; i++) {
10354       if(SiS_Pr->CP_DataValid[i]) {
10355          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10356             "Non-standard LCD/DVI-D timing data no. %d:\n", i);
10357          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10358             "   HDisplay %d HSync %d HSyncEnd %d HTotal %d\n",
10359             SiS_Pr->CP_HDisplay[i], SiS_Pr->CP_HSyncStart[i],
10360             SiS_Pr->CP_HSyncEnd[i], SiS_Pr->CP_HTotal[i]);
10361          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10362             "   VDisplay %d VSync %d VSyncEnd %d VTotal %d\n",
10363             SiS_Pr->CP_VDisplay[i], SiS_Pr->CP_VSyncStart[i],
10364             SiS_Pr->CP_VSyncEnd[i], SiS_Pr->CP_VTotal[i]);
10365          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10366             "   Pixel clock: %3.3fMhz\n", (float)SiS_Pr->CP_Clock[i] / 1000);
10367          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
10368             "   To use this, add \"%dx%d\" to the list of Modes in the Screen section\n",
10369             SiS_Pr->CP_HDisplay[i],
10370             SiS_Pr->CP_VDisplay[i]);
10371       }
10372    }
10373
10374    if(paneltype) {
10375        if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
10376        if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
10377        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
10378        SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,paneltype);
10379        cr37 &= 0xf1;
10380        SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0x0c,cr37);
10381        SiS_Pr->PanelSelfDetected = TRUE;
10382 #ifdef TWDEBUG
10383        xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3, 
10384            "LCD sense: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
10385 #endif  
10386    } else {
10387        SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x32,~0x08);
10388        SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,0x00);
10389    }
10390    return 0;
10391 }
10392    
10393 USHORT
10394 SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS)
10395 {
10396    USHORT DDCdatatype,flag;
10397    BOOLEAN foundcrt = FALSE;
10398    int retry;
10399    unsigned char buffer[256];
10400
10401    if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
10402
10403    if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2, 0, FALSE) == 0xFFFF) return 0;
10404    
10405    SiS_Pr->SiS_DDC_SecAddr = 0x00;
10406    
10407    /* Probe supported DA's */
10408    flag = SiS_ProbeDDC(SiS_Pr);
10409    if(flag & 0x10) {
10410       SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;        /* EDID V2 (FP) */
10411       DDCdatatype = 4;
10412    } else if(flag & 0x08) {
10413       SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;        /* EDID V2 (P&D-D Monitor) */
10414       DDCdatatype = 3;
10415    } else if(flag & 0x02) {
10416       SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;        /* EDID V1 */
10417       DDCdatatype = 1;
10418    } else {
10419         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10420                 "VGA2 sense: Do DDC answer\n");
10421         return 0;                               /* no DDC support (or no device attached) */
10422    }
10423
10424    /* Read the entire EDID */
10425    retry = 2;
10426    do {
10427       if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
10428          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10429                 "VGA2 sense: DDC read failed (attempt %d), %s\n",
10430                 (3-retry), (retry == 1) ? "giving up" : "retrying");
10431          retry--;
10432          if(retry == 0) return 0xFFFF;
10433       } else break;
10434    } while(1);
10435
10436    /* Analyze EDID. We don't have many chances to
10437     * distinguish a flat panel from a CRT...
10438     */
10439    switch(DDCdatatype) {
10440    case 1:
10441       if(!(checkedid1(buffer))) {
10442           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
10443                 "VGA2 sense: EDID corrupt\n");
10444           return 0;
10445       }
10446       if(buffer[0x14] & 0x80) {                 /* Display uses digital input */
10447           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
10448                 "VGA2 sense: Attached display expects digital input\n");
10449           return 0;
10450       }
10451       SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
10452       SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
10453       foundcrt = TRUE;
10454       break;
10455    case 3:
10456    case 4:
10457       if(!(checkedid2(buffer))) {
10458           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
10459                 "VGA2 sense: EDID corrupt\n");
10460           return 0;
10461       }
10462       if( ((buffer[0x41] & 0x0f) != 0x01) &&    /* Display does not support analog input */
10463           ((buffer[0x41] & 0x0f) != 0x02) &&
10464           ((buffer[0x41] & 0xf0) != 0x10) &&
10465           ((buffer[0x41] & 0xf0) != 0x20) ) {
10466           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
10467                 "VGA2 sense: Attached display does not support analog input (0x%02x)\n",
10468                 buffer[0x41]);
10469           return 0;
10470       }
10471       SiS_Pr->CP_Vendor = buffer[2] | (buffer[1] << 8);
10472       SiS_Pr->CP_Product = buffer[3] | (buffer[4] << 8);
10473       foundcrt = TRUE;
10474       break;
10475    }
10476
10477    if(foundcrt) {
10478       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
10479    }
10480    return(0);
10481 }
10482
10483 #endif
10484
10485 void
10486 SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh)
10487 {
10488   USHORT tempbl;
10489
10490   tempbl = SiS_GetCH70xx(SiS_Pr,(tempax & 0x00FF));
10491   tempbl = (((tempbl & tempbh) << 8) | tempax);
10492   SiS_SetCH70xx(SiS_Pr,tempbl);
10493 }
10494
10495 /* Generic I2C functions for Chrontel & DDC --------- */
10496
10497 static void
10498 SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
10499 {
10500   SiS_SetSCLKHigh(SiS_Pr);
10501   SiS_WaitRetrace1(SiS_Pr);
10502
10503   SiS_SetSCLKLow(SiS_Pr);
10504   SiS_WaitRetrace1(SiS_Pr);
10505 }
10506
10507 USHORT
10508 SiS_ReadDDC1Bit(SiS_Private *SiS_Pr)
10509 {
10510    SiS_WaitRetrace1(SiS_Pr);
10511    return((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
10512 }
10513
10514 /* Set I2C start condition */
10515 /* This is done by a SD high-to-low transition while SC is high */
10516 static USHORT
10517 SiS_SetStart(SiS_Private *SiS_Pr)
10518 {
10519   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                                /* (SC->low)  */
10520   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10521                   SiS_Pr->SiS_DDC_Index,
10522                   SiS_Pr->SiS_DDC_NData,
10523                   SiS_Pr->SiS_DDC_Data);                                   /* SD->high */
10524   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                               /* SC->high */
10525   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10526                   SiS_Pr->SiS_DDC_Index,
10527                   SiS_Pr->SiS_DDC_NData,
10528                   0x00);                                                   /* SD->low = start condition */
10529   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                               /* (SC->low) */
10530   return 0;
10531 }
10532
10533 /* Set I2C stop condition */
10534 /* This is done by a SD low-to-high transition while SC is high */
10535 static USHORT
10536 SiS_SetStop(SiS_Private *SiS_Pr)
10537 {
10538   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                                /* (SC->low) */
10539   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10540                   SiS_Pr->SiS_DDC_Index,
10541                   SiS_Pr->SiS_DDC_NData,
10542                   0x00);                                                   /* SD->low   */
10543   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                               /* SC->high  */
10544   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10545                   SiS_Pr->SiS_DDC_Index,
10546                   SiS_Pr->SiS_DDC_NData,
10547                   SiS_Pr->SiS_DDC_Data);                                   /* SD->high = stop condition */
10548   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                               /* (SC->high) */
10549   return 0;
10550 }
10551
10552 /* Write 8 bits of data */
10553 static USHORT
10554 SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
10555 {
10556   USHORT i,flag,temp;
10557
10558   flag = 0x80;
10559   for(i=0; i<8; i++) {
10560     SiS_SetSCLKLow(SiS_Pr);                                                   /* SC->low */
10561     if(tempax & flag) {
10562       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10563                       SiS_Pr->SiS_DDC_Index,
10564                       SiS_Pr->SiS_DDC_NData,
10565                       SiS_Pr->SiS_DDC_Data);                                  /* Write bit (1) to SD */
10566     } else {
10567       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10568                       SiS_Pr->SiS_DDC_Index,
10569                       SiS_Pr->SiS_DDC_NData,
10570                       0x00);                                                  /* Write bit (0) to SD */
10571     }
10572     SiS_SetSCLKHigh(SiS_Pr);                                                  /* SC->high */
10573     flag >>= 1;
10574   }
10575   temp = SiS_CheckACK(SiS_Pr);                                                /* Check acknowledge */
10576   return(temp);
10577 }
10578
10579 static USHORT
10580 SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
10581 {
10582   USHORT i,temp,getdata;
10583
10584   getdata=0;
10585   for(i=0; i<8; i++) {
10586     getdata <<= 1;
10587     SiS_SetSCLKLow(SiS_Pr);
10588     SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10589                     SiS_Pr->SiS_DDC_Index,
10590                     SiS_Pr->SiS_DDC_NData,
10591                     SiS_Pr->SiS_DDC_Data);
10592     SiS_SetSCLKHigh(SiS_Pr);
10593     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
10594     if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
10595   }
10596   return(getdata);
10597 }
10598
10599 static USHORT
10600 SiS_SetSCLKLow(SiS_Private *SiS_Pr)
10601 {
10602   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10603                   SiS_Pr->SiS_DDC_Index,
10604                   SiS_Pr->SiS_DDC_NClk,
10605                   0x00);                                        /* SetSCLKLow()  */
10606   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
10607   return 0;
10608 }
10609
10610 static USHORT
10611 SiS_SetSCLKHigh(SiS_Private *SiS_Pr)
10612 {
10613   USHORT temp, watchdog=1000;
10614
10615   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10616                   SiS_Pr->SiS_DDC_Index,
10617                   SiS_Pr->SiS_DDC_NClk,
10618                   SiS_Pr->SiS_DDC_Clk);                         /* SetSCLKHigh()  */
10619   do {
10620     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
10621   } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
10622   if (!watchdog) {
10623 #ifdef TWDEBUG
10624         xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n");
10625 #endif
10626         return 0xFFFF;
10627   }
10628   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
10629   return 0;
10630 }
10631
10632 /* Check I2C acknowledge */
10633 /* Returns 0 if ack ok, non-0 if ack not ok */
10634 static USHORT
10635 SiS_CheckACK(SiS_Private *SiS_Pr)
10636 {
10637   USHORT tempah;
10638
10639   SiS_SetSCLKLow(SiS_Pr);                                          /* (SC->low) */
10640   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10641                   SiS_Pr->SiS_DDC_Index,
10642                   SiS_Pr->SiS_DDC_NData,
10643                   SiS_Pr->SiS_DDC_Data);                           /* (SD->high) */
10644   SiS_SetSCLKHigh(SiS_Pr);                                         /* SC->high = clock impulse for ack */
10645   tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
10646   SiS_SetSCLKLow(SiS_Pr);                                          /* SC->low = end of clock impulse */
10647   if(tempah & SiS_Pr->SiS_DDC_Data) return(1);                     /* Ack OK if bit = 0 */
10648   else return(0);
10649 }
10650
10651 /* End of I2C functions ----------------------- */
10652
10653
10654 /* =============== SiS 315/330 O.E.M. ================= */
10655
10656 #ifdef SIS315H
10657
10658 static USHORT
10659 GetRAMDACromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
10660 {
10661   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
10662   USHORT romptr;
10663
10664   if(HwInfo->jChipType < SIS_330) {
10665      romptr = SISGETROMW(0x128);
10666      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
10667         romptr = SISGETROMW(0x12a);
10668   } else {
10669      romptr = SISGETROMW(0x1a8);
10670      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
10671         romptr = SISGETROMW(0x1aa);
10672   }
10673   return(romptr);
10674 }
10675
10676 static USHORT
10677 GetLCDromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
10678 {
10679   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
10680   USHORT romptr;
10681
10682   if(HwInfo->jChipType < SIS_330) {
10683      romptr = SISGETROMW(0x120);
10684      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
10685         romptr = SISGETROMW(0x122);
10686   } else {
10687      romptr = SISGETROMW(0x1a0);
10688      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
10689         romptr = SISGETROMW(0x1a2);
10690   }
10691   return(romptr);
10692 }
10693
10694 static USHORT
10695 GetTVromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
10696 {
10697   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
10698   USHORT romptr;
10699
10700   if(HwInfo->jChipType < SIS_330) {
10701      romptr = SISGETROMW(0x114);
10702      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
10703         romptr = SISGETROMW(0x11a);
10704   } else {
10705      romptr = SISGETROMW(0x194);
10706      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
10707         romptr = SISGETROMW(0x19a);
10708   }
10709   return(romptr);
10710 }
10711
10712 static USHORT
10713 GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
10714 {
10715   USHORT index;
10716
10717   if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
10718      if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
10719         if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
10720            index >>= 4;
10721            index *= 3;
10722            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
10723            else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
10724            return index;
10725         }
10726      }
10727   }
10728
10729   index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
10730   if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
10731   else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
10732   index--;
10733   index *= 3;
10734   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
10735   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
10736   return index;
10737 }
10738
10739 static USHORT
10740 GetLCDPtrIndex(SiS_Private *SiS_Pr)
10741 {
10742   USHORT index;
10743
10744   index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
10745   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
10746   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
10747   return index;
10748 }
10749
10750 static USHORT
10751 GetTVPtrIndex(SiS_Private *SiS_Pr)
10752 {
10753   USHORT index;
10754
10755   index = 0;
10756   if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
10757   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
10758
10759   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
10760
10761   index <<= 1;
10762
10763   if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
10764      (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
10765      index++;
10766   }
10767
10768   return index;
10769 }
10770
10771 static ULONG
10772 GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
10773 {
10774    USHORT index = 0, temp = 0;
10775
10776    if(SiS_Pr->SiS_TVMode & TVSetPAL)   index = 1;
10777    if(SiS_Pr->SiS_TVMode & TVSetPALM)  index = 2;
10778    if(SiS_Pr->SiS_TVMode & TVSetPALN)  index = 3;
10779    if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
10780    if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
10781       index = 4;
10782       if(SiS_Pr->SiS_TVMode & TVSetPALM)  index++;
10783       if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
10784    }
10785
10786    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
10787       if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
10788          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
10789          index += addme;
10790          temp++;
10791       }
10792       temp += 0x0100;
10793    }
10794    return(ULONG)(index | (temp << 16));
10795 }
10796
10797 static ULONG
10798 GetOEMTVPtr661_2_OLD(SiS_Private *SiS_Pr)
10799 {
10800    return(GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
10801 }
10802
10803 #if 0
10804 static ULONG
10805 GetOEMTVPtr661_2_NEW(SiS_Private *SiS_Pr)
10806 {
10807    return(GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
10808 }
10809 #endif
10810
10811 static int
10812 GetOEMTVPtr661(SiS_Private *SiS_Pr)
10813 {
10814    int index = 0;
10815
10816    if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
10817    if(SiS_Pr->SiS_ROMNew) {
10818       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
10819       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
10820       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
10821       if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
10822    } else {
10823       if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
10824       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
10825       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
10826       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
10827    }
10828
10829    if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
10830
10831    return index;
10832 }
10833
10834 static void
10835 SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
10836 {
10837   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
10838   USHORT delay=0,index,myindex,temp,romptr=0;
10839   BOOLEAN dochiptest = TRUE;
10840
10841   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10842      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
10843   } else {
10844      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
10845   }
10846
10847   /* Find delay (from ROM, internal tables, PCI subsystem) */
10848
10849   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {                    /* ------------ VGA */
10850      
10851      if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10852         romptr = GetRAMDACromptr(SiS_Pr, HwInfo);
10853      }
10854      if(romptr) delay = ROMAddr[romptr];
10855      else {
10856         delay = 0x04;
10857         if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
10858            if(IS_SIS650) {
10859               delay = 0x0a;
10860            } else if(IS_SIS740) {
10861               delay = 0x00;
10862            } else if(HwInfo->jChipType < SIS_330) {
10863               delay = 0x0c;
10864            } else {
10865               delay = 0x0c;
10866            }
10867         } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
10868            delay = 0x00;
10869         }
10870      }
10871
10872   } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {  /* ---------- LCD/LCDA */
10873
10874      BOOLEAN gotitfrompci = FALSE;
10875
10876      /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
10877
10878      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10879         if(SiS_Pr->PDC != -1) {
10880            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
10881            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
10882            return;
10883         }
10884      } else {
10885         if(SiS_Pr->PDCA != -1) {
10886            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
10887            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
10888            return;
10889         }
10890      }
10891
10892      /* Custom Panel? */
10893
10894      if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
10895         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10896            delay = 0x00;
10897            if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
10898               delay = 0x20;
10899            }
10900            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
10901         } else {
10902            delay = 0x0c;
10903            if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x03;
10904            else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
10905               if(IS_SIS740) delay = 0x01;
10906               else          delay = 0x03;
10907            }
10908            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
10909         }
10910         return;
10911      }
10912
10913      /* This is a piece of typical SiS crap: They code the OEM LCD
10914       * delay into the code, at no defined place in the BIOS.
10915       * We now have to start doing a PCI subsystem check here.
10916       */
10917
10918      switch(SiS_Pr->SiS_CustomT) {
10919      case CUT_COMPAQ1280:
10920      case CUT_COMPAQ12802:
10921         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10922            gotitfrompci = TRUE;
10923            dochiptest = FALSE;
10924            delay = 0x03;
10925         }
10926         break;
10927      case CUT_CLEVO1400:
10928      case CUT_CLEVO14002:
10929         gotitfrompci = TRUE;
10930         dochiptest = FALSE;
10931         delay = 0x02;
10932         break;
10933      case CUT_CLEVO1024:
10934      case CUT_CLEVO10242:
10935         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10936            gotitfrompci = TRUE;
10937            dochiptest = FALSE;
10938            delay = 0x33;
10939            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
10940            delay &= 0x0f;
10941         }
10942         break;
10943      }
10944
10945      /* Could we find it through the PCI ID? If no, use ROM or table */
10946
10947      if(!gotitfrompci) {
10948
10949         index = GetLCDPtrIndexBIOS(SiS_Pr, HwInfo);
10950         myindex = GetLCDPtrIndex(SiS_Pr);
10951
10952         if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
10953
10954            if(SiS_IsNotM650orLater(SiS_Pr, HwInfo)) {
10955
10956               if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10957                  /* Always use the second pointer on 650; some BIOSes */
10958                  /* still carry old 301 data at the first location    */
10959                  /* romptr = SISGETROMW(0x120);                       */
10960                  /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
10961                  romptr = SISGETROMW(0x122);
10962                  if(!romptr) return;
10963                  delay = ROMAddr[(romptr + index)];
10964               } else {
10965                  delay = SiS310_LCDDelayCompensation_650301LV[myindex];
10966               }
10967
10968           } else {
10969
10970              delay = SiS310_LCDDelayCompensation_651301LV[myindex];
10971              if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
10972                 delay = SiS310_LCDDelayCompensation_651302LV[myindex];
10973
10974           }
10975
10976         } else if(SiS_Pr->SiS_UseROM                          &&
10977                   (!(SiS_Pr->SiS_ROMNew))                     &&
10978                   (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
10979                   (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
10980                   (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)) {
10981
10982            /* Data for 1280x1024 wrong in 301B BIOS */
10983            romptr = GetLCDromptr(SiS_Pr, HwInfo);
10984            if(!romptr) return;
10985            delay = ROMAddr[(romptr + index)];
10986
10987         } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
10988
10989            if(IS_SIS740) delay = 0x03;
10990            else          delay = 0x00;
10991
10992         } else {
10993
10994            delay = SiS310_LCDDelayCompensation_301[myindex];
10995            if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
10996               if(IS_SIS740) delay = 0x01;
10997               else if(HwInfo->jChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
10998               else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
10999            } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
11000               if(IS_SIS740) delay = 0x01;  /* ? */
11001               else          delay = 0x03;
11002            } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
11003               if(IS_SIS740) delay = 0x01;
11004               else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
11005            }
11006
11007         }
11008
11009      }  /* got it from PCI */
11010
11011      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
11012         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
11013         dochiptest = FALSE;
11014      }
11015      
11016   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 /* ------------ TV */
11017
11018      index = GetTVPtrIndex(SiS_Pr);
11019      
11020      if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
11021
11022         if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
11023
11024            if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
11025               /* Always use the second pointer on 650; some BIOSes */
11026               /* still carry old 301 data at the first location    */
11027               /* romptr = SISGETROMW(0x114);                       */
11028               /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
11029               romptr = SISGETROMW(0x11a);
11030               if(!romptr) return;
11031               delay = ROMAddr[romptr + index];
11032
11033            } else {
11034
11035               delay = SiS310_TVDelayCompensation_301B[index];
11036
11037            }
11038
11039         } else {
11040
11041            switch(SiS_Pr->SiS_CustomT) {
11042            case CUT_COMPAQ1280:
11043            case CUT_COMPAQ12802:
11044            case CUT_CLEVO1400:
11045            case CUT_CLEVO14002:
11046               delay = 0x02;
11047               dochiptest = FALSE;
11048               break;
11049            case CUT_CLEVO1024:
11050            case CUT_CLEVO10242:
11051               delay = 0x03;
11052               dochiptest = FALSE;
11053               break;
11054            default:
11055               delay = SiS310_TVDelayCompensation_651301LV[index];
11056               if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
11057                  delay = SiS310_TVDelayCompensation_651302LV[index];
11058               }
11059            }
11060         }
11061
11062      } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
11063
11064         romptr = GetTVromptr(SiS_Pr, HwInfo);
11065         if(!romptr) return;
11066         delay = ROMAddr[romptr + index];
11067
11068      } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
11069
11070         delay = SiS310_TVDelayCompensation_LVDS[index];
11071
11072      } else {
11073
11074         delay = SiS310_TVDelayCompensation_301[index];
11075         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
11076            if(IS_SIS740) {
11077               delay = SiS310_TVDelayCompensation_740301B[index];
11078               /* LV: use 301 data? BIOS bug? */
11079            } else {
11080               delay = SiS310_TVDelayCompensation_301B[index];
11081               if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
11082            }
11083         }
11084
11085      }
11086
11087      if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
11088         delay &= 0x0f;
11089         dochiptest = FALSE;
11090      }
11091     
11092   } else return;
11093
11094   /* Write delay */
11095
11096   if(SiS_Pr->SiS_VBType & VB_SISVB) {
11097
11098      if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && dochiptest) {
11099
11100         temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
11101         if(temp == 8) {         /* 1400x1050 BIOS (COMPAL) */
11102            delay &= 0x0f;
11103            delay |= 0xb0;
11104         } else if(temp == 6) {
11105            delay &= 0x0f;
11106            delay |= 0xc0;
11107         } else if(temp > 7) {   /* 1280x1024 BIOS (which one?) */
11108            delay = 0x35;
11109         }
11110         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
11111
11112      } else {
11113
11114         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
11115
11116      }
11117
11118   } else {  /* LVDS */
11119
11120      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
11121         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
11122      } else {
11123         if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
11124            delay <<= 4;
11125            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
11126         } else {
11127            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
11128         }
11129      }
11130
11131   }
11132
11133 }
11134
11135 static void
11136 SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11137                USHORT ModeNo,USHORT ModeIdIndex)
11138 {
11139   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11140   USHORT index,temp,temp1,romptr=0;
11141
11142   if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
11143
11144   if(ModeNo<=0x13)
11145      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
11146   else
11147      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
11148
11149   temp = GetTVPtrIndex(SiS_Pr);
11150   temp >>= 1;     /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
11151   temp1 = temp;
11152
11153   if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
11154      if(HwInfo->jChipType >= SIS_661) {
11155         temp1 = GetOEMTVPtr661(SiS_Pr);
11156         temp1 >>= 1;
11157         romptr = SISGETROMW(0x260);
11158         if(HwInfo->jChipType >= SIS_760) {
11159            romptr = SISGETROMW(0x360);
11160         }
11161      } else if(HwInfo->jChipType >= SIS_330) {
11162         romptr = SISGETROMW(0x192);
11163      } else {
11164         romptr = SISGETROMW(0x112);
11165      }
11166   }
11167
11168   if(romptr) {
11169      temp1 <<= 1;
11170      temp = ROMAddr[romptr + temp1 + index];
11171   } else {
11172      temp = SiS310_TVAntiFlick1[temp][index];
11173   }
11174   temp <<= 4;
11175
11176   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp);  /* index 0A D[6:4] */
11177 }
11178
11179 static void
11180 SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11181                USHORT ModeNo,USHORT ModeIdIndex)
11182 {
11183   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11184   USHORT index,temp,temp1,romptr=0;
11185
11186   temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1;    /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
11187
11188   if(ModeNo <= 0x13)
11189      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
11190   else
11191      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
11192
11193   if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
11194      if(HwInfo->jChipType >= SIS_661) {
11195         romptr = SISGETROMW(0x26c);
11196         if(HwInfo->jChipType >= SIS_760) {
11197            romptr = SISGETROMW(0x36c);
11198         }
11199         temp1 = GetOEMTVPtr661(SiS_Pr);
11200         temp1 >>= 1;
11201      } else if(HwInfo->jChipType >= SIS_330) {
11202         romptr = SISGETROMW(0x1a4);
11203      } else {
11204         romptr = SISGETROMW(0x124);
11205      }
11206   }
11207
11208   if(romptr) {
11209      temp1 <<= 1;
11210      temp = ROMAddr[romptr + temp1 + index];
11211   } else {
11212      temp = SiS310_TVEdge1[temp][index];
11213   }
11214   temp <<= 5;
11215   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp);  /* index 0A D[7:5] */
11216 }
11217
11218 static void
11219 SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11220            USHORT ModeNo,USHORT ModeIdIndex)
11221 {
11222   USHORT index, temp, i, j;
11223
11224   if(ModeNo <= 0x13) {
11225      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
11226   } else {
11227      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
11228   }
11229
11230   temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
11231
11232   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)        temp = 1;  /* NTSC-J uses PAL */
11233   else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
11234   else if(SiS_Pr->SiS_TVMode & TVSetPALN)    temp = 4;  /* PAL-N */
11235   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1;  /* HiVision uses PAL */
11236
11237   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
11238      for(i=0x35, j=0; i<=0x38; i++, j++) {
11239         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
11240      }
11241      for(i=0x48; i<=0x4A; i++, j++) {
11242         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
11243      }
11244   } else {
11245      for(i=0x35, j=0; i<=0x38; i++, j++) {
11246         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
11247      }
11248   }
11249 }
11250
11251 static void
11252 SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11253              USHORT ModeNo,USHORT ModeIdIndex)
11254 {
11255   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11256   USHORT index,temp,i,j,resinfo,romptr=0;
11257   ULONG  lindex;
11258
11259   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
11260
11261   /* NTSC-J data not in BIOS, and already set in SetGroup2 */
11262   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
11263
11264   if((HwInfo->jChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
11265      lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
11266      lindex <<= 2;
11267      for(j=0, i=0x31; i<=0x34; i++, j++) {
11268         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
11269      }
11270      return;
11271   }
11272
11273   /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
11274   if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
11275
11276   if(ModeNo<=0x13) {
11277      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
11278   } else {
11279      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
11280   }
11281
11282   temp = GetTVPtrIndex(SiS_Pr);
11283   /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
11284    * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
11285    */
11286   if(SiS_Pr->SiS_UseROM) {
11287      romptr = SISGETROMW(0x116);
11288      if(HwInfo->jChipType >= SIS_330) {
11289         romptr = SISGETROMW(0x196);
11290      }
11291      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
11292         romptr = SISGETROMW(0x11c);
11293         if(HwInfo->jChipType >= SIS_330) {
11294            romptr = SISGETROMW(0x19c);
11295         }
11296         if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
11297            romptr = SISGETROMW(0x116);
11298            if(HwInfo->jChipType >= SIS_330) {
11299               romptr = SISGETROMW(0x196);
11300            }
11301         }
11302      }
11303   }
11304   if(romptr) {
11305      romptr += (temp << 2);
11306      for(j=0, i=0x31; i<=0x34; i++, j++) {
11307         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11308      }
11309   } else {
11310      index = temp % 2;
11311      temp >>= 1;          /* 0:NTSC, 1:PAL, 2:HiTV */
11312      for(j=0, i=0x31; i<=0x34; i++, j++) {
11313         if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV))
11314            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
11315         else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
11316            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
11317         else
11318            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
11319      }
11320   }
11321
11322   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
11323      if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
11324         if((resinfo == SIS_RI_640x480) ||
11325            (resinfo == SIS_RI_800x600)) {
11326            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
11327            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
11328            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
11329            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
11330         } else if(resinfo == SIS_RI_1024x768) {
11331            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
11332            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
11333            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
11334            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
11335         }
11336      }
11337   }
11338 }
11339
11340 static void
11341 SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
11342                 USHORT ModeIdIndex, USHORT RTI)
11343 {
11344    USHORT delay = 0, romptr = 0, index, lcdpdcindex;
11345    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11346
11347    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
11348       return;
11349
11350    /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
11351    /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
11352
11353    if(SiS_Pr->SiS_ROMNew) {
11354       if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)                         ||
11355          ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
11356           (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
11357          index = 25;
11358          if(SiS_Pr->UseCustomMode) {
11359             index = SiS_Pr->CSRClock;
11360          } else if(ModeNo > 0x13) {
11361             index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI,HwInfo);
11362             index = SiS_Pr->SiS_VCLKData[index].CLOCK;
11363          }
11364          if(index < 25) index = 25;
11365          index = ((index / 25) - 1) << 1;
11366          if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
11367             index++;
11368          }
11369          romptr = SISGETROMW(0x104);
11370          delay = ROMAddr[romptr + index];
11371          if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
11372             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
11373             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
11374          } else {
11375             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
11376             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
11377          }
11378          return;
11379       }
11380    }
11381
11382    /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
11383
11384    if(SiS_Pr->UseCustomMode) delay = 0x04;
11385    else if(ModeNo <= 0x13)   delay = 0x04;
11386    else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
11387    delay |= (delay << 8);
11388
11389    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
11390
11391       /* 3. TV */
11392
11393       index = GetOEMTVPtr661(SiS_Pr);
11394       if(SiS_Pr->SiS_ROMNew) {
11395          romptr = SISGETROMW(0x106);
11396          if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
11397          delay = ROMAddr[romptr + index];
11398       } else {
11399          delay = 0x04;
11400          if(index > 3) delay = 0;
11401       }
11402
11403    } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11404
11405       /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
11406
11407       if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
11408           ((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) ) {
11409
11410          lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
11411
11412          /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
11413          delay = ROMAddr[romptr + lcdpdcindex + 1];     /* LCD  */
11414          delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
11415
11416       } else {
11417
11418          /* TMDS: Set our own, since BIOS has no idea */
11419          /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
11420          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
11421             switch(SiS_Pr->SiS_LCDResInfo) {
11422             case Panel_1024x768:  delay = 0x0008; break;
11423             case Panel_1280x720:  delay = 0x0004; break;
11424             case Panel_1280x768:
11425             case Panel_1280x768_2:delay = 0x0004; break;
11426             case Panel_1280x800:
11427             case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
11428             case Panel_1280x1024: delay = 0x1e04; break;
11429             case Panel_1400x1050: delay = 0x0004; break;
11430             case Panel_1600x1200: delay = 0x0400; break;
11431             case Panel_1680x1050: delay = 0x0e04; break;
11432             default:
11433                if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
11434                   delay = 0x0008;
11435                } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
11436                   delay = 0x1e04;
11437                } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
11438                   delay = 0x0004;
11439                } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
11440                   delay = 0x0400;
11441                } else
11442                   delay = 0x0e04;
11443                break;
11444             }
11445          }
11446
11447          /* Override by detected or user-set values */
11448          /* (but only if, for some reason, we can't read value from BIOS) */
11449          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
11450             delay = SiS_Pr->PDC & 0x1f;
11451          }
11452          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
11453             delay = (SiS_Pr->PDCA & 0x1f) << 8;
11454          }
11455
11456       }
11457
11458    }
11459
11460    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
11461       delay >>= 8;
11462       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
11463       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
11464    } else {
11465       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
11466       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
11467    }
11468 }
11469
11470 static void
11471 SetCRT2SyncDither661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT RTI)
11472 {
11473    USHORT infoflag;
11474    UCHAR temp;
11475
11476    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11477
11478       if(ModeNo <= 0x13) {
11479          infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
11480       } else if(SiS_Pr->UseCustomMode) {
11481          infoflag = SiS_Pr->CInfoFlag;
11482       } else {
11483          infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
11484       }
11485
11486       if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
11487          infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
11488       }
11489
11490       infoflag &= 0xc0;
11491
11492       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
11493          temp = (infoflag >> 6) | 0x0c;
11494          if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
11495             temp ^= 0x04;
11496             if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
11497          }
11498          SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
11499       } else {
11500          temp = 0x30;
11501          if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
11502          temp |= infoflag;
11503          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
11504          temp = 0;
11505          if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
11506             if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
11507          }
11508          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
11509       }
11510
11511    }
11512 }
11513
11514 static void
11515 SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
11516 {
11517    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11518    USHORT romptr, temp1, temp2;
11519
11520    if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
11521       if(SiS_Pr->LVDSHL != -1) {
11522          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
11523       }
11524    }
11525
11526    if(SiS_Pr->SiS_ROMNew) {
11527
11528       if((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) {
11529          if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
11530             temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
11531             temp2 = 0xfc;
11532             if(SiS_Pr->LVDSHL != -1) {
11533               temp1 &= 0xfc;
11534               temp2 = 0xf3;
11535             }
11536             SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
11537          }
11538          if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
11539             temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
11540             SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
11541          }
11542       }
11543
11544    }
11545 }
11546
11547 static void
11548 SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11549                   USHORT ModeNo,USHORT ModeIdIndex,USHORT RRTI)
11550 {
11551    if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
11552       SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
11553       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11554          SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
11555          SetPanelParms661(SiS_Pr,HwInfo);
11556       }
11557    } else {
11558       SetDelayComp(SiS_Pr,HwInfo,ModeNo);
11559    }
11560
11561    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
11562       SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11563       SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11564       SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11565       if(SiS_Pr->SiS_VBType & VB_SIS301) {
11566          SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11567       }
11568    }
11569 }
11570
11571 static void
11572 SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11573                   USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI)
11574 {
11575    if(SiS_Pr->SiS_VBType & VB_SISVB) {
11576
11577       SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
11578
11579       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11580          SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
11581          SetPanelParms661(SiS_Pr,HwInfo);
11582       }
11583
11584       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
11585          SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11586          SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11587          SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11588          if(SiS_Pr->SiS_VBType & VB_SIS301) {
11589             SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11590          }
11591       }
11592    }
11593 }
11594
11595 /* FinalizeLCD
11596  * This finalizes some CRT2 registers for the very panel used.
11597  * If we have a backup if these registers, we use it; otherwise
11598  * we set the register according to most BIOSes. However, this
11599  * function looks quite different in every BIOS, so you better
11600  * pray that we have a backup...
11601  */
11602 static void
11603 SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
11604                 PSIS_HW_INFO HwInfo)
11605 {
11606   USHORT tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
11607   USHORT resinfo,modeflag;
11608
11609   if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) return;
11610   if(SiS_Pr->SiS_ROMNew) return;
11611
11612   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11613      if(SiS_Pr->LVDSHL != -1) {
11614         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
11615      }
11616   }
11617
11618   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
11619   if(SiS_Pr->UseCustomMode) return;
11620
11621   switch(SiS_Pr->SiS_CustomT) {
11622   case CUT_COMPAQ1280:
11623   case CUT_COMPAQ12802:
11624   case CUT_CLEVO1400:
11625   case CUT_CLEVO14002:
11626      return;
11627   }
11628
11629   if(ModeNo <= 0x13) {
11630      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
11631      modeflag =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
11632   } else {
11633      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
11634      modeflag =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
11635   }
11636
11637   if(IS_SIS650) {
11638      if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
11639         if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
11640            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
11641         } else {
11642            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
11643         }
11644      }
11645   }
11646
11647   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
11648      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11649         /* Maybe all panels? */
11650         if(SiS_Pr->LVDSHL == -1) {
11651            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
11652         }
11653         return;
11654      }
11655   }
11656
11657   if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
11658      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11659         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11660            if(SiS_Pr->LVDSHL == -1) {
11661               /* Maybe all panels? */
11662               SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
11663            }
11664            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
11665               tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
11666               if(tempch == 3) {
11667                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
11668                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
11669                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
11670                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
11671               }
11672            }
11673            return;
11674         }
11675      }
11676   }
11677
11678   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11679      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11680         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
11681            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
11682 #ifdef SET_EMI
11683            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
11684 #endif
11685            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
11686         }
11687      } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
11688         if(SiS_Pr->LVDSHL == -1) {
11689            /* Maybe ACER only? */
11690            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
11691         }
11692      }
11693      tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
11694      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
11695         if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
11696            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
11697         } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11698            if(tempch == 0x03) {
11699               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
11700               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
11701               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
11702               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
11703            }
11704            if((SiS_Pr->Backup == TRUE) && (SiS_Pr->Backup_Mode == ModeNo)) {
11705               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
11706               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
11707               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
11708               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
11709               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
11710               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
11711               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
11712               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
11713               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
11714               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
11715            } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {  /* 1.10.8w */
11716               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
11717               if(ModeNo <= 0x13) {
11718                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
11719                  if((resinfo == 0) || (resinfo == 2)) return;
11720                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
11721                  if((resinfo == 1) || (resinfo == 3)) return;
11722               }
11723               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
11724               if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
11725                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);  /* 1.10.7u */
11726 #if 0
11727                  tempbx = 806;  /* 0x326 */                      /* other older BIOSes */
11728                  tempbx--;
11729                  temp = tempbx & 0xff;
11730                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
11731                  temp = (tempbx >> 8) & 0x03;
11732                  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
11733 #endif
11734               }
11735            } else if(ModeNo <= 0x13) {
11736               if(ModeNo <= 1) {
11737                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
11738                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
11739                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
11740                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
11741               }
11742               if(!(modeflag & HalfDCLK)) {
11743                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
11744                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
11745                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
11746                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
11747                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
11748                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
11749                  if(ModeNo == 0x12) {
11750                     switch(tempch) {
11751                        case 0:
11752                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
11753                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
11754                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
11755                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
11756                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
11757                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
11758                           break;
11759                        case 2:
11760                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
11761                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
11762                           break;
11763                        case 3:
11764                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
11765                           break;
11766                     }
11767                  }
11768               }
11769            }
11770         }
11771      } else {
11772         tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
11773         tempcl &= 0x0f;
11774         tempbh &= 0x70;
11775         tempbh >>= 4;
11776         tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
11777         tempbx = (tempbh << 8) | tempbl;
11778         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11779            if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
11780               if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
11781                  tempbx = 770;
11782               } else {
11783                  if(tempbx > 770) tempbx = 770;
11784                  if(SiS_Pr->SiS_VGAVDE < 600) {
11785                     tempax = 768 - SiS_Pr->SiS_VGAVDE;
11786                     tempax >>= 4;                                /* 1.10.7w; 1.10.6s: 3;  */
11787                     if(SiS_Pr->SiS_VGAVDE <= 480)  tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
11788                     tempbx -= tempax;
11789                  }
11790               }
11791            } else return;
11792         }
11793         temp = tempbx & 0xff;
11794         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
11795         temp = ((tempbx & 0xff00) >> 4) | tempcl;
11796         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
11797      }
11798   }
11799 }
11800
11801 #endif
11802
11803 /*  =================  SiS 300 O.E.M. ================== */
11804
11805 #ifdef SIS300
11806
11807 static void
11808 SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11809                USHORT ModeNo,USHORT ModeIdIndex, USHORT RefTabIndex)
11810 {
11811   USHORT crt2crtc=0, modeflag, myindex=0;
11812   UCHAR  temp;
11813   int i;
11814
11815   if(ModeNo <= 0x13) {
11816      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
11817      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
11818   } else {
11819      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
11820      crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
11821   }
11822
11823   crt2crtc &= 0x3f;
11824
11825   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
11826      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
11827   }
11828
11829   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
11830      if(modeflag & HalfDCLK) myindex = 1;
11831
11832      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
11833         for(i=0; i<7; i++) {
11834            if(barco_p1[myindex][crt2crtc][i][0]) {
11835               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
11836                               barco_p1[myindex][crt2crtc][i][0],
11837                               barco_p1[myindex][crt2crtc][i][2],
11838                               barco_p1[myindex][crt2crtc][i][1]);
11839            }
11840         }
11841      }
11842      temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
11843      if(temp & 0x80) {
11844         temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
11845         temp++;
11846         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
11847      }
11848   }
11849 }
11850
11851 static USHORT
11852 GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int Flag)
11853 {
11854   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11855   USHORT tempbx=0,romptr=0;
11856   UCHAR customtable300[] = {
11857         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
11858         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
11859   };
11860   UCHAR customtable630[] = {
11861         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
11862         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
11863   };
11864
11865   if(HwInfo->jChipType == SIS_300) {
11866
11867     tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
11868     if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
11869     tempbx -= 2;
11870     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
11871     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11872        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
11873     }
11874     if(SiS_Pr->SiS_UseROM) {
11875        if(ROMAddr[0x235] & 0x80) {
11876           tempbx = SiS_Pr->SiS_LCDTypeInfo;
11877           if(Flag) {
11878              romptr = SISGETROMW(0x255);
11879              if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
11880              else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
11881              if(tempbx == 0xFF) return 0xFFFF;
11882           }
11883           tempbx <<= 1;
11884           if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
11885        }
11886     }
11887
11888   } else {
11889
11890     if(Flag) {
11891        if(SiS_Pr->SiS_UseROM) {
11892           romptr = SISGETROMW(0x255);
11893           if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
11894           else       tempbx = 0xff;
11895        } else {
11896           tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
11897        }
11898        if(tempbx == 0xFF) return 0xFFFF;
11899        tempbx <<= 2;
11900        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
11901        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
11902        return tempbx;
11903     }
11904     tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
11905     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
11906     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
11907
11908   }
11909
11910   return tempbx;
11911 }
11912
11913 static void
11914 SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11915                USHORT ModeNo,USHORT ModeIdIndex)
11916 {
11917   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11918   USHORT index,temp,romptr=0;
11919
11920   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
11921
11922   if(SiS_Pr->SiS_UseROM) {
11923      if(!(ROMAddr[0x237] & 0x01)) return;
11924      if(!(ROMAddr[0x237] & 0x02)) return;
11925      romptr = SISGETROMW(0x24b);
11926   }
11927
11928   /* The Panel Compensation Delay should be set according to tables
11929    * here. Unfortunately, various BIOS versions don't case about
11930    * a uniform way using eg. ROM byte 0x220, but use different
11931    * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
11932    * Thus we don't set this if the user select a custom pdc or if
11933    * we otherwise detected a valid pdc.
11934    */
11935   if(SiS_Pr->PDC != -1) return;
11936
11937   temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 0);
11938
11939   if(SiS_Pr->UseCustomMode)
11940      index = 0;
11941   else
11942      index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
11943
11944   if(HwInfo->jChipType != SIS_300) {
11945      if(romptr) {
11946         romptr += (temp * 2);
11947         romptr = SISGETROMW(romptr);
11948         romptr += index;
11949         temp = ROMAddr[romptr];
11950      } else {
11951         if(SiS_Pr->SiS_VBType & VB_SISVB) {
11952            temp = SiS300_OEMLCDDelay2[temp][index];
11953         } else {
11954            temp = SiS300_OEMLCDDelay3[temp][index];
11955         }
11956      }
11957   } else {
11958      if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
11959         if(romptr) {
11960            romptr += (temp * 2);
11961            romptr = SISGETROMW(romptr);
11962            romptr += index;
11963            temp = ROMAddr[romptr];
11964         } else {
11965            temp = SiS300_OEMLCDDelay5[temp][index];
11966         }
11967      } else {
11968         if(SiS_Pr->SiS_UseROM) {
11969            romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
11970            if(romptr) {
11971               romptr += (temp * 2);
11972               romptr = SISGETROMW(romptr);
11973               romptr += index;
11974               temp = ROMAddr[romptr];
11975            } else {
11976               temp = SiS300_OEMLCDDelay4[temp][index];
11977            }
11978         } else {
11979            temp = SiS300_OEMLCDDelay4[temp][index];
11980         }
11981      }
11982   }
11983   temp &= 0x3c;
11984   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
11985 }
11986
11987 static void
11988 SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11989               USHORT ModeNo,USHORT ModeIdIndex)
11990 {
11991 #if 0  /* Unfinished; Data table missing */
11992   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11993   USHORT index,temp;
11994
11995   if((SiS_Pr->SiS_UseROM) {
11996      if(!(ROMAddr[0x237] & 0x01)) return;
11997      if(!(ROMAddr[0x237] & 0x04)) return;
11998      /* No rom pointer in BIOS header! */
11999   }
12000
12001   temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 1);
12002   if(temp = 0xFFFF) return;
12003
12004   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
12005   for(i=0x14, j=0; i<=0x17; i++, j++) {
12006       SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
12007   }
12008   SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
12009
12010   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
12011   SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
12012   SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
12013   SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
12014   for(i=0x1b, j=3; i<=0x1d; i++, j++) {
12015       SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
12016   }
12017 #endif
12018 }
12019
12020 static USHORT
12021 GetOEMTVPtr(SiS_Private *SiS_Pr)
12022 {
12023   USHORT index;
12024
12025   index = 0;
12026   if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  index += 4;
12027   if(SiS_Pr->SiS_VBType & VB_SISVB) {
12028      if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)  index += 2;
12029      else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
12030      else if(SiS_Pr->SiS_TVMode & TVSetPAL)   index += 1;
12031   } else {
12032      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
12033      if(SiS_Pr->SiS_TVMode & TVSetPAL)        index += 1;
12034   }
12035   return index;
12036 }
12037
12038 static void
12039 SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12040               USHORT ModeNo,USHORT ModeIdIndex)
12041 {
12042   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
12043   USHORT index,temp,romptr=0;
12044
12045   if(SiS_Pr->SiS_UseROM) {
12046      if(!(ROMAddr[0x238] & 0x01)) return;
12047      if(!(ROMAddr[0x238] & 0x02)) return;
12048      romptr = SISGETROMW(0x241);
12049   }
12050
12051   temp = GetOEMTVPtr(SiS_Pr);
12052
12053   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
12054
12055   if(romptr) {
12056      romptr += (temp * 2);
12057      romptr = SISGETROMW(romptr);
12058      romptr += index;
12059      temp = ROMAddr[romptr];
12060   } else {
12061      if(SiS_Pr->SiS_VBType & VB_SISVB) {
12062         temp = SiS300_OEMTVDelay301[temp][index];
12063      } else {
12064         temp = SiS300_OEMTVDelayLVDS[temp][index];
12065      }
12066   }
12067   temp &= 0x3c;
12068   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
12069 }
12070
12071 static void
12072 SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12073                   USHORT ModeNo, USHORT ModeIdIndex)
12074 {
12075   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
12076   USHORT index,temp,romptr=0;
12077
12078   if(SiS_Pr->SiS_UseROM) {
12079      if(!(ROMAddr[0x238] & 0x01)) return;
12080      if(!(ROMAddr[0x238] & 0x04)) return;
12081      romptr = SISGETROMW(0x243);
12082   }
12083
12084   temp = GetOEMTVPtr(SiS_Pr);
12085
12086   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
12087
12088   if(romptr) {
12089      romptr += (temp * 2);
12090      romptr = SISGETROMW(romptr);
12091      romptr += index;
12092      temp = ROMAddr[romptr];
12093   } else {
12094      temp = SiS300_OEMTVFlicker[temp][index];
12095   }
12096   temp &= 0x70;
12097   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
12098 }
12099
12100 static void
12101 SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12102                 USHORT ModeNo,USHORT ModeIdIndex)
12103 {
12104   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
12105   USHORT index,i,j,temp,romptr=0;
12106
12107   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
12108
12109   if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
12110
12111   if(SiS_Pr->SiS_UseROM) {
12112      if(!(ROMAddr[0x238] & 0x01)) return;
12113      if(!(ROMAddr[0x238] & 0x08)) return;
12114      romptr = SISGETROMW(0x245);
12115   }
12116
12117   temp = GetOEMTVPtr(SiS_Pr);
12118
12119   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
12120
12121   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
12122      for(i=0x31, j=0; i<=0x34; i++, j++) {
12123         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
12124      }
12125   } else {
12126      if(romptr) {
12127         romptr += (temp * 2);
12128         romptr = SISGETROMW(romptr);
12129         romptr += (index * 4);
12130         for(i=0x31, j=0; i<=0x34; i++, j++) {
12131            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
12132         }
12133      } else {
12134         for(i=0x31, j=0; i<=0x34; i++, j++) {
12135            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
12136         }
12137      }
12138   }
12139 }
12140
12141 static void
12142 SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12143               USHORT ModeNo,USHORT ModeIdIndex)
12144 {
12145   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
12146   USHORT index,temp,i,j,romptr=0;
12147
12148   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
12149
12150   if(SiS_Pr->SiS_UseROM) {
12151      if(!(ROMAddr[0x238] & 0x01)) return;
12152      if(!(ROMAddr[0x238] & 0x10)) return;
12153      romptr = SISGETROMW(0x247);
12154   }
12155
12156   temp = GetOEMTVPtr(SiS_Pr);
12157
12158   if(SiS_Pr->SiS_TVMode & TVSetPALM)      temp = 8;
12159   else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
12160   /* NTSCJ uses NTSC filters */
12161
12162   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
12163
12164   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
12165       for(i=0x35, j=0; i<=0x38; i++, j++) {
12166         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
12167       }
12168       for(i=0x48; i<=0x4A; i++, j++) {
12169         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
12170       }
12171   } else {
12172       if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
12173          romptr += (temp * 2);
12174          romptr = SISGETROMW(romptr);
12175          romptr += (index * 4);
12176          for(i=0x35, j=0; i<=0x38; i++, j++) {
12177             SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
12178          }
12179       } else {
12180          for(i=0x35, j=0; i<=0x38; i++, j++) {
12181             SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
12182          }
12183       }
12184   }
12185 }
12186
12187 static USHORT
12188 SiS_SearchVBModeID(SiS_Private *SiS_Pr, USHORT *ModeNo)
12189 {
12190    USHORT ModeIdIndex;
12191    UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO;
12192
12193    if(*ModeNo <= 5) *ModeNo |= 1;
12194
12195    for(ModeIdIndex=0; ; ModeIdIndex++) {
12196       if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
12197       if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF)    return 0;
12198    }
12199
12200    if(*ModeNo != 0x07) {
12201       if(*ModeNo > 0x03) return ModeIdIndex;
12202       if(VGAINFO & 0x80) return ModeIdIndex;
12203       ModeIdIndex++;
12204    }
12205
12206    if(VGAINFO & 0x10) ModeIdIndex++;   /* 400 lines */
12207                                        /* else 350 lines */
12208    return ModeIdIndex;
12209 }
12210
12211 static void
12212 SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12213                   USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTableIndex)
12214 {
12215   USHORT OEMModeIdIndex=0;
12216
12217   if(!SiS_Pr->UseCustomMode) {
12218      OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
12219      if(!(OEMModeIdIndex)) return;
12220   }
12221
12222   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
12223      SetOEMLCDDelay(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12224      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
12225         SetOEMLCDData(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12226      }
12227   }
12228   if(SiS_Pr->UseCustomMode) return;
12229   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
12230      SetOEMTVDelay(SiS_Pr, HwInfo, ModeNo,OEMModeIdIndex);
12231      if(SiS_Pr->SiS_VBType & VB_SISVB) {
12232         SetOEMAntiFlicker(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12233         SetOEMPhaseIncr(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12234         SetOEMYFilter(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12235      }
12236   }
12237 }
12238 #endif
12239