vserver 2.0 rc7
[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 static void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx);
90
91 /*********************************************/
92 /*         HELPER: Lock/Unlock CRT2          */
93 /*********************************************/
94
95 void
96 SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
97 {
98    if(HwInfo->jChipType >= SIS_315H)
99       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
100    else
101       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
102 }
103
104 static void
105 SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
106 {
107    if(HwInfo->jChipType >= SIS_315H)
108       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
109    else
110       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
111 }
112
113 /*********************************************/
114 /*            HELPER: Write SR11             */
115 /*********************************************/
116
117 static void
118 SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
119 {
120    if(HwInfo->jChipType >= SIS_661) {
121       DataAND &= 0x0f;
122       DataOR  &= 0x0f;
123    }
124    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
125 }
126
127 /*********************************************/
128 /*    HELPER: Get Pointer to LCD structure   */
129 /*********************************************/
130
131 #ifdef SIS315H
132 static UCHAR *
133 GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
134 {
135    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
136    UCHAR  *myptr = NULL;
137    USHORT romindex = 0, reg = 0, idx = 0;
138
139    /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
140     * due to the variaty of panels the BIOS doesn't know about.
141     * Exception: If the BIOS has better knowledge (such as in case
142     * of machines with a 301C and a panel that does not support DDC)
143     * use the BIOS data as well.
144     */
145
146    if((SiS_Pr->SiS_ROMNew) &&
147       ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
148
149       if(HwInfo->jChipType < SIS_661) reg = 0x3c;
150       else                            reg = 0x7d;
151
152       idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
153
154       if(idx < (8*26)) {
155          myptr = (UCHAR *)&SiS_LCDStruct661[idx];
156       }
157       romindex = SISGETROMW(0x100);
158       if(romindex) {
159          romindex += idx;
160          myptr = &ROMAddr[romindex];
161       }
162    }
163    return myptr;
164 }
165
166 static USHORT
167 GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
168 {
169    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
170    USHORT romptr = 0;
171
172    /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
173     * due to the variaty of panels the BIOS doesn't know about.
174     * Exception: If the BIOS has better knowledge (such as in case
175     * of machines with a 301C and a panel that does not support DDC)
176     * use the BIOS data as well.
177     */
178
179    if((SiS_Pr->SiS_ROMNew) &&
180       ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
181       romptr = SISGETROMW(0x102);
182       romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
183    }
184
185    return(romptr);
186 }
187 #endif
188
189 /*********************************************/
190 /*           Adjust Rate for CRT2            */
191 /*********************************************/
192
193 static BOOLEAN
194 SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
195                    USHORT RRTI, USHORT *i, PSIS_HW_INFO HwInfo)
196 {
197   USHORT checkmask=0,modeid,infoflag;
198
199   modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
200
201   if(SiS_Pr->SiS_VBType & VB_SISVB) {
202
203      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
204
205         checkmask |= SupportRAMDAC2;
206         if(HwInfo->jChipType >= SIS_315H) {
207            checkmask |= SupportRAMDAC2_135;
208            if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
209               checkmask |= SupportRAMDAC2_162;
210               if(SiS_Pr->SiS_VBType & VB_SIS301C) {
211                  checkmask |= SupportRAMDAC2_202;
212               }
213            }
214         }
215
216      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
217
218         checkmask |= SupportLCD;
219         if(HwInfo->jChipType >= SIS_315H) {
220            if(SiS_Pr->SiS_VBType & VB_SISVB) {
221               if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
222                  if(modeid == 0x2e) checkmask |= Support64048060Hz;
223               }
224            }
225         }
226
227      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
228
229         checkmask |= SupportHiVision;
230
231      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
232
233         checkmask |= SupportTV;
234         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
235            checkmask |= SupportTV1024;
236            if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
237               if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
238                  checkmask |= SupportYPbPr750p;
239               }
240            }
241         }
242
243      }
244
245   } else {      /* LVDS */
246
247      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
248         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
249            checkmask |= SupportCHTV;
250         }
251      }
252
253      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
254         checkmask |= SupportLCD;
255      }
256
257   }
258
259   /* Look backwards in table for matching CRT2 mode */
260   for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
261      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
262      if(infoflag & checkmask) return TRUE;
263      if((*i) == 0) break;
264   }
265
266   /* Look through the whole mode-section of the table from the beginning
267    * for a matching CRT2 mode if no mode was found yet.
268    */
269   for((*i) = 0; ; (*i)++) {
270      if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
271      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
272      if(infoflag & checkmask) return TRUE;
273   }
274   return FALSE;
275 }
276
277 /*********************************************/
278 /*              Get rate index               */
279 /*********************************************/
280
281 USHORT
282 SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
283                PSIS_HW_INFO HwInfo)
284 {
285   SHORT  LCDRefreshIndex[] = { 0x00, 0x00, 0x01, 0x01,
286                                0x01, 0x01, 0x01, 0x01,
287                                0x01, 0x01, 0x01, 0x01,
288                                0x01, 0x01, 0x01, 0x01,
289                                0x00, 0x00, 0x00, 0x00 };
290   USHORT RRTI,i,backup_i;
291   USHORT modeflag,index,temp,backupindex;
292
293   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
294   if(ModeNo == 0xfe) return 0;
295
296   if(ModeNo <= 0x13) {
297      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
298   } else {
299      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
300   }
301
302   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
303      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
304         if(modeflag & HalfDCLK) return 0;
305      }
306   }
307
308   if(ModeNo < 0x14) return 0xFFFF;
309
310   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
311   backupindex = index;
312
313   if(index > 0) index--;
314
315   if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
316      if(SiS_Pr->SiS_VBType & VB_SISVB) {
317         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
318            if(SiS_Pr->SiS_VBType & VB_NoLCD)            index = 0;
319            else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
320         }
321         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
322            if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
323               temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
324               if(index > temp) index = temp;
325            }
326         }
327      } else {
328         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
329         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
330            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
331         }
332      }
333   }
334
335   RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
336   ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
337
338   if(HwInfo->jChipType >= SIS_315H) {
339      if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
340         if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
341             (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
342            if(backupindex <= 1) RRTI++;
343         }
344      }
345   }
346
347   i = 0;
348   do {
349      if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
350      temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
351      temp &= ModeTypeMask;
352      if(temp < SiS_Pr->SiS_ModeType) break;
353      i++;
354      index--;
355   } while(index != 0xFFFF);
356
357   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
358      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
359         temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
360         if(temp & InterlaceMode) i++;
361      }
362   }
363
364   i--;
365
366   if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
367      backup_i = i;
368      if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i, HwInfo))) {
369         i = backup_i;
370      }
371   }
372
373   return(RRTI + i);
374 }
375
376 /*********************************************/
377 /*            STORE CRT2 INFO in CR34        */
378 /*********************************************/
379
380 static void
381 SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo)
382 {
383   USHORT temp1,temp2;
384
385   /* Store CRT1 ModeNo in CR34 */
386   SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
387   temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
388   temp2 = ~(SetInSlaveMode >> 8);
389   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
390 }
391
392 /*********************************************/
393 /*    HELPER: GET SOME DATA FROM BIOS ROM    */
394 /*********************************************/
395
396 #ifdef SIS300
397 static BOOLEAN
398 SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
399 {
400   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
401   USHORT temp,temp1;
402
403   if(SiS_Pr->SiS_UseROM) {
404      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
405         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
406         temp1 = SISGETROMW(0x23b);
407         if(temp1 & temp) return TRUE;
408      }
409   }
410   return FALSE;
411 }
412
413 static BOOLEAN
414 SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
415 {
416   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
417   USHORT temp,temp1;
418
419   if(SiS_Pr->SiS_UseROM) {
420      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
421         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
422         temp1 = SISGETROMW(0x23d);
423         if(temp1 & temp) return TRUE;
424      }
425   }
426   return FALSE;
427 }
428 #endif
429
430 /*********************************************/
431 /*          HELPER: DELAY FUNCTIONS          */
432 /*********************************************/
433
434 void
435 SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime)
436 {
437   USHORT i, j;
438
439   for(i=0; i<delaytime; i++) {
440      j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
441   }
442 }
443
444 #if defined(SIS300) || defined(SIS315H)
445 static void
446 SiS_GenericDelay(SiS_Private *SiS_Pr, USHORT delay)
447 {
448   USHORT temp,flag;
449
450   flag = SiS_GetRegByte(0x61) & 0x10;
451
452   while(delay) {
453      temp = SiS_GetRegByte(0x61) & 0x10;
454      if(temp == flag) continue;
455      flag = temp;
456      delay--;
457   }
458 }
459 #endif
460
461 #ifdef SIS315H
462 static void
463 SiS_LongDelay(SiS_Private *SiS_Pr, USHORT delay)
464 {
465   while(delay--) {
466      SiS_GenericDelay(SiS_Pr,0x19df);
467   }
468 }
469 #endif
470
471 #if defined(SIS300) || defined(SIS315H)
472 static void
473 SiS_ShortDelay(SiS_Private *SiS_Pr, USHORT delay)
474 {
475   while(delay--) {
476      SiS_GenericDelay(SiS_Pr,0x42);
477   }
478 }
479 #endif
480
481 static void
482 SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
483 {
484 #if defined(SIS300) || defined(SIS315H)
485   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
486   USHORT PanelID, DelayIndex, Delay=0;
487 #endif
488
489   if(HwInfo->jChipType < SIS_315H) {
490
491 #ifdef SIS300
492
493       PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
494       if(SiS_Pr->SiS_VBType & VB_SISVB) {
495          if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
496          if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
497       }
498       DelayIndex = PanelID >> 4;
499       if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
500          Delay = 3;
501       } else {
502          if(DelayTime >= 2) DelayTime -= 2;
503          if(!(DelayTime & 0x01)) {
504             Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
505          } else {
506             Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
507          }
508          if(SiS_Pr->SiS_UseROM) {
509             if(ROMAddr[0x220] & 0x40) {
510                if(!(DelayTime & 0x01)) Delay = (USHORT)ROMAddr[0x225];
511                else                    Delay = (USHORT)ROMAddr[0x226];
512             }
513          }
514       }
515       SiS_ShortDelay(SiS_Pr, Delay);
516
517 #endif  /* SIS300 */
518
519    } else {
520
521 #ifdef SIS315H
522
523       if((HwInfo->jChipType >= SIS_661)    ||
524          (HwInfo->jChipType <= SIS_315PRO) ||
525          (HwInfo->jChipType == SIS_330)    ||
526          (SiS_Pr->SiS_ROMNew)) {
527
528          if(!(DelayTime & 0x01)) {
529             SiS_DDC2Delay(SiS_Pr, 0x1000);
530          } else {
531             SiS_DDC2Delay(SiS_Pr, 0x4000);
532          }
533
534       } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
535          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
536          (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) {                  /* 315 series, LVDS; Special */
537
538          if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
539             PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
540             if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
541                if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
542             }
543             if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
544                DelayIndex = PanelID & 0x0f;
545             } else {
546                DelayIndex = PanelID >> 4;
547             }
548             if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
549                Delay = 3;
550             } else {
551                if(DelayTime >= 2) DelayTime -= 2;
552                if(!(DelayTime & 0x01)) {
553                   Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
554                } else {
555                   Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
556                }
557                if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
558                   if(ROMAddr[0x13c] & 0x40) {
559                      if(!(DelayTime & 0x01)) {
560                         Delay = (USHORT)ROMAddr[0x17e];
561                      } else {
562                         Delay = (USHORT)ROMAddr[0x17f];
563                      }
564                   }
565                }
566             }
567             SiS_ShortDelay(SiS_Pr, Delay);
568          }
569
570       } else if(SiS_Pr->SiS_VBType & VB_SISVB) {                        /* 315 series, all bridges */
571
572          DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
573          if(!(DelayTime & 0x01)) {
574             Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
575          } else {
576             Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
577          }
578          Delay <<= 8;
579          SiS_DDC2Delay(SiS_Pr, Delay);
580
581       }
582
583 #endif /* SIS315H */
584
585    }
586 }
587
588 #ifdef SIS315H
589 static void
590 SiS_PanelDelayLoop(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
591                       USHORT DelayTime, USHORT DelayLoop)
592 {
593    int i;
594    for(i=0; i<DelayLoop; i++) {
595       SiS_PanelDelay(SiS_Pr, HwInfo, DelayTime);
596    }
597 }
598 #endif
599
600 /*********************************************/
601 /*    HELPER: WAIT-FOR-RETRACE FUNCTIONS     */
602 /*********************************************/
603
604 void
605 SiS_WaitRetrace1(SiS_Private *SiS_Pr)
606 {
607   USHORT watchdog;
608
609   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
610   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
611
612   watchdog = 65535;
613   while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
614   watchdog = 65535;
615   while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
616 }
617
618 #if defined(SIS300) || defined(SIS315H)
619 static void
620 SiS_WaitRetrace2(SiS_Private *SiS_Pr, USHORT reg)
621 {
622   USHORT watchdog;
623
624   watchdog = 65535;
625   while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
626   watchdog = 65535;
627   while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
628 }
629 #endif
630
631 static void
632 SiS_WaitVBRetrace(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
633 {
634   if(HwInfo->jChipType < SIS_315H) {
635 #ifdef SIS300
636      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
637         if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
638      }
639      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
640         SiS_WaitRetrace1(SiS_Pr);
641      } else {
642         SiS_WaitRetrace2(SiS_Pr, 0x25);
643      }
644 #endif
645   } else {
646 #ifdef SIS315H
647      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
648         SiS_WaitRetrace1(SiS_Pr);
649      } else {
650         SiS_WaitRetrace2(SiS_Pr, 0x30);
651      }
652 #endif
653   }
654 }
655
656 static void
657 SiS_VBWait(SiS_Private *SiS_Pr)
658 {
659   USHORT tempal,temp,i,j;
660
661   temp = 0;
662   for(i=0; i<3; i++) {
663     for(j=0; j<100; j++) {
664        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
665        if(temp & 0x01) {
666           if((tempal & 0x08))  continue;
667           else break;
668        } else {
669           if(!(tempal & 0x08)) continue;
670           else break;
671        }
672     }
673     temp ^= 0x01;
674   }
675 }
676
677 static void
678 SiS_VBLongWait(SiS_Private *SiS_Pr)
679 {
680   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
681      SiS_VBWait(SiS_Pr);
682   } else {
683      SiS_WaitRetrace1(SiS_Pr);
684   }
685 }
686
687 /*********************************************/
688 /*               HELPER: MISC                */
689 /*********************************************/
690
691 #ifdef SIS300
692 static BOOLEAN
693 SiS_Is301B(SiS_Private *SiS_Pr)
694 {
695   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
696   return FALSE;
697 }
698 #endif
699
700 static BOOLEAN
701 SiS_CRT2IsLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
702 {
703   USHORT flag;
704
705   if(HwInfo->jChipType == SIS_730) {
706      flag = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13);
707      if(flag & 0x20) return TRUE;
708   }
709   flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
710   if(flag & 0x20) return TRUE;
711   return FALSE;
712 }
713
714 BOOLEAN
715 SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
716 {
717 #ifdef SIS315H
718   USHORT flag;
719
720   if(HwInfo->jChipType >= SIS_315H) {
721      if((HwInfo->jChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
722         flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
723         if(flag & EnableDualEdge) return TRUE;
724      }
725   }
726 #endif
727   return FALSE;
728 }
729
730 BOOLEAN
731 SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
732 {
733 #ifdef SIS315H
734   USHORT flag;
735
736   if(HwInfo->jChipType >= SIS_315H) {
737      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
738      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
739   }
740 #endif
741   return FALSE;
742 }
743
744 #ifdef SIS315H
745 static BOOLEAN
746 SiS_IsVAorLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
747 {
748   if(SiS_IsVAMode(SiS_Pr,HwInfo))   return TRUE;
749   if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) return TRUE;
750   return FALSE;
751 }
752 #endif
753
754 static BOOLEAN
755 SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
756 {
757 #ifdef SIS315H
758   if(HwInfo->jChipType >= SIS_315H) {
759      if((SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ||
760         (SiS_IsVAMode(SiS_Pr, HwInfo))) {
761         if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
762      }
763   }
764 #endif
765   return FALSE;
766 }
767
768 #ifdef SIS315H
769 static BOOLEAN
770 SiS_TVEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
771 {
772   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
773   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV302LV)) {
774      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
775   }
776   return FALSE;
777 }
778 #endif
779
780 #ifdef SIS315H
781 static BOOLEAN
782 SiS_LCDAEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
783 {
784   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
785   return FALSE;
786 }
787 #endif
788
789 #ifdef SIS315H
790 static BOOLEAN
791 SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
792 {
793   if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
794      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
795   }
796   return FALSE;
797 }
798 #endif
799
800 #ifdef SIS315H
801 static BOOLEAN
802 SiS_IsNotM650orLater(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
803 {
804   USHORT flag;
805
806   if(HwInfo->jChipType == SIS_650) {
807      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f);
808      flag &= 0xF0;
809      /* Check for revision != A0 only */
810      if((flag == 0xe0) || (flag == 0xc0) ||
811         (flag == 0xb0) || (flag == 0x90)) return FALSE;
812   } else if(HwInfo->jChipType >= SIS_661) return FALSE;
813   return TRUE;
814 }
815 #endif
816
817 #ifdef SIS315H
818 static BOOLEAN
819 SiS_IsYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
820 {
821   USHORT flag;
822
823   if(HwInfo->jChipType >= SIS_315H) {
824      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
825      if(flag & EnableCHYPbPr) return TRUE;  /* = YPrPb = 0x08 */
826   }
827   return FALSE;
828 }
829 #endif
830
831 #ifdef SIS315H
832 static BOOLEAN
833 SiS_IsChScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
834 {
835   USHORT flag;
836
837   if(HwInfo->jChipType >= SIS_315H) {
838      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
839      if(flag & EnableCHScart) return TRUE;  /* = Scart = 0x04 */
840   }
841   return FALSE;
842 }
843 #endif
844
845 #ifdef SIS315H
846 static BOOLEAN
847 SiS_IsTVOrYPbPrOrScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
848 {
849   USHORT flag;
850
851   if(HwInfo->jChipType >= SIS_315H) {
852      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
853      if(flag & SetCRT2ToTV)        return TRUE;
854      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
855      if(flag & EnableCHYPbPr)      return TRUE;  /* = YPrPb = 0x08 */
856      if(flag & EnableCHScart)      return TRUE;  /* = Scart = 0x04 - TW */
857   } else {
858      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
859      if(flag & SetCRT2ToTV)        return TRUE;
860   }
861   return FALSE;
862 }
863 #endif
864
865 #ifdef SIS315H
866 static BOOLEAN
867 SiS_IsLCDOrLCDA(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
868 {
869   USHORT flag;
870
871   if(HwInfo->jChipType >= SIS_315H) {
872      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
873      if(flag & SetCRT2ToLCD) return TRUE;
874      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
875      if(flag & SetToLCDA)    return TRUE;
876   } else {
877      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
878      if(flag & SetCRT2ToLCD) return TRUE;
879   }
880   return FALSE;
881 }
882 #endif
883
884 static BOOLEAN
885 SiS_BridgeIsOn(SiS_Private *SiS_Pr)
886 {
887   USHORT flag;
888
889   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
890      return TRUE;
891   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
892      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
893      if((flag == 1) || (flag == 2)) return TRUE;
894   }
895   return FALSE;
896 }
897
898 static BOOLEAN
899 SiS_BridgeIsEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
900 {
901   USHORT flag;
902
903   if(SiS_BridgeIsOn(SiS_Pr)) {
904      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
905      if(HwInfo->jChipType < SIS_315H) {
906        flag &= 0xa0;
907        if((flag == 0x80) || (flag == 0x20)) return TRUE;
908      } else {
909        flag &= 0x50;
910        if((flag == 0x40) || (flag == 0x10)) return TRUE;
911      }
912   }
913   return FALSE;
914 }
915
916 static BOOLEAN
917 SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
918 {
919   USHORT flag1;
920
921   flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
922   if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
923   return FALSE;
924 }
925
926 /*********************************************/
927 /*       GET VIDEO BRIDGE CONFIG INFO        */
928 /*********************************************/
929
930 /* Setup general purpose IO for Chrontel communication */
931 void
932 SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo)
933 {
934    unsigned long  acpibase;
935    unsigned short temp;
936
937    if(!(SiS_Pr->SiS_ChSW)) return;
938
939 #ifdef LINUX_KERNEL
940    SiS_SetRegLong(0xcf8,0x80000874);                   /* get ACPI base */
941    acpibase = SiS_GetRegLong(0xcfc);
942 #else
943    acpibase = pciReadLong(0x00000800, 0x74);
944 #endif
945    acpibase &= 0xFFFF;
946    temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c));  /* ACPI register 0x3c: GP Event 1 I/O mode select */
947    temp &= 0xFEFF;
948    SiS_SetRegShort((USHORT)(acpibase + 0x3c), temp);
949    temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c));
950    temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a));  /* ACPI register 0x3a: GP Pin Level (low/high) */
951    temp &= 0xFEFF;
952    if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
953    SiS_SetRegShort((USHORT)(acpibase + 0x3a), temp);
954    temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a));
955 }
956
957 void
958 SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
959               PSIS_HW_INFO HwInfo, int checkcrt2mode)
960 {
961   USHORT tempax,tempbx,temp;
962   USHORT modeflag, resinfo=0;
963
964   if(ModeNo <= 0x13) {
965      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
966   } else if(SiS_Pr->UseCustomMode) {
967      modeflag = SiS_Pr->CModeFlag;
968   } else {
969      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
970      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
971   }
972
973   SiS_Pr->SiS_SetFlag = 0;
974
975   SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
976
977   tempbx = 0;
978   if(SiS_BridgeIsOn(SiS_Pr)) {
979         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
980 #if 0
981         if(HwInfo->jChipType < SIS_661) {
982            /* NO - YPbPr not set yet ! */
983            if(SiS_Pr->SiS_YPbPr & <all ypbpr except 525i>) {
984               temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode);       /* 0x83 */
985               temp |= SetCRT2ToHiVision;                                        /* 0x80 */
986            }
987            if(SiS_Pr->SiS_YPbPr & <ypbpr525i>) {
988               temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode);       /* 0x83 */
989               temp |= SetCRT2ToSVIDEO;                                          /* 0x08 */
990            }
991         }
992 #endif
993         tempbx |= temp;
994         tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
995         tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
996         tempbx |= tempax;
997
998 #ifdef SIS315H
999         if(HwInfo->jChipType >= SIS_315H) {
1000            if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
1001               if(ModeNo == 0x03) {
1002                  /* Mode 0x03 is never in driver mode */
1003                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
1004               }
1005               if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
1006                  /* Reset LCDA setting if not driver mode */
1007                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
1008               }
1009               if(IS_SIS650) {
1010                  if(SiS_Pr->SiS_UseLCDA) {
1011                     if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
1012                        if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
1013                           SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
1014                        }
1015                     }
1016                  }
1017               }
1018               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1019               if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
1020                  tempbx |= SetCRT2ToLCDA;
1021               }
1022            }
1023
1024            if(SiS_Pr->SiS_VBType & (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
1025               tempbx &= ~(SetCRT2ToRAMDAC);
1026            }
1027
1028            if(HwInfo->jChipType >= SIS_661) {
1029               tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
1030               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1031               if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
1032                  if(temp & 0x04) {
1033                     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
1034                     if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
1035                     else             tempbx |= SetCRT2ToYPbPr525750;
1036                  }
1037               } else if(SiS_Pr->SiS_VBType & VB_SISHIVISION) {
1038                  if(temp & 0x04) {
1039                     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
1040                     if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
1041                  }
1042               }
1043            }
1044
1045            if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1046               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1047               if(temp & SetToLCDA) {
1048                  tempbx |= SetCRT2ToLCDA;
1049               }
1050               if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1051                  if(temp & EnableCHYPbPr) {
1052                     tempbx |= SetCRT2ToCHYPbPr;
1053                  }
1054               }
1055            }
1056         }
1057
1058 #endif  /* SIS315H */
1059
1060         if(SiS_Pr->SiS_VBType & VB_SISVB) {
1061            temp = SetCRT2ToSVIDEO   |
1062                   SetCRT2ToAVIDEO   |
1063                   SetCRT2ToSCART    |
1064                   SetCRT2ToLCDA     |
1065                   SetCRT2ToLCD      |
1066                   SetCRT2ToRAMDAC   |
1067                   SetCRT2ToHiVision |
1068                   SetCRT2ToYPbPr525750;
1069         } else {
1070            if(HwInfo->jChipType >= SIS_315H) {
1071               if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1072                  temp = SetCRT2ToAVIDEO |
1073                         SetCRT2ToSVIDEO |
1074                         SetCRT2ToSCART  |
1075                         SetCRT2ToLCDA   |
1076                         SetCRT2ToLCD    |
1077                         SetCRT2ToCHYPbPr;
1078               } else {
1079                  temp = SetCRT2ToLCDA   |
1080                         SetCRT2ToLCD;
1081               }
1082            } else {
1083               if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1084                  temp = SetCRT2ToTV | SetCRT2ToLCD;
1085               } else {
1086                  temp = SetCRT2ToLCD;
1087               }
1088            }
1089         }
1090
1091         if(!(tempbx & temp)) {
1092            tempax = DisableCRT2Display;
1093            tempbx = 0;
1094         }
1095
1096         if(SiS_Pr->SiS_VBType & VB_SISVB) {
1097            USHORT clearmask = ( DriverMode         |
1098                                 DisableCRT2Display |
1099                                 LoadDACFlag        |
1100                                 SetNotSimuMode     |
1101                                 SetInSlaveMode     |
1102                                 SetPALTV           |
1103                                 SwitchCRT2         |
1104                                 SetSimuScanMode );
1105            if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
1106            if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
1107            if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
1108            if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
1109            if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
1110            if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
1111         } else {
1112            if(HwInfo->jChipType >= SIS_315H) {
1113               if(tempbx & SetCRT2ToLCDA) {
1114                  tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
1115               }
1116            }
1117            if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1118               if(tempbx & SetCRT2ToTV) {
1119                  tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
1120               }
1121            }
1122            if(tempbx & SetCRT2ToLCD) {
1123               tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
1124            }
1125            if(HwInfo->jChipType >= SIS_315H) {
1126               if(tempbx & SetCRT2ToLCDA) {
1127                  tempbx |= SetCRT2ToLCD;
1128               }
1129            }
1130         }
1131
1132         if(tempax & DisableCRT2Display) {
1133            if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
1134               tempbx = SetSimuScanMode | DisableCRT2Display;
1135            }
1136         }
1137
1138         if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
1139
1140         /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
1141         if(SiS_Pr->SiS_ModeType <= ModeVGA) {
1142            if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
1143                ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
1144                modeflag &= (~CRT2Mode);
1145            }
1146         }
1147
1148         if(!(tempbx & SetSimuScanMode)) {
1149            if(tempbx & SwitchCRT2) {
1150               if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1151                  if( (HwInfo->jChipType >= SIS_315H) &&
1152                      (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
1153                     if(resinfo != SIS_RI_1600x1200) {
1154                        tempbx |= SetSimuScanMode;
1155                     }
1156                  } else {
1157                     tempbx |= SetSimuScanMode;
1158                  }
1159               }
1160            } else {
1161               if(SiS_BridgeIsEnabled(SiS_Pr,HwInfo)) {
1162                  if(!(tempbx & DriverMode)) {
1163                     if(SiS_BridgeInSlavemode(SiS_Pr)) {
1164                        tempbx |= SetSimuScanMode;
1165                     }
1166                  }
1167               }
1168            }
1169         }
1170
1171         if(!(tempbx & DisableCRT2Display)) {
1172            if(tempbx & DriverMode) {
1173               if(tempbx & SetSimuScanMode) {
1174                  if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
1175                     if( (HwInfo->jChipType >= SIS_315H) &&
1176                         (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
1177                        if(resinfo != SIS_RI_1600x1200) {
1178                           tempbx |= SetInSlaveMode;
1179                        }
1180                     } else {
1181                        tempbx |= SetInSlaveMode;
1182                     }
1183                  }
1184               }
1185            } else {
1186               tempbx |= SetInSlaveMode;
1187            }
1188         }
1189
1190   }
1191
1192   SiS_Pr->SiS_VBInfo = tempbx;
1193
1194   if(HwInfo->jChipType == SIS_630) {
1195      SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
1196   }
1197
1198 #ifdef TWDEBUG
1199 #ifdef LINUX_KERNEL
1200   printk(KERN_DEBUG "sisfb: (VBInfo= 0x%04x, SetFlag=0x%04x)\n",
1201       SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1202 #endif
1203 #ifdef LINUX_XF86
1204   xf86DrvMsgVerb(0, X_PROBED, 3, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
1205       SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
1206 #endif
1207 #endif
1208 }
1209
1210 /*********************************************/
1211 /*           DETERMINE YPbPr MODE            */
1212 /*********************************************/
1213
1214 void
1215 SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
1216 {
1217
1218   UCHAR temp;
1219
1220   /* Note: This variable is only used on 30xLV systems.
1221    * CR38 has a different meaning on LVDS/CH7019 systems.
1222    * On 661 and later, these bits moved to CR35.
1223    *
1224    * On 301, 301B, only HiVision 1080i is supported.
1225    * On 30xLV, 301C, only YPbPr 1080i is supported.
1226    */
1227
1228   SiS_Pr->SiS_YPbPr = 0;
1229   if(HwInfo->jChipType >= SIS_661) return;
1230
1231   if(SiS_Pr->SiS_VBType) {
1232      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1233         SiS_Pr->SiS_YPbPr = YPbPrHiVision;
1234      }
1235   }
1236
1237   if(HwInfo->jChipType >= SIS_315H) {
1238      if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_SIS301C)) {
1239         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1240         if(temp & 0x08) {
1241            switch((temp >> 4)) {
1242            case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
1243            case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
1244            case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
1245            case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
1246            }
1247         }
1248      }
1249   }
1250
1251 }
1252
1253 /*********************************************/
1254 /*           DETERMINE TVMode flag           */
1255 /*********************************************/
1256
1257 void
1258 SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo)
1259 {
1260   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
1261   USHORT temp, temp1, resinfo = 0, romindex = 0;
1262   UCHAR  OutputSelect = *SiS_Pr->pSiS_OutputSelect;
1263
1264   SiS_Pr->SiS_TVMode = 0;
1265
1266   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
1267   if(SiS_Pr->UseCustomMode) return;
1268
1269   if(ModeNo > 0x13) {
1270      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1271   }
1272
1273   if(HwInfo->jChipType < SIS_661) {
1274
1275      if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
1276
1277      if(SiS_Pr->SiS_VBType & VB_SISVB) {
1278         temp = 0;
1279         if((HwInfo->jChipType == SIS_630) ||
1280            (HwInfo->jChipType == SIS_730)) {
1281            temp = 0x35;
1282            romindex = 0xfe;
1283         } else if(HwInfo->jChipType >= SIS_315H) {
1284            temp = 0x38;
1285            romindex = 0xf3;
1286            if(HwInfo->jChipType >= SIS_330) romindex = 0x11b;
1287         }
1288         if(temp) {
1289            if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
1290               OutputSelect = ROMAddr[romindex];
1291               if(!(OutputSelect & EnablePALMN)) {
1292                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
1293               }
1294            }
1295            temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
1296            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1297               if(temp1 & EnablePALM) {          /* 0x40 */
1298                  SiS_Pr->SiS_TVMode |= TVSetPALM;
1299                  SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1300               } else if(temp1 & EnablePALN) {   /* 0x80 */
1301                  SiS_Pr->SiS_TVMode |= TVSetPALN;
1302               }
1303            } else {
1304               if(temp1 & EnableNTSCJ) {         /* 0x40 */
1305                  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1306               }
1307            }
1308         }
1309         /* Translate HiVision/YPbPr to our new flags */
1310         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1311            if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1312            else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1313            else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
1314            else                                        SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1315            if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
1316               SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
1317               SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
1318            } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
1319               SiS_Pr->SiS_TVMode |= TVSetPAL;
1320            }
1321         }
1322      } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1323         if(SiS_Pr->SiS_CHOverScan) {
1324            if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
1325               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1326               if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
1327                  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1328               }
1329            } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1330               temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
1331               if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
1332                  SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1333               }
1334            }
1335            if(SiS_Pr->SiS_CHSOverScan) {
1336               SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1337            }
1338         }
1339         if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1340            temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
1341            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
1342               if(temp & EnablePALM)      SiS_Pr->SiS_TVMode |= TVSetPALM;
1343               else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
1344            } else {
1345               if(temp & EnableNTSCJ) {
1346                  SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1347               }
1348            }
1349         }
1350      }
1351
1352   } else {  /* 661 and later */
1353
1354      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1355      if(temp1 & 0x01) {
1356         SiS_Pr->SiS_TVMode |= TVSetPAL;
1357         if(temp1 & 0x08) {
1358            SiS_Pr->SiS_TVMode |= TVSetPALN;
1359         } else if(temp1 & 0x04) {
1360            if(SiS_Pr->SiS_VBType & VB_SISVB) {
1361               SiS_Pr->SiS_TVMode &= ~TVSetPAL;
1362            }
1363            SiS_Pr->SiS_TVMode |= TVSetPALM;
1364         }
1365      } else {
1366         if(temp1 & 0x02) {
1367            SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
1368         }
1369      }
1370      if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
1371         if(SiS_Pr->SiS_CHOverScan) {
1372            if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
1373               SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
1374            }
1375         }
1376      }
1377      if(SiS_Pr->SiS_VBType & VB_SISVB) {
1378         if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1379            temp1 &= 0xe0;
1380            if(temp1 == 0x00)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
1381            else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
1382            else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
1383         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1384            SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
1385         }
1386         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
1387            if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
1388               SiS_Pr->SiS_TVMode |= TVAspect169;
1389            } else {
1390               temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
1391               if(temp1 & 0x02) {
1392                  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
1393                     SiS_Pr->SiS_TVMode |= TVAspect169;
1394                  } else {
1395                     SiS_Pr->SiS_TVMode |= TVAspect43LB;
1396                  }
1397               } else {
1398                  SiS_Pr->SiS_TVMode |= TVAspect43;
1399               }
1400            }
1401         }
1402      }
1403   }
1404
1405   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
1406
1407   if(SiS_Pr->SiS_VBType & VB_SISVB) {
1408
1409      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
1410         SiS_Pr->SiS_TVMode |= TVSetPAL;
1411         SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
1412      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
1413         if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
1414            SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
1415         }
1416      }
1417
1418      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1419         if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
1420            SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
1421         }
1422      }
1423
1424      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
1425         /* BIOS sets TVNTSC1024 without checking 525p here. Wrong? */
1426         if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr525p | TVSetYPbPr750p))) {
1427            if(resinfo == SIS_RI_1024x768) {
1428               SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
1429            }
1430         }
1431      }
1432
1433      SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
1434      if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
1435         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
1436         SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1437      } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
1438         SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1439      } else if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
1440         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
1441            SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
1442         }
1443      }
1444
1445   }
1446
1447   SiS_Pr->SiS_VBInfo &= ~SetPALTV;
1448
1449 #ifdef TWDEBUG
1450   xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
1451 #endif
1452 }
1453
1454 /*********************************************/
1455 /*               GET LCD INFO                */
1456 /*********************************************/
1457
1458 static USHORT
1459 SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr)
1460 {
1461    USHORT temp = SiS_Pr->SiS_LCDResInfo;
1462    /* Translate my LCDResInfo to BIOS value */
1463    if(temp == Panel_1280x768_2)  temp = Panel_1280x768;
1464    if(temp == Panel_1280x800_2)  temp = Panel_1280x800;
1465    return temp;
1466 }
1467
1468 static void
1469 SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
1470 {
1471 #ifdef SIS315H
1472    UCHAR  *ROMAddr;
1473    USHORT temp;
1474
1475 #ifdef TWDEBUG
1476    xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
1477         SiS_Pr->PanelHT, SiS_Pr->PanelVT,
1478         SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1479         SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1480         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1481         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1482         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1483 #endif
1484
1485    if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
1486       if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
1487          SiS_Pr->SiS_NeedRomModeData = TRUE;
1488          SiS_Pr->PanelHT  = temp;
1489       }
1490       if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
1491          SiS_Pr->SiS_NeedRomModeData = TRUE;
1492          SiS_Pr->PanelVT  = temp;
1493       }
1494       SiS_Pr->PanelHRS = SISGETROMW(10);
1495       SiS_Pr->PanelHRE = SISGETROMW(12);
1496       SiS_Pr->PanelVRS = SISGETROMW(14);
1497       SiS_Pr->PanelVRE = SISGETROMW(16);
1498       SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1499       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
1500          SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)((UCHAR)ROMAddr[18]);
1501       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
1502          SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
1503       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
1504          SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
1505
1506 #ifdef TWDEBUG
1507       xf86DrvMsg(0, X_INFO, "Paneldata BIOS:  [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
1508         SiS_Pr->PanelHT, SiS_Pr->PanelVT,
1509         SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
1510         SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
1511         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
1512         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
1513         SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
1514 #endif
1515
1516    }
1517 #endif
1518 }
1519
1520 static void
1521 SiS_CheckScaling(SiS_Private *SiS_Pr, USHORT resinfo, const UCHAR *nonscalingmodes)
1522 {
1523     int i = 0;
1524     while(nonscalingmodes[i] != 0xff) {
1525         if(nonscalingmodes[i++] == resinfo) {
1526            if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
1527               (SiS_Pr->UsePanelScaler == -1)) {
1528               SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1529            }
1530            break;
1531         }
1532     }
1533 }
1534
1535 void
1536 SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
1537                   PSIS_HW_INFO HwInfo)
1538 {
1539 #ifdef SIS300
1540   UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
1541   const unsigned char SiS300SeriesLCDRes[] =
1542           { 0,  1,  2,  3,  7,  4,  5,  8,
1543             0,  0, 10,  0,  0,  0,  0, 15 };
1544 #endif
1545 #ifdef SIS315H
1546   UCHAR   *myptr = NULL;
1547 #endif
1548   USHORT  temp,modeflag,resinfo=0,modexres=0,modeyres=0;
1549   BOOLEAN panelcanscale = FALSE;
1550
1551   SiS_Pr->SiS_LCDResInfo  = 0;
1552   SiS_Pr->SiS_LCDTypeInfo = 0;
1553   SiS_Pr->SiS_LCDInfo     = 0;
1554   SiS_Pr->PanelHRS        = 999; /* HSync start */
1555   SiS_Pr->PanelHRE        = 999; /* HSync end */
1556   SiS_Pr->PanelVRS        = 999; /* VSync start */
1557   SiS_Pr->PanelVRE        = 999; /* VSync end */
1558   SiS_Pr->SiS_NeedRomModeData = FALSE;
1559
1560   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
1561
1562   if(ModeNo <= 0x13) {
1563      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
1564   } else if(SiS_Pr->UseCustomMode) {
1565      modeflag = SiS_Pr->CModeFlag;
1566   } else {
1567      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1568      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
1569      modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
1570      modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
1571   }
1572
1573   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
1574
1575   /* For broken BIOSes: Assume 1024x768 */
1576   if(temp == 0) temp = 0x02;
1577
1578   if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
1579      SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
1580   } else if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
1581      SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
1582   } else {
1583      SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
1584   }
1585   temp &= 0x0f;
1586 #ifdef SIS300
1587   if(HwInfo->jChipType < SIS_315H) {
1588      /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
1589      if(SiS_Pr->SiS_VBType & VB_SIS301) {
1590         if(temp < 0x0f) temp &= 0x07;
1591      }
1592      /* Translate 300 series LCDRes to 315 series for unified usage */
1593      temp = SiS300SeriesLCDRes[temp];
1594   }
1595 #endif
1596
1597   /* Translate to our internal types */
1598   if(HwInfo->jChipType == SIS_550) {
1599      if(temp == Panel310_640x480_2) temp = Panel_640x480_2;
1600      if(temp == Panel310_640x480_3) temp = Panel_640x480_3;
1601   }
1602
1603   if(SiS_Pr->SiS_VBType & VB_SISLVDS) { /* SiS LVDS */
1604      if(temp == Panel310_1280x768) {
1605         temp = Panel_1280x768_2;
1606      }
1607      if(SiS_Pr->SiS_ROMNew) {
1608         if(temp == Panel661_1280x800) {
1609            temp = Panel_1280x800_2;
1610         }
1611      }
1612   }
1613
1614   SiS_Pr->SiS_LCDResInfo = temp;
1615
1616   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1617      if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
1618         SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
1619      } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
1620         SiS_Pr->SiS_LCDResInfo = Panel_848x480;
1621      }
1622   }
1623
1624   if(SiS_Pr->SiS_VBType & VB_SISVB) {
1625      if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
1626         SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
1627   } else {
1628      if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
1629         SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
1630   }
1631
1632   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
1633   SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
1634   /* Need temp below! */
1635
1636   /* These can't scale no matter what */
1637   switch(SiS_Pr->SiS_LCDResInfo) {
1638   case Panel_1280x960:
1639       SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1640   }
1641
1642   panelcanscale = (SiS_Pr->SiS_LCDInfo & DontExpandLCD) ? TRUE : FALSE;
1643
1644   if(!SiS_Pr->UsePanelScaler)          SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
1645   else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1646
1647   /* Dual link, Pass 1:1 BIOS default, etc. */
1648 #ifdef SIS315H
1649   if(HwInfo->jChipType >= SIS_661) {
1650      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1651         if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1652      }
1653      if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
1654         if(SiS_Pr->SiS_ROMNew) {
1655            if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1656         } else if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
1657            if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1658         }
1659      }
1660   } else if(HwInfo->jChipType >= SIS_315H) {
1661      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
1662         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
1663      }
1664      if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
1665         SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
1666         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
1667         if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
1668         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
1669            if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1670         }
1671      } else if(!(SiS_Pr->SiS_ROMNew)) {
1672         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
1673            if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
1674               (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
1675               SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1676            }
1677            if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
1678               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
1679               (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
1680               (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
1681               SiS_Pr->SiS_LCDInfo |= LCDDualLink;
1682            }
1683         }
1684      }
1685   }
1686 #endif
1687
1688   /* Pass 1:1 */
1689   if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
1690      /* Always center screen on LVDS (if scaling is disabled) */
1691      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1692   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
1693      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
1694         /* Always center screen on SiS LVDS (if scaling is disabled) */
1695         SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1696      } else {
1697         /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
1698         if(panelcanscale)             SiS_Pr->SiS_LCDInfo |= LCDPass11;
1699         if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
1700      }
1701   }
1702
1703   SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1704   SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1705
1706   switch(SiS_Pr->SiS_LCDResInfo) {
1707      case Panel_320x480:    SiS_Pr->PanelXRes =  320; SiS_Pr->PanelYRes =  480;
1708                             SiS_Pr->PanelHT   =  400; SiS_Pr->PanelVT   =  525;
1709                             SiS_Pr->PanelVCLKIdx300 = VCLK28;
1710                             SiS_Pr->PanelVCLKIdx315 = VCLK28;
1711                             break;
1712      case Panel_640x480_2:
1713      case Panel_640x480_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
1714                             SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
1715                             SiS_Pr->PanelVCLKIdx300 = VCLK28;
1716                             SiS_Pr->PanelVCLKIdx315 = VCLK28;
1717                             break;
1718      case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
1719                                                       SiS_Pr->PanelVRE  =    3;
1720                             SiS_Pr->PanelVCLKIdx300 = VCLK28;
1721                             SiS_Pr->PanelVCLKIdx315 = VCLK28;
1722                             break;
1723      case Panel_800x600:    SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600;
1724                             SiS_Pr->PanelHT   = 1056; SiS_Pr->PanelVT   =  628;
1725                             SiS_Pr->PanelHRS  =   40; SiS_Pr->PanelHRE  =  128;
1726                             SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    4;
1727                             SiS_Pr->PanelVCLKIdx300 = VCLK40;
1728                             SiS_Pr->PanelVCLKIdx315 = VCLK40;
1729                             break;
1730      case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
1731                             SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
1732                             SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
1733                             SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
1734                             SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1735                             SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
1736                             break;
1737      case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
1738                             SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
1739                             SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
1740                             SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1741                             if(HwInfo->jChipType < SIS_315H) {
1742                                SiS_Pr->PanelHRS = 23;
1743                                                       SiS_Pr->PanelVRE  =    5;
1744                             }
1745                             SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1746                             SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
1747                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1748                             break;
1749      case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
1750                             SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
1751                             SiS_Pr->PanelHRS  =   24;
1752                             SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1753                             if(HwInfo->jChipType < SIS_315H) {
1754                                SiS_Pr->PanelHRS = 23;
1755                                                       SiS_Pr->PanelVRE  =    5;
1756                             }
1757                             SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
1758                             SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
1759                             break;
1760      case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
1761                             break;
1762      case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
1763                             SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
1764                             SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
1765                             SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
1766                             SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
1767                             /* Data above for TMDS (projector); get from BIOS for LVDS */
1768                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1769                             break;
1770      case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
1771                             if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1772                                SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
1773                                SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
1774                                SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
1775                             } else {
1776                                SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
1777                                SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRS  =  112;
1778                                SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1779                                SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
1780                                SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
1781                             }
1782                             break;
1783      case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
1784                             SiS_Pr->PanelHT   = 1660; SiS_Pr->PanelVT   =  806;
1785                             SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
1786                             SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1787                             SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
1788                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1789                             break;
1790      case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
1791                             SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
1792                             SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
1793                             SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
1794                             SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
1795                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1796                             break;
1797      case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
1798                             SiS_Pr->PanelHT   = 1552; SiS_Pr->PanelVT   =  812;
1799                             SiS_Pr->PanelHRS   =  48; SiS_Pr->PanelHRE  =  112;
1800                             SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
1801                             SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
1802                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1803                             break;
1804      case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
1805                             SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
1806                             SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1807                             SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
1808                             if(resinfo == SIS_RI_1280x1024) {
1809                                SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
1810                                SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
1811                             }
1812                             break;
1813      case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
1814                             SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
1815                             SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
1816                             SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
1817                             SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
1818                             SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1819                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1820                             break;
1821      case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
1822                             SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
1823                             SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112; /* HRE OK for LVDS, not for LCDA */
1824                             SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
1825                             SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
1826                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1827                             break;
1828      case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
1829                             SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
1830                             SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
1831                             SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
1832                             SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
1833                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1834                             break;
1835      case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
1836                             SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
1837                             SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
1838                             SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
1839                             SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
1840                             SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
1841                             break;
1842      case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
1843                             SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
1844                             break;
1845      case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
1846                             SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
1847                             break;
1848      case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
1849                             SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
1850                             SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
1851                             SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
1852                             if(SiS_Pr->CP_PreferredIndex != -1) {
1853                                SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
1854                                SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
1855                                SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
1856                                SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
1857                                SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
1858                                SiS_Pr->PanelHRE  = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
1859                                SiS_Pr->PanelVRS  = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
1860                                SiS_Pr->PanelVRE  = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
1861                                SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
1862                                SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
1863                                SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
1864                                SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
1865                                if(SiS_Pr->CP_PrefClock) {
1866                                   int idx;
1867                                   SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
1868                                   SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
1869                                   if(HwInfo->jChipType < SIS_315H) idx = VCLK_CUSTOM_300;
1870                                   else                             idx = VCLK_CUSTOM_315;
1871                                   SiS_Pr->SiS_VCLKData[idx].CLOCK =
1872                                      SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
1873                                   SiS_Pr->SiS_VCLKData[idx].SR2B =
1874                                      SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
1875                                   SiS_Pr->SiS_VCLKData[idx].SR2C =
1876                                      SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
1877                                }
1878                             }
1879                             break;
1880      default:               SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
1881                             SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
1882                             break;
1883   }
1884
1885   /* Special cases */
1886   if( (SiS_Pr->SiS_IF_DEF_FSTN)              ||
1887       (SiS_Pr->SiS_IF_DEF_DSTN)              ||
1888       (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1889       (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
1890       (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
1891      SiS_Pr->PanelHRS = 999;
1892      SiS_Pr->PanelHRE = 999;
1893   }
1894
1895   if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
1896       (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
1897       (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
1898      SiS_Pr->PanelVRS = 999;
1899      SiS_Pr->PanelVRE = 999;
1900   }
1901
1902   /* DontExpand overrule */
1903   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
1904
1905      if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (modeflag & NoSupportLCDScale)) {
1906         /* No scaling for this mode on any panel (LCD=CRT2)*/
1907         SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1908      }
1909
1910      switch(SiS_Pr->SiS_LCDResInfo) {
1911
1912      case Panel_Custom:
1913      case Panel_1152x864:
1914      case Panel_1280x768:       /* TMDS only */
1915         SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1916         break;
1917
1918      case Panel_800x600: {
1919         static const UCHAR nonscalingmodes[] = {
1920            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
1921         };
1922         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1923         break;
1924      }
1925      case Panel_1024x768: {
1926         static const UCHAR nonscalingmodes[] = {
1927            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1928            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1929            0xff
1930         };
1931         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1932         break;
1933      }
1934      case Panel_1280x720: {
1935         static const UCHAR nonscalingmodes[] = {
1936            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1937            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1938            0xff
1939         };
1940         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1941         if(SiS_Pr->PanelHT == 1650) {
1942            SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1943         }
1944         break;
1945      }
1946      case Panel_1280x768_2: {  /* LVDS only */
1947         static const UCHAR nonscalingmodes[] = {
1948            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1949            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1950            SIS_RI_1152x768,0xff
1951         };
1952         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1953         switch(resinfo) {
1954         case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
1955                                   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1956                                }
1957                                break;
1958         }
1959         break;
1960      }
1961      case Panel_1280x800: {     /* SiS TMDS special (Averatec 6200 series) */
1962         static const UCHAR nonscalingmodes[] = {
1963            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1964            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1965            SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
1966         };
1967         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1968         break;
1969      }
1970      case Panel_1280x800_2:  {  /* SiS LVDS */
1971         static const UCHAR nonscalingmodes[] = {
1972            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1973            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1974            SIS_RI_1152x768,0xff
1975         };
1976         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1977         switch(resinfo) {
1978         case SIS_RI_1280x720:
1979         case SIS_RI_1280x768:  if(SiS_Pr->UsePanelScaler == -1) {
1980                                   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
1981                                }
1982                                break;
1983         }
1984         break;
1985      }
1986      case Panel_1280x960: {
1987         static const UCHAR nonscalingmodes[] = {
1988            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1989            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
1990            SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
1991            0xff
1992         };
1993         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
1994         break;
1995      }
1996      case Panel_1280x1024: {
1997         static const UCHAR nonscalingmodes[] = {
1998            SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
1999            SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2000            SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2001            SIS_RI_1280x960,0xff
2002         };
2003         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2004         break;
2005      }
2006      case Panel_1400x1050: {
2007         static const UCHAR nonscalingmodes[] = {
2008              SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2009              SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2010              SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x960,
2011              0xff
2012         };
2013         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2014         switch(resinfo) {
2015         case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
2016                                   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2017                                }
2018                                break;
2019         case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
2020                                break;
2021         }
2022         break;
2023      }
2024      case Panel_1600x1200: {
2025         static const UCHAR nonscalingmodes[] = {
2026              SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2027              SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2028              SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
2029              SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
2030         };
2031         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2032         break;
2033      }
2034      case Panel_1680x1050: {
2035         static const UCHAR nonscalingmodes[] = {
2036              SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
2037              SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
2038              SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,
2039              0xff
2040         };
2041         SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
2042         break;
2043      }
2044      }
2045   }
2046
2047   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2048      if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
2049         SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
2050      }
2051   }
2052
2053 #ifdef SIS300
2054   if(HwInfo->jChipType < SIS_315H) {
2055      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2056         if(SiS_Pr->SiS_UseROM) {
2057            if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
2058               if(!(ROMAddr[0x235] & 0x02)) {
2059                  SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2060               }
2061            }
2062         }
2063      } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
2064         if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
2065            SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
2066         }
2067      }
2068   }
2069 #endif
2070
2071   /* Special cases */
2072
2073   if(modexres == SiS_Pr->PanelXRes && modeyres == SiS_Pr->PanelYRes) {
2074      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2075   }
2076
2077   if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
2078      SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2079   }
2080
2081   switch(SiS_Pr->SiS_LCDResInfo) {
2082   case Panel_640x480:
2083      SiS_Pr->SiS_LCDInfo |= LCDPass11;
2084      break;
2085   case Panel_1280x800:
2086      /* Don't pass 1:1 by default (TMDS special) */
2087      if(SiS_Pr->CenterScreen == -1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2088      break;
2089   case Panel_1280x960:
2090      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2091      break;
2092   case Panel_Custom:
2093      if((!SiS_Pr->CP_PrefClock) ||
2094         (modexres > SiS_Pr->PanelXRes) || (modeyres > SiS_Pr->PanelYRes)) {
2095         SiS_Pr->SiS_LCDInfo |= LCDPass11;
2096      }
2097      break;
2098   }
2099
2100   if(SiS_Pr->UseCustomMode) {
2101      SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
2102   }
2103
2104   /* (In)validate LCDPass11 flag */
2105   if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2106      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
2107   }
2108
2109   /* LVDS DDA */
2110   if(!((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
2111
2112      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
2113         if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
2114            if(ModeNo == 0x12) {
2115               if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
2116                  SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2117               }
2118            } else if(ModeNo > 0x13) {
2119               if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
2120                  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2121                     if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
2122                        SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2123                     }
2124                  }
2125               }
2126            }
2127         }
2128      }
2129
2130      if(modeflag & HalfDCLK) {
2131         if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
2132            SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2133         } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
2134            SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2135         } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
2136            SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2137         } else if(ModeNo > 0x13) {
2138            if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
2139               if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2140            } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
2141               if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
2142            }
2143         }
2144      }
2145
2146   }
2147
2148   /* VESA timing */
2149   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2150      if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
2151         SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2152      }
2153   } else {
2154      SiS_Pr->SiS_SetFlag |= LCDVESATiming;
2155   }
2156
2157 #ifdef LINUX_KERNEL
2158 #ifdef TWDEBUG
2159   printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
2160         SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
2161 #endif
2162 #endif
2163 #ifdef LINUX_XF86
2164   xf86DrvMsgVerb(0, X_PROBED, 4,
2165         "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
2166         SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
2167 #endif
2168 }
2169
2170 /*********************************************/
2171 /*                 GET VCLK                  */
2172 /*********************************************/
2173
2174 USHORT
2175 SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
2176                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
2177 {
2178   USHORT CRT2Index,VCLKIndex=0,VCLKIndexGEN=0;
2179   USHORT modeflag,resinfo,tempbx;
2180   const UCHAR *CHTVVCLKPtr = NULL;
2181
2182   if(ModeNo <= 0x13) {
2183      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2184      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
2185      CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2186      VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
2187   } else {
2188      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2189      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2190      CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2191      VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
2192      if(HwInfo->jChipType < SIS_315H) VCLKIndexGEN &= 0x3f;
2193   }
2194
2195   if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
2196
2197      if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2198
2199         CRT2Index >>= 6;
2200         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {       /*  LCD */
2201
2202            if(HwInfo->jChipType < SIS_315H) {
2203               VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2204               if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2205                  VCLKIndex = VCLKIndexGEN;
2206               }
2207            } else {
2208               VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2209               if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
2210                  switch(resinfo) {
2211                  /* Only those whose IndexGEN doesn't match VBVCLK array */
2212                  case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
2213                  case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
2214                  case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
2215                  case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
2216                  case SIS_RI_848x480:  VCLKIndex = VCLK_848x480;  break;
2217                  case SIS_RI_856x480:  VCLKIndex = VCLK_856x480;  break;
2218                  case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
2219                  case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
2220                  case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
2221                  case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
2222                  default:              VCLKIndex = VCLKIndexGEN;
2223                  }
2224
2225                  if(ModeNo <= 0x13) {
2226                     if(HwInfo->jChipType <= SIS_315PRO) {
2227                        if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
2228                     } else {
2229                        if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
2230                     }
2231                  }
2232                  if(HwInfo->jChipType <= SIS_315PRO) {
2233                     if(VCLKIndex == 0) VCLKIndex = 0x41;
2234                     if(VCLKIndex == 1) VCLKIndex = 0x43;
2235                     if(VCLKIndex == 4) VCLKIndex = 0x44;
2236                  }
2237               }
2238            }
2239
2240         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                   /*  TV */
2241
2242            if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
2243               if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)             VCLKIndex = HiTVVCLKDIV2;
2244               else                                              VCLKIndex = HiTVVCLK;
2245               if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
2246                  if(modeflag & Charx8Dot)                       VCLKIndex = HiTVSimuVCLK;
2247                  else                                           VCLKIndex = HiTVTextVCLK;
2248               }
2249            } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)       VCLKIndex = YPbPr750pVCLK;
2250            else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)         VCLKIndex = TVVCLKDIV2;
2251            else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)           VCLKIndex = TVVCLKDIV2;
2252            else                                                 VCLKIndex = TVVCLK;
2253
2254            if(HwInfo->jChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
2255            else                             VCLKIndex += TVCLKBASE_315;
2256
2257         } else {                                                        /* VGA2 */
2258
2259            VCLKIndex = VCLKIndexGEN;
2260            if(HwInfo->jChipType < SIS_315H) {
2261               if(ModeNo > 0x13) {
2262                  if( (HwInfo->jChipType == SIS_630) &&
2263                      (HwInfo->jChipRevision >= 0x30)) {
2264                     if(VCLKIndex == 0x14) VCLKIndex = 0x34;
2265                  }
2266                  /* Better VGA2 clock for 1280x1024@75 */
2267                  if(VCLKIndex == 0x17) VCLKIndex = 0x45;
2268               }
2269            }
2270         }
2271
2272      } else {   /* If not programming CRT2 */
2273
2274         VCLKIndex = VCLKIndexGEN;
2275         if(HwInfo->jChipType < SIS_315H) {
2276            if(ModeNo > 0x13) {
2277               if( (HwInfo->jChipType != SIS_630) &&
2278                   (HwInfo->jChipType != SIS_300) ) {
2279                  if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2280               }
2281            }
2282         }
2283      }
2284
2285   } else {       /*   LVDS  */
2286
2287      VCLKIndex = CRT2Index;
2288
2289      if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
2290
2291         if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
2292
2293            VCLKIndex &= 0x1f;
2294            tempbx = 0;
2295            if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2296            if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2297               tempbx += 2;
2298               if(SiS_Pr->SiS_ModeType > ModeVGA) {
2299                  if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
2300               }
2301               if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2302                  tempbx = 4;
2303                  if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2304               } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2305                  tempbx = 6;
2306                  if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
2307               }
2308            }
2309            switch(tempbx) {
2310              case  0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC;  break;
2311              case  1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC;  break;
2312              case  2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL;   break;
2313              case  3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
2314              case  4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM;  break;
2315              case  5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM;  break;
2316              case  6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN;  break;
2317              case  7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN;  break;
2318              case  8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL;  break;
2319              default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
2320            }
2321            VCLKIndex = CHTVVCLKPtr[VCLKIndex];
2322
2323         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2324
2325            if(HwInfo->jChipType < SIS_315H) {
2326               VCLKIndex = SiS_Pr->PanelVCLKIdx300;
2327            } else {
2328               VCLKIndex = SiS_Pr->PanelVCLKIdx315;
2329            }
2330
2331            /* Special Timing: Barco iQ Pro R series */
2332            if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
2333
2334            /* Special Timing: 848x480 parallel lvds */
2335            if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
2336               if(HwInfo->jChipType < SIS_315H) {
2337                  VCLKIndex = VCLK34_300;
2338                  /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2339               } else {
2340                  VCLKIndex = VCLK34_315;
2341                  /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
2342               }
2343            }
2344
2345         } else {
2346
2347            VCLKIndex = VCLKIndexGEN;
2348            if(HwInfo->jChipType < SIS_315H) {
2349               if(ModeNo > 0x13) {
2350                  if( (HwInfo->jChipType == SIS_630) &&
2351                      (HwInfo->jChipRevision >= 0x30) ) {
2352                     if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
2353                  }
2354               }
2355            }
2356         }
2357
2358      } else {  /* if not programming CRT2 */
2359
2360         VCLKIndex = VCLKIndexGEN;
2361         if(HwInfo->jChipType < SIS_315H) {
2362            if(ModeNo > 0x13) {
2363               if( (HwInfo->jChipType != SIS_630) &&
2364                   (HwInfo->jChipType != SIS_300) ) {
2365                  if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
2366               }
2367 #if 0
2368               if(HwInfo->jChipType == SIS_730) {
2369                  if(VCLKIndex == 0x0b) VCLKIndex = 0x40;   /* 1024x768-70 */
2370                  if(VCLKIndex == 0x0d) VCLKIndex = 0x41;   /* 1024x768-75 */
2371               }
2372 #endif
2373            }
2374         }
2375
2376      }
2377
2378   }
2379
2380 #ifdef TWDEBUG
2381   xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
2382 #endif
2383
2384   return(VCLKIndex);
2385 }
2386
2387 /*********************************************/
2388 /*        SET CRT2 MODE TYPE REGISTERS       */
2389 /*********************************************/
2390
2391 static void
2392 SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
2393                     PSIS_HW_INFO HwInfo)
2394 {
2395   USHORT i,j,modeflag;
2396   USHORT tempcl,tempah=0;
2397 #if defined(SIS300) || defined(SIS315H)
2398   USHORT tempbl;
2399 #endif
2400 #ifdef SIS315H
2401   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
2402   USHORT tempah2, tempbl2;
2403 #endif
2404
2405   if(ModeNo <= 0x13) {
2406      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2407   } else if(SiS_Pr->UseCustomMode) {
2408      modeflag = SiS_Pr->CModeFlag;
2409   } else {
2410      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2411   }
2412
2413   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2414
2415      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40);
2416      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
2417
2418   } else {
2419
2420      for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
2421      if(HwInfo->jChipType >= SIS_315H) {
2422         SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
2423      }
2424
2425      tempcl = SiS_Pr->SiS_ModeType;
2426
2427      if(HwInfo->jChipType < SIS_315H) {
2428
2429 #ifdef SIS300    /* ---- 300 series ---- */
2430
2431         /* For 301BDH: (with LCD via LVDS) */
2432         if(SiS_Pr->SiS_VBType & VB_NoLCD) {
2433            tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
2434            tempbl &= 0xef;
2435            tempbl |= 0x02;
2436            if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2437               tempbl |= 0x10;
2438               tempbl &= 0xfd;
2439            }
2440            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
2441         }
2442
2443         if(ModeNo > 0x13) {
2444            tempcl -= ModeVGA;
2445            if((tempcl > 0) || (tempcl == 0)) {      /* tempcl is USHORT -> always true! */
2446               tempah = ((0x10 >> tempcl) | 0x80);
2447            }
2448         } else tempah = 0x80;
2449
2450         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  tempah ^= 0xA0;
2451
2452 #endif  /* SIS300 */
2453
2454      } else {
2455
2456 #ifdef SIS315H    /* ------- 315/330 series ------ */
2457
2458         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
2459            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2460               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x08);
2461            }
2462         }
2463
2464         if(ModeNo > 0x13) {
2465            tempcl -= ModeVGA;
2466            if((tempcl > 0) || (tempcl == 0)) {  /* tempcl is USHORT -> always true! */
2467               tempah = (0x08 >> tempcl);
2468               if (tempah == 0) tempah = 1;
2469               tempah |= 0x40;
2470            }
2471         } else tempah = 0x40;
2472
2473         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
2474
2475 #endif  /* SIS315H */
2476
2477      }
2478
2479      if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
2480
2481      if(HwInfo->jChipType < SIS_315H) {
2482         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2483      } else {
2484         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2485            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2486         } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2487            if(IS_SIS740) {
2488               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
2489            } else {
2490               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
2491            }
2492         }
2493      }
2494
2495      if(SiS_Pr->SiS_VBType & VB_SISVB) {
2496
2497         tempah = 0x01;
2498         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2499            tempah |= 0x02;
2500         }
2501         if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
2502            tempah ^= 0x05;
2503            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
2504               tempah ^= 0x01;
2505            }
2506         }
2507
2508         if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
2509
2510         if(HwInfo->jChipType < SIS_315H) {
2511
2512            tempah = (tempah << 5) & 0xFF;
2513            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2514            tempah = (tempah >> 5) & 0xFF;
2515
2516         } else {
2517
2518            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF8,tempah);
2519
2520         }
2521
2522         if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
2523            tempah |= 0x10;
2524         }
2525
2526         tempah |= 0x80;
2527         if(SiS_Pr->SiS_VBType & VB_SIS301) {
2528            if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
2529         }
2530
2531         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2532            if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
2533               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2534                  tempah |= 0x20;
2535               }
2536            }
2537         }
2538
2539         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
2540
2541         tempah = 0x80;
2542         if(SiS_Pr->SiS_VBType & VB_SIS301) {
2543            if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
2544         }
2545
2546         if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempah |= 0x40;
2547
2548         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2549            if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
2550               tempah |= 0x40;
2551            }
2552         }
2553
2554         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
2555
2556      } else {  /* LVDS */
2557
2558         if(HwInfo->jChipType >= SIS_315H) {
2559
2560 #ifdef SIS315H
2561            /* LVDS can only be slave in 8bpp modes */
2562            tempah = 0x80;
2563            if((modeflag & CRT2Mode) && (SiS_Pr->SiS_ModeType > ModeVGA)) {
2564               if(SiS_Pr->SiS_VBInfo & DriverMode) {
2565                  tempah |= 0x02;
2566               }
2567            }
2568
2569            if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
2570               tempah |= 0x02;
2571            }
2572
2573            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
2574               tempah ^= 0x01;
2575            }
2576
2577            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2578               tempah = 1;
2579            }
2580
2581            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
2582 #endif
2583
2584         } else {
2585
2586 #ifdef SIS300
2587            tempah = 0;
2588            if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
2589               tempah |= 0x02;
2590            }
2591            tempah <<= 5;
2592
2593            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
2594
2595            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
2596 #endif
2597
2598         }
2599
2600      }
2601
2602   }  /* LCDA */
2603
2604   if(SiS_Pr->SiS_VBType & VB_SISVB) {
2605
2606      if(HwInfo->jChipType >= SIS_315H) {
2607
2608 #ifdef SIS315H
2609         unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
2610
2611         /* The following is nearly unpreditable and varies from machine
2612          * to machine. Especially the 301DH seems to be a real trouble
2613          * maker. Some BIOSes simply set the registers (like in the
2614          * NoLCD-if-statements here), some set them according to the
2615          * LCDA stuff. It is very likely that some machines are not
2616          * treated correctly in the following, very case-orientated
2617          * code. What do I do then...?
2618          */
2619
2620         /* 740 variants match for 30xB, 301B-DH, 30xLV */
2621
2622         if(!(IS_SIS740)) {
2623            tempah = 0x04;                                                  /* For all bridges */
2624            tempbl = 0xfb;
2625            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2626               tempah = 0x00;
2627               if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
2628                  tempbl = 0xff;
2629               }
2630            }
2631            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2632         }
2633
2634         /* The following two are responsible for eventually wrong colors
2635          * in TV output. The DH (VB_NoLCD) conditions are unknown; the
2636          * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
2637          * in a 650 box (Jake). What is the criteria?
2638          */
2639
2640         if((IS_SIS740) || (HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
2641            tempah = 0x30;
2642            tempbl = 0xc0;
2643            if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2644               ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
2645               tempah = 0x00;
2646               tempbl = 0x00;
2647            }
2648            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,tempah);
2649            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
2650         } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
2651            /* Fixes "TV-blue-bug" on 315+301 */
2652            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf);     /* For 301   */
2653            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
2654         } else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
2655            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);      /* For 30xLV */
2656            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
2657         } else if((SiS_Pr->SiS_VBType & VB_NoLCD) && (bridgerev == 0xb0)) {
2658            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);      /* For 30xB-DH rev b0 (or "DH on 651"?) */
2659            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
2660         } else {
2661            tempah = 0x30; tempah2 = 0xc0;                      /* For 30xB (and 301BDH rev b1) */
2662            tempbl = 0xcf; tempbl2 = 0x3f;
2663            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2664               tempah = tempah2 = 0x00;
2665               if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
2666                  tempbl = tempbl2 = 0xff;
2667               }
2668            }
2669            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
2670            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
2671         }
2672
2673         if(IS_SIS740) {
2674            tempah = 0x80;
2675            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
2676            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
2677         } else {
2678            tempah = 0x00;
2679            tempbl = 0x7f;
2680            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2681               tempbl = 0xff;
2682               if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) tempah = 0x80;
2683            }
2684            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
2685         }
2686
2687 #endif /* SIS315H */
2688
2689      } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
2690
2691 #ifdef SIS300
2692         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
2693
2694         if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
2695            ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
2696             (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
2697            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
2698         } else {
2699            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x23,0x80);
2700         }
2701 #endif
2702
2703      }
2704
2705      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
2706         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
2707         if(SiS_Pr->SiS_VBType & VB_SIS301C) {
2708            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
2709         }
2710      }
2711
2712   } else {  /* LVDS */
2713
2714 #ifdef SIS315H
2715      if(HwInfo->jChipType >= SIS_315H) {
2716
2717         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
2718
2719            tempah = 0x04;
2720            tempbl = 0xfb;
2721            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2722               tempah = 0x00;
2723               if(SiS_IsDualEdge(SiS_Pr, HwInfo)) tempbl = 0xff;
2724            }
2725            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
2726
2727            if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
2728               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2729            }
2730
2731            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2732
2733         } else if(HwInfo->jChipType == SIS_550) {
2734
2735            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
2736            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
2737
2738         }
2739
2740      }
2741 #endif
2742
2743   }
2744
2745 }
2746
2747 /*********************************************/
2748 /*            GET RESOLUTION DATA            */
2749 /*********************************************/
2750
2751 USHORT
2752 SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
2753 {
2754   if(ModeNo <= 0x13) return((USHORT)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
2755   else               return((USHORT)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
2756 }
2757
2758 static void
2759 SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
2760                    PSIS_HW_INFO HwInfo)
2761 {
2762   USHORT xres,yres,modeflag=0,resindex;
2763
2764   if(SiS_Pr->UseCustomMode) {
2765      xres = SiS_Pr->CHDisplay;
2766      if(SiS_Pr->CModeFlag & HalfDCLK) xres *= 2;
2767      SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2768      yres = SiS_Pr->CVDisplay;
2769      if(SiS_Pr->CModeFlag & DoubleScanMode) yres *= 2;
2770      SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
2771      return;
2772   }
2773
2774   resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
2775
2776   if(ModeNo <= 0x13) {
2777      xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
2778      yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
2779   } else {
2780      xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
2781      yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
2782      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2783   }
2784
2785   if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
2786
2787      if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
2788         if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
2789            if(yres == 350) yres = 400;
2790         }
2791         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
2792            if(ModeNo == 0x12) yres = 400;
2793         }
2794      }
2795
2796      if(modeflag & HalfDCLK)       xres *= 2;
2797      if(modeflag & DoubleScanMode) yres *= 2;
2798
2799   }
2800
2801   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
2802
2803 #if 0
2804         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
2805            if(xres == 720) xres = 640;
2806         }
2807 #endif
2808
2809         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
2810            switch(SiS_Pr->SiS_LCDResInfo) {
2811            case Panel_1024x768:
2812               if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
2813                  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2814                     if(yres == 350) yres = 357;
2815                     if(yres == 400) yres = 420;
2816                     if(yres == 480) yres = 525;
2817                  }
2818               }
2819               break;
2820            case Panel_1280x1024:
2821               if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2822                  /* BIOS bug - does this regardless of scaling */
2823                  if(yres == 400) yres = 405;
2824               }
2825               if(yres == 350) yres = 360;
2826               if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
2827                  if(yres == 360) yres = 375;
2828               }
2829               break;
2830            case Panel_1600x1200:
2831               if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
2832                  if(yres == 1024) yres = 1056;
2833               }
2834               break;
2835            }
2836         }
2837
2838   } else {
2839
2840      if(SiS_Pr->SiS_VBType & VB_SISVB) {
2841         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
2842            if(xres == 720) xres = 640;
2843         }
2844      } else if(xres == 720) xres = 640;
2845
2846      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
2847         yres = 400;
2848         if(HwInfo->jChipType >= SIS_315H) {
2849            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
2850         } else {
2851            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
2852         }
2853         if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN)  yres = 480;
2854      }
2855
2856   }
2857   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
2858   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
2859 }
2860
2861 /*********************************************/
2862 /*           GET CRT2 TIMING DATA            */
2863 /*********************************************/
2864
2865 static BOOLEAN
2866 SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
2867                    USHORT RefreshRateTableIndex, USHORT *ResIndex,
2868                    USHORT *DisplayType)
2869  {
2870   USHORT modeflag=0;
2871
2872   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
2873      if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2874         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
2875      }
2876   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
2877      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))    return FALSE;
2878   } else
2879      return FALSE;
2880
2881   if(ModeNo <= 0x13) {
2882      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
2883      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2884   } else {
2885      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
2886      (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2887   }
2888
2889   (*ResIndex) &= 0x3F;
2890
2891   if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
2892      (*DisplayType) = 18;
2893      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
2894      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
2895         (*DisplayType) += 2;
2896         if(SiS_Pr->SiS_ModeType > ModeVGA) {
2897            if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 99;
2898         }
2899         if(SiS_Pr->SiS_TVMode & TVSetPALM) {
2900            (*DisplayType) = 18;  /* PALM uses NTSC data */
2901            if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
2902         } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
2903            (*DisplayType) = 20;  /* PALN uses PAL data  */
2904            if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
2905         }
2906      }
2907   } else {
2908      switch(SiS_Pr->SiS_LCDResInfo) {
2909      case Panel_640x480:   (*DisplayType) = 50; break;
2910      case Panel_640x480_2: (*DisplayType) = 52; break;
2911      case Panel_640x480_3: (*DisplayType) = 54; break;
2912      case Panel_800x600:   (*DisplayType) =  0; break;
2913      case Panel_1024x600:  (*DisplayType) = 23; break;
2914      case Panel_1024x768:  (*DisplayType) =  4; break;
2915      case Panel_1152x768:  (*DisplayType) = 27; break;
2916      case Panel_1280x768:  (*DisplayType) = 40; break;
2917      case Panel_1280x1024: (*DisplayType) =  8; break;
2918      case Panel_1400x1050: (*DisplayType) = 14; break;
2919      case Panel_1600x1200: (*DisplayType) = 36; break;
2920      default: return FALSE;
2921      }
2922
2923      if(modeflag & HalfDCLK) (*DisplayType)++;
2924
2925      switch(SiS_Pr->SiS_LCDResInfo) {
2926      case Panel_640x480:
2927      case Panel_640x480_2:
2928      case Panel_640x480_3:
2929         break;
2930      default:
2931         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
2932      }
2933
2934      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
2935         (*DisplayType) = 12;
2936         if(modeflag & HalfDCLK) (*DisplayType)++;
2937      }
2938   }
2939
2940 #if 0
2941   if(SiS_Pr->SiS_IF_DEF_FSTN) {
2942      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
2943         (*DisplayType) = 22;
2944      }
2945   }
2946 #endif
2947
2948   return TRUE;
2949 }
2950
2951 static void
2952 SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
2953                USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex,
2954                PSIS_HW_INFO HwInfo)
2955 {
2956   USHORT tempbx=0,tempal=0,resinfo=0;
2957
2958   if(ModeNo <= 0x13) {
2959      tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
2960   } else {
2961      tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
2962      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
2963   }
2964
2965   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_IF_DEF_LVDS == 0)) {
2966
2967      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
2968
2969         tempbx = SiS_Pr->SiS_LCDResInfo;
2970         if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
2971
2972         if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
2973            if     (resinfo == SIS_RI_1280x800)  tempal =  9;
2974            else if(resinfo == SIS_RI_1400x1050) tempal = 11;
2975         } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
2976                   (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2)) {
2977            if     (resinfo == SIS_RI_1280x768)  tempal =  9;
2978         }
2979
2980         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
2981            /* Pass 1:1 only (center-screen handled outside) */
2982            /* This is never called for the panel's native resolution */
2983            /* since Pass1:1 will not be set in this case */
2984            tempbx = 100;
2985            if(ModeNo >= 0x13) {
2986               tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
2987            }
2988         }
2989
2990 #ifdef SIS315H
2991         if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
2992            if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
2993               if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
2994                  tempbx = 200;
2995                  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
2996               }
2997            }
2998         }
2999 #endif
3000
3001      } else {                                                   /* TV */
3002
3003         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3004            /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
3005            tempbx = 2;
3006            if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3007               tempbx = 13;
3008               if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
3009            }
3010         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3011            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      tempbx = 7;
3012            else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
3013            else                                         tempbx = 5;
3014            if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
3015         } else {
3016            if(SiS_Pr->SiS_TVMode & TVSetPAL)            tempbx = 3;
3017            else                                         tempbx = 4;
3018            if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
3019         }
3020
3021      }
3022
3023      tempal &= 0x3F;
3024
3025      if(ModeNo > 0x13) {
3026         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
3027            if(tempal == 6) tempal = 7;
3028            if((resinfo == SIS_RI_720x480) ||
3029               (resinfo == SIS_RI_720x576) ||
3030               (resinfo == SIS_RI_768x576)) {
3031               tempal = 6;
3032               if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) {
3033                  if(resinfo == SIS_RI_720x480) tempal = 9;
3034               }
3035            }
3036            if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3037               if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3038                  if(resinfo == SIS_RI_1024x768) tempal = 8;
3039               }
3040               if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3041                  if((resinfo == SIS_RI_720x576) ||
3042                     (resinfo == SIS_RI_768x576)) {
3043                     tempal = 8;
3044                  }
3045                  if(resinfo == SIS_RI_1280x720) tempal = 9;
3046               }
3047            }
3048         }
3049      }
3050
3051      *CRT2Index = tempbx;
3052      *ResIndex = tempal;
3053
3054   } else {   /* LVDS, 301B-DH (if running on LCD) */
3055
3056      tempbx = 0;
3057      if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
3058
3059         tempbx = 10;
3060         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
3061         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
3062            tempbx += 2;
3063            if(SiS_Pr->SiS_ModeType > ModeVGA) {
3064               if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
3065            }
3066            if(SiS_Pr->SiS_TVMode & TVSetPALM) {
3067               tempbx = 90;
3068               if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
3069            } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
3070               tempbx = 92;
3071               if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
3072            }
3073         }
3074
3075      } else {
3076
3077         switch(SiS_Pr->SiS_LCDResInfo) {
3078         case Panel_640x480:   tempbx = 6;  break;
3079         case Panel_640x480_2:
3080         case Panel_640x480_3: tempbx = 30; break;
3081         case Panel_800x600:   tempbx = 0;  break;
3082         case Panel_1024x600:  tempbx = 15; break;
3083         case Panel_1024x768:  tempbx = 2;  break;
3084         case Panel_1152x768:  tempbx = 17; break;
3085         case Panel_1280x768:  tempbx = 18; break;
3086         case Panel_1280x1024: tempbx = 4;  break;
3087         case Panel_1400x1050: tempbx = 8;  break;
3088         case Panel_1600x1200: tempbx = 21; break;
3089         case Panel_Barco1366: tempbx = 80; break;
3090         }
3091
3092         switch(SiS_Pr->SiS_LCDResInfo) {
3093         case Panel_640x480:
3094         case Panel_640x480_2:
3095         case Panel_640x480_3:
3096            break;
3097         default:
3098            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3099         }
3100
3101         if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 7;
3102
3103         if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
3104            tempbx = 82;
3105            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3106         } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
3107            tempbx = 84;
3108            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
3109         }
3110
3111         if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
3112            (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
3113            if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
3114               (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
3115               tempal = 0;
3116            }
3117         }
3118
3119      }
3120
3121      (*CRT2Index) = tempbx;
3122      (*ResIndex) = tempal & 0x1F;
3123   }
3124 }
3125
3126 static void
3127 SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
3128                    USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
3129 {
3130   USHORT tempax=0,tempbx=0;
3131   USHORT temp1=0,modeflag=0,tempcx=0;
3132   USHORT index;
3133
3134   SiS_Pr->SiS_RVBHCMAX  = 1;
3135   SiS_Pr->SiS_RVBHCFACT = 1;
3136
3137   if(ModeNo <= 0x13) {
3138
3139      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3140      index = SiS_GetModePtr(SiS_Pr,ModeNo,ModeIdIndex);
3141
3142      tempax = SiS_Pr->SiS_StandTable[index].CRTC[0];
3143      tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
3144      temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
3145
3146   } else {
3147
3148      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3149      index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
3150
3151      tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
3152      tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
3153      tempax &= 0x03FF;
3154      tempbx = SiS_Pr->SiS_CRT1Table[index].CR[6];
3155      tempcx = SiS_Pr->SiS_CRT1Table[index].CR[13] << 8;
3156      tempcx &= 0x0100;
3157      tempcx <<= 2;
3158      tempbx |= tempcx;
3159      temp1  = SiS_Pr->SiS_CRT1Table[index].CR[7];
3160
3161   }
3162
3163   if(temp1 & 0x01) tempbx |= 0x0100;
3164   if(temp1 & 0x20) tempbx |= 0x0200;
3165
3166   tempax += 5;
3167
3168   /* Charx8Dot is no more used (and assumed), so we set it */
3169   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
3170      modeflag |= Charx8Dot;
3171   }
3172
3173   if(modeflag & Charx8Dot) tempax *= 8;
3174   else                     tempax *= 9;
3175
3176   if(modeflag & HalfDCLK)  tempax <<= 1;
3177
3178   tempbx++;
3179
3180   SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
3181   SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
3182 }
3183
3184 static void
3185 SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
3186                     USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
3187 {
3188    USHORT CRT2Index, ResIndex;
3189    const SiS_LVDSDataStruct *LVDSData = NULL;
3190
3191    SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
3192
3193    if(SiS_Pr->SiS_VBType & VB_SISVB) {
3194       SiS_Pr->SiS_RVBHCMAX  = 1;
3195       SiS_Pr->SiS_RVBHCFACT = 1;
3196       SiS_Pr->SiS_NewFlickerMode = 0;
3197       SiS_Pr->SiS_RVBHRS = 50;
3198       SiS_Pr->SiS_RY1COE = 0;
3199       SiS_Pr->SiS_RY2COE = 0;
3200       SiS_Pr->SiS_RY3COE = 0;
3201       SiS_Pr->SiS_RY4COE = 0;
3202    }
3203
3204    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3205
3206 #ifdef SIS315H
3207       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3208          if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3209             if(SiS_Pr->UseCustomMode) {
3210                SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
3211                SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
3212             } else {
3213                if(ModeNo < 0x13) {
3214                   ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3215                } else {
3216                   ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
3217                }
3218                SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
3219                SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
3220                SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
3221                SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
3222             }
3223          } else {
3224             SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
3225             SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
3226          }
3227       } else {
3228          /* This handles custom modes and custom panels */
3229          SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3230          SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3231          SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
3232          SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
3233          SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
3234          SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
3235       }
3236
3237       SiS_CalcLCDACRT1Timing(SiS_Pr,ModeNo,ModeIdIndex);
3238
3239 #endif
3240
3241    } else {
3242
3243       /* 301BDH needs LVDS Data */
3244       if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3245          SiS_Pr->SiS_IF_DEF_LVDS = 1;
3246       }
3247
3248       SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
3249                                 &CRT2Index, &ResIndex, HwInfo);
3250
3251       /* 301BDH needs LVDS Data */
3252       if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3253          SiS_Pr->SiS_IF_DEF_LVDS = 0;
3254       }
3255
3256       switch (CRT2Index) {
3257          case  0: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
3258          case  1: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2;    break;
3259          case  2: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
3260          case  3: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2;   break;
3261          case  4: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1;  break;
3262          case  5: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2;  break;
3263          case  6: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
3264          case  7: LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1;    break;
3265          case  8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1;  break;
3266          case  9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2;  break;
3267          case 10: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
3268          case 11: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
3269          case 12: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
3270          case 13: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
3271          case 14: LVDSData = SiS_Pr->SiS_LVDS320x480Data_1;    break;
3272          case 15: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
3273          case 16: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2;   break;
3274          case 17: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1;   break;
3275          case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2;   break;
3276          case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1;   break;
3277          case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2;   break;
3278          case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1;  break;
3279          case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2;  break;
3280          case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2;    break;
3281          case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
3282          case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
3283          case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
3284          case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2;  break;
3285          case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
3286          case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
3287          case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
3288          case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
3289          case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
3290          case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
3291          case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;        break;  /* Super Overscan */
3292          default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
3293       }
3294
3295       SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
3296       SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
3297       SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
3298       SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
3299
3300       if(!(SiS_Pr->SiS_VBType & VB_SISVB)) {
3301          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
3302             if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3303                SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
3304                SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
3305                if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
3306                   if(ResIndex < 0x08) {
3307                      SiS_Pr->SiS_HDE = 1280;
3308                      SiS_Pr->SiS_VDE = 1024;
3309                   }
3310                }
3311             }
3312          }
3313       }
3314    }
3315 }
3316
3317 static void
3318 SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
3319                    USHORT RefreshRateTableIndex,
3320                    PSIS_HW_INFO HwInfo)
3321 {
3322   UCHAR  *ROMAddr = NULL;
3323   USHORT tempax,tempbx,modeflag,romptr=0;
3324   USHORT resinfo,CRT2Index,ResIndex;
3325   const SiS_LCDDataStruct *LCDPtr = NULL;
3326   const SiS_TVDataStruct  *TVPtr  = NULL;
3327 #ifdef SIS315H
3328   SHORT  resinfo661;
3329 #endif
3330
3331   if(ModeNo <= 0x13) {
3332      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3333      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
3334   } else if(SiS_Pr->UseCustomMode) {
3335      modeflag = SiS_Pr->CModeFlag;
3336      resinfo = 0;
3337   } else {
3338      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3339      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
3340 #ifdef SIS315H
3341      resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
3342      if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
3343          (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
3344          (resinfo661 >= 0)                     &&
3345          (SiS_Pr->SiS_NeedRomModeData) ) {
3346         if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
3347            if((romptr = (SISGETROMW(21)))) {
3348               romptr += (resinfo661 * 10);
3349               ROMAddr = HwInfo->pjVirtualRomBase;
3350            }
3351         }
3352      }
3353 #endif
3354   }
3355   
3356   SiS_Pr->SiS_NewFlickerMode = 0;
3357   SiS_Pr->SiS_RVBHRS = 50;
3358   SiS_Pr->SiS_RY1COE = 0;
3359   SiS_Pr->SiS_RY2COE = 0;
3360   SiS_Pr->SiS_RY3COE = 0;
3361   SiS_Pr->SiS_RY4COE = 0;
3362
3363   SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex,HwInfo);
3364
3365   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){
3366
3367      if(SiS_Pr->UseCustomMode) {
3368
3369         SiS_Pr->SiS_RVBHCMAX  = 1;
3370         SiS_Pr->SiS_RVBHCFACT = 1;
3371         SiS_Pr->SiS_VGAHT     = SiS_Pr->CHTotal;
3372         SiS_Pr->SiS_VGAVT     = SiS_Pr->CVTotal;
3373         SiS_Pr->SiS_HT        = SiS_Pr->CHTotal;
3374         SiS_Pr->SiS_VT        = SiS_Pr->CVTotal;
3375         SiS_Pr->SiS_HDE       = SiS_Pr->SiS_VGAHDE;
3376         SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
3377
3378      } else {
3379
3380         SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3381
3382      }
3383
3384   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3385
3386      SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3387                     &CRT2Index,&ResIndex,HwInfo);
3388
3389      switch(CRT2Index) {
3390         case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
3391         case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
3392         case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
3393         case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
3394         case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
3395         case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
3396         case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
3397         case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
3398         case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
3399         case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
3400         case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
3401         case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
3402         case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
3403         default: TVPtr = SiS_Pr->SiS_StPALData;     break;
3404      }
3405
3406      SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
3407      SiS_Pr->SiS_RVBHCFACT = (TVPtr+ResIndex)->RVBHCFACT;
3408      SiS_Pr->SiS_VGAHT     = (TVPtr+ResIndex)->VGAHT;
3409      SiS_Pr->SiS_VGAVT     = (TVPtr+ResIndex)->VGAVT;
3410      SiS_Pr->SiS_HDE       = (TVPtr+ResIndex)->TVHDE;
3411      SiS_Pr->SiS_VDE       = (TVPtr+ResIndex)->TVVDE;
3412      SiS_Pr->SiS_RVBHRS    = (TVPtr+ResIndex)->RVBHRS;
3413      SiS_Pr->SiS_NewFlickerMode = (TVPtr+ResIndex)->FlickerMode;
3414      if(modeflag & HalfDCLK) {
3415         SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
3416      }
3417
3418      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
3419
3420         if((resinfo == SIS_RI_1024x768)  ||
3421            (resinfo == SIS_RI_1280x1024) ||
3422            (resinfo == SIS_RI_1280x720)) {
3423            SiS_Pr->SiS_NewFlickerMode = 0x40;
3424         }
3425
3426         if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
3427
3428         SiS_Pr->SiS_HT = ExtHiTVHT;
3429         SiS_Pr->SiS_VT = ExtHiTVVT;
3430         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
3431            if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
3432               SiS_Pr->SiS_HT = StHiTVHT;
3433               SiS_Pr->SiS_VT = StHiTVVT;
3434 #if 0
3435               if(!(modeflag & Charx8Dot)) {
3436                  SiS_Pr->SiS_HT = StHiTextTVHT;
3437                  SiS_Pr->SiS_VT = StHiTextTVVT;
3438               }
3439 #endif
3440            }
3441         }
3442
3443      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
3444
3445         if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
3446            SiS_Pr->SiS_HT = 1650;
3447            SiS_Pr->SiS_VT = 750;
3448         } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
3449            SiS_Pr->SiS_HT = NTSCHT;
3450            SiS_Pr->SiS_VT = NTSCVT;
3451         } else {
3452            SiS_Pr->SiS_HT = NTSCHT;
3453            if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
3454            SiS_Pr->SiS_VT = NTSCVT;
3455         }
3456
3457      } else {
3458
3459         SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
3460         SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
3461         SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
3462         SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
3463
3464         if(modeflag & HalfDCLK) {
3465            SiS_Pr->SiS_RY1COE = 0x00;
3466            SiS_Pr->SiS_RY2COE = 0xf4;
3467            SiS_Pr->SiS_RY3COE = 0x10;
3468            SiS_Pr->SiS_RY4COE = 0x38;
3469         }
3470
3471         if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
3472            SiS_Pr->SiS_HT = NTSCHT;
3473            if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
3474            SiS_Pr->SiS_VT = NTSCVT;
3475         } else {
3476            SiS_Pr->SiS_HT = PALHT;
3477            SiS_Pr->SiS_VT = PALVT;
3478         }
3479
3480      }
3481
3482   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3483
3484      SiS_Pr->SiS_RVBHCMAX  = 1;
3485      SiS_Pr->SiS_RVBHCFACT = 1;
3486
3487      if(SiS_Pr->UseCustomMode) {
3488
3489         SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal;
3490         SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal;
3491         SiS_Pr->SiS_HT    = SiS_Pr->CHTotal;
3492         SiS_Pr->SiS_VT    = SiS_Pr->CVTotal;
3493         SiS_Pr->SiS_HDE   = SiS_Pr->SiS_VGAHDE;
3494         SiS_Pr->SiS_VDE   = SiS_Pr->SiS_VGAVDE;
3495
3496      } else {
3497
3498         BOOLEAN gotit = FALSE;
3499
3500         if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
3501
3502            SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
3503            SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
3504            SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
3505            SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
3506            gotit = TRUE;
3507
3508         } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
3509
3510 #ifdef SIS315H
3511            SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
3512            SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
3513            SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
3514            SiS_Pr->SiS_VGAVT     = ROMAddr[romptr+4] | ((ROMAddr[romptr+3] & 0xf0) << 4);
3515            SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
3516            SiS_Pr->SiS_VT        = ROMAddr[romptr+7] | ((ROMAddr[romptr+6] & 0xf0) << 4);
3517            if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
3518            else {
3519               SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
3520               SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
3521               SiS_Pr->SiS_VGAHT   = SiS_Pr->PanelHT;
3522               SiS_Pr->SiS_VGAVT   = SiS_Pr->PanelVT;
3523               SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
3524               SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
3525               gotit = TRUE;
3526            }
3527 #endif
3528
3529         }
3530
3531         if(!gotit) {
3532
3533            SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
3534                           &CRT2Index,&ResIndex,HwInfo);
3535
3536            switch(CRT2Index) {
3537               case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
3538               case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
3539               case Panel_1280x720      :
3540               case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
3541               case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
3542               case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
3543               case Panel_1280x800      :
3544               case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
3545               case Panel_1280x800_2    :
3546               case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data;    break;
3547               case Panel_1280x960      :
3548               case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
3549               case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
3550               case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
3551               case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
3552               case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
3553               case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
3554               case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
3555               case Panel_1680x1050     :
3556               case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
3557               case 100                 : LCDPtr = SiS_Pr->SiS_NoScaleData;          break;
3558 #ifdef SIS315H
3559               case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
3560               case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
3561 #endif
3562               default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
3563            }
3564
3565 #ifdef TWDEBUG
3566            xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
3567 #endif
3568
3569            SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
3570            SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
3571            SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
3572            SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
3573            SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
3574            SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
3575
3576         }
3577
3578         tempax = SiS_Pr->PanelXRes;
3579         tempbx = SiS_Pr->PanelYRes;
3580
3581         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3582            if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
3583               if(HwInfo->jChipType < SIS_315H) {
3584                  if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3585                  else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3586               }
3587            } else {
3588               if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
3589               else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
3590               else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
3591               else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
3592               else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
3593               else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
3594            }
3595         } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) {
3596            if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
3597            else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
3598            else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
3599         } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
3600            if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
3601            else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
3602            else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
3603         } else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) {
3604            if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
3605               if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
3606               else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
3607            }
3608         }
3609
3610         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3611            tempax = SiS_Pr->SiS_VGAHDE;
3612            tempbx = SiS_Pr->SiS_VGAVDE;
3613         }
3614
3615         SiS_Pr->SiS_HDE = tempax;
3616         SiS_Pr->SiS_VDE = tempbx;
3617      }
3618   }
3619 }
3620
3621 static void
3622 SiS_GetCRT2Data(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
3623                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
3624 {
3625
3626   if(SiS_Pr->SiS_VBType & VB_SISVB) {
3627
3628      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
3629         SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3630      } else {
3631         if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
3632            /* Need LVDS Data for LCD on 301B-DH */
3633            SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3634         } else {
3635            SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3636         }
3637      }
3638
3639   } else {
3640
3641      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
3642
3643   }
3644 }
3645
3646 /*********************************************/
3647 /*         GET LVDS DES (SKEW) DATA          */
3648 /*********************************************/
3649
3650 static void
3651 SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
3652                   USHORT RefreshRateTableIndex, USHORT *PanelIndex,
3653                   USHORT *ResIndex, PSIS_HW_INFO HwInfo)
3654 {
3655   USHORT modeflag;
3656
3657   if(ModeNo <= 0x13) {
3658      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3659      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
3660   } else {
3661      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
3662      (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
3663   }
3664
3665   (*ResIndex) &= 0x1F;
3666   (*PanelIndex) = 0;
3667
3668   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
3669      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
3670         (*PanelIndex) = 50;
3671         if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) (*PanelIndex) += 2;
3672         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*PanelIndex) += 1;
3673         /* Nothing special needed for SOverscan    */
3674         /* PALM uses NTSC data, PALN uses PAL data */
3675      }
3676   }
3677
3678   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
3679      *PanelIndex = SiS_Pr->SiS_LCDTypeInfo;
3680      if(HwInfo->jChipType >= SIS_661) {
3681         /* As long as we don's use the BIOS tables, we
3682          * need to convert the TypeInfo as for 315 series
3683          */
3684         (*PanelIndex) = SiS_Pr->SiS_LCDResInfo - 1;
3685      }
3686      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3687         (*PanelIndex) += 16;
3688         if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
3689            (*PanelIndex) = 32;
3690            if(modeflag & HalfDCLK) (*PanelIndex)++;
3691         }
3692      }
3693   }
3694
3695   if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
3696      if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
3697         (*ResIndex) = 7;
3698         if(HwInfo->jChipType < SIS_315H) {
3699            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) (*ResIndex)++;
3700         }
3701      }
3702   }
3703 }
3704
3705 static void
3706 SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
3707                    USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
3708 {
3709   USHORT modeflag;
3710   USHORT PanelIndex,ResIndex;
3711   const  SiS_LVDSDesStruct *PanelDesPtr = NULL;
3712
3713   SiS_Pr->SiS_LCDHDES = 0;
3714   SiS_Pr->SiS_LCDVDES = 0;
3715
3716   if( (SiS_Pr->UseCustomMode)                    ||
3717       (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
3718       (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
3719       ((SiS_Pr->SiS_VBType & VB_SISVB) &&
3720        (SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
3721        (SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
3722      return;
3723   }
3724
3725   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3726
3727 #ifdef SIS315H
3728      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3729         /* non-pass 1:1 only, see above */
3730         if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
3731            SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
3732         }
3733         if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
3734            SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
3735         }
3736      }
3737      if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
3738         switch(SiS_Pr->SiS_CustomT) {
3739         case CUT_UNIWILL1024:
3740         case CUT_UNIWILL10242:
3741         case CUT_CLEVO1400:
3742            if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3743               SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3744            }
3745            break;
3746         }
3747         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
3748            if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
3749               SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
3750            }
3751         }
3752      }
3753 #endif
3754
3755   } else {
3756
3757      SiS_GetLVDSDesPtr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
3758                        &PanelIndex, &ResIndex, HwInfo);
3759
3760      switch(PanelIndex) {
3761         case  0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1;    break;   /* ---  */
3762         case  1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1;    break;
3763         case  2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1;    break;
3764         case  3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1;    break;
3765         case  4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1;    break;
3766         case  5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1;    break;
3767         case  6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1;    break;
3768         case  7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1;    break;
3769         case  8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1;    break;
3770         case  9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1;    break;
3771         case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1;    break;
3772         case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1;    break;
3773         case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1;    break;
3774         case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1;    break;
3775         case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;    break;
3776         case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1;    break;
3777         case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2;    break;    /* --- */
3778         case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2;    break;
3779         case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2;    break;
3780         case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2;    break;
3781         case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2;    break;
3782         case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2;    break;
3783         case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2;    break;
3784         case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2;    break;
3785         case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2;    break;
3786         case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2;    break;
3787         case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2;    break;
3788         case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2;    break;
3789         case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2;    break;
3790         case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2;    break;
3791         case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2;    break;
3792         case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2;    break;
3793         case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1;    break;    /* pass 1:1 */
3794         case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2;    break;
3795         case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData; break;    /* TV */
3796         case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break;
3797         case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData;  break;
3798         case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData;  break;
3799         default: return;
3800      }
3801
3802      SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
3803      SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
3804
3805      if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
3806         modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
3807         if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
3808            if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
3809         } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
3810            if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
3811               if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
3812                  if(HwInfo->jChipType < SIS_315H) {
3813                     if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
3814                  } else {
3815                     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
3816                     if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
3817                     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
3818                     if(!(modeflag & HalfDCLK)) {
3819                        SiS_Pr->SiS_LCDHDES = 320;
3820                        if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
3821                        if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
3822                     }
3823                  }
3824               }
3825            }
3826         }
3827      }
3828   }
3829 }
3830
3831 /*********************************************/
3832 /*           DISABLE VIDEO BRIDGE            */
3833 /*********************************************/
3834
3835 /* NEVER use any variables (VBInfo), this will be called
3836  * from outside the context of modeswitch!
3837  * MUST call getVBType before calling this
3838  */
3839 void
3840 SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
3841 {
3842 #ifdef SIS315H
3843   USHORT tempah,pushax=0,modenum;
3844 #endif
3845   USHORT temp=0;
3846
3847   if(SiS_Pr->SiS_VBType & VB_SISVB) {
3848
3849      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
3850
3851         if(HwInfo->jChipType < SIS_315H) {
3852
3853 #ifdef SIS300      /* 300 series */
3854
3855            if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
3856               if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3857                  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
3858               } else {
3859                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
3860               }
3861               SiS_PanelDelay(SiS_Pr, HwInfo, 3);
3862            }
3863            if(SiS_Is301B(SiS_Pr)) {
3864               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
3865               SiS_ShortDelay(SiS_Pr,1);
3866            }
3867            SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
3868            SiS_DisplayOff(SiS_Pr);
3869            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3870            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
3871            SiS_UnLockCRT2(SiS_Pr,HwInfo);
3872            if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
3873               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
3874               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
3875            }
3876            if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
3877                (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
3878               SiS_PanelDelay(SiS_Pr, HwInfo, 2);
3879               if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3880                  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
3881               } else {
3882                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
3883               }
3884            }
3885
3886 #endif  /* SIS300 */
3887
3888         } else {
3889
3890 #ifdef SIS315H     /* 315 series */
3891
3892            BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
3893                               (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
3894
3895            modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
3896
3897            if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3898
3899 #ifdef SET_EMI
3900               if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
3901                  if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
3902                     SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
3903                  }
3904               }
3905 #endif
3906               if( (modenum <= 0x13)                  ||
3907                   (SiS_IsVAMode(SiS_Pr,HwInfo))      ||
3908                   (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
3909                  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
3910                  if(custom1) SiS_PanelDelay(SiS_Pr, HwInfo, 3);
3911               }
3912
3913               if(!custom1) {
3914                  SiS_DDC2Delay(SiS_Pr,0xff00);
3915                  SiS_DDC2Delay(SiS_Pr,0xe000);
3916                  SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
3917                  pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
3918                  if(IS_SIS740) {
3919                     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
3920                  }
3921                  SiS_PanelDelay(SiS_Pr, HwInfo, 3);
3922               }
3923
3924            }
3925
3926            if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
3927               if(HwInfo->jChipType < SIS_340) {
3928                  tempah = 0xef;
3929                  if(SiS_IsVAMode(SiS_Pr,HwInfo)) tempah = 0xf7;
3930                  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
3931               }
3932            }
3933
3934            if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3935               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
3936            }
3937
3938            tempah = 0x3f;
3939            if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
3940               tempah = 0x7f;
3941               if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) tempah = 0xbf;
3942            }
3943            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
3944
3945            if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
3946               ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
3947
3948               SiS_DisplayOff(SiS_Pr);
3949               if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3950                  SiS_PanelDelay(SiS_Pr, HwInfo, 2);
3951               }
3952               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3953               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
3954
3955            }
3956
3957            if((!(SiS_IsVAMode(SiS_Pr,HwInfo))) ||
3958               ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
3959
3960               if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
3961                  SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
3962                  SiS_DisplayOff(SiS_Pr);
3963               }
3964               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
3965
3966               if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3967                  SiS_PanelDelay(SiS_Pr, HwInfo, 2);
3968               }
3969
3970               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
3971               temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
3972               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
3973               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
3974               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
3975
3976            }
3977
3978            if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
3979               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
3980            }
3981
3982            if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
3983
3984               if(!custom1) {
3985
3986                  if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
3987                     if(!(SiS_CRT2IsLCD(SiS_Pr,HwInfo))) {
3988                        if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
3989                           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
3990                        }
3991                     }
3992                  }
3993
3994                  SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
3995
3996                  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
3997                     if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
3998                        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 20);
3999                     }
4000                  }
4001
4002               } else {
4003
4004                  if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
4005                     (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
4006                     if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
4007                        (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
4008                        SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4009                        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
4010                        SiS_PanelDelay(SiS_Pr, HwInfo, 4);
4011                     }
4012                  }
4013
4014               }
4015            }
4016
4017 #endif /* SIS315H */
4018
4019         }
4020
4021      } else {     /* ============ For 301 ================ */
4022
4023         if(HwInfo->jChipType < SIS_315H) {
4024 #ifdef SIS300
4025            if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4026               SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
4027               SiS_PanelDelay(SiS_Pr, HwInfo, 3);
4028            }
4029 #endif
4030         }
4031
4032         SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
4033         SiS_DisplayOff(SiS_Pr);
4034
4035         if(HwInfo->jChipType >= SIS_315H) {
4036            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4037         }
4038
4039         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);                /* disable lock mode */
4040
4041         if(HwInfo->jChipType >= SIS_315H) {
4042             temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
4043             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
4044             SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4045             SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
4046         } else {
4047 #ifdef SIS300
4048             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
4049             if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
4050                 (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
4051                 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4052                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
4053             }
4054 #endif
4055         }
4056
4057       }
4058
4059   } else {     /* ============ For LVDS =============*/
4060
4061     if(HwInfo->jChipType < SIS_315H) {
4062
4063 #ifdef SIS300   /* 300 series */
4064
4065         if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
4066            SiS_SetCH700x(SiS_Pr,0x090E);
4067         }
4068
4069         if(HwInfo->jChipType == SIS_730) {
4070            if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4071               SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4072            }
4073            if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4074               SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
4075               SiS_PanelDelay(SiS_Pr, HwInfo, 3);
4076            }
4077         } else {
4078            if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
4079               if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4080                  if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4081                     SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4082                     if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
4083                        SiS_DisplayOff(SiS_Pr);
4084                     }
4085                     SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
4086                     SiS_PanelDelay(SiS_Pr, HwInfo, 3);
4087                  }
4088               }
4089            }
4090         }
4091
4092         SiS_DisplayOff(SiS_Pr);
4093
4094         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4095
4096         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4097         SiS_UnLockCRT2(SiS_Pr,HwInfo);
4098         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
4099         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
4100
4101         if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
4102             (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
4103            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4104            SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
4105         }
4106
4107 #endif  /* SIS300 */
4108
4109     } else {
4110
4111 #ifdef SIS315H  /* 315 series */
4112
4113         if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
4114            if(HwInfo->jChipType < SIS_340) {
4115               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
4116            }
4117         }
4118
4119         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4120
4121            if(HwInfo->jChipType == SIS_740) {
4122               temp = SiS_GetCH701x(SiS_Pr,0x61);
4123               if(temp < 1) {
4124                  SiS_SetCH701x(SiS_Pr,0xac76);
4125                  SiS_SetCH701x(SiS_Pr,0x0066);
4126               }
4127
4128               if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4129                   (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
4130                  SiS_SetCH701x(SiS_Pr,0x3e49);
4131               }
4132            }
4133
4134            if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4135                (SiS_IsVAMode(SiS_Pr,HwInfo)) ) {
4136               SiS_Chrontel701xBLOff(SiS_Pr);
4137               SiS_Chrontel701xOff(SiS_Pr,HwInfo);
4138            }
4139
4140            if(HwInfo->jChipType != SIS_740) {
4141               if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4142                   (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
4143                  SiS_SetCH701x(SiS_Pr,0x0149);
4144               }
4145            }
4146
4147         }
4148
4149         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4150            SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
4151            SiS_PanelDelay(SiS_Pr, HwInfo, 3);
4152         }
4153
4154         if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4155             (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4156             (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo))) ) {
4157            SiS_DisplayOff(SiS_Pr);
4158         }
4159
4160         if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4161             (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4162             (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
4163            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
4164         }
4165
4166         if(HwInfo->jChipType == SIS_740) {
4167            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4168         }
4169
4170         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
4171
4172         if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4173             (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4174             (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
4175            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
4176         }
4177
4178         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4179            if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4180               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4181               if(HwInfo->jChipType == SIS_550) {
4182                  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
4183                  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
4184               }
4185            }
4186         } else {
4187            if(HwInfo->jChipType == SIS_740) {
4188               if(SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) {
4189                  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4190               }
4191            } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
4192               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
4193            }
4194         }
4195
4196         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
4197            if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
4198               /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
4199            } else {
4200               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
4201            }
4202         }
4203
4204         SiS_UnLockCRT2(SiS_Pr,HwInfo);
4205
4206         if(HwInfo->jChipType == SIS_550) {
4207            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
4208            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
4209         } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
4210                    (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
4211                    (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
4212            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4213         }
4214
4215         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4216            if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4217               if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4218                  SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4219                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
4220               }
4221            }
4222         }
4223
4224 #endif  /* SIS315H */
4225
4226     }  /* 315 series */
4227
4228   }  /* LVDS */
4229
4230 }
4231
4232 /*********************************************/
4233 /*            ENABLE VIDEO BRIDGE            */
4234 /*********************************************/
4235
4236 /* NEVER use any variables (VBInfo), this will be called
4237  * from outside the context of a mode switch!
4238  * MUST call getVBType before calling this
4239  */
4240 static void
4241 SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
4242 {
4243   USHORT temp=0,tempah;
4244 #ifdef SIS315H
4245   USHORT temp1,pushax=0;
4246   BOOLEAN delaylong = FALSE;
4247 #endif
4248
4249   if(SiS_Pr->SiS_VBType & VB_SISVB) {
4250
4251     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ====== For 301B et al  ====== */
4252
4253       if(HwInfo->jChipType < SIS_315H) {
4254
4255 #ifdef SIS300     /* 300 series */
4256
4257          if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4258             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4259                SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4260             } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4261                SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
4262             }
4263             if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_NoLCD)) {
4264                if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
4265                   SiS_PanelDelay(SiS_Pr, HwInfo, 0);
4266                }
4267             }
4268          }
4269
4270          if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
4271             (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
4272
4273             SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* Enable CRT2 */
4274             SiS_DisplayOn(SiS_Pr);
4275             SiS_UnLockCRT2(SiS_Pr,HwInfo);
4276             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4277             if(SiS_BridgeInSlavemode(SiS_Pr)) {
4278                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4279             } else {
4280                SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4281             }
4282             if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4283                if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4284                   if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4285                      SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4286                   }
4287                   SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4288                   SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
4289                }
4290             }
4291
4292          } else {
4293
4294             temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
4295             if(SiS_BridgeInSlavemode(SiS_Pr)) {
4296                tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4297                if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4298             }
4299             SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4300             SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4301             SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
4302             SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
4303             SiS_DisplayOn(SiS_Pr);
4304             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4305                if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4306                   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4307                      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4308                         SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4309                      }
4310                      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4311                   }
4312                }
4313             }
4314
4315          }
4316
4317
4318 #endif /* SIS300 */
4319
4320       } else {
4321
4322 #ifdef SIS315H    /* 315 series */
4323
4324 #ifdef SET_EMI
4325          UCHAR   r30=0, r31=0, r32=0, r33=0, cr36=0;
4326          /* USHORT  emidelay=0; */
4327 #endif
4328
4329          if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4330             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
4331 #ifdef SET_EMI
4332             if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4333                SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4334             }
4335 #endif
4336          }
4337
4338          if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
4339             if(HwInfo->jChipType < SIS_340) {
4340                tempah = 0x10;
4341                if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
4342                   if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
4343                   else                              tempah = 0x08;
4344                }
4345                SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
4346             }
4347          }
4348
4349          if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4350
4351             SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
4352             SiS_DisplayOff(SiS_Pr);
4353             pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
4354             if(IS_SIS740) {
4355                SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
4356             }
4357
4358             if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
4359                if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
4360                   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
4361                   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
4362                   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
4363                   if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4364                      SiS_GenericDelay(SiS_Pr, 0x4500);
4365                   }
4366                }
4367             }
4368
4369             if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
4370                SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
4371                delaylong = TRUE;
4372             }
4373
4374          }
4375
4376          if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
4377
4378             temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
4379             if(SiS_BridgeInSlavemode(SiS_Pr)) {
4380                tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4381                if(!(tempah & SetCRT2ToRAMDAC)) {
4382                   if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
4383                }
4384             }
4385             SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4386
4387             SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
4388
4389             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4390             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4391
4392             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4393                SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4394             }
4395
4396          } else {
4397
4398             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
4399
4400          }
4401
4402          SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
4403          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4404
4405          tempah = 0xc0;
4406          if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
4407             tempah = 0x80;
4408             if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) tempah = 0x40;
4409          }
4410          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
4411
4412          if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
4413
4414             SiS_PanelDelay(SiS_Pr, HwInfo, 2);
4415
4416             SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
4417             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
4418
4419             if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
4420 #ifdef SET_EMI
4421                if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4422                   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
4423                   SiS_GenericDelay(SiS_Pr, 0x500);
4424                }
4425 #endif
4426                SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
4427
4428                if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4429 #ifdef SET_EMI
4430                   cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
4431
4432                   if(SiS_Pr->SiS_ROMNew) {
4433                      UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
4434                      USHORT romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo);
4435                      if(romptr) {
4436                         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
4437                         SiS_Pr->EMI_30 = 0;
4438                         SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
4439                         SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
4440                         SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
4441                         if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
4442                         /* emidelay = SISGETROMW((romptr + 0x22)); */
4443                         SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = TRUE;
4444                      }
4445                   }
4446
4447                   /*                                              (P4_30|0x40)  */
4448                   /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
4449                   /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
4450                   /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
4451                   /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
4452                   /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
4453                   /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
4454                   /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
4455                   /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
4456                   /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
4457
4458                   if(SiS_Pr->HaveEMI) {
4459                      r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
4460                      r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
4461                   } else {
4462                      r30 = 0;
4463                   }
4464
4465                   /* EMI_30 is read at driver start; however, the BIOS sets this
4466                    * (if it is used) only if the LCD is in use. In case we caught
4467                    * the machine while on TV output, this bit is not set and we
4468                    * don't know if it should be set - hence our detection is wrong.
4469                    * Work-around this here:
4470                    */
4471
4472                   if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
4473                      switch((cr36 & 0x0f)) {
4474                      case 2:
4475                         r30 |= 0x40;
4476                         if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
4477                         if(!SiS_Pr->HaveEMI) {
4478                            r31 = 0x05; r32 = 0x60; r33 = 0x33;
4479                            if((cr36 & 0xf0) == 0x30) {
4480                               r31 = 0x0d; r32 = 0x70; r33 = 0x40;
4481                            }
4482                         }
4483                         break;
4484                      case 3:  /* 1280x1024 */
4485                         if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
4486                         if(!SiS_Pr->HaveEMI) {
4487                            r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4488                            if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4489                               r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
4490                            }
4491                         }
4492                         break;
4493                      case 9:  /* 1400x1050 */
4494                         r30 |= 0x40;
4495                         if(!SiS_Pr->HaveEMI) {
4496                            r31 = 0x05; r32 = 0x60; r33 = 0x00;
4497                            if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4498                               r31 = 0x0d; r32 = 0x70; r33 = 0x40;  /* BIOS values */
4499                            }
4500                         }
4501                         break;
4502                      case 11: /* 1600x1200 - unknown */
4503                         r30 |= 0x40;
4504                         if(!SiS_Pr->HaveEMI) {
4505                            r31 = 0x05; r32 = 0x60; r33 = 0x00;
4506                         }
4507                      }
4508                   }
4509
4510                   /* BIOS values don't work so well sometimes */
4511                   if(!SiS_Pr->OverruleEMI) {
4512 #ifdef COMPAL_HACK
4513                      if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
4514                         if((cr36 & 0x0f) == 0x09) {
4515                            r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
4516                         }
4517                      }
4518 #endif
4519 #ifdef COMPAQ_HACK
4520                      if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
4521                         if((cr36 & 0x0f) == 0x03) {
4522                            r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
4523                         }
4524                      }
4525 #endif
4526 #ifdef ASUS_HACK
4527                      if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
4528                         if((cr36 & 0x0f) == 0x02) {
4529                            /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
4530                            /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
4531                            /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
4532                            /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
4533                         }
4534                      }
4535 #endif
4536                   }
4537
4538                   if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
4539                      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
4540                      SiS_GenericDelay(SiS_Pr, 0x500);
4541                   }
4542                   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
4543                   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
4544                   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
4545 #endif  /* SET_EMI */
4546
4547                   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
4548
4549 #ifdef SET_EMI
4550                   if( (SiS_LCDAEnabled(SiS_Pr, HwInfo)) ||
4551                       (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
4552                      if(r30 & 0x40) {
4553                         SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
4554                         if(delaylong) {
4555                            SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
4556                            delaylong = FALSE;
4557                         }
4558                         SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4559                         if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
4560                            SiS_GenericDelay(SiS_Pr, 0x500);
4561                         }
4562                         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   /* Enable */
4563                      }
4564                   }
4565 #endif
4566                }
4567             }
4568
4569             if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4570                if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
4571                   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
4572                   if(delaylong) {
4573                      SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
4574                   }
4575                   SiS_WaitVBRetrace(SiS_Pr,HwInfo);
4576                   if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
4577                      SiS_GenericDelay(SiS_Pr, 0x500);
4578                   }
4579                   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
4580                }
4581             }
4582
4583             SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
4584             SiS_DisplayOn(SiS_Pr);
4585             SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
4586
4587          }
4588
4589          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4590             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4591          }
4592
4593 #endif /* SIS315H */
4594
4595       }
4596
4597     } else {    /* ============  For 301 ================ */
4598
4599        if(HwInfo->jChipType < SIS_315H) {
4600           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4601              SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
4602              SiS_PanelDelay(SiS_Pr, HwInfo, 0);
4603           }
4604        }
4605
4606        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
4607        if(SiS_BridgeInSlavemode(SiS_Pr)) {
4608           tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
4609           if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
4610        }
4611        SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
4612
4613        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                  /* enable CRT2 */
4614
4615        if(HwInfo->jChipType >= SIS_315H) {
4616           temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4617           if(!(temp & 0x80)) {
4618              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);         /* BVBDOENABLE=1 */
4619           }
4620        }
4621
4622        SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);     /* enable VB processor */
4623
4624        SiS_VBLongWait(SiS_Pr);
4625        SiS_DisplayOn(SiS_Pr);
4626        if(HwInfo->jChipType >= SIS_315H) {
4627           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4628        }
4629        SiS_VBLongWait(SiS_Pr);
4630
4631        if(HwInfo->jChipType < SIS_315H) {
4632           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4633              SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4634              SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
4635           }
4636        }
4637
4638     }
4639
4640   } else {   /* =================== For LVDS ================== */
4641
4642     if(HwInfo->jChipType < SIS_315H) {
4643
4644 #ifdef SIS300    /* 300 series */
4645
4646        if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4647           if(HwInfo->jChipType == SIS_730) {
4648              SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4649              SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4650              SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4651           }
4652           SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
4653           if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
4654              SiS_PanelDelay(SiS_Pr, HwInfo, 0);
4655           }
4656        }
4657
4658        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4659        SiS_DisplayOn(SiS_Pr);
4660        SiS_UnLockCRT2(SiS_Pr,HwInfo);
4661        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
4662        if(SiS_BridgeInSlavemode(SiS_Pr)) {
4663           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
4664        } else {
4665           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
4666        }
4667
4668        if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
4669           if(!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
4670              SiS_WaitVBRetrace(SiS_Pr, HwInfo);
4671              SiS_SetCH700x(SiS_Pr,0x0B0E);
4672           }
4673        }
4674
4675        if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4676           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
4677              if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
4678                 if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
4679                    SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4680                    SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4681                 }
4682                 SiS_WaitVBRetrace(SiS_Pr, HwInfo);
4683                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
4684              }
4685           }
4686        }
4687
4688 #endif  /* SIS300 */
4689
4690     } else {
4691
4692 #ifdef SIS315H    /* 315 series */
4693
4694        if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
4695           if(HwInfo->jChipType < SIS_340) {
4696              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
4697           }
4698        }
4699
4700        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4701           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4702              SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
4703              SiS_PanelDelay(SiS_Pr, HwInfo, 0);
4704           }
4705        }
4706
4707        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
4708        SiS_UnLockCRT2(SiS_Pr,HwInfo);
4709
4710        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
4711
4712        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4713           temp = SiS_GetCH701x(SiS_Pr,0x66);
4714           temp &= 0x20;
4715           SiS_Chrontel701xBLOff(SiS_Pr);
4716        }
4717
4718        if(HwInfo->jChipType != SIS_550) {
4719           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
4720        }
4721
4722        if(HwInfo->jChipType == SIS_740) {
4723           if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4724              if(SiS_IsLCDOrLCDA(SiS_Pr, HwInfo)) {
4725                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
4726              }
4727           }
4728        }
4729
4730        temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
4731        if(!(temp1 & 0x80)) {
4732           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
4733        }
4734
4735        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4736           if(temp) {
4737              SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
4738           }
4739        }
4740
4741        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4742           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4743              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
4744              if(HwInfo->jChipType == SIS_550) {
4745                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
4746                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
4747              }
4748           }
4749        } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
4750           if(HwInfo->jChipType != SIS_740) {
4751              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
4752           }
4753        }
4754
4755        if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4756           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
4757        }
4758
4759        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4760           if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) {
4761              SiS_Chrontel701xOn(SiS_Pr,HwInfo);
4762           }
4763           if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
4764               (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
4765              SiS_ChrontelDoSomething1(SiS_Pr,HwInfo);
4766           }
4767        }
4768
4769        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
4770           if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4771              if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
4772                  (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
4773                 SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
4774                 SiS_ChrontelInitTVVSync(SiS_Pr,HwInfo);
4775              }
4776           }
4777        } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
4778           if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
4779              if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
4780                 SiS_PanelDelay(SiS_Pr, HwInfo, 1);
4781                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
4782              }
4783           }
4784        }
4785
4786 #endif  /* SIS315H */
4787
4788     } /* 310 series */
4789
4790   }  /* LVDS */
4791
4792 }
4793
4794 /*********************************************/
4795 /*         SET PART 1 REGISTER GROUP         */
4796 /*********************************************/
4797
4798 /* Set CRT2 OFFSET / PITCH */
4799 static void
4800 SiS_SetCRT2Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
4801                   USHORT RRTI, PSIS_HW_INFO HwInfo)
4802 {
4803   USHORT offset;
4804   UCHAR temp;
4805
4806   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
4807
4808   offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI,HwInfo);
4809
4810   if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
4811      (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
4812      offset >>= 1;
4813   }
4814
4815   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
4816   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
4817   temp = (UCHAR)(((offset >> 3) & 0xFF) + 1);
4818   if(offset % 8) temp++;
4819   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
4820 }
4821
4822 /* Set CRT2 sync and PanelLink mode */
4823 static void
4824 SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT RefreshRateTableIndex,
4825                 PSIS_HW_INFO HwInfo)
4826 {
4827   USHORT tempah=0,tempbl,infoflag;
4828
4829   tempbl = 0xC0;
4830
4831   if(SiS_Pr->UseCustomMode) {
4832      infoflag = SiS_Pr->CInfoFlag;
4833   } else {
4834      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
4835   }
4836
4837   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {                                    /* LVDS */
4838
4839      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4840         tempah = 0;
4841      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
4842         tempah = SiS_Pr->SiS_LCDInfo;
4843      } else tempah = infoflag >> 8;
4844      tempah &= 0xC0;
4845      tempah |= 0x20;
4846      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4847      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4848         if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
4849            (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
4850            tempah |= 0xf0;
4851         }
4852         if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
4853             (SiS_Pr->SiS_IF_DEF_DSTN) ||
4854             (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
4855             (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
4856            tempah |= 0x30;
4857         }
4858      }
4859      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
4860         if(HwInfo->jChipType >= SIS_315H) {
4861            tempah >>= 3;
4862            tempah &= 0x18;
4863            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
4864            /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
4865         } else {
4866            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
4867         }
4868      } else {
4869         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4870      }
4871
4872   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
4873
4874      if(HwInfo->jChipType < SIS_315H) {
4875
4876 #ifdef SIS300  /* ---- 300 series --- */
4877
4878         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {                   /* 630 - 301B(-DH) */
4879
4880            tempah = infoflag >> 8;
4881            tempbl = 0;
4882            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4883               if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4884                  tempah = SiS_Pr->SiS_LCDInfo;
4885                  tempbl = (tempah >> 6) & 0x03;
4886               }
4887            }
4888            tempah &= 0xC0;
4889            tempah |= 0x20;
4890            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4891            tempah |= 0xc0;
4892            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4893            if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
4894               SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4895            }
4896
4897         } else {                                                        /* 630 - 301 */
4898
4899            tempah = infoflag >> 8;
4900            tempah &= 0xC0;
4901            tempah |= 0x20;
4902            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4903            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4904
4905         }
4906
4907 #endif /* SIS300 */
4908
4909      } else {
4910
4911 #ifdef SIS315H  /* ------- 315 series ------ */
4912
4913         if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {                     /* 315 - LVDS */
4914
4915            tempbl = 0;
4916            if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
4917               (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
4918               tempah = infoflag >> 8;
4919               if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4920                 tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
4921               }
4922            } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
4923                      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
4924               tempah = infoflag >> 8;
4925               tempbl = 0x03;
4926            } else {
4927               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
4928               tempbl = (tempah >> 6) & 0x03;
4929               tempbl |= 0x08;
4930               if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
4931            }
4932            tempah &= 0xC0;
4933            tempah |= 0x20;
4934            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4935            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
4936            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4937            if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
4938               if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4939                  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4940               }
4941            }
4942
4943         } else {                                                        /* 315 - TMDS */
4944
4945            tempah = tempbl = infoflag >> 8;
4946            if(!SiS_Pr->UseCustomMode) {
4947               tempbl = 0;
4948               if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4949                  if(ModeNo <= 0x13) {
4950                     tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
4951                  }
4952               }
4953               if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
4954                  if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
4955                     if(SiS_Pr->SiS_LCDInfo & LCDSync) {
4956                        tempah = SiS_Pr->SiS_LCDInfo;
4957                        tempbl = (tempah >> 6) & 0x03;
4958                     }
4959                  }
4960               }
4961            }
4962            tempah &= 0xC0;
4963            tempah |= 0x20;
4964            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
4965            if(SiS_Pr->SiS_VBType & VB_NoLCD) {
4966               /* Imitate BIOS bug */
4967               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
4968            }
4969            if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
4970               tempah >>= 3;
4971               tempah &= 0x18;
4972               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
4973            } else {
4974               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
4975               if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
4976                  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
4977                     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
4978                  }
4979               }
4980            }
4981
4982         }
4983 #endif  /* SIS315H */
4984       }
4985    }
4986 }
4987
4988 /* Set CRT2 FIFO on 300/630/730 */
4989 #ifdef SIS300
4990 static void
4991 SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
4992                     PSIS_HW_INFO HwInfo)
4993 {
4994   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
4995   USHORT temp,index;
4996   USHORT modeidindex,refreshratetableindex;
4997   USHORT VCLK=0,MCLK,colorth=0,data2=0;
4998   USHORT tempal, tempah, tempbx, tempcl, tempax;
4999   USHORT CRT1ModeNo,CRT2ModeNo;
5000   USHORT SelectRate_backup;
5001   ULONG  data,eax;
5002   const UCHAR  LatencyFactor[] = {
5003         97, 88, 86, 79, 77, 00,       /*; 64  bit    BQ=2   */
5004         00, 87, 85, 78, 76, 54,       /*; 64  bit    BQ=1   */
5005         97, 88, 86, 79, 77, 00,       /*; 128 bit    BQ=2   */
5006         00, 79, 77, 70, 68, 48,       /*; 128 bit    BQ=1   */
5007         80, 72, 69, 63, 61, 00,       /*; 64  bit    BQ=2   */
5008         00, 70, 68, 61, 59, 37,       /*; 64  bit    BQ=1   */
5009         86, 77, 75, 68, 66, 00,       /*; 128 bit    BQ=2   */
5010         00, 68, 66, 59, 57, 37        /*; 128 bit    BQ=1   */
5011   };
5012   const UCHAR  LatencyFactor730[] = {
5013          69, 63, 61,
5014          86, 79, 77,
5015         103, 96, 94,
5016         120,113,111,
5017         137,130,128,    /* <-- last entry, data below */
5018         137,130,128,    /* to avoid using illegal values */
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         137,130,128,
5029   };
5030   const UCHAR ThLowB[]   = {
5031         81, 4, 72, 6, 88, 8,120,12,
5032         55, 4, 54, 6, 66, 8, 90,12,
5033         42, 4, 45, 6, 55, 8, 75,12
5034   };
5035   const UCHAR ThTiming[] = {
5036         1, 2, 2, 3, 0, 1, 1, 2
5037   };
5038
5039   SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
5040
5041   if(!SiS_Pr->CRT1UsesCustomMode) {
5042
5043      CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 /* get CRT1 ModeNo */
5044      SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
5045      SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
5046      SiS_Pr->SiS_SelectCRT2Rate = 0;
5047      refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex, HwInfo);
5048
5049      if(CRT1ModeNo >= 0x13) {
5050         index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
5051         index &= 0x3F;
5052         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                       /* Get VCLK */
5053
5054         colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex);     /* Get colordepth */
5055         colorth >>= 1;
5056         if(!colorth) colorth++;
5057      }
5058
5059   } else {
5060
5061      CRT1ModeNo = 0xfe;
5062      VCLK = SiS_Pr->CSRClock_CRT1;                                      /* Get VCLK */
5063      data2 = (SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2;
5064      switch(data2) {                                                    /* Get color depth */
5065         case 0 : colorth = 1; break;
5066         case 1 : colorth = 1; break;
5067         case 2 : colorth = 2; break;
5068         case 3 : colorth = 2; break;
5069         case 4 : colorth = 3; break;
5070         case 5 : colorth = 4; break;
5071         default: colorth = 2;
5072      }
5073
5074   }
5075
5076   if(CRT1ModeNo >= 0x13) {
5077     if(HwInfo->jChipType == SIS_300) {
5078        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
5079     } else {
5080        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
5081     }
5082     index &= 0x07;
5083     MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;                         /* Get MCLK */
5084
5085     data2 = (colorth * VCLK) / MCLK;
5086
5087     temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5088     temp = ((temp & 0x00FF) >> 6) << 1;
5089     if(temp == 0) temp = 1;
5090     temp <<= 2;
5091     temp &= 0xff;
5092
5093     data2 = temp - data2;
5094
5095     if((28 * 16) % data2) {
5096         data2 = (28 * 16) / data2;
5097         data2++;
5098     } else {
5099         data2 = (28 * 16) / data2;
5100     }
5101
5102     if(HwInfo->jChipType == SIS_300) {
5103
5104         tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
5105         tempah &= 0x62;
5106         tempah >>= 1;
5107         tempal = tempah;
5108         tempah >>= 3;
5109         tempal |= tempah;
5110         tempal &= 0x07;
5111         tempcl = ThTiming[tempal];
5112         tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
5113         tempbx >>= 6;
5114         tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5115         tempah >>= 4;
5116         tempah &= 0x0c;
5117         tempbx |= tempah;
5118         tempbx <<= 1;
5119         tempal = ThLowB[tempbx + 1];
5120         tempal *= tempcl;
5121         tempal += ThLowB[tempbx];
5122         data = tempal;
5123
5124     } else if(HwInfo->jChipType == SIS_730) {
5125
5126 #ifdef LINUX_KERNEL
5127        SiS_SetRegLong(0xcf8,0x80000050);
5128        eax = SiS_GetRegLong(0xcfc);
5129 #else
5130        eax = pciReadLong(0x00000000, 0x50);
5131 #endif
5132        tempal = (USHORT)(eax >> 8);
5133        tempal &= 0x06;
5134        tempal <<= 5;
5135
5136 #ifdef LINUX_KERNEL
5137        SiS_SetRegLong(0xcf8,0x800000A0);
5138        eax = SiS_GetRegLong(0xcfc);
5139 #else
5140        eax = pciReadLong(0x00000000, 0xA0);
5141 #endif
5142        temp = (USHORT)(eax >> 28);
5143        temp &= 0x0F;
5144        tempal |= temp;
5145
5146        tempbx = tempal;   /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
5147        tempbx = 0;        /* -- do it like the BIOS anyway... */
5148        tempax = tempbx;
5149        tempbx &= 0xc0;
5150        tempbx >>= 6;
5151        tempax &= 0x0f;
5152        tempax *= 3;
5153        tempbx += tempax;
5154
5155        data = LatencyFactor730[tempbx];
5156        data += 15;
5157        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5158        if(!(temp & 0x80)) data += 5;
5159
5160     } else {
5161
5162        index = 0;
5163        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5164        if(temp & 0x0080) index += 12;
5165
5166 #ifdef LINUX_KERNEL
5167        SiS_SetRegLong(0xcf8,0x800000A0);
5168        eax = SiS_GetRegLong(0xcfc);
5169 #else
5170        /* We use pci functions X offers. We use tag 0, because
5171         * we want to read/write to the host bridge (which is always
5172         * 00:00.0 on 630, 730 and 540), not the VGA device.
5173         */
5174        eax = pciReadLong(0x00000000, 0xA0);
5175 #endif
5176        temp = (USHORT)(eax >> 24);
5177        if(!(temp&0x01)) index += 24;
5178
5179 #ifdef LINUX_KERNEL
5180        SiS_SetRegLong(0xcf8,0x80000050);
5181        eax = SiS_GetRegLong(0xcfc);
5182 #else
5183        eax = pciReadLong(0x00000000, 0x50);
5184 #endif
5185        temp=(USHORT)(eax >> 24);
5186        if(temp & 0x01) index += 6;
5187
5188        temp = (temp & 0x0F) >> 1;
5189        index += temp;
5190
5191        data = LatencyFactor[index];
5192        data += 15;
5193        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
5194        if(!(temp & 0x80)) data += 5;
5195     }
5196
5197     data += data2;                              /* CRT1 Request Period */
5198
5199     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5200     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
5201
5202     if(!SiS_Pr->UseCustomMode) {
5203
5204        CRT2ModeNo = ModeNo;
5205        SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
5206
5207        refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex, HwInfo);
5208
5209        index = SiS_GetVCLK2Ptr(SiS_Pr,CRT2ModeNo,modeidindex,
5210                                refreshratetableindex,HwInfo);
5211        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                /* Get VCLK  */
5212
5213        if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
5214           if(SiS_Pr->SiS_UseROM) {
5215              if(ROMAddr[0x220] & 0x01) {
5216                 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
5217              }
5218           }
5219        }
5220
5221     } else {
5222
5223        CRT2ModeNo = 0xfe;
5224        VCLK = SiS_Pr->CSRClock;                                 /* Get VCLK */
5225
5226     }
5227
5228     colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex); /* Get colordepth */
5229     colorth >>= 1;
5230     if(!colorth) colorth++;
5231
5232     data = data * VCLK * colorth;
5233     if(data % (MCLK << 4)) {
5234         data = data / (MCLK << 4);
5235         data++;
5236     } else {
5237         data = data / (MCLK << 4);
5238     }
5239
5240     if(data <= 6) data = 6;
5241     if(data > 0x14) data = 0x14;
5242
5243     temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x01);
5244     if(HwInfo->jChipType == SIS_300) {
5245        if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13;
5246        else             temp = (temp & (~0x1F)) | 0x16;
5247        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
5248           temp = (temp & (~0x1F)) | 0x13;
5249        }
5250     } else {
5251        if( ( (HwInfo->jChipType == SIS_630) ||
5252              (HwInfo->jChipType == SIS_730) )  &&
5253            (HwInfo->jChipRevision >= 0x30) ) /* 630s or 730(s?) */
5254       {
5255           temp = (temp & (~0x1F)) | 0x1b;
5256       } else {
5257           temp = (temp & (~0x1F)) | 0x16;
5258       }
5259     }
5260     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
5261
5262     if( (HwInfo->jChipType == SIS_630) &&
5263         (HwInfo->jChipRevision >= 0x30) ) /* 630s, NOT 730 */
5264     {
5265         if(data > 0x13) data = 0x13;
5266     }
5267     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
5268
5269   } else {  /* If mode <= 0x13, we just restore everything */
5270
5271     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
5272     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
5273
5274   }
5275 }
5276 #endif
5277
5278 /* Set CRT2 FIFO on 315/330 series */
5279 #ifdef SIS315H
5280 static void
5281 SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
5282 {
5283   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
5284   if( (HwInfo->jChipType == SIS_760)      &&
5285       (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
5286       (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
5287       (SiS_Pr->SiS_VGAHDE >= 1280)        &&
5288       (SiS_Pr->SiS_VGAVDE >= 1024) ) {
5289      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
5290      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
5291      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5292      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
5293      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
5294      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
5295   } else {
5296      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);
5297   }
5298
5299 }
5300 #endif
5301
5302 static USHORT
5303 SiS_GetVGAHT2(SiS_Private *SiS_Pr)
5304 {
5305   ULONG tempax,tempbx;
5306
5307   tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
5308   tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
5309   tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
5310   return((USHORT)tempax);
5311 }
5312
5313 /* Set Part 1 / SiS bridge slave mode */
5314 static void
5315 SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
5316                   PSIS_HW_INFO HwInfo,USHORT RefreshRateTableIndex)
5317 {
5318   USHORT  push1,push2;
5319   USHORT  tempax,tempbx,tempcx,temp;
5320   USHORT  resinfo,modeflag,xres=0;
5321   unsigned char p1_7, p1_8;
5322
5323   if(ModeNo <= 0x13) {
5324      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5325      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
5326   } else if(SiS_Pr->UseCustomMode) {
5327      modeflag = SiS_Pr->CModeFlag;
5328      resinfo = 0;
5329      xres = SiS_Pr->CHDisplay;
5330   } else {
5331      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5332      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5333      xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
5334   }
5335
5336   /* The following is only done if bridge is in slave mode: */
5337
5338   if((HwInfo->jChipType >= SIS_661) && (ModeNo > 0x13)) {
5339      if(xres >= 1600) {
5340         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
5341      }
5342   }
5343
5344   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0xff);                  /* set MAX HT */
5345
5346   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)  modeflag |= Charx8Dot;
5347
5348   if(modeflag & Charx8Dot) tempcx = 0x08;
5349   else                     tempcx = 0x09;
5350
5351   tempax = SiS_Pr->SiS_VGAHDE;                                  /* 0x04 Horizontal Display End */
5352   if(modeflag & HalfDCLK) tempax >>= 1;
5353   tempax = ((tempax / tempcx) - 1) & 0xff;
5354   tempbx = tempax;
5355
5356   temp = tempax;
5357   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,temp);
5358
5359   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5360      if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
5361         temp += 2;
5362      }
5363   }
5364   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
5365      if(resinfo == SIS_RI_800x600) temp -= 2;
5366   }
5367   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x05,temp);                 /* 0x05 Horizontal Display Start */
5368
5369   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x06,0x03);                 /* 0x06 Horizontal Blank end     */
5370
5371   tempax = 0xFFFF;
5372   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempax = SiS_GetVGAHT2(SiS_Pr);
5373   if(tempax >= SiS_Pr->SiS_VGAHT) tempax = SiS_Pr->SiS_VGAHT;
5374   if(modeflag & HalfDCLK)         tempax >>= 1;
5375   tempax = (tempax / tempcx) - 5;
5376   tempcx = tempax;
5377
5378   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
5379      temp = tempcx - 1;
5380      if(!(modeflag & HalfDCLK)) {
5381         temp -= 6;
5382         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
5383            temp -= 2;
5384            if(ModeNo > 0x13) temp -= 10;
5385         }
5386      }
5387   } else {
5388      tempcx = (tempcx + tempbx) >> 1;
5389      temp = (tempcx & 0x00FF) + 2;
5390      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5391         temp--;
5392         if(!(modeflag & HalfDCLK)) {
5393            if((modeflag & Charx8Dot)) {
5394               temp += 4;
5395               if(SiS_Pr->SiS_VGAHDE >= 800) temp -= 6;
5396               if(HwInfo->jChipType >= SIS_315H) {
5397                  if(SiS_Pr->SiS_VGAHDE == 800) temp += 2;
5398               }
5399            }
5400         }
5401      } else {
5402         if(!(modeflag & HalfDCLK)) {
5403            temp -= 4;
5404            if((SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
5405               (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)) {
5406               if(SiS_Pr->SiS_VGAHDE >= 800) {
5407                  temp -= 7;
5408                  if(HwInfo->jChipType < SIS_315H) {
5409                     if(SiS_Pr->SiS_ModeType == ModeEGA) {
5410                        if(SiS_Pr->SiS_VGAVDE == 1024) {
5411                           temp += 15;
5412                           if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
5413                              temp += 7;
5414                        }
5415                     }
5416                  }
5417                  if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
5418                     if(SiS_Pr->SiS_VGAHDE >= 1280) {
5419                        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
5420                     }
5421                  }
5422               }
5423            }
5424         }
5425      }
5426   }
5427
5428   p1_7 = temp;
5429   p1_8 = 0x00;
5430
5431   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
5432      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
5433         if(ModeNo <= 0x01) {
5434            p1_7 = 0x2a;
5435            if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_8 = 0x61;
5436            else                                 p1_8 = 0x41;
5437         } else if(SiS_Pr->SiS_ModeType == ModeText) {
5438            if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_7 = 0x54;
5439            else                                 p1_7 = 0x55;
5440            p1_8 = 0x00;
5441         } else if(ModeNo <= 0x13) {
5442            if(modeflag & HalfDCLK) {
5443               if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
5444                  p1_7 = 0x30;
5445                  p1_8 = 0x03;
5446               } else {
5447                  p1_7 = 0x2f;
5448                  p1_8 = 0x02;
5449               }
5450            } else {
5451               p1_7 = 0x5b;
5452               p1_8 = 0x03;
5453            }
5454         } else if( ((HwInfo->jChipType >= SIS_315H) &&
5455                     ((ModeNo == 0x50) || (ModeNo == 0x56) || (ModeNo == 0x53))) ||
5456                    ((HwInfo->jChipType < SIS_315H) &&
5457                     (resinfo == SIS_RI_320x200 || resinfo == SIS_RI_320x240)) ) {
5458            if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
5459               p1_7 = 0x30,
5460               p1_8 = 0x03;
5461            } else {
5462               p1_7 = 0x2f;
5463               p1_8 = 0x03;
5464            }
5465         }
5466      }
5467   }
5468
5469   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
5470      if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p)) {
5471         p1_7 = 0x63;
5472         if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) p1_7 = 0x55;
5473      }
5474      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
5475         if(!(modeflag & HalfDCLK)) {
5476            p1_7 = 0xb2;
5477            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
5478               p1_7 = 0xab;
5479            }
5480         }
5481      } else {
5482         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
5483            if(modeflag & HalfDCLK) p1_7 = 0x30;
5484         }
5485      }
5486   }
5487
5488   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,p1_7);                  /* 0x07 Horizontal Retrace Start */
5489   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,p1_8);                  /* 0x08 Horizontal Retrace End   */
5490
5491   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x03);                  /* 0x18 SR08 (FIFO Threshold?)   */
5492
5493   SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x19,0xF0);
5494
5495   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,0xFF);                  /* 0x09 Set Max VT    */
5496
5497   tempcx = 0x121;
5498   tempbx = SiS_Pr->SiS_VGAVDE;                                  /* 0x0E Vertical Display End */
5499   if     (tempbx == 357) tempbx = 350;
5500   else if(tempbx == 360) tempbx = 350;
5501   else if(tempbx == 375) tempbx = 350;
5502   else if(tempbx == 405) tempbx = 400;
5503   else if(tempbx == 420) tempbx = 400;
5504   else if(tempbx == 525) tempbx = 480;
5505   push2 = tempbx;
5506   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
5507      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5508         if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
5509            if     (tempbx == 350) tempbx += 5;
5510            else if(tempbx == 480) tempbx += 5;
5511         }
5512      }
5513   }
5514   tempbx -= 2;
5515   temp = tempbx & 0x00FF;
5516   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);                  /* 0x10 vertical Blank Start */
5517
5518   tempbx = push2;
5519   tempbx--;
5520   temp = tempbx & 0x00FF;
5521 #if 0
5522   /* Missing code from 630/301B 2.04.5a and 650/302LV 1.10.6s (calles int 2f) */
5523   if(xxx()) {
5524       if(temp == 0xdf) temp = 0xda;
5525   }
5526 #endif
5527   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);
5528
5529   temp = 0;
5530   if(modeflag & DoubleScanMode) temp |= 0x80;
5531   if(HwInfo->jChipType >= SIS_661) {
5532      if(tempbx & 0x0200)        temp |= 0x20;
5533      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x0B,0x5F,temp);
5534      if(tempbx & 0x0100)  tempcx |= 0x000a;
5535      if(tempbx & 0x0400)  tempcx |= 0x1200;
5536   } else {
5537      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);
5538      if(tempbx & 0x0100)  tempcx |= 0x0002;
5539      if(tempbx & 0x0400)  tempcx |= 0x0600;
5540   }
5541
5542   if(tempbx & 0x0200)  tempcx |= 0x0040;
5543
5544   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,0x00);                  /* 0x11 Vertical Blank End */
5545
5546   tempax = (SiS_Pr->SiS_VGAVT - tempbx) >> 2;
5547
5548   if((ModeNo > 0x13) || (HwInfo->jChipType < SIS_315H)) {
5549      if(resinfo != SIS_RI_1280x1024) {
5550         tempbx += (tempax << 1);
5551      }
5552   } else if(HwInfo->jChipType >= SIS_315H) {
5553      if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
5554         tempbx += (tempax << 1);
5555      }
5556   }
5557
5558   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
5559      tempbx -= 10;
5560   } else {
5561      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
5562         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
5563            tempbx += 40;
5564            if(HwInfo->jChipType >= SIS_315H) {
5565               if(SiS_Pr->SiS_VGAHDE == 800) tempbx += 10;
5566            }
5567         }
5568      }
5569   }
5570   tempax >>= 2;
5571   tempax++;
5572   tempax += tempbx;
5573   push1 = tempax;
5574   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
5575      if(tempbx <= 513)  {
5576         if(tempax >= 513) tempbx = 513;
5577      }
5578   }
5579   temp = tempbx & 0x00FF;
5580   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                  /* 0x0C Vertical Retrace Start */
5581
5582   tempbx--;
5583   temp = tempbx & 0x00FF;
5584   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);
5585
5586   if(tempbx & 0x0100) tempcx |= 0x0008;
5587
5588   if(tempbx & 0x0200) {
5589      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x0B,0x20);
5590   }
5591   tempbx++;
5592
5593   if(tempbx & 0x0100) tempcx |= 0x0004;
5594   if(tempbx & 0x0200) tempcx |= 0x0080;
5595   if(tempbx & 0x0400) {
5596      if(HwInfo->jChipType >= SIS_661)        tempcx |= 0x0800;
5597      else if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x0800;
5598      else                                    tempcx |= 0x0C00;
5599   }
5600
5601   tempbx = push1;
5602   temp = tempbx & 0x000F;
5603   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                  /* 0x0D vertical Retrace End */
5604
5605   if(tempbx & 0x0010) tempcx |= 0x2000;
5606
5607   temp = tempcx & 0x00FF;
5608   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);                  /* 0x0A CR07 */
5609
5610   temp = (tempcx & 0xFF00) >> 8;
5611   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                  /* 0x17 SR0A */
5612
5613   tempax = modeflag;
5614   temp = (tempax & 0xFF00) >> 8;
5615   temp = (temp >> 1) & 0x09;
5616   if(!(SiS_Pr->SiS_VBType & VB_SIS301)) temp |= 0x01;           /* Always 8 dotclock */
5617   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                  /* 0x16 SR01 */
5618
5619   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00);                  /* 0x0F CR14 */
5620
5621   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00);                  /* 0x12 CR17 */
5622
5623   temp = 0x00;
5624   if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5625      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
5626         temp = 0x80;
5627      }
5628   }
5629   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                  /* 0x1A SR0E */
5630
5631   temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
5632   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
5633 }
5634
5635 /* Setup panel link
5636  * This is used for LVDS, LCDA and Chrontel TV output
5637  * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
5638  */
5639 static void
5640 SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
5641                    PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
5642 {
5643   USHORT modeflag,resinfo;
5644   USHORT push2,tempax,tempbx,tempcx,temp;
5645   ULONG tempeax=0,tempebx,tempecx,tempvcfact=0;
5646   BOOLEAN islvds = FALSE, issis  = FALSE, chkdclkfirst = FALSE;
5647 #ifdef SIS300
5648   USHORT crt2crtc;
5649 #endif
5650 #ifdef SIS315H
5651   USHORT pushcx;
5652 #endif
5653
5654   if(ModeNo <= 0x13) {
5655      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
5656      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
5657 #ifdef SIS300
5658      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5659 #endif
5660   } else if(SiS_Pr->UseCustomMode) {
5661      modeflag = SiS_Pr->CModeFlag;
5662      resinfo = 0;
5663 #ifdef SIS300
5664      crt2crtc = 0;
5665 #endif
5666   } else {
5667      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
5668      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
5669 #ifdef SIS300
5670      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
5671 #endif
5672   }
5673
5674   /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
5675   if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
5676      islvds = TRUE;
5677   }
5678
5679   /* is really sis if sis bridge, but not 301B-DH */
5680   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
5681      issis = TRUE;
5682   }
5683
5684   if((HwInfo->jChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
5685      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
5686         chkdclkfirst = TRUE;
5687      }
5688   }
5689
5690 #ifdef SIS315H
5691   if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
5692      if(IS_SIS330) {
5693         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5694      } else if(IS_SIS740) {
5695         if(islvds) {
5696            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5697            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
5698         } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5699            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
5700         }
5701      } else {
5702         if(islvds) {
5703            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
5704            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
5705         } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
5706            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
5707            if(SiS_Pr->SiS_VBType & VB_SIS301C) {
5708               if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
5709                  (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
5710                  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
5711               }
5712            }
5713         }
5714      }
5715   }
5716 #endif
5717
5718   /* Horizontal */
5719
5720   tempax = SiS_Pr->SiS_LCDHDES;
5721   if(islvds) {
5722      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5723         if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
5724            if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
5725               (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
5726               tempax -= 8;
5727            }
5728         }
5729      }
5730   }
5731
5732   temp = (tempax & 0x0007);
5733   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                  /* BPLHDESKEW[2:0]   */
5734   temp = (tempax >> 3) & 0x00FF;
5735   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                  /* BPLHDESKEW[10:3]  */
5736
5737   tempbx = SiS_Pr->SiS_HDE;
5738   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5739      if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
5740         (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
5741         tempbx >>= 1;
5742      }
5743      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5744         tempbx = SiS_Pr->PanelXRes;
5745      }
5746   }
5747
5748   tempax += tempbx;
5749   if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
5750
5751   temp = tempax;
5752   if(temp & 0x07) temp += 8;
5753   temp >>= 3;
5754   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                  /* BPLHDEE  */
5755
5756   tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
5757
5758   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5759      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5760         if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
5761      }
5762   }
5763
5764   tempcx += tempax;
5765   if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
5766
5767   temp = (tempcx >> 3) & 0x00FF;
5768   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5769      if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5770         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5771            switch(ModeNo) {
5772            case 0x04:
5773            case 0x05:
5774            case 0x0d: temp = 0x56; break;
5775            case 0x10: temp = 0x60; break;
5776            case 0x13: temp = 0x5f; break;
5777            case 0x40:
5778            case 0x41:
5779            case 0x4f:
5780            case 0x43:
5781            case 0x44:
5782            case 0x62:
5783            case 0x56:
5784            case 0x53:
5785            case 0x5d:
5786            case 0x5e: temp = 0x54; break;
5787            }
5788         }
5789      }
5790   }
5791   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);                  /* BPLHRS */
5792
5793   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5794      temp += 2;
5795      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5796         temp += 8;
5797         if(SiS_Pr->PanelHRE != 999) {
5798            temp = tempcx + SiS_Pr->PanelHRE;
5799            if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
5800            temp >>= 3;
5801         }
5802      }
5803   } else {
5804      temp += 10;
5805   }
5806
5807   temp &= 0x1F;
5808   temp |= ((tempcx & 0x07) << 5);
5809 #if 0
5810   if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;                      /* WRONG? BIOS loads cl, not ah */
5811 #endif
5812   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);                  /* BPLHRE */
5813
5814   /* Vertical */
5815
5816   tempax = SiS_Pr->SiS_VGAVDE;
5817   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5818      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5819         tempax = SiS_Pr->PanelYRes;
5820      }
5821   }
5822
5823   tempbx = SiS_Pr->SiS_LCDVDES + tempax;
5824   if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
5825
5826   push2 = tempbx;
5827
5828   tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
5829   if(HwInfo->jChipType < SIS_315H) {
5830      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5831         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5832            tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
5833         }
5834      }
5835   }
5836   if(islvds) tempcx >>= 1;
5837   else       tempcx >>= 2;
5838
5839   if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
5840       (!(SiS_Pr->SiS_LCDInfo & LCDPass11))                  &&
5841       (SiS_Pr->PanelVRS != 999) ) {
5842      tempcx = SiS_Pr->PanelVRS;
5843      tempbx += tempcx;
5844      if(issis) tempbx++;
5845   } else {
5846      tempbx += tempcx;
5847      if(HwInfo->jChipType < SIS_315H) tempbx++;
5848      else if(issis)                   tempbx++;
5849   }
5850
5851   if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;        /* BPLVRS  */
5852
5853   temp = tempbx & 0x00FF;
5854   if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
5855      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
5856         if(ModeNo == 0x10) temp = 0xa9;
5857      }
5858   }
5859   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
5860
5861   tempcx >>= 3;
5862   tempcx++;
5863
5864   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5865      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
5866         if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
5867      }
5868   }
5869
5870   tempcx += tempbx;
5871   temp = tempcx & 0x000F;
5872   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);        /* BPLVRE  */
5873
5874   temp = ((tempbx >> 8) & 0x07) << 3;
5875   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
5876      if(SiS_Pr->SiS_HDE != 640) {
5877         if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
5878      }
5879   } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
5880   if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
5881   tempbx = 0x87;
5882   if((HwInfo->jChipType >= SIS_315H) ||
5883      (HwInfo->jChipRevision >= 0x30)) {
5884      tempbx = 0x07;
5885      if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
5886         if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
5887      }
5888      /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit mutliplexed) via VGA2 */
5889      if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
5890         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
5891            if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
5892         } else {
5893            if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
5894         }
5895      }
5896   }
5897   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
5898
5899   tempbx = push2;                                               /* BPLVDEE */
5900
5901   tempcx = SiS_Pr->SiS_LCDVDES;                                 /* BPLVDES */
5902
5903   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
5904      switch(SiS_Pr->SiS_LCDResInfo) {
5905      case Panel_640x480:
5906         tempbx = SiS_Pr->SiS_VGAVDE - 1;
5907         tempcx = SiS_Pr->SiS_VGAVDE;
5908         break;
5909      case Panel_800x600:
5910         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5911            if(resinfo == SIS_RI_800x600) tempcx++;
5912         }
5913         break;
5914      case Panel_1024x600:
5915         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5916            if(resinfo == SIS_RI_1024x600) tempcx++;
5917            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
5918               if(resinfo == SIS_RI_800x600) tempcx++;
5919            }
5920         }
5921         break;
5922      case Panel_1024x768:
5923         if(HwInfo->jChipType < SIS_315H) {
5924            if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
5925               if(resinfo == SIS_RI_1024x768) tempcx++;
5926            }
5927         }
5928         break;
5929      }
5930   }
5931
5932   temp = ((tempbx >> 8) & 0x07) << 3;
5933   temp = temp | ((tempcx >> 8) & 0x07);
5934   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
5935   /* if(SiS_Pr->SiS_IF_DEF_FSTN) tempbx++;  */
5936   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
5937   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
5938
5939   /* Vertical scaling */
5940
5941   if(HwInfo->jChipType < SIS_315H) {
5942
5943 #ifdef SIS300      /* 300 series */
5944      tempeax = SiS_Pr->SiS_VGAVDE << 6;
5945      temp = (tempeax % (ULONG)SiS_Pr->SiS_VDE);
5946      tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
5947      if(temp) tempeax++;
5948
5949      if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
5950
5951      temp = (USHORT)(tempeax & 0x00FF);
5952      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);       /* BPLVCFACT */
5953      tempvcfact = temp;
5954 #endif /* SIS300 */
5955
5956   } else {
5957
5958 #ifdef SIS315H  /* 315 series */
5959      tempeax = SiS_Pr->SiS_VGAVDE << 18;
5960      tempebx = SiS_Pr->SiS_VDE;
5961      temp = (tempeax % tempebx);
5962      tempeax = tempeax / tempebx;
5963      if(temp) tempeax++;
5964      tempvcfact = tempeax;
5965
5966      temp = (USHORT)(tempeax & 0x00FF);
5967      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
5968      temp = (USHORT)((tempeax & 0x00FF00) >> 8);
5969      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
5970      temp = (USHORT)((tempeax & 0x00030000) >> 16);
5971      if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
5972      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
5973
5974      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
5975         temp = (USHORT)(tempeax & 0x00FF);
5976         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
5977         temp = (USHORT)((tempeax & 0x00FF00) >> 8);
5978         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
5979         temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
5980         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
5981         temp = 0;
5982         if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
5983         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
5984      }
5985 #endif
5986
5987   }
5988
5989   /* Horizontal scaling */
5990
5991   tempeax = SiS_Pr->SiS_VGAHDE;         /* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
5992   if(chkdclkfirst) {
5993      if(modeflag & HalfDCLK) tempeax >>= 1;
5994   }
5995   tempebx = tempeax << 16;
5996   if(SiS_Pr->SiS_HDE == tempeax) {
5997      tempecx = 0xFFFF;
5998   } else {
5999      tempecx = tempebx / SiS_Pr->SiS_HDE;
6000      if(HwInfo->jChipType >= SIS_315H) {
6001         if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
6002      }
6003   }
6004
6005   if(HwInfo->jChipType >= SIS_315H) {
6006      tempeax = (tempebx / tempecx) - 1;
6007   } else {
6008      tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
6009   }
6010   tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
6011   temp = (USHORT)(tempecx & 0x00FF);
6012   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
6013
6014   if(HwInfo->jChipType >= SIS_315H) {
6015      tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
6016      tempbx = (USHORT)(tempeax & 0xFFFF);
6017   } else {
6018      tempeax = SiS_Pr->SiS_VGAVDE << 6;
6019      tempbx = tempvcfact & 0x3f;
6020      if(tempbx == 0) tempbx = 64;
6021      tempeax /= tempbx;
6022      tempbx = (USHORT)(tempeax & 0xFFFF);
6023   }
6024   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
6025   if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
6026      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
6027      else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480)             tempbx = 1;
6028   }
6029
6030   temp = ((tempbx >> 8) & 0x07) << 3;
6031   temp = temp | ((tempecx >> 8) & 0x07);
6032   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
6033   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
6034
6035   tempecx >>= 16;                                               /* BPLHCFACT  */
6036   if(!chkdclkfirst) {
6037      if(modeflag & HalfDCLK) tempecx >>= 1;
6038   }
6039   temp = (USHORT)((tempecx & 0xFF00) >> 8);
6040   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
6041   temp = (USHORT)(tempecx & 0x00FF);
6042   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
6043
6044 #ifdef SIS315H
6045   if(HwInfo->jChipType >= SIS_315H) {
6046      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
6047         if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
6048            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
6049         }
6050      } else {
6051         if(islvds) {
6052            if(HwInfo->jChipType == SIS_740) {
6053               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
6054            } else {
6055               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
6056            }
6057         }
6058      }
6059   }
6060 #endif
6061
6062 #ifdef SIS300
6063   if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
6064      int i;
6065      UCHAR TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
6066      UCHAR TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
6067      UCHAR TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
6068
6069      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
6070      for(i=0; i<5; i++) {
6071         SiS_SetTrumpionBlock(SiS_Pr, &SiS300_TrumpionData[crt2crtc][0]);
6072      }
6073      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6074         if(ModeNo == 0x13) {
6075            for(i=0; i<4; i++) {
6076               SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
6077            }
6078         } else if(ModeNo == 0x10) {
6079            for(i=0; i<4; i++) {
6080               SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
6081               SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
6082            }
6083         }
6084      }
6085      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
6086   }
6087 #endif
6088
6089 #ifdef SIS315H
6090   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
6091      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x25,0x00);
6092      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x26,0x00);
6093      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x27,0x00);
6094      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
6095      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
6096      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
6097      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
6098      tempax = SiS_Pr->SiS_HDE;                                  /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
6099      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6100         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
6101      tempax += 64;
6102      temp = tempax & 0x00FF;
6103      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,temp);
6104      temp = ((tempax & 0xFF00) >> 8) << 3;
6105      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
6106      tempax += 32;                                              /* Blpe=lBlps+32 */
6107      temp = tempax & 0x00FF;
6108      if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0;
6109      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,temp);
6110      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00);               /* Bflml=0 */
6111      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
6112
6113      tempax = SiS_Pr->SiS_VDE;
6114      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6115         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
6116      tempax >>= 1;
6117      temp = tempax & 0x00FF;
6118      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,temp);
6119      temp = ((tempax & 0xFF00) >> 8) << 3;
6120      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
6121
6122      tempeax = SiS_Pr->SiS_HDE;
6123      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6124         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempeax >>= 1;
6125      tempeax <<= 2;                                             /* BDxFIFOSTOP = (HDE*4)/128 */
6126      tempebx = 128;
6127      temp = (USHORT)(tempeax % tempebx);
6128      tempeax = tempeax / tempebx;
6129      if(temp) tempeax++;
6130      temp = (USHORT)(tempeax & 0x003F);
6131      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x45,~0x0FF,temp);
6132      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00);               /* BDxWadrst0 */
6133      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
6134      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
6135      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
6136
6137      tempax = SiS_Pr->SiS_HDE;
6138      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6139         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
6140      tempax >>= 4;                                              /* BDxWadroff = HDE*4/8/8 */
6141      pushcx = tempax;
6142      temp = tempax & 0x00FF;
6143      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
6144      temp = ((tempax & 0xFF00) >> 8) << 3;
6145      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
6146
6147      tempax = SiS_Pr->SiS_VDE;                                  /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
6148      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
6149         SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
6150      tempeax = (tempax * pushcx);
6151      tempebx = 0x00100000 + tempeax;
6152      temp = (USHORT)tempebx & 0x000000FF;
6153      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
6154      temp = (USHORT)((tempebx & 0x0000FF00) >> 8);
6155      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
6156      temp = (USHORT)((tempebx & 0x00FF0000) >> 16);
6157      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
6158      temp = (USHORT)(((tempebx & 0x01000000) >> 24) << 7);
6159      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
6160
6161      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
6162      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0x50);
6163      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,0x00);
6164      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x01);
6165      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0x38);
6166
6167      if(SiS_Pr->SiS_IF_DEF_FSTN) {
6168         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2b,0x02);
6169         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2c,0x00);
6170         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x00);
6171         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,0x0c);
6172         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,0x00);
6173         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,0x00);
6174         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,0x80);
6175         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,0xA0);
6176         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3a,0x00);
6177         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
6178         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3c,0x00);
6179         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3d,0x10);
6180         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3e,0x00);
6181         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3f,0x00);
6182         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,0x10);
6183         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,0x25);
6184         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,0x80);
6185         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,0x14);
6186         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x44,0x03);
6187         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,0x0a);
6188      }
6189   }
6190 #endif  /* SIS315H */
6191 }
6192
6193 /* Set Part 1 */
6194 static void
6195 SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
6196               PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
6197 {
6198 #if defined(SIS300) || defined(SIS315H)
6199   UCHAR   *ROMAddr = HwInfo->pjVirtualRomBase;
6200 #endif
6201   USHORT  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
6202   USHORT  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
6203 #ifdef SIS315H
6204   USHORT  tempbl=0;
6205 #endif
6206
6207   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
6208      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
6209      return;
6210   }
6211
6212   if(ModeNo <= 0x13) {
6213      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6214   } else if(SiS_Pr->UseCustomMode) {
6215      modeflag = SiS_Pr->CModeFlag;
6216   } else {
6217      CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
6218      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
6219      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6220   }
6221
6222   SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
6223
6224   if( ! ((HwInfo->jChipType >= SIS_315H) &&
6225          (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
6226          (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
6227
6228      if(HwInfo->jChipType < SIS_315H ) {
6229 #ifdef SIS300
6230         SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
6231 #endif
6232      } else {
6233 #ifdef SIS315H
6234         SiS_SetCRT2FIFO_310(SiS_Pr, HwInfo);
6235 #endif
6236      }
6237
6238      /* 1. Horizontal setup */
6239
6240      if(HwInfo->jChipType < SIS_315H ) {
6241
6242 #ifdef SIS300   /* ------------- 300 series --------------*/
6243
6244         temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;                   /* BTVGA2HT 0x08,0x09 */
6245         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
6246
6247         temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
6248         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
6249
6250         temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
6251         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
6252
6253         pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
6254         tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
6255         tempbx = pushbx + tempcx;
6256         tempcx <<= 1;
6257         tempcx += tempbx;
6258
6259         bridgeadd = 12;
6260
6261 #endif /* SIS300 */
6262
6263      } else {
6264
6265 #ifdef SIS315H  /* ------------------- 315/330 series --------------- */
6266
6267         tempcx = SiS_Pr->SiS_VGAHT;                               /* BTVGA2HT 0x08,0x09 */
6268         if(modeflag & HalfDCLK) {
6269            if(SiS_Pr->SiS_VBType & VB_SISVB) {
6270               tempcx >>= 1;
6271            } else {
6272               tempax = SiS_Pr->SiS_VGAHDE >> 1;
6273               tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
6274               if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
6275                  tempcx = SiS_Pr->SiS_HT - tempax;
6276               }
6277            }
6278         }
6279         tempcx--;
6280         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx);            /* CRT2 Horizontal Total */
6281         temp = (tempcx >> 4) & 0xF0;
6282         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
6283
6284         tempcx = SiS_Pr->SiS_VGAHT;                               /* BTVGA2HDEE 0x0A,0x0C */
6285         tempbx = SiS_Pr->SiS_VGAHDE;
6286         tempcx -= tempbx;
6287         tempcx >>= 2;
6288         if(modeflag & HalfDCLK) {
6289            tempbx >>= 1;
6290            tempcx >>= 1;
6291         }
6292         tempbx += 16;
6293
6294         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx);            /* CRT2 Horizontal Display Enable End */
6295
6296         pushbx = tempbx;
6297         tempcx >>= 1;
6298         tempbx += tempcx;
6299         tempcx += tempbx;
6300
6301         bridgeadd = 16;
6302
6303         if(SiS_Pr->SiS_VBType & VB_SISVB) {
6304            if(HwInfo->jChipType >= SIS_661) {
6305               if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
6306                  (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
6307                  if(resinfo == SIS_RI_1280x1024) {
6308                     tempcx = (tempcx & 0xff00) | 0x30;
6309                  } else if(resinfo == SIS_RI_1600x1200) {
6310                     tempcx = (tempcx & 0xff00) | 0xff;
6311                  }
6312               }
6313            }
6314         }
6315
6316 #endif  /* SIS315H */
6317
6318      }  /* 315/330 series */
6319
6320      if(SiS_Pr->SiS_VBType & VB_SISVB) {
6321
6322         if(SiS_Pr->UseCustomMode) {
6323            tempbx = SiS_Pr->CHSyncStart + bridgeadd;
6324            tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
6325            tempax = SiS_Pr->SiS_VGAHT;
6326            if(modeflag & HalfDCLK) tempax >>= 1;
6327            tempax--;
6328            if(tempcx > tempax) tempcx = tempax;
6329         }
6330
6331         if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6332            unsigned char cr4, cr14, cr5, cr15;
6333            if(SiS_Pr->UseCustomMode) {
6334               cr4  = SiS_Pr->CCRT1CRTC[4];
6335               cr14 = SiS_Pr->CCRT1CRTC[14];
6336               cr5  = SiS_Pr->CCRT1CRTC[5];
6337               cr15 = SiS_Pr->CCRT1CRTC[15];
6338            } else {
6339               cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
6340               cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
6341               cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
6342               cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
6343            }
6344            tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3;                /* (VGAHRS-3)*8 */
6345            tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
6346            tempcx &= 0x00FF;
6347            tempcx |= (tempbx & 0xFF00);
6348            tempbx += bridgeadd;
6349            tempcx += bridgeadd;
6350            tempax = SiS_Pr->SiS_VGAHT;
6351            if(modeflag & HalfDCLK) tempax >>= 1;
6352            tempax--;
6353            if(tempcx > tempax) tempcx = tempax;
6354         }
6355
6356         if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6357            tempbx = 1040;
6358            tempcx = 1044;   /* HWCursor bug! */
6359         }
6360
6361      }
6362
6363      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx);               /* CRT2 Horizontal Retrace Start */
6364
6365      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx);               /* CRT2 Horizontal Retrace End */
6366
6367      temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
6368      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                 /* Overflow */
6369
6370      /* 2. Vertical setup */
6371
6372      tempcx = SiS_Pr->SiS_VGAVT - 1;
6373      temp = tempcx & 0x00FF;
6374
6375      if(HwInfo->jChipType < SIS_661) {
6376         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6377            if(HwInfo->jChipType < SIS_315H) {
6378               if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6379                  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
6380                     temp--;
6381                  }
6382               }
6383            } else {
6384               temp--;
6385            }
6386         } else if(HwInfo->jChipType >= SIS_315H) {
6387            temp--;
6388         }
6389      }
6390      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
6391
6392      tempbx = SiS_Pr->SiS_VGAVDE - 1;
6393      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx);               /* CRT2 Vertical Display Enable End */
6394
6395      temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
6396      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
6397
6398      if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
6399         tempbx++;
6400         tempax = tempbx;
6401         tempcx++;
6402         tempcx -= tempax;
6403         tempcx >>= 2;
6404         tempbx += tempcx;
6405         if(tempcx < 4) tempcx = 4;
6406         tempcx >>= 2;
6407         tempcx += tempbx;
6408         tempcx++;
6409      } else {
6410         tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
6411         tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
6412      }
6413
6414      if(SiS_Pr->SiS_VBType & VB_SISVB) {
6415         if(SiS_Pr->UseCustomMode) {
6416            tempbx = SiS_Pr->CVSyncStart;
6417            tempcx = SiS_Pr->CVSyncEnd;
6418         }
6419         if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
6420            unsigned char cr8, cr7, cr13;
6421            if(SiS_Pr->UseCustomMode) {
6422               cr8    = SiS_Pr->CCRT1CRTC[8];
6423               cr7    = SiS_Pr->CCRT1CRTC[7];
6424               cr13   = SiS_Pr->CCRT1CRTC[13];
6425               tempcx = SiS_Pr->CCRT1CRTC[9];
6426            } else {
6427               cr8    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
6428               cr7    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
6429               cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
6430               tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
6431            }
6432            tempbx = cr8;
6433            if(cr7  & 0x04) tempbx |= 0x0100;
6434            if(cr7  & 0x80) tempbx |= 0x0200;
6435            if(cr13 & 0x08) tempbx |= 0x0400;
6436         }
6437      }
6438      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
6439
6440      temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
6441      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow */
6442
6443      /* 3. Panel delay compensation */
6444
6445      if(HwInfo->jChipType < SIS_315H) {
6446
6447 #ifdef SIS300  /* ---------- 300 series -------------- */
6448
6449         if(SiS_Pr->SiS_VBType & VB_SISVB) {
6450            temp = 0x20;
6451            if(HwInfo->jChipType == SIS_300) {
6452               temp = 0x10;
6453               if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
6454               if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6455            }
6456            if(SiS_Pr->SiS_VBType & VB_SIS301) {
6457               if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
6458            }
6459            if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
6460            if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
6461            if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)             temp = 0x08;
6462            if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6463               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)       temp = 0x2c;
6464               else                                          temp = 0x20;
6465            }
6466            if(SiS_Pr->SiS_UseROM) {
6467               if(ROMAddr[0x220] & 0x80) {
6468                  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
6469                     temp = ROMAddr[0x221];
6470                  else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
6471                     temp = ROMAddr[0x222];
6472                  else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
6473                     temp = ROMAddr[0x223];
6474                  else
6475                     temp = ROMAddr[0x224];
6476                  temp &= 0x3c;
6477               }
6478            }
6479            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6480               if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC & 0x3c;
6481            }
6482
6483         } else {
6484            temp = 0x20;
6485            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
6486               if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
6487            }
6488            if(SiS_Pr->SiS_UseROM) {
6489               if(ROMAddr[0x220] & 0x80) {
6490                  temp = ROMAddr[0x220] & 0x3c;
6491               }
6492            }
6493            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6494               if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
6495            }
6496         }
6497
6498         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
6499
6500 #endif  /* SIS300 */
6501
6502      } else {
6503
6504 #ifdef SIS315H   /* --------------- 315/330 series ---------------*/
6505
6506         if(HwInfo->jChipType < SIS_661) {
6507
6508            if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
6509
6510               if(HwInfo->jChipType == SIS_740) temp = 0x03;
6511               else                             temp = 0x00;
6512
6513               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
6514               tempbl = 0xF0;
6515               if(HwInfo->jChipType == SIS_650) {
6516                  if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6517                     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
6518                  }
6519               }
6520
6521               if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
6522                  temp = 0x08;
6523                  tempbl = 0;
6524                  if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
6525                     if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
6526                  }
6527               }
6528
6529               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp);      /* Panel Link Delay Compensation */
6530            }
6531
6532         } /* < 661 */
6533
6534         tempax = 0;
6535         if(modeflag & DoubleScanMode) tempax |= 0x80;
6536         if(modeflag & HalfDCLK)       tempax |= 0x40;
6537         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
6538
6539 #endif  /* SIS315H */
6540
6541      }
6542
6543   }  /* Slavemode */
6544
6545   if(SiS_Pr->SiS_VBType & VB_SISVB) {
6546      if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
6547         /* For 301BDH with LCD, we set up the Panel Link */
6548         SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
6549      } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6550         SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
6551      }
6552   } else {
6553      if(HwInfo->jChipType < SIS_315H) {
6554         SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
6555      } else {
6556         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
6557            if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
6558               SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
6559            }
6560         } else {
6561            SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
6562         }
6563      }
6564   }
6565 }
6566
6567 /*********************************************/
6568 /*         SET PART 2 REGISTER GROUP         */
6569 /*********************************************/
6570
6571 #ifdef SIS315H
6572 static UCHAR *
6573 SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
6574 {
6575    const UCHAR  *tableptr = NULL;
6576    USHORT       a, b, p = 0;
6577
6578    a = SiS_Pr->SiS_VGAHDE;
6579    b = SiS_Pr->SiS_HDE;
6580    if(tabletype) {
6581       a = SiS_Pr->SiS_VGAVDE;
6582       b = SiS_Pr->SiS_VDE;
6583    }
6584
6585    if(a < b) {
6586       tableptr = SiS_Part2CLVX_1;
6587    } else if(a == b) {
6588       tableptr = SiS_Part2CLVX_2;
6589    } else {
6590       if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6591          tableptr = SiS_Part2CLVX_4;
6592       } else {
6593          tableptr = SiS_Part2CLVX_3;
6594       }
6595       if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6596          if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)        tableptr = SiS_Part2CLVX_3;
6597          else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   tableptr = SiS_Part2CLVX_3;
6598          else                                           tableptr = SiS_Part2CLVX_5;
6599       } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6600          tableptr = SiS_Part2CLVX_6;
6601       }
6602       do {
6603          if((tableptr[p] | tableptr[p+1] << 8) == a) break;
6604          p += 0x42;
6605       } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
6606       if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
6607    }
6608    p += 2;
6609    return((UCHAR *)&tableptr[p]);
6610 }
6611
6612 static void
6613 SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
6614                     USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
6615 {
6616    UCHAR *tableptr;
6617    int i, j;
6618    UCHAR temp;
6619
6620    if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
6621
6622    tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0, HwInfo);
6623    for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
6624       SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6625    }
6626    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
6627       tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1, HwInfo);
6628       for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
6629          SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
6630       }
6631    }
6632    temp = 0x10;
6633    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp |= 0x04;
6634    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
6635 }
6636
6637 static BOOLEAN
6638 SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
6639                     USHORT RefreshRateTableIndex,USHORT *CRT2Index,
6640                     USHORT *ResIndex,PSIS_HW_INFO HwInfo)
6641 {
6642
6643   if(HwInfo->jChipType < SIS_315H) return FALSE;
6644
6645   if(ModeNo <= 0x13)
6646      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6647   else
6648      (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6649
6650   (*ResIndex) &= 0x3f;
6651   (*CRT2Index) = 0;
6652
6653   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6654      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6655         (*CRT2Index) = 200;
6656      }
6657   }
6658
6659   if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
6660      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
6661         if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
6662      }
6663   }
6664   return(((*CRT2Index) != 0));
6665 }
6666 #endif
6667
6668 #ifdef SIS300
6669 static void
6670 SiS_Group2LCDSpecial(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT crt2crtc)
6671 {
6672    USHORT tempcx;
6673    const UCHAR atable[] = {
6674        0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
6675        0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
6676    };
6677
6678    if(!SiS_Pr->UseCustomMode) {
6679       if( ( ( (HwInfo->jChipType == SIS_630) ||
6680               (HwInfo->jChipType == SIS_730) ) &&
6681             (HwInfo->jChipRevision > 2) )  &&
6682           (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
6683           (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
6684           (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
6685          if(ModeNo == 0x13) {
6686             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
6687             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
6688             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
6689          } else {
6690             if((crt2crtc & 0x3F) == 4) {
6691                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
6692                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
6693                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
6694                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
6695                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
6696             }
6697          }
6698       }
6699
6700       if(HwInfo->jChipType < SIS_315H) {
6701          if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
6702             crt2crtc &= 0x1f;
6703             tempcx = 0;
6704             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6705                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6706                   tempcx += 7;
6707                }
6708             }
6709             tempcx += crt2crtc;
6710             if(crt2crtc >= 4) {
6711                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
6712             }
6713
6714             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
6715                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6716                   if(crt2crtc == 4) {
6717                      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
6718                   }
6719                }
6720             }
6721             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
6722             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
6723          }
6724       }
6725    }
6726 }
6727
6728 /* For ECS A907. Highly preliminary. */
6729 static void
6730 SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
6731                     USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
6732                     USHORT ModeNo)
6733 {
6734   USHORT crt2crtc, resindex;
6735   int    i,j;
6736   const  SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
6737
6738   if(HwInfo->jChipType != SIS_300) return;
6739   if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
6740   if(SiS_Pr->UseCustomMode) return;
6741
6742   if(ModeNo <= 0x13) {
6743      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6744   } else {
6745      crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6746   }
6747
6748   resindex = crt2crtc & 0x3F;
6749   if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6750   else                                    CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
6751
6752   /* The BIOS code (1.16.51,56) is obviously a fragment! */
6753   if(ModeNo > 0x13) {
6754      CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
6755      resindex = 4;
6756   }
6757
6758   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
6759   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
6760   for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
6761         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6762   }
6763   for(j = 0x1c; j <= 0x1d; i++, j++ ) {
6764         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6765   }
6766   for(j = 0x1f; j <= 0x21; i++, j++ ) {
6767         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
6768   }
6769   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
6770   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
6771 }
6772 #endif
6773
6774 static void
6775 SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo)
6776 {
6777   if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
6778   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
6779   if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
6780
6781   if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
6782      if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6783         const UCHAR specialtv[] = {
6784                 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
6785                 0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
6786                 0x58,0xe4,0x73,0xda,0x13
6787         };
6788         int i, j;
6789         for(i = 0x1c, j = 0; i <= 0x30; i++, j++) {
6790            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,specialtv[j]);
6791         }
6792         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,0x72);
6793         if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
6794            if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6795               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
6796               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
6797            } else {
6798               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);  /* 15 */
6799               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a);  /* 1b */
6800            }
6801         }
6802      }
6803   } else {
6804      if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
6805         (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
6806         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 21 */
6807         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 5a */
6808      } else {
6809         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a);  /* 21 */
6810         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53);  /* 5a */
6811      }
6812   }
6813 }
6814
6815 static void
6816 SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
6817 {
6818   USHORT temp;
6819
6820   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
6821      if(SiS_Pr->SiS_VGAVDE == 525) {
6822         temp = 0xc3;
6823         if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6824            temp++;
6825            if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
6826         }
6827         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6828         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
6829      } else if(SiS_Pr->SiS_VGAVDE == 420) {
6830         temp = 0x4d;
6831         if(SiS_Pr->SiS_ModeType <= ModeVGA) {
6832            temp++;
6833            if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
6834         }
6835         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
6836      }
6837   }
6838
6839   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
6840      if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
6841         if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
6842            SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
6843            /* Not always for LV, see SetGrp2 */
6844         }
6845         temp = 1;
6846         if(ModeNo <= 0x13) temp = 3;
6847         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
6848      }
6849 #if 0
6850      /* 651+301C, for 1280x768 - do I really need that? */
6851      if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
6852         if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
6853            if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
6854               ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
6855               SiS_SetReg(SiS_Part2Port,0x01,0x2b);
6856               SiS_SetReg(SiS_Part2Port,0x02,0x13);
6857               SiS_SetReg(SiS_Part2Port,0x04,0xe5);
6858               SiS_SetReg(SiS_Part2Port,0x05,0x08);
6859               SiS_SetReg(SiS_Part2Port,0x06,0xe2);
6860               SiS_SetReg(SiS_Part2Port,0x1c,0x21);
6861               SiS_SetReg(SiS_Part2Port,0x1d,0x45);
6862               SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
6863               SiS_SetReg(SiS_Part2Port,0x20,0x00);
6864               SiS_SetReg(SiS_Part2Port,0x21,0xa9);
6865               SiS_SetReg(SiS_Part2Port,0x23,0x0b);
6866               SiS_SetReg(SiS_Part2Port,0x25,0x04);
6867            }
6868         }
6869      }
6870 #endif
6871   }
6872 }
6873
6874 static void
6875 SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
6876               PSIS_HW_INFO HwInfo)
6877 {
6878   USHORT      i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
6879   USHORT      push2, modeflag, crt2crtc, bridgeoffset;
6880   ULONG       longtemp;
6881   const       UCHAR *PhasePoint;
6882   const       UCHAR *TimingPoint;
6883 #ifdef SIS315H
6884   USHORT      resindex, CRT2Index;
6885   const       SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
6886
6887   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
6888 #endif
6889
6890   if(ModeNo <= 0x13) {
6891      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
6892      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
6893   } else if(SiS_Pr->UseCustomMode) {
6894      modeflag = SiS_Pr->CModeFlag;
6895      crt2crtc = 0;
6896   } else {
6897      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
6898      crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
6899   }
6900
6901   temp = 0;
6902   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO)) temp |= 0x08;
6903   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x04;
6904   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)     temp |= 0x02;
6905   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)  temp |= 0x01;
6906
6907   if(!(SiS_Pr->SiS_TVMode & TVSetPAL))        temp |= 0x10;
6908
6909   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
6910
6911   PhasePoint  = SiS_Pr->SiS_PALPhase;
6912   TimingPoint = SiS_Pr->SiS_PALTiming;
6913
6914   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
6915
6916      TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
6917      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
6918         TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
6919         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
6920            TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
6921 #if 0
6922            if(!(modeflag & Charx8Dot))  TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
6923 #endif
6924         }
6925      }
6926
6927   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
6928
6929      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      TimingPoint = &SiS_YPbPrTable[2][0];
6930      else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) TimingPoint = &SiS_YPbPrTable[1][0];
6931      else                                         TimingPoint = &SiS_YPbPrTable[0][0];
6932
6933      PhasePoint = SiS_Pr->SiS_NTSCPhase;
6934
6935   } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
6936
6937      if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
6938          ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6939            (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6940         PhasePoint = SiS_Pr->SiS_PALPhase2;
6941      }
6942
6943   } else {
6944
6945      TimingPoint = SiS_Pr->SiS_NTSCTiming;
6946      PhasePoint  = SiS_Pr->SiS_NTSCPhase;
6947      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
6948         PhasePoint = SiS_Pr->SiS_PALPhase;
6949      }
6950
6951      if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
6952          ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6953            (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6954         PhasePoint = SiS_Pr->SiS_NTSCPhase2;
6955         if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
6956            PhasePoint = SiS_Pr->SiS_PALPhase2;
6957         }
6958      }
6959
6960   }
6961
6962   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6963      PhasePoint = SiS_Pr->SiS_PALMPhase;
6964      if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
6965          ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6966            (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6967         PhasePoint = SiS_Pr->SiS_PALMPhase2;
6968      }
6969   }
6970
6971   if(SiS_Pr->SiS_TVMode & TVSetPALN) {
6972      PhasePoint = SiS_Pr->SiS_PALNPhase;
6973      if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
6974          ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
6975            (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
6976         PhasePoint = SiS_Pr->SiS_PALNPhase2;
6977      }
6978   }
6979
6980   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
6981      PhasePoint = SiS_Pr->SiS_SpecialPhase;
6982      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
6983         PhasePoint = SiS_Pr->SiS_SpecialPhaseM;
6984      } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
6985         PhasePoint = SiS_Pr->SiS_SpecialPhaseJ;
6986      }
6987   }
6988
6989   for(i=0x31, j=0; i<=0x34; i++, j++) {
6990      SiS_SetReg(SiS_Pr->SiS_Part2Port,i,PhasePoint[j]);
6991   }
6992
6993   for(i=0x01, j=0; i<=0x2D; i++, j++) {
6994      SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6995   }
6996   for(i=0x39; i<=0x45; i++, j++) {
6997      SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
6998   }
6999
7000   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7001      if(SiS_Pr->SiS_ModeType != ModeText) {
7002         SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
7003      }
7004   }
7005
7006   SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
7007
7008   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,SiS_Pr->SiS_RY1COE);
7009   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,SiS_Pr->SiS_RY2COE);
7010   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
7011   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
7012
7013   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)    tempax = 950;
7014   else if(SiS_Pr->SiS_TVMode & TVSetPAL)        tempax = 520;
7015   else                                          tempax = 440; /* NTSC, YPbPr 525, 750 */
7016
7017   if( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) && (SiS_Pr->SiS_VDE <= tempax) ) ||
7018       ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
7019         ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
7020
7021      tempax -= SiS_Pr->SiS_VDE;
7022      tempax >>= 2;
7023      tempax &= 0x00ff;
7024
7025      temp = tempax + (USHORT)TimingPoint[0];
7026      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7027
7028      temp = tempax + (USHORT)TimingPoint[1];
7029      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7030
7031      if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
7032         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7033            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 19 */
7034            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 52 */
7035         } else {
7036            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
7037            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
7038         }
7039      }
7040
7041   }
7042
7043   tempcx = SiS_Pr->SiS_HT;
7044   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
7045   tempcx--;
7046   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
7047   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
7048   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
7049
7050   tempcx = SiS_Pr->SiS_HT >> 1;
7051   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
7052   tempcx += 7;
7053   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
7054   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
7055
7056   tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
7057   tempbx += tempcx;
7058   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
7059   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
7060
7061   tempbx += 8;
7062   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7063      tempbx -= 4;
7064      tempcx = tempbx;
7065   }
7066   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
7067
7068   j += 2;
7069   tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
7070   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
7071   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
7072
7073   tempcx += 8;
7074   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
7075   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
7076
7077   tempcx = SiS_Pr->SiS_HT >> 1;
7078   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
7079   j += 2;
7080   tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
7081   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
7082
7083   tempcx -= 11;
7084   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
7085      tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
7086   }
7087   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
7088
7089   tempbx = SiS_Pr->SiS_VDE;
7090   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7091      if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
7092      if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
7093      if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
7094   } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
7095              (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
7096      tempbx >>= 1;
7097      if(HwInfo->jChipType >= SIS_315H) {
7098         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7099            if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
7100         } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7101            if(SiS_Pr->SiS_ModeType <= ModeVGA) {
7102               if(crt2crtc == 4) tempbx++;
7103            }
7104         }
7105      }
7106      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7107         if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7108            if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
7109         }
7110         if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
7111            if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
7112         }
7113      }
7114   }
7115   tempbx -= 2;
7116   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
7117
7118   temp = (tempcx >> 8) & 0x0F;
7119   temp |= ((tempbx >> 2) & 0xC0);
7120   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
7121      temp |= 0x10;
7122      if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
7123   }
7124   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
7125
7126   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
7127      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
7128   }
7129
7130 #if 0
7131   /* TEST qqqq */
7132   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7133      for(i=0x01, j=0; i<=0x2D; i++, j++) {
7134         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
7135      }
7136      for(i=0x39; i<=0x45; i++, j++) {
7137         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
7138      }
7139   }
7140 #endif
7141
7142   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
7143      tempbx = SiS_Pr->SiS_VDE;
7144      if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
7145          (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
7146         tempbx >>= 1;
7147      }
7148      tempbx -= 3;
7149      temp = ((tempbx >> 3) & 0x60) | 0x18;
7150      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
7151      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
7152
7153      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
7154         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
7155      }
7156   }
7157
7158   tempbx = 0;
7159   if(!(modeflag & HalfDCLK)) {
7160      if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
7161         tempax = 0;
7162         tempbx |= 0x20;
7163      }
7164   }
7165
7166   tempch = tempcl = 0x01;
7167   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7168      if(SiS_Pr->SiS_VGAHDE >= 1024) {
7169         if((!(modeflag & HalfDCLK)) || (HwInfo->jChipType < SIS_315H)) {
7170            tempch = 0x19;
7171            tempcl = 0x20;
7172            if(SiS_Pr->SiS_VGAHDE >= 1280) {
7173               tempch = 0x14;
7174               tempbx &= ~0x20;
7175            }
7176         }
7177      }
7178   }
7179
7180   if(!(tempbx & 0x20)) {
7181      if(modeflag & HalfDCLK) tempcl <<= 1;
7182      longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
7183      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) longtemp <<= 3;
7184      tempax = longtemp / SiS_Pr->SiS_HDE;
7185      if(longtemp % SiS_Pr->SiS_HDE) tempax++;
7186      tempbx |= ((tempax >> 8) & 0x1F);
7187      tempcx = tempax >> 13;
7188   }
7189
7190   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
7191   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
7192
7193   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
7194
7195      tempcx &= 0x07;
7196      if(tempbx & 0x20) tempcx = 0;
7197      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
7198
7199      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7200         tempbx = 0x0382;
7201         tempcx = 0x007e;
7202      } else {
7203         tempbx = 0x0369;
7204         tempcx = 0x0061;
7205      }
7206      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
7207      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
7208      temp = (tempcx & 0x0300) >> 6;
7209      temp |= ((tempbx >> 8) & 0x03);
7210      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7211         temp |= 0x10;
7212         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)      temp |= 0x20;
7213         else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) temp |= 0x40;
7214      }
7215      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
7216
7217      temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7218      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
7219
7220      SiS_SetTVSpecial(SiS_Pr, ModeNo);
7221
7222      if(SiS_Pr->SiS_VBType & VB_SIS301C) {
7223         temp = 0;
7224         if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
7225         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
7226      }
7227
7228   }
7229
7230   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7231      if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
7232         temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
7233         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
7234      }
7235      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
7236   }
7237
7238   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7239      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
7240         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,0x00);
7241      }
7242   }
7243
7244   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) return;
7245
7246   /* From here: Part2 LCD setup */
7247
7248   tempbx = SiS_Pr->SiS_HDE;
7249   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7250   tempbx--;                                     /* RHACTE = HDE - 1 */
7251   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
7252   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
7253
7254   temp = 0x01;
7255   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7256      if(SiS_Pr->SiS_ModeType == ModeEGA) {
7257         if(SiS_Pr->SiS_VGAHDE >= 1024) {
7258            temp = 0x02;
7259            if(HwInfo->jChipType >= SIS_315H) {
7260               if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7261                  temp = 0x01;
7262               }
7263            }
7264         }
7265      }
7266   }
7267   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
7268
7269   tempbx = SiS_Pr->SiS_VDE - 1;
7270   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
7271   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
7272
7273   tempcx = SiS_Pr->SiS_VT - 1;
7274   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
7275   temp = (tempcx >> 3) & 0xE0;
7276   if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
7277      /* Enable dithering; only do this for 32bpp mode */
7278      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
7279         temp |= 0x10;
7280      }
7281   }
7282   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
7283
7284   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
7285   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
7286
7287   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
7288   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
7289
7290 #ifdef SIS315H
7291   if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7292                                                 &CRT2Index, &resindex, HwInfo)) {
7293       switch(CRT2Index) {
7294         case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
7295         case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
7296         default:  CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;   break;
7297       }
7298
7299       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
7300       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
7301       for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
7302         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7303       }
7304       for(j = 0x1c; j <= 0x1d; i++, j++ ) {
7305         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7306       }
7307       for(j = 0x1f; j <= 0x21; i++, j++ ) {
7308         SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
7309       }
7310       SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
7311       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
7312
7313       SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7314
7315
7316   } else {
7317 #endif
7318
7319     /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
7320     /*             Clevo dual-link 1024x768 */
7321     /*             Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
7322     /*             Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
7323
7324     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7325        if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
7326           tempbx = SiS_Pr->SiS_VDE - 1;
7327           tempcx = SiS_Pr->SiS_VT - 1;
7328        } else {
7329           tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7330           tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
7331        }
7332     } else {
7333        tempbx = SiS_Pr->PanelYRes;
7334        tempcx = SiS_Pr->SiS_VT;
7335        tempax = 1;
7336        if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7337           tempax = SiS_Pr->PanelYRes;
7338           /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
7339           if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
7340              tempax = tempcx = 0;
7341           } else {
7342              tempax -= SiS_Pr->SiS_VDE;
7343           }
7344           tempax >>= 1;
7345        }
7346        tempcx -= tempax; /* lcdvdes */
7347        tempbx -= tempax; /* lcdvdee */
7348     }
7349
7350     /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
7351
7352 #ifdef TWDEBUG
7353     xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
7354 #endif
7355
7356     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);      /* lcdvdes  */
7357     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);      /* lcdvdee  */
7358
7359     temp = (tempbx >> 5) & 0x38;
7360     temp |= ((tempcx >> 8) & 0x07);
7361     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
7362
7363     tempax = SiS_Pr->SiS_VDE;
7364     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7365        tempax = SiS_Pr->PanelYRes;
7366     }
7367     tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
7368     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7369        if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7370           tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
7371        }
7372     }
7373
7374     tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
7375     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7376        if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
7377           if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
7378              tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
7379              if(tempax % 4) { tempax >>= 2; tempax++; }
7380              else           { tempax >>= 2;           }
7381              tempbx -= (tempax - 1);
7382           } else {
7383              tempbx -= 10;
7384              if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
7385           }
7386        }
7387     }
7388     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
7389        tempbx++;
7390        if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
7391           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
7392              tempbx = 770;
7393              tempcx = 3;
7394           }
7395        }
7396     }
7397
7398     /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
7399
7400     if(SiS_Pr->UseCustomMode) {
7401        tempbx = SiS_Pr->CVSyncStart;
7402     }
7403
7404 #ifdef TWDEBUG
7405     xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
7406 #endif
7407
7408     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);          /* lcdvrs */
7409
7410     temp = (tempbx >> 4) & 0xF0;
7411     tempbx += (tempcx + 1);
7412     temp |= (tempbx & 0x0F);
7413
7414     if(SiS_Pr->UseCustomMode) {
7415        temp &= 0xf0;
7416        temp |= (SiS_Pr->CVSyncEnd & 0x0f);
7417     }
7418
7419 #ifdef TWDEBUG
7420     xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
7421 #endif
7422
7423     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
7424
7425 #ifdef SIS300
7426     SiS_Group2LCDSpecial(SiS_Pr, HwInfo, ModeNo, crt2crtc);
7427 #endif
7428
7429     bridgeoffset = 7;
7430     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)          bridgeoffset += 2;
7431     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) bridgeoffset++;
7432     if(SiS_IsDualLink(SiS_Pr, HwInfo))                   bridgeoffset++;
7433
7434     temp = 0;
7435     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7436        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7437           temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7438           if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp >>= 1;
7439        }
7440     }
7441     temp += bridgeoffset;
7442     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);             /* lcdhdes */
7443     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
7444
7445     tempcx = SiS_Pr->SiS_HT;
7446     tempax = tempbx = SiS_Pr->SiS_HDE;
7447     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7448        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
7449           tempax = SiS_Pr->PanelXRes;
7450           tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
7451        }
7452     }
7453     if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
7454        tempcx >>= 1;
7455        tempbx >>= 1;
7456        tempax >>= 1;
7457     }
7458
7459 #ifdef TWDEBUG
7460     xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
7461 #endif
7462
7463     tempbx += bridgeoffset;
7464
7465     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);          /* lcdhdee */
7466     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
7467
7468     tempcx = (tempcx - tempax) >> 2;
7469
7470     tempbx += tempcx;
7471     push2 = tempbx;
7472
7473     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
7474        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
7475           if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
7476              if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
7477           }
7478        }
7479     }
7480
7481     if(SiS_Pr->UseCustomMode) {
7482        tempbx = SiS_Pr->CHSyncStart;
7483        if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7484        tempbx += bridgeoffset;
7485     }
7486
7487 #ifdef TWDEBUG
7488     xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
7489 #endif
7490
7491     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);          /* lcdhrs */
7492     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
7493
7494     tempbx = push2;
7495
7496     tempcx <<= 1;
7497     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
7498        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
7499     }
7500     tempbx += tempcx;
7501
7502     if(SiS_Pr->UseCustomMode) {
7503        tempbx = SiS_Pr->CHSyncEnd;
7504        if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7505        tempbx += bridgeoffset;
7506     }
7507
7508 #ifdef TWDEBUG
7509     xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
7510 #endif
7511
7512     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);          /* lcdhre */
7513
7514     SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
7515
7516 #ifdef SIS300
7517     SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex, RefreshRateTableIndex, ModeNo);
7518 #endif
7519 #ifdef SIS315H
7520   } /* CRT2-LCD from table */
7521 #endif
7522 }
7523
7524 /*********************************************/
7525 /*         SET PART 3 REGISTER GROUP         */
7526 /*********************************************/
7527
7528 static void
7529 SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7530               PSIS_HW_INFO HwInfo)
7531 {
7532   USHORT        i;
7533   const UCHAR   *tempdi;
7534
7535   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
7536
7537 #ifndef SIS_CP
7538   SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
7539 #else
7540   SIS_CP_INIT301_CP
7541 #endif
7542
7543   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
7544      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7545      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7546   } else {
7547      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xF5);
7548      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xB7);
7549   }
7550
7551   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
7552      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x13,0xFA);
7553      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x14,0xC8);
7554      SiS_SetReg(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
7555   }
7556
7557   tempdi = NULL;
7558   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7559      tempdi = SiS_Pr->SiS_HiTVGroup3Data;
7560      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
7561         tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
7562      }
7563   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
7564      if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7565         tempdi = SiS_HiTVGroup3_1;
7566         if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) tempdi = SiS_HiTVGroup3_2;
7567      }
7568   }
7569   if(tempdi) {
7570      for(i=0; i<=0x3E; i++) {
7571         SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
7572      }
7573      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
7574         if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
7575            SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
7576         }
7577      }
7578   }
7579
7580 #ifdef SIS_CP
7581   SIS_CP_INIT301_CP2
7582 #endif
7583 }
7584
7585 /*********************************************/
7586 /*         SET PART 4 REGISTER GROUP         */
7587 /*********************************************/
7588
7589 #ifdef SIS315H
7590 static void
7591 SiS_ShiftXPos(SiS_Private *SiS_Pr, int shift)
7592 {
7593    USHORT temp, temp1, temp2;
7594
7595    temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
7596    temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
7597    temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7598    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
7599    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
7600    temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
7601    temp = (USHORT)((int)(temp) + shift);
7602    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
7603    temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
7604    temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
7605    temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
7606    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
7607    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
7608 }
7609
7610 static void
7611 SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
7612                     USHORT ModeNo, USHORT ModeIdIndex)
7613 {
7614    USHORT temp, temp1, resinfo = 0;
7615
7616    if(!(SiS_Pr->SiS_VBType & VB_SIS301C)) return;
7617    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
7618
7619    if(ModeNo > 0x13) {
7620       resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7621    }
7622
7623    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
7624    temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
7625    if(!(temp & 0x01)) {
7626       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
7627       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
7628       if((HwInfo->jChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
7629          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
7630       }
7631       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
7632       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
7633       else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
7634       else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
7635       else                                         temp = 0x0402;
7636       if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
7637          temp1 = 0;
7638          if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
7639          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
7640          if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
7641          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
7642       } else {
7643          temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
7644          if(temp1 == 0x01) temp |= 0x01;
7645          if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
7646          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
7647       }
7648       SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
7649       if(ModeNo > 0x13) {
7650          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
7651       }
7652
7653       if(HwInfo->jChipType >= SIS_661) {                /* ? */
7654          if(SiS_Pr->SiS_TVMode & TVAspect43) {
7655             if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
7656                if(resinfo == SIS_RI_1024x768) {
7657                   SiS_ShiftXPos(SiS_Pr, 97);
7658                } else {
7659                   SiS_ShiftXPos(SiS_Pr, 111);
7660                }
7661             } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
7662                SiS_ShiftXPos(SiS_Pr, 136);
7663             }
7664          }
7665       }
7666    }
7667 }
7668 #endif
7669
7670 static void
7671 SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7672                  USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
7673 {
7674   USHORT vclkindex;
7675   USHORT temp, reg1, reg2;
7676
7677   if(SiS_Pr->UseCustomMode) {
7678      reg1 = SiS_Pr->CSR2B;
7679      reg2 = SiS_Pr->CSR2C;
7680   } else {
7681      vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7682                                  HwInfo);
7683      reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
7684      reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
7685   }
7686
7687   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
7688      if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
7689         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
7690         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
7691         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
7692      } else {
7693         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7694         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7695      }
7696   } else {
7697      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x01);
7698      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
7699      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
7700   }
7701   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
7702   temp = 0x08;
7703   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
7704   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
7705 }
7706
7707 static void
7708 SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7709               USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
7710 {
7711   USHORT tempax,tempcx,tempbx,modeflag,temp,resinfo;
7712   ULONG tempebx,tempeax,templong;
7713
7714   if(ModeNo <= 0x13) {
7715      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7716      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
7717   } else if(SiS_Pr->UseCustomMode) {
7718      modeflag = SiS_Pr->CModeFlag;
7719      resinfo = 0;
7720   } else {
7721      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7722      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
7723   }
7724
7725   if(HwInfo->jChipType >= SIS_315H) {
7726      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
7727         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7728            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7729         }
7730      }
7731   }
7732
7733   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV)) {
7734      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7735         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
7736      }
7737   }
7738
7739   if(HwInfo->jChipType >= SIS_315H) {
7740      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
7741         if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
7742            if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
7743               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7744            } else {
7745               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7746            }
7747
7748            if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
7749               SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7750 #ifdef SET_EMI
7751               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7752 #endif
7753               SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7754            }
7755         }
7756         return;
7757      }
7758   }
7759
7760   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
7761
7762   tempbx = SiS_Pr->SiS_RVBHCMAX;
7763   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
7764
7765   temp = (tempbx >> 1) & 0x80;
7766
7767   tempcx = SiS_Pr->SiS_VGAHT - 1;
7768   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
7769
7770   temp |= ((tempcx >> 5) & 0x78);
7771
7772   tempcx = SiS_Pr->SiS_VGAVT - 1;
7773   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
7774   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
7775
7776   temp |= ((tempcx >> 8) & 0x07);
7777   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
7778
7779   tempbx = SiS_Pr->SiS_VGAHDE;
7780   if(modeflag & HalfDCLK)            tempbx >>= 1;
7781   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7782
7783   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7784      temp = 0;
7785      if(tempbx > 800)        temp = 0x60;
7786   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7787      temp = 0;
7788      if(tempbx == 1024)      temp = 0xA0;
7789      else if(tempbx > 1024)  temp = 0xC0;
7790   } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
7791      temp = 0;
7792      if(tempbx >= 1280)      temp = 0x40;
7793      else if(tempbx >= 1024) temp = 0x20;
7794   } else {
7795      temp = 0x80;
7796      if(tempbx >= 1024)      temp = 0xA0;
7797   }
7798
7799   if(SiS_Pr->SiS_VBType & VB_SIS301) {
7800      if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) temp |= 0x0A;
7801   }
7802
7803   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
7804
7805   tempeax = SiS_Pr->SiS_VGAVDE;
7806   tempebx = SiS_Pr->SiS_VDE;
7807   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
7808      if(!(temp & 0xE0)) tempebx >>=1;
7809   }
7810
7811   tempcx = SiS_Pr->SiS_RVBHRS;
7812   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
7813   tempcx >>= 8;
7814   tempcx |= 0x40;
7815
7816   if(tempeax <= tempebx) {
7817      tempcx ^= 0x40;
7818   } else {
7819      tempeax -= tempebx;
7820   }
7821
7822   tempeax *= (256 * 1024);
7823   templong = tempeax % tempebx;
7824   tempeax /= tempebx;
7825   if(templong) tempeax++;
7826
7827   temp = (USHORT)(tempeax & 0x000000FF);
7828   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
7829   temp = (USHORT)((tempeax & 0x0000FF00) >> 8);
7830   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
7831   temp = (USHORT)((tempeax >> 12) & 0x70); /* sic! */
7832   temp |= (tempcx & 0x4F);
7833   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
7834
7835   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
7836
7837      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
7838
7839      /* Calc Linebuffer max address and set/clear decimode */
7840      tempbx = 0;
7841      if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
7842      tempax = SiS_Pr->SiS_VGAHDE;
7843      if(modeflag & HalfDCLK)            tempax >>= 1;
7844      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
7845      if(tempax > 800) {
7846         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7847            tempax -= 800;
7848         } else {  /* 651+301C: Only if TVNoHiviNoYPbPr */
7849            tempbx = 0x08;
7850            if(tempax == 1024) tempax *= 25;
7851            else               tempax *= 20;
7852            temp = tempax % 32;
7853            tempax /= 32;
7854            if(temp) tempax++;
7855            tempax++;
7856            if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) ||
7857               (SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
7858               if(resinfo == SIS_RI_1024x768) {
7859                  /* Otherwise white line at right edge */
7860                  tempax = (tempax & 0xff00) | 0x20;
7861               }
7862            }
7863         }
7864      }
7865      tempax--;
7866      temp = ((tempax >> 4) & 0x30) | tempbx;
7867      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
7868      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
7869
7870      temp = 0x0036; tempbx = 0xD0;
7871      if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
7872         temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
7873      }
7874      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
7875         if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
7876            temp |= 0x01;
7877            if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
7878               if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
7879                  temp &= ~0x01;
7880               }
7881            }
7882         }
7883      }
7884      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
7885
7886      tempbx = SiS_Pr->SiS_HT >> 1;
7887      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
7888      tempbx -= 2;
7889      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
7890      temp = (tempbx >> 5) & 0x38;
7891      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
7892
7893      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
7894         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
7895            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
7896            /* LCD-too-dark-error-source, see FinalizeLCD() */
7897         }
7898         if(HwInfo->jChipType >= SIS_315H) {
7899            if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
7900               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
7901            } else {
7902               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
7903            }
7904         }
7905         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
7906            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
7907 #ifdef SET_EMI
7908            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
7909 #endif
7910            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
7911         }
7912      }
7913
7914   }  /* 301B */
7915
7916   SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
7917 }
7918
7919 /*********************************************/
7920 /*         SET PART 5 REGISTER GROUP         */
7921 /*********************************************/
7922
7923 static void
7924 SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7925               PSIS_HW_INFO HwInfo)
7926 {
7927
7928   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)  return;
7929
7930   if(SiS_Pr->SiS_ModeType == ModeVGA) {
7931      if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
7932         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
7933         SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
7934      }
7935   }
7936 }
7937
7938 /*********************************************/
7939 /*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
7940 /*********************************************/
7941
7942 static void
7943 SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
7944                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
7945 {
7946   USHORT tempah,i,modeflag,j;
7947   USHORT ResIndex,DisplayType;
7948   const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL;
7949
7950   if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
7951   else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
7952
7953   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
7954      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
7955      (SiS_Pr->SiS_CustomT == CUT_PANEL848))
7956      return;
7957
7958   if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
7959                           &ResIndex, &DisplayType))) {
7960      return;
7961   }
7962
7963   if(HwInfo->jChipType < SIS_315H) {
7964      if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
7965   }
7966
7967   switch(DisplayType) {
7968     case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1;           break;
7969     case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H;         break;
7970     case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2;           break;
7971     case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H;         break;
7972     case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
7973     case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H;        break;
7974     case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2;          break;
7975     case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H;        break;
7976     case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1;         break;
7977     case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H;       break;
7978     case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2;         break;
7979     case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2_H;       break;
7980     case 12: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1;           break;
7981     case 13: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H;         break;
7982     case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1;         break;
7983     case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1_H;       break;
7984     case 16: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2;         break;
7985     case 17: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2_H;       break;
7986     case 18: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC;               break;
7987     case 19: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC;               break;
7988     case 20: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL;                break;
7989     case 21: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL;                break;
7990     case 22: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x480_1;           break; /* FSTN */
7991     case 23: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1;          break;
7992     case 24: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H;        break;
7993     case 25: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2;          break;
7994     case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H;        break;
7995     case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1;          break;
7996     case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1_H;        break;
7997     case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2;          break;
7998     case 30: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2_H;        break;
7999     case 36: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1;         break;
8000     case 37: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1_H;       break;
8001     case 38: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2;         break;
8002     case 39: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2_H;       break;
8003     case 40: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1;          break;
8004     case 41: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1_H;        break;
8005     case 42: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2;          break;
8006     case 43: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2_H;        break;
8007     case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1;           break;
8008     case 51: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H;         break;
8009     case 52: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2;           break;
8010     case 53: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2_H;         break;
8011     case 54: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3;           break;
8012     case 55: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3_H;         break;
8013     case 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL;               break;
8014     default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
8015   }
8016
8017   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
8018
8019   tempah = (LVDSCRT1Ptr + ResIndex)->CR[0];
8020   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,tempah);
8021
8022   for(i=0x02,j=1;i<=0x05;i++,j++){
8023     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8024     SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
8025   }
8026   for(i=0x06,j=5;i<=0x07;i++,j++){
8027     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8028     SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
8029   }
8030   for(i=0x10,j=7;i<=0x11;i++,j++){
8031     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8032     SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
8033   }
8034   for(i=0x15,j=9;i<=0x16;i++,j++){
8035     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8036     SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
8037   }
8038   for(i=0x0A,j=11;i<=0x0C;i++,j++){
8039     tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
8040     SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
8041   }
8042
8043   tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
8044   tempah &= 0xE0;
8045   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
8046
8047   tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
8048   tempah &= 0x01;
8049   tempah <<= 5;
8050   if(modeflag & DoubleScanMode)  tempah |= 0x080;
8051   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
8052 }
8053
8054 /*********************************************/
8055 /*              SET CRT2 ECLK                */
8056 /*********************************************/
8057
8058 static void
8059 SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
8060            USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
8061 {
8062   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
8063   USHORT clkbase, vclkindex=0;
8064   UCHAR  sr2b, sr2c;
8065
8066   if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) || (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
8067         SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
8068         if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) {
8069            RefreshRateTableIndex--;
8070         }
8071         vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
8072                                     RefreshRateTableIndex, HwInfo);
8073         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8074   } else {
8075         vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
8076                                     RefreshRateTableIndex, HwInfo);
8077   }
8078
8079   sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
8080   sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
8081
8082   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
8083      if(SiS_Pr->SiS_UseROM) {
8084         if(ROMAddr[0x220] & 0x01) {
8085            sr2b = ROMAddr[0x227];
8086            sr2c = ROMAddr[0x228];
8087         }
8088      }
8089   }
8090
8091   clkbase = 0x02B;
8092   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
8093      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
8094         clkbase += 3;
8095      }
8096   }
8097
8098   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
8099   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
8100   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
8101   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
8102   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
8103   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
8104   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
8105   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
8106   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
8107 }
8108
8109 /*********************************************/
8110 /*           SET UP CHRONTEL CHIPS           */
8111 /*********************************************/
8112
8113 static void
8114 SiS_SetCHTVReg(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
8115                USHORT RefreshRateTableIndex)
8116 {
8117 #if defined(SIS300) || defined(SIS315H)
8118   USHORT temp, tempbx;
8119 #endif
8120   USHORT tempcl;
8121   USHORT TVType, resindex;
8122   const SiS_CHTVRegDataStruct *CHTVRegData = NULL;
8123
8124   if(ModeNo <= 0x13)
8125      tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
8126   else
8127      tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
8128
8129   TVType = 0;
8130   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
8131   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
8132         TVType += 2;
8133         if(SiS_Pr->SiS_ModeType > ModeVGA) {
8134            if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
8135         }
8136         if(SiS_Pr->SiS_TVMode & TVSetPALM) {
8137                 TVType = 4;
8138                 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
8139         } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
8140                 TVType = 6;
8141                 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
8142         }
8143   }
8144   switch(TVType) {
8145      case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
8146      case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
8147      case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
8148      case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
8149      case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
8150      case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
8151      case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
8152      case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
8153      case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
8154      default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
8155   }
8156   resindex = tempcl & 0x3F;
8157
8158   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
8159
8160 #ifdef SIS300
8161
8162      /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
8163
8164      /* We don't support modes >800x600 */
8165      if (resindex > 5) return;
8166
8167      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
8168         SiS_SetCH700x(SiS_Pr,0x4304);   /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
8169         SiS_SetCH700x(SiS_Pr,0x6909);   /* Black level for PAL (105)*/
8170      } else {
8171         SiS_SetCH700x(SiS_Pr,0x0304);   /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
8172         SiS_SetCH700x(SiS_Pr,0x7109);   /* Black level for NTSC (113)*/
8173      }
8174
8175      temp = CHTVRegData[resindex].Reg[0];
8176      tempbx=((temp&0x00FF)<<8)|0x00;    /* Mode register */
8177      SiS_SetCH700x(SiS_Pr,tempbx);
8178      temp = CHTVRegData[resindex].Reg[1];
8179      tempbx=((temp&0x00FF)<<8)|0x07;    /* Start active video register */
8180      SiS_SetCH700x(SiS_Pr,tempbx);
8181      temp = CHTVRegData[resindex].Reg[2];
8182      tempbx=((temp&0x00FF)<<8)|0x08;    /* Position overflow register */
8183      SiS_SetCH700x(SiS_Pr,tempbx);
8184      temp = CHTVRegData[resindex].Reg[3];
8185      tempbx=((temp&0x00FF)<<8)|0x0A;    /* Horiz Position register */
8186      SiS_SetCH700x(SiS_Pr,tempbx);
8187      temp = CHTVRegData[resindex].Reg[4];
8188      tempbx=((temp&0x00FF)<<8)|0x0B;    /* Vertical Position register */
8189      SiS_SetCH700x(SiS_Pr,tempbx);
8190
8191      /* Set minimum flicker filter for Luma channel (SR1-0=00),
8192                 minimum text enhancement (S3-2=10),
8193                 maximum flicker filter for Chroma channel (S5-4=10)
8194                 =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
8195       */
8196      SiS_SetCH700x(SiS_Pr,0x2801);
8197
8198      /* Set video bandwidth
8199             High bandwith Luma composite video filter(S0=1)
8200             low bandwith Luma S-video filter (S2-1=00)
8201             disable peak filter in S-video channel (S3=0)
8202             high bandwidth Chroma Filter (S5-4=11)
8203             =00110001=0x31
8204      */
8205      SiS_SetCH700x(SiS_Pr,0xb103);       /* old: 3103 */
8206
8207      /* Register 0x3D does not exist in non-macrovision register map
8208             (Maybe this is a macrovision register?)
8209       */
8210 #ifndef SIS_CP
8211      SiS_SetCH70xx(SiS_Pr,0x003D);
8212 #endif
8213
8214      /* Register 0x10 only contains 1 writable bit (S0) for sensing,
8215             all other bits a read-only. Macrovision?
8216       */
8217      SiS_SetCH70xxANDOR(SiS_Pr,0x0010,0x1F);
8218
8219      /* Register 0x11 only contains 3 writable bits (S0-S2) for
8220             contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
8221       */
8222      SiS_SetCH70xxANDOR(SiS_Pr,0x0211,0xF8);
8223
8224      /* Clear DSEN
8225       */
8226      SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xEF);
8227
8228      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {             /* ---- NTSC ---- */
8229        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
8230          if(resindex == 0x04) {                         /* 640x480 overscan: Mode 16 */
8231            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);      /* loop filter off */
8232            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);      /* ACIV on, no need to set FSCI */
8233          } else if(resindex == 0x05) {                  /* 800x600 overscan: Mode 23 */
8234            SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0);      /* 0x18-0x1f: FSCI 469,762,048 */
8235            SiS_SetCH70xxANDOR(SiS_Pr,0x0C19,0xF0);
8236            SiS_SetCH70xxANDOR(SiS_Pr,0x001A,0xF0);
8237            SiS_SetCH70xxANDOR(SiS_Pr,0x001B,0xF0);
8238            SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xF0);
8239            SiS_SetCH70xxANDOR(SiS_Pr,0x001D,0xF0);
8240            SiS_SetCH70xxANDOR(SiS_Pr,0x001E,0xF0);
8241            SiS_SetCH70xxANDOR(SiS_Pr,0x001F,0xF0);
8242            SiS_SetCH70xxANDOR(SiS_Pr,0x0120,0xEF);       /* Loop filter on for mode 23 */
8243            SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE);       /* ACIV off, need to set FSCI */
8244          }
8245        } else {
8246          if(resindex == 0x04) {                          /* ----- 640x480 underscan; Mode 17 */
8247            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);       /* loop filter off */
8248            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
8249          } else if(resindex == 0x05) {                   /* ----- 800x600 underscan: Mode 24 */
8250 #if 0
8251            SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0);       /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
8252            SiS_SetCH70xxANDOR(SiS_Pr,0x0919,0xF0);       /* FSCI for mode 24 is 428,554,851 */
8253            SiS_SetCH70xxANDOR(SiS_Pr,0x081A,0xF0);       /* 198b3a63 */
8254            SiS_SetCH70xxANDOR(SiS_Pr,0x0b1B,0xF0);
8255            SiS_SetCH70xxANDOR(SiS_Pr,0x041C,0xF0);
8256            SiS_SetCH70xxANDOR(SiS_Pr,0x011D,0xF0);
8257            SiS_SetCH70xxANDOR(SiS_Pr,0x061E,0xF0);
8258            SiS_SetCH70xxANDOR(SiS_Pr,0x051F,0xF0);
8259            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);       /* loop filter off for mode 24 */
8260            SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE);       /* ACIV off, need to set FSCI */
8261 #endif     /* All alternatives wrong (datasheet wrong?), don't use FSCI */
8262            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);       /* loop filter off */
8263            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
8264          }
8265        }
8266      } else {                                           /* ---- PAL ---- */
8267            /* We don't play around with FSCI in PAL mode */
8268          if(resindex == 0x04) {
8269            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);      /* loop filter off */
8270            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);      /* ACIV on */
8271          } else {
8272            SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);      /* loop filter off */
8273            SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);      /* ACIV on */
8274          }
8275      }
8276      
8277 #endif  /* 300 */
8278
8279   } else {
8280
8281      /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
8282
8283 #ifdef SIS315H
8284
8285      /* We don't support modes >1024x768 */
8286      if (resindex > 6) return;
8287
8288      temp = CHTVRegData[resindex].Reg[0];
8289      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
8290         temp |= 0x10;
8291      }
8292      tempbx=((temp & 0x00FF) << 8) | 0x00;
8293      SiS_SetCH701x(SiS_Pr,tempbx);
8294
8295      temp = CHTVRegData[resindex].Reg[1];
8296      tempbx=((temp & 0x00FF) << 8) | 0x01;
8297      SiS_SetCH701x(SiS_Pr,tempbx);
8298
8299      temp = CHTVRegData[resindex].Reg[2];
8300      tempbx=((temp & 0x00FF) << 8) | 0x02;
8301      SiS_SetCH701x(SiS_Pr,tempbx);
8302
8303      temp = CHTVRegData[resindex].Reg[3];
8304      tempbx=((temp & 0x00FF) << 8) | 0x04;
8305      SiS_SetCH701x(SiS_Pr,tempbx);
8306
8307      temp = CHTVRegData[resindex].Reg[4];
8308      tempbx=((temp & 0x00FF) << 8) | 0x03;
8309      SiS_SetCH701x(SiS_Pr,tempbx);
8310
8311      temp = CHTVRegData[resindex].Reg[5];
8312      tempbx=((temp & 0x00FF) << 8) | 0x05;
8313      SiS_SetCH701x(SiS_Pr,tempbx);
8314
8315      temp = CHTVRegData[resindex].Reg[6];
8316      tempbx=((temp & 0x00FF) << 8) | 0x06;
8317      SiS_SetCH701x(SiS_Pr,tempbx);
8318
8319      temp = CHTVRegData[resindex].Reg[7];
8320      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
8321         temp = 0x66;
8322      }
8323      tempbx=((temp & 0x00FF) << 8) | 0x07;
8324      SiS_SetCH701x(SiS_Pr,tempbx);
8325
8326      temp = CHTVRegData[resindex].Reg[8];
8327      tempbx=((temp & 0x00FF) << 8) | 0x08;
8328      SiS_SetCH701x(SiS_Pr,tempbx);
8329
8330      temp = CHTVRegData[resindex].Reg[9];
8331      tempbx=((temp & 0x00FF) << 8) | 0x15;
8332      SiS_SetCH701x(SiS_Pr,tempbx);
8333
8334      temp = CHTVRegData[resindex].Reg[10];
8335      tempbx=((temp & 0x00FF) << 8) | 0x1f;
8336      SiS_SetCH701x(SiS_Pr,tempbx);
8337
8338      temp = CHTVRegData[resindex].Reg[11];
8339      tempbx=((temp & 0x00FF) << 8) | 0x0c;
8340      SiS_SetCH701x(SiS_Pr,tempbx);
8341
8342      temp = CHTVRegData[resindex].Reg[12];
8343      tempbx=((temp & 0x00FF) << 8) | 0x0d;
8344      SiS_SetCH701x(SiS_Pr,tempbx);
8345
8346      temp = CHTVRegData[resindex].Reg[13];
8347      tempbx=((temp & 0x00FF) << 8) | 0x0e;
8348      SiS_SetCH701x(SiS_Pr,tempbx);
8349
8350      temp = CHTVRegData[resindex].Reg[14];
8351      tempbx=((temp & 0x00FF) << 8) | 0x0f;
8352      SiS_SetCH701x(SiS_Pr,tempbx);
8353
8354      temp = CHTVRegData[resindex].Reg[15];
8355      tempbx=((temp & 0x00FF) << 8) | 0x10;
8356      SiS_SetCH701x(SiS_Pr,tempbx);
8357
8358      temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
8359      /* D1 should be set for PAL, PAL-N and NTSC-J,
8360         but I won't do that for PAL unless somebody
8361         tells me to do so. Since the BIOS uses
8362         non-default CIV values and blacklevels,
8363         this might be compensated anyway.
8364       */
8365      if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
8366      SiS_SetCH701x(SiS_Pr,((temp << 8) | 0x21));
8367
8368 #endif  /* 315 */
8369
8370   }
8371
8372 #ifdef SIS_CP
8373   SIS_CP_INIT301_CP3
8374 #endif
8375
8376 }
8377
8378 void
8379 SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8380 {
8381   USHORT temp;
8382
8383   /* Enable Chrontel 7019 LCD panel backlight */
8384   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8385      if(HwInfo->jChipType == SIS_740) {
8386         SiS_SetCH701x(SiS_Pr,0x6566);
8387      } else {
8388         temp = SiS_GetCH701x(SiS_Pr,0x66);
8389         temp |= 0x20;
8390         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
8391      }
8392   }
8393 }
8394
8395 void
8396 SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr)
8397 {
8398   USHORT temp;
8399
8400   /* Disable Chrontel 7019 LCD panel backlight */
8401   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8402      temp = SiS_GetCH701x(SiS_Pr,0x66);
8403      temp &= 0xDF;
8404      SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
8405   }
8406 }
8407
8408 #ifdef SIS315H  /* ----------- 315 series only ---------- */
8409
8410 static void
8411 SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8412 {
8413   UCHAR regtable[]      = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
8414   UCHAR table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
8415   UCHAR table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
8416   UCHAR asus1024_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8417   UCHAR asus1400_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
8418   UCHAR table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8419   UCHAR table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
8420   UCHAR *tableptr = NULL;
8421   int i;
8422
8423   /* Set up Power up/down timing */
8424
8425   if(HwInfo->jChipType == SIS_740) {
8426      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8427         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
8428         else                                      tableptr = table1024_740;
8429      } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8430                (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8431                (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8432         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
8433         else                                      tableptr = table1400_740;
8434      } else return;
8435   } else {
8436      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
8437         tableptr = table1024_650;
8438      } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
8439                (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
8440                (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
8441         tableptr = table1400_650;
8442      } else return;
8443   }
8444
8445   for(i=0; i<5; i++) {
8446      SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
8447   }
8448 }
8449
8450 static void
8451 SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8452 {
8453   UCHAR regtable[]      = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
8454                             0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66 };
8455   UCHAR table1024_740[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8456                             0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44 };
8457   UCHAR table1280_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8458                             0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
8459   UCHAR table1400_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8460                             0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
8461   UCHAR table1600_740[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8462                             0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44 };
8463   UCHAR table1024_650[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
8464                             0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02 };
8465   UCHAR table1280_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
8466                             0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02 };
8467   UCHAR table1400_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
8468                             0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02 };
8469   UCHAR table1600_650[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
8470                             0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a };
8471   UCHAR *tableptr = NULL;
8472   USHORT tempbh;
8473   int i;
8474
8475   if(HwInfo->jChipType == SIS_740) {
8476      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
8477      else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
8478      else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
8479      else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
8480      else return;
8481   } else {
8482      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
8483      else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
8484      else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
8485      else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
8486      else return;
8487   }
8488
8489   tempbh = SiS_GetCH701x(SiS_Pr,0x74);
8490   if((tempbh == 0xf6) || (tempbh == 0xc7)) {
8491      tempbh = SiS_GetCH701x(SiS_Pr,0x73);
8492      if(tempbh == 0xc8) {
8493         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
8494      } else if(tempbh == 0xdb) {
8495         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
8496         if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
8497      } else if(tempbh == 0xde) {
8498         if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
8499      }
8500   }
8501
8502   if(HwInfo->jChipType == SIS_740) tempbh = 0x0d;
8503   else                             tempbh = 0x0c;
8504
8505   for(i = 0; i < tempbh; i++) {
8506      SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
8507   }
8508   SiS_ChrontelPowerSequencing(SiS_Pr,HwInfo);
8509   tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
8510   tempbh |= 0xc0;
8511   SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1e);
8512
8513   if(HwInfo->jChipType == SIS_740) {
8514      tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
8515      tempbh &= 0xfb;
8516      SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1c);
8517      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8518      tempbh = SiS_GetCH701x(SiS_Pr,0x64);
8519      tempbh |= 0x40;
8520      SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x64);
8521      tempbh = SiS_GetCH701x(SiS_Pr,0x03);
8522      tempbh &= 0x3f;
8523      SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x03);
8524   }
8525 }
8526
8527 static void
8528 SiS_ChrontelResetVSync(SiS_Private *SiS_Pr)
8529 {
8530   unsigned char temp, temp1;
8531
8532   temp1 = SiS_GetCH701x(SiS_Pr,0x49);
8533   SiS_SetCH701x(SiS_Pr,0x3e49);
8534   temp = SiS_GetCH701x(SiS_Pr,0x47);
8535   temp &= 0x7f; /* Use external VSYNC */
8536   SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
8537   SiS_LongDelay(SiS_Pr,3);
8538   temp = SiS_GetCH701x(SiS_Pr,0x47);
8539   temp |= 0x80; /* Use internal VSYNC */
8540   SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
8541   SiS_SetCH701x(SiS_Pr,(temp1 << 8) | 0x49);
8542 }
8543
8544 static void
8545 SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8546 {
8547   USHORT temp;
8548
8549   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8550      if(HwInfo->jChipType == SIS_740) {
8551         temp = SiS_GetCH701x(SiS_Pr,0x1c);
8552         temp |= 0x04;   /* Invert XCLK phase */
8553         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
8554      }
8555      if(SiS_IsYPbPr(SiS_Pr, HwInfo)) {
8556         temp = SiS_GetCH701x(SiS_Pr,0x01);
8557         temp &= 0x3f;
8558         temp |= 0x80;   /* Enable YPrPb (HDTV) */
8559         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
8560      }
8561      if(SiS_IsChScart(SiS_Pr, HwInfo)) {
8562         temp = SiS_GetCH701x(SiS_Pr,0x01);
8563         temp &= 0x3f;
8564         temp |= 0xc0;   /* Enable SCART + CVBS */
8565         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
8566      }
8567      if(HwInfo->jChipType == SIS_740) {
8568         SiS_ChrontelResetVSync(SiS_Pr);
8569         SiS_SetCH701x(SiS_Pr,0x2049);   /* Enable TV path */
8570      } else {
8571         SiS_SetCH701x(SiS_Pr,0x2049);   /* Enable TV path */
8572         temp = SiS_GetCH701x(SiS_Pr,0x49);
8573         if(SiS_IsYPbPr(SiS_Pr,HwInfo)) {
8574            temp = SiS_GetCH701x(SiS_Pr,0x73);
8575            temp |= 0x60;
8576            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x73);
8577         }
8578         temp = SiS_GetCH701x(SiS_Pr,0x47);
8579         temp &= 0x7f;
8580         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
8581         SiS_LongDelay(SiS_Pr,2);
8582         temp = SiS_GetCH701x(SiS_Pr,0x47);
8583         temp |= 0x80;
8584         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
8585      }
8586   }
8587 }
8588
8589 static void
8590 SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8591 {
8592   USHORT temp;
8593
8594   /* Complete power down of LVDS */
8595   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8596      if(HwInfo->jChipType == SIS_740) {
8597         SiS_LongDelay(SiS_Pr,1);
8598         SiS_GenericDelay(SiS_Pr,0x16ff);
8599         SiS_SetCH701x(SiS_Pr,0xac76);
8600         SiS_SetCH701x(SiS_Pr,0x0066);
8601      } else {
8602         SiS_LongDelay(SiS_Pr,2);
8603         temp = SiS_GetCH701x(SiS_Pr,0x76);
8604         temp &= 0xfc;
8605         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
8606         SiS_SetCH701x(SiS_Pr,0x0066);
8607      }
8608   }
8609 }
8610
8611 static void
8612 SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8613 {
8614      USHORT temp;
8615
8616      if(HwInfo->jChipType == SIS_740) {
8617
8618         temp = SiS_GetCH701x(SiS_Pr,0x4a);  /* Version ID */
8619         temp &= 0x01;
8620         if(!temp) {
8621
8622            if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
8623               temp = SiS_GetCH701x(SiS_Pr,0x49);
8624               SiS_SetCH701x(SiS_Pr,0x3e49);
8625            }
8626            /* Reset Chrontel 7019 datapath */
8627            SiS_SetCH701x(SiS_Pr,0x1048);
8628            SiS_LongDelay(SiS_Pr,1);
8629            SiS_SetCH701x(SiS_Pr,0x1848);
8630
8631            if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
8632               SiS_ChrontelResetVSync(SiS_Pr);
8633               SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x49);
8634            }
8635
8636         } else {
8637
8638            /* Clear/set/clear GPIO */
8639            temp = SiS_GetCH701x(SiS_Pr,0x5c);
8640            temp &= 0xef;
8641            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
8642            temp = SiS_GetCH701x(SiS_Pr,0x5c);
8643            temp |= 0x10;
8644            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
8645            temp = SiS_GetCH701x(SiS_Pr,0x5c);
8646            temp &= 0xef;
8647            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
8648            temp = SiS_GetCH701x(SiS_Pr,0x61);
8649            if(!temp) {
8650               SiS_SetCH701xForLCD(SiS_Pr, HwInfo);
8651            }
8652         }
8653
8654      } else { /* 650 */
8655         /* Reset Chrontel 7019 datapath */
8656         SiS_SetCH701x(SiS_Pr,0x1048);
8657         SiS_LongDelay(SiS_Pr,1);
8658         SiS_SetCH701x(SiS_Pr,0x1848);
8659      }
8660 }
8661
8662 static void
8663 SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8664 {
8665      USHORT temp;
8666
8667      if(HwInfo->jChipType == SIS_740) {
8668
8669         if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
8670            SiS_ChrontelResetVSync(SiS_Pr);
8671         }
8672
8673      } else {
8674
8675         SiS_SetCH701x(SiS_Pr,0xaf76);  /* Power up LVDS block */
8676         temp = SiS_GetCH701x(SiS_Pr,0x49);
8677         temp &= 1;
8678         if(temp != 1) {  /* TV block powered? (0 = yes, 1 = no) */
8679            temp = SiS_GetCH701x(SiS_Pr,0x47);
8680            temp &= 0x70;
8681            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);  /* enable VSYNC */
8682            SiS_LongDelay(SiS_Pr,3);
8683            temp = SiS_GetCH701x(SiS_Pr,0x47);
8684            temp |= 0x80;
8685            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);  /* disable VSYNC */
8686         }
8687
8688      }
8689 }
8690
8691 static void
8692 SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
8693 {
8694      USHORT temp,temp1;
8695
8696      if(HwInfo->jChipType == SIS_740) {
8697
8698         temp = SiS_GetCH701x(SiS_Pr,0x61);
8699         if(temp < 1) {
8700            temp++;
8701            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
8702         }
8703         SiS_SetCH701x(SiS_Pr,0x4566);  /* Panel power on */
8704         SiS_SetCH701x(SiS_Pr,0xaf76);  /* All power on */
8705         SiS_LongDelay(SiS_Pr,1);
8706         SiS_GenericDelay(SiS_Pr,0x16ff);
8707
8708      } else {  /* 650 */
8709
8710         temp1 = 0;
8711         temp = SiS_GetCH701x(SiS_Pr,0x61);
8712         if(temp < 2) {
8713            temp++;
8714            SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
8715            temp1 = 1;
8716         }
8717         SiS_SetCH701x(SiS_Pr,0xac76);
8718         temp = SiS_GetCH701x(SiS_Pr,0x66);
8719         temp |= 0x5f;
8720         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
8721         if(ModeNo > 0x13) {
8722            if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
8723               SiS_GenericDelay(SiS_Pr,0x3ff);
8724            } else {
8725               SiS_GenericDelay(SiS_Pr,0x2ff);
8726            }
8727         } else {
8728            if(!temp1)
8729               SiS_GenericDelay(SiS_Pr,0x2ff);
8730         }
8731         temp = SiS_GetCH701x(SiS_Pr,0x76);
8732         temp |= 0x03;
8733         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
8734         temp = SiS_GetCH701x(SiS_Pr,0x66);
8735         temp &= 0x7f;
8736         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
8737         SiS_LongDelay(SiS_Pr,1);
8738
8739      }
8740 }
8741
8742 static void
8743 SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8744 {
8745      USHORT temp,tempcl,tempch;
8746
8747      SiS_LongDelay(SiS_Pr, 1);
8748      tempcl = 3;
8749      tempch = 0;
8750
8751      do {
8752        temp = SiS_GetCH701x(SiS_Pr,0x66);
8753        temp &= 0x04;  /* PLL stable? -> bail out */
8754        if(temp == 0x04) break;
8755
8756        if(HwInfo->jChipType == SIS_740) {
8757           /* Power down LVDS output, PLL normal operation */
8758           SiS_SetCH701x(SiS_Pr,0xac76);
8759        }
8760
8761        SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
8762
8763        if(tempcl == 0) {
8764            if(tempch == 3) break;
8765            SiS_ChrontelResetDB(SiS_Pr,HwInfo);
8766            tempcl = 3;
8767            tempch++;
8768        }
8769        tempcl--;
8770        temp = SiS_GetCH701x(SiS_Pr,0x76);
8771        temp &= 0xfb;  /* Reset PLL */
8772        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
8773        SiS_LongDelay(SiS_Pr,2);
8774        temp = SiS_GetCH701x(SiS_Pr,0x76);
8775        temp |= 0x04;  /* PLL normal operation */
8776        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
8777        if(HwInfo->jChipType == SIS_740) {
8778           SiS_SetCH701x(SiS_Pr,0xe078); /* PLL loop filter */
8779        } else {
8780           SiS_SetCH701x(SiS_Pr,0x6078);
8781        }
8782        SiS_LongDelay(SiS_Pr,2);
8783     } while(0);
8784
8785     SiS_SetCH701x(SiS_Pr,0x0077);  /* MV? */
8786 }
8787
8788 static void
8789 SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
8790 {
8791      USHORT temp;
8792
8793      temp = SiS_GetCH701x(SiS_Pr,0x03);
8794      temp |= 0x80;      /* Set datapath 1 to TV   */
8795      temp &= 0xbf;      /* Set datapath 2 to LVDS */
8796      SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
8797
8798      if(HwInfo->jChipType == SIS_740) {
8799
8800         temp = SiS_GetCH701x(SiS_Pr,0x1c);
8801         temp &= 0xfb;   /* Normal XCLK phase */
8802         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
8803
8804         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
8805
8806         temp = SiS_GetCH701x(SiS_Pr,0x64);
8807         temp |= 0x40;   /* ? Bit not defined */
8808         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x64);
8809
8810         temp = SiS_GetCH701x(SiS_Pr,0x03);
8811         temp &= 0x3f;   /* D1 input to both LVDS and TV */
8812         SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
8813
8814         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
8815            SiS_SetCH701x(SiS_Pr,0x4063); /* LVDS off */
8816            SiS_LongDelay(SiS_Pr, 1);
8817            SiS_SetCH701x(SiS_Pr,0x0063); /* LVDS on */
8818            SiS_ChrontelResetDB(SiS_Pr, HwInfo);
8819            SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
8820            SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
8821         } else {
8822            temp = SiS_GetCH701x(SiS_Pr,0x66);
8823            if(temp != 0x45) {
8824               SiS_ChrontelResetDB(SiS_Pr, HwInfo);
8825               SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
8826               SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
8827            }
8828         }
8829
8830      } else { /* 650 */
8831
8832         SiS_ChrontelResetDB(SiS_Pr,HwInfo);
8833         SiS_ChrontelDoSomething2(SiS_Pr,HwInfo);
8834         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
8835         SiS_ChrontelDoSomething3(SiS_Pr,temp,HwInfo);
8836         SiS_SetCH701x(SiS_Pr,0xaf76);  /* All power on, LVDS normal operation */
8837
8838      }
8839
8840 }
8841 #endif  /* 315 series  */
8842
8843 /*********************************************/
8844 /*      MAIN: SET CRT2 REGISTER GROUP        */
8845 /*********************************************/
8846
8847 BOOLEAN
8848 SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
8849 {
8850 #ifdef SIS300
8851    UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
8852 #endif
8853    USHORT ModeIdIndex, RefreshRateTableIndex;
8854 #if 0
8855    USHORT temp;
8856 #endif
8857
8858    SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
8859
8860    if(!SiS_Pr->UseCustomMode) {
8861       SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex);
8862    } else {
8863       ModeIdIndex = 0;
8864    }
8865
8866    /* Used for shifting CR33 */
8867    SiS_Pr->SiS_SelectCRT2Rate = 4;
8868
8869    SiS_UnLockCRT2(SiS_Pr, HwInfo);
8870
8871    RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
8872
8873    SiS_SaveCRT2Info(SiS_Pr,ModeNo);
8874
8875    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8876       SiS_DisableBridge(SiS_Pr,HwInfo);
8877       if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (HwInfo->jChipType == SIS_730)) {
8878          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
8879       }
8880       SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
8881    }
8882
8883    if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
8884       SiS_LockCRT2(SiS_Pr, HwInfo);
8885       SiS_DisplayOn(SiS_Pr);
8886       return TRUE;
8887    }
8888
8889    SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8890
8891    /* Set up Panel Link for LVDS and LCDA */
8892    SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
8893    if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
8894        ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
8895        ((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
8896       SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8897    }
8898
8899 #ifdef LINUX_XF86
8900 #ifdef TWDEBUG
8901   xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES);
8902   xf86DrvMsg(0, X_INFO, "(init301: HDE     0x%03x VDE     0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE);
8903   xf86DrvMsg(0, X_INFO, "(init301: VGAHDE  0x%03x VGAVDE  0x%03x)\n", SiS_Pr->SiS_VGAHDE, SiS_Pr->SiS_VGAVDE);
8904   xf86DrvMsg(0, X_INFO, "(init301: HT      0x%03x VT      0x%03x)\n", SiS_Pr->SiS_HT, SiS_Pr->SiS_VT);
8905   xf86DrvMsg(0, X_INFO, "(init301: VGAHT   0x%03x VGAVT   0x%03x)\n", SiS_Pr->SiS_VGAHT, SiS_Pr->SiS_VGAVT);
8906 #endif
8907 #endif
8908
8909    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8910       SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
8911    }
8912
8913    if(SiS_Pr->SiS_VBType & VB_SISVB) {
8914
8915         if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8916
8917            SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8918 #ifdef SIS315H
8919            SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8920 #endif
8921            SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
8922            SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
8923 #ifdef SIS315H
8924            SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
8925 #endif
8926            SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
8927
8928            SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
8929
8930            /* For 301BDH (Panel link initialization): */
8931            if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
8932               if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
8933                  if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
8934                     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
8935                        SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
8936                                        RefreshRateTableIndex,HwInfo);
8937                     }
8938                  }
8939               }
8940               SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,
8941                               RefreshRateTableIndex,HwInfo);
8942            }
8943         }
8944
8945    } else {
8946
8947         SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
8948
8949         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
8950            SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
8951         }
8952
8953         SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
8954
8955         if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8956            if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
8957               if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
8958                  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
8959 #ifdef SIS315H
8960                     SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
8961 #endif
8962                  }
8963               }
8964               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
8965                  SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
8966               }
8967            }
8968         }
8969
8970    }
8971
8972 #ifdef SIS300
8973    if(HwInfo->jChipType < SIS_315H) {
8974       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
8975          if(SiS_Pr->SiS_UseOEM) {
8976             if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
8977                if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
8978                   SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
8979                                     RefreshRateTableIndex);
8980                }
8981             } else {
8982                SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
8983                                  RefreshRateTableIndex);
8984             }
8985          }
8986          if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
8987             if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
8988                (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
8989                SetOEMLCDData2(SiS_Pr, HwInfo, ModeNo, ModeIdIndex,RefreshRateTableIndex);
8990             }
8991             SiS_DisplayOn(SiS_Pr);
8992          }
8993       }
8994    }
8995 #endif
8996
8997 #ifdef SIS315H
8998    if(HwInfo->jChipType >= SIS_315H) {
8999       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
9000          if(HwInfo->jChipType < SIS_661) {
9001             SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
9002             SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
9003          } else {
9004             SiS_OEM661Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
9005          }
9006          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
9007       }
9008    }
9009 #endif
9010
9011    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
9012       SiS_EnableBridge(SiS_Pr, HwInfo);
9013    }
9014
9015    SiS_DisplayOn(SiS_Pr);
9016
9017    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
9018       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
9019          /* Disable LCD panel when using TV */
9020          SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFF,0x0C);
9021       } else {
9022          /* Disable TV when using LCD */
9023          SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8);
9024       }
9025    }
9026
9027    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
9028       SiS_LockCRT2(SiS_Pr,HwInfo);
9029    }
9030
9031    return TRUE;
9032 }
9033
9034
9035 /*********************************************/
9036 /*     ENABLE/DISABLE LCD BACKLIGHT (SIS)    */
9037 /*********************************************/
9038
9039 void
9040 SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
9041 {
9042   /* Switch on LCD backlight on SiS30xLV */
9043   SiS_DDC2Delay(SiS_Pr,0xff00);
9044   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
9045      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
9046      SiS_WaitVBRetrace(SiS_Pr,HwInfo);
9047   }
9048   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
9049      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
9050   }
9051 }
9052
9053 void
9054 SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
9055 {
9056   /* Switch off LCD backlight on SiS30xLV */
9057   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
9058   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
9059   SiS_DDC2Delay(SiS_Pr,0xe000);
9060 }
9061
9062 /*********************************************/
9063 /*          DDC RELATED FUNCTIONS            */
9064 /*********************************************/
9065
9066 static void
9067 SiS_SetupDDCN(SiS_Private *SiS_Pr)
9068 {
9069   SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
9070   SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
9071   if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
9072      SiS_Pr->SiS_DDC_NData &= 0x0f;
9073      SiS_Pr->SiS_DDC_NClk  &= 0x0f;
9074   }
9075 }
9076
9077 #ifdef SIS300
9078 static UCHAR *
9079 SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
9080 {
9081   int i, j, num;
9082   USHORT tempah,temp;
9083   UCHAR *mydataptr;
9084
9085   for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
9086      mydataptr = dataptr;
9087      num = *mydataptr++;
9088      if(!num) return mydataptr;
9089      if(i) {
9090         SiS_SetStop(SiS_Pr);
9091         SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT*2);
9092      }
9093      if(SiS_SetStart(SiS_Pr)) continue;         /* Set start condition */
9094      tempah = SiS_Pr->SiS_DDC_DeviceAddr;
9095      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write DAB (S0=0=write) */
9096      if(temp) continue;                         /*    (ERROR: no ack) */
9097      tempah = *mydataptr++;
9098      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write register number */
9099      if(temp) continue;                         /*    (ERROR: no ack) */
9100      for(j=0; j<num; j++) {
9101         tempah = *mydataptr++;
9102         temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
9103         if(temp) break;
9104      }
9105      if(temp) continue;
9106      if(SiS_SetStop(SiS_Pr)) continue;
9107      return mydataptr;
9108   }
9109   return NULL;
9110 }
9111
9112 static BOOLEAN
9113 SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
9114 {
9115   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;            /* DAB (Device Address Byte) */
9116   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9117   SiS_Pr->SiS_DDC_Data  = 0x02;                 /* Bitmask in IndexReg for Data */
9118   SiS_Pr->SiS_DDC_Clk   = 0x01;                 /* Bitmask in IndexReg for Clk */
9119   SiS_SetupDDCN(SiS_Pr);
9120
9121   SiS_SetSwitchDDC2(SiS_Pr);
9122
9123   while(*dataptr) {
9124      dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
9125      if(!dataptr) return FALSE;
9126   }
9127 #ifdef TWDEBUG
9128   xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
9129 #endif
9130   return TRUE;
9131 }
9132 #endif
9133
9134 /* The Chrontel 700x is connected to the 630/730 via
9135  * the 630/730's DDC/I2C port.
9136  *
9137  * On 630(S)T chipset, the index changed from 0x11 to
9138  * 0x0a, possibly for working around the DDC problems
9139  */
9140
9141 static BOOLEAN
9142 SiS_SetChReg(SiS_Private *SiS_Pr, USHORT tempbx, USHORT myor)
9143 {
9144   USHORT tempah,temp,i;
9145
9146   for(i=0; i<20; i++) {                         /* Do 20 attempts to write */
9147      if(i) {
9148         SiS_SetStop(SiS_Pr);
9149         SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9150      }
9151      if(SiS_SetStart(SiS_Pr)) continue;         /* Set start condition */
9152      tempah = SiS_Pr->SiS_DDC_DeviceAddr;
9153      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write DAB (S0=0=write) */
9154      if(temp) continue;                         /*    (ERROR: no ack) */
9155      tempah = tempbx & 0x00FF;                  /* Write RAB */
9156      tempah |= myor;                            /* (700x: set bit 7, see datasheet) */
9157      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
9158      if(temp) continue;                         /*    (ERROR: no ack) */
9159      tempah = (tempbx & 0xFF00) >> 8;
9160      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write data */
9161      if(temp) continue;                         /*    (ERROR: no ack) */
9162      if(SiS_SetStop(SiS_Pr)) continue;          /* Set stop condition */
9163      SiS_Pr->SiS_ChrontelInit = 1;
9164      return TRUE;
9165   }
9166   return FALSE;
9167 }
9168
9169 #if 0
9170 #ifdef SIS300
9171 /* Write Trumpion register */
9172 static void
9173 SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
9174 {
9175   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;            /* DAB (Device Address Byte) */
9176   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9177   SiS_Pr->SiS_DDC_Data  = 0x02;                 /* Bitmask in IndexReg for Data */
9178   SiS_Pr->SiS_DDC_Clk   = 0x01;                 /* Bitmask in IndexReg for Clk */
9179   SiS_SetupDDCN(SiS_Pr);
9180   SiS_SetChReg(SiS_Pr, tempbx, 0);
9181 }
9182 #endif
9183 #endif
9184
9185 /* Write to Chrontel 700x */
9186 /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
9187 void
9188 SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
9189 {
9190   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
9191
9192   if(!(SiS_Pr->SiS_ChrontelInit)) {
9193      SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
9194      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
9195      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
9196      SiS_SetupDDCN(SiS_Pr);
9197   }
9198
9199   if( (!(SiS_SetChReg(SiS_Pr, tempbx, 0x80))) &&
9200       (!(SiS_Pr->SiS_ChrontelInit)) ) {
9201      SiS_Pr->SiS_DDC_Index = 0x0a;              /* Bit 7 = SC;  Bit 6 = SD */
9202      SiS_Pr->SiS_DDC_Data  = 0x80;              /* Bitmask in IndexReg for Data */
9203      SiS_Pr->SiS_DDC_Clk   = 0x40;              /* Bitmask in IndexReg for Clk */
9204      SiS_SetupDDCN(SiS_Pr);
9205
9206      SiS_SetChReg(SiS_Pr, tempbx, 0x80);
9207   }
9208 }
9209
9210 /* Write to Chrontel 701x */
9211 /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
9212 void
9213 SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
9214 {
9215   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9216   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
9217   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
9218   SiS_SetupDDCN(SiS_Pr);
9219   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB (Device Address Byte) */
9220   SiS_SetChReg(SiS_Pr, tempbx, 0);
9221 }
9222
9223 static void
9224 SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
9225 {
9226   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
9227      SiS_SetCH700x(SiS_Pr,tempbx);
9228   else
9229      SiS_SetCH701x(SiS_Pr,tempbx);
9230 }
9231
9232 static USHORT
9233 SiS_GetChReg(SiS_Private *SiS_Pr, USHORT myor)
9234 {
9235   USHORT tempah,temp,i;
9236
9237   for(i=0; i<20; i++) {                         /* Do 20 attempts to read */
9238      if(i) {
9239         SiS_SetStop(SiS_Pr);
9240         SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
9241      }
9242      if(SiS_SetStart(SiS_Pr)) continue;         /* Set start condition */
9243      tempah = SiS_Pr->SiS_DDC_DeviceAddr;
9244      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* Write DAB (S0=0=write) */
9245      if(temp) continue;                         /*        (ERROR: no ack) */
9246      tempah = SiS_Pr->SiS_DDC_ReadAddr | myor;  /* Write RAB (700x: | 0x80) */
9247      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
9248      if(temp) continue;                         /*        (ERROR: no ack) */
9249      if (SiS_SetStart(SiS_Pr)) continue;        /* Re-start */
9250      tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01;/* DAB | 0x01 = Read */
9251      temp = SiS_WriteDDC2Data(SiS_Pr,tempah);   /* DAB (S0=1=read) */
9252      if(temp) continue;                         /*        (ERROR: no ack) */
9253      tempah = SiS_ReadDDC2Data(SiS_Pr,tempah);  /* Read byte */
9254      if(SiS_SetStop(SiS_Pr)) continue;          /* Stop condition */
9255      SiS_Pr->SiS_ChrontelInit = 1;
9256      return(tempah);
9257   }
9258   return 0xFFFF;
9259 }
9260
9261 #if 0
9262 #ifdef SIS300
9263 /* Read from Trumpion */
9264 static USHORT
9265 SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
9266 {
9267   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;    /* DAB */
9268   SiS_Pr->SiS_DDC_Index = 0x11;         /* Bit 0 = SC;  Bit 1 = SD */
9269   SiS_Pr->SiS_DDC_Data  = 0x02;         /* Bitmask in IndexReg for Data */
9270   SiS_Pr->SiS_DDC_Clk   = 0x01;         /* Bitmask in IndexReg for Clk */
9271   SiS_SetupDDCN(SiS_Pr);
9272   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9273   return(SiS_GetChReg(SiS_Pr,0));
9274 }
9275 #endif
9276 #endif
9277
9278 /* Read from Chrontel 700x */
9279 /* Parameter is [Register no (S7-S0)] */
9280 USHORT
9281 SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
9282 {
9283   USHORT result;
9284
9285   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
9286
9287   if(!(SiS_Pr->SiS_ChrontelInit)) {
9288      SiS_Pr->SiS_DDC_Index = 0x11;              /* Bit 0 = SC;  Bit 1 = SD */
9289      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
9290      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
9291      SiS_SetupDDCN(SiS_Pr);
9292   }
9293
9294   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9295
9296   if( ((result = SiS_GetChReg(SiS_Pr,0x80)) == 0xFFFF) &&
9297       (!SiS_Pr->SiS_ChrontelInit) ) {
9298
9299      SiS_Pr->SiS_DDC_Index = 0x0a;
9300      SiS_Pr->SiS_DDC_Data  = 0x80;
9301      SiS_Pr->SiS_DDC_Clk   = 0x40;
9302      SiS_SetupDDCN(SiS_Pr);
9303
9304      result = SiS_GetChReg(SiS_Pr,0x80);
9305   }
9306   return(result);
9307 }
9308
9309 /* Read from Chrontel 701x */
9310 /* Parameter is [Register no (S7-S0)] */
9311 USHORT
9312 SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
9313 {
9314   SiS_Pr->SiS_DDC_Index = 0x11;                 /* Bit 0 = SC;  Bit 1 = SD */
9315   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
9316   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
9317   SiS_SetupDDCN(SiS_Pr);
9318   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;            /* DAB */
9319
9320   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
9321
9322   return(SiS_GetChReg(SiS_Pr,0));
9323 }
9324
9325 /* Read from Chrontel 70xx */
9326 /* Parameter is [Register no (S7-S0)] */
9327 static USHORT
9328 SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
9329 {
9330   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
9331      return(SiS_GetCH700x(SiS_Pr, tempbx));
9332   else
9333      return(SiS_GetCH701x(SiS_Pr, tempbx));
9334 }
9335
9336 /* Our own DDC functions */
9337 static USHORT
9338 SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
9339                 USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32)
9340 {
9341      unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
9342      unsigned char flag, cr32;
9343      USHORT        temp = 0, myadaptnum = adaptnum;
9344
9345      if(adaptnum != 0) {
9346         if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0xFFFF;
9347         if((VBFlags & VB_30xBDH) && (adaptnum == 1)) return 0xFFFF;
9348      }  
9349      
9350      /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
9351      
9352      SiS_Pr->SiS_ChrontelInit = 0;   /* force re-detection! */
9353
9354      SiS_Pr->SiS_DDC_SecAddr = 0;
9355      SiS_Pr->SiS_DDC_DeviceAddr = ddcdtype[DDCdatatype];
9356      SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_P3c4;
9357      SiS_Pr->SiS_DDC_Index = 0x11;
9358      flag = 0xff;
9359
9360      cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
9361
9362 #if 0
9363      if(VBFlags & VB_SISBRIDGE) {
9364         if(myadaptnum == 0) {
9365            if(!(cr32 & 0x20)) {
9366               myadaptnum = 2;
9367               if(!(cr32 & 0x10)) {
9368                  myadaptnum = 1;
9369                  if(!(cr32 & 0x08)) {
9370                     myadaptnum = 0;
9371                  }
9372               }
9373            }
9374         }
9375      }
9376 #endif
9377
9378      if(VGAEngine == SIS_300_VGA) {             /* 300 series */
9379         
9380         if(myadaptnum != 0) {
9381            flag = 0;
9382            if(VBFlags & VB_SISBRIDGE) {
9383               SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9384               SiS_Pr->SiS_DDC_Index = 0x0f;
9385            }
9386         }
9387
9388         if(!(VBFlags & VB_301)) {
9389            if((cr32 & 0x80) && (checkcr32)) {
9390               if(myadaptnum >= 1) {
9391                  if(!(cr32 & 0x08)) {
9392                      myadaptnum = 1;
9393                      if(!(cr32 & 0x10)) return 0xFFFF;
9394                  }
9395               }
9396            }
9397         }
9398
9399         temp = 4 - (myadaptnum * 2);
9400         if(flag) temp = 0;
9401
9402      } else {                                           /* 315/330 series */
9403
9404         /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
9405
9406         if(VBFlags & VB_SISBRIDGE) {
9407            if(myadaptnum == 2) {
9408               myadaptnum = 1;
9409            }
9410         }
9411
9412         if(myadaptnum == 1) {
9413            flag = 0;
9414            if(VBFlags & VB_SISBRIDGE) {
9415               SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
9416               SiS_Pr->SiS_DDC_Index = 0x0f;
9417            }
9418         }
9419
9420         if((cr32 & 0x80) && (checkcr32)) {
9421            if(myadaptnum >= 1) {
9422               if(!(cr32 & 0x08)) {
9423                  myadaptnum = 1;
9424                  if(!(cr32 & 0x10)) return 0xFFFF;
9425               }
9426            }
9427         }
9428
9429         temp = myadaptnum;
9430         if(myadaptnum == 1) {
9431            temp = 0;
9432            if(VBFlags & VB_LVDS) flag = 0xff;
9433         }
9434
9435         if(flag) temp = 0;
9436     }
9437     
9438     SiS_Pr->SiS_DDC_Data = 0x02 << temp;
9439     SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
9440
9441     SiS_SetupDDCN(SiS_Pr);
9442
9443 #ifdef TWDEBUG
9444     xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
9445                 SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
9446 #endif
9447     
9448     return 0;
9449 }
9450
9451 static USHORT
9452 SiS_WriteDABDDC(SiS_Private *SiS_Pr)
9453 {
9454    if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9455    if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
9456         return 0xFFFF;
9457    }
9458    if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
9459         return 0xFFFF;
9460    }
9461    return(0);
9462 }
9463
9464 static USHORT
9465 SiS_PrepareReadDDC(SiS_Private *SiS_Pr)
9466 {
9467    if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
9468    if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
9469         return 0xFFFF;
9470    }
9471    return(0);
9472 }
9473
9474 static USHORT
9475 SiS_PrepareDDC(SiS_Private *SiS_Pr)
9476 {
9477    if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
9478    if(SiS_PrepareReadDDC(SiS_Pr)) return(SiS_PrepareReadDDC(SiS_Pr));
9479    return(0);
9480 }
9481
9482 static void
9483 SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno)
9484 {
9485    SiS_SetSCLKLow(SiS_Pr);
9486    if(yesno) {
9487       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9488                       SiS_Pr->SiS_DDC_Index,
9489                       SiS_Pr->SiS_DDC_NData,
9490                       SiS_Pr->SiS_DDC_Data);
9491    } else {
9492       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
9493                       SiS_Pr->SiS_DDC_Index,
9494                       SiS_Pr->SiS_DDC_NData,
9495                       0);
9496    }
9497    SiS_SetSCLKHigh(SiS_Pr);
9498 }
9499
9500 static USHORT
9501 SiS_DoProbeDDC(SiS_Private *SiS_Pr)
9502 {
9503     unsigned char mask, value;
9504     USHORT  temp, ret=0;
9505     BOOLEAN failed = FALSE;
9506
9507     SiS_SetSwitchDDC2(SiS_Pr);
9508     if(SiS_PrepareDDC(SiS_Pr)) {
9509          SiS_SetStop(SiS_Pr);
9510 #ifdef TWDEBUG
9511          xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n");
9512 #endif
9513          return(0xFFFF);
9514     }
9515     mask = 0xf0;
9516     value = 0x20;
9517     if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9518        temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
9519        SiS_SendACK(SiS_Pr, 0);
9520        if(temp == 0) {
9521            mask = 0xff;
9522            value = 0xff;
9523        } else {
9524            failed = TRUE;
9525            ret = 0xFFFF;
9526 #ifdef TWDEBUG
9527            xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n");
9528 #endif
9529        }
9530     }
9531     if(failed == FALSE) {
9532        temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
9533        SiS_SendACK(SiS_Pr, 1);
9534        temp &= mask;
9535        if(temp == value) ret = 0;
9536        else {
9537           ret = 0xFFFF;
9538 #ifdef TWDEBUG
9539           xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n");
9540 #endif
9541           if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
9542              if(temp == 0x30) ret = 0;
9543           }
9544        }
9545     }
9546     SiS_SetStop(SiS_Pr);
9547     return(ret);
9548 }
9549
9550 static USHORT
9551 SiS_ProbeDDC(SiS_Private *SiS_Pr)
9552 {
9553    USHORT flag;
9554
9555    flag = 0x180;
9556    SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
9557    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x02;
9558    SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;
9559    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x08;
9560    SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
9561    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
9562    if(!(flag & 0x1a)) flag = 0;
9563    return(flag);
9564 }
9565
9566 static USHORT
9567 SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
9568 {
9569    USHORT flag, length, i;
9570    unsigned char chksum,gotcha;
9571
9572    if(DDCdatatype > 4) return 0xFFFF;  
9573
9574    flag = 0;
9575    SiS_SetSwitchDDC2(SiS_Pr);
9576    if(!(SiS_PrepareDDC(SiS_Pr))) {
9577       length = 127;
9578       if(DDCdatatype != 1) length = 255;
9579       chksum = 0;
9580       gotcha = 0;
9581       for(i=0; i<length; i++) {
9582          buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
9583          chksum += buffer[i];
9584          gotcha |= buffer[i];
9585          SiS_SendACK(SiS_Pr, 0);
9586       }
9587       buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
9588       chksum += buffer[i];
9589       SiS_SendACK(SiS_Pr, 1);
9590       if(gotcha) flag = (USHORT)chksum;
9591       else flag = 0xFFFF;
9592    } else {
9593       flag = 0xFFFF;
9594    }
9595    SiS_SetStop(SiS_Pr);
9596    return(flag);
9597 }
9598
9599 /* Our private DDC functions
9600
9601    It complies somewhat with the corresponding VESA function
9602    in arguments and return values.
9603
9604    Since this is probably called before the mode is changed,
9605    we use our pre-detected pSiS-values instead of SiS_Pr as
9606    regards chipset and video bridge type.
9607
9608    Arguments:
9609        adaptnum: 0=CRT1(analog), 1=CRT2/LCD(digital), 2=CRT2/VGA2(analog)
9610                  CRT2 DDC is only supported on SiS301, 301B, 301C, 302B.
9611                  LCDA is CRT1, but DDC is read from CRT2 port.
9612        DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
9613        buffer: ptr to 256 data bytes which will be filled with read data.
9614
9615    Returns 0xFFFF if error, otherwise
9616        if DDCdatatype > 0:  Returns 0 if reading OK (included a correct checksum)
9617        if DDCdatatype = 0:  Returns supported DDC modes
9618
9619  */
9620 USHORT
9621 SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
9622               USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer)
9623 {
9624    unsigned char sr1f,cr17=1;
9625    USHORT result;
9626
9627    if(adaptnum > 2) return 0xFFFF;
9628    if(DDCdatatype > 4) return 0xFFFF;
9629    if((!(VBFlags & VB_VIDEOBRIDGE)) && (adaptnum > 0)) return 0xFFFF;
9630    if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE) == 0xFFFF) return 0xFFFF;
9631
9632    sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
9633    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
9634    if(VGAEngine == SIS_300_VGA) {
9635       cr17 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80;
9636       if(!cr17) {
9637          SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x17,0x80);
9638          SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x01);
9639          SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
9640       }
9641    }
9642    if((sr1f) || (!cr17)) {
9643       SiS_WaitRetrace1(SiS_Pr);
9644       SiS_WaitRetrace1(SiS_Pr);
9645       SiS_WaitRetrace1(SiS_Pr);
9646       SiS_WaitRetrace1(SiS_Pr);
9647    }
9648
9649    if(DDCdatatype == 0) {
9650       result = SiS_ProbeDDC(SiS_Pr);
9651    } else {
9652       result = SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer);
9653       if((!result) && (DDCdatatype == 1)) {
9654          if((buffer[0] == 0x00) && (buffer[1] == 0xff) &&
9655             (buffer[2] == 0xff) && (buffer[3] == 0xff) &&
9656             (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
9657             (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
9658             (buffer[0x12] == 1)) {
9659             if(adaptnum == 1) {
9660                if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
9661             } else {
9662                if(buffer[0x14] & 0x80)    result = 0xFFFE;
9663             }
9664          }
9665       }
9666    }
9667    SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,sr1f);
9668    if(VGAEngine == SIS_300_VGA) {
9669       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x17,0x7f,cr17);
9670    }
9671    return result;
9672 }
9673
9674 #ifdef LINUX_XF86
9675
9676 static BOOLEAN
9677 checkedid1(unsigned char *buffer)
9678 {
9679    /* Check header */
9680    if((buffer[0] != 0x00) ||
9681       (buffer[1] != 0xff) ||
9682       (buffer[2] != 0xff) ||
9683       (buffer[3] != 0xff) ||
9684       (buffer[4] != 0xff) ||
9685       (buffer[5] != 0xff) ||
9686       (buffer[6] != 0xff) ||
9687       (buffer[7] != 0x00))
9688       return FALSE;
9689
9690    /* Check EDID version and revision */
9691    if((buffer[0x12] != 1) || (buffer[0x13] > 4)) return FALSE;
9692
9693    /* Check week of manufacture for sanity */
9694    if(buffer[0x10] > 53) return FALSE;
9695
9696    /* Check year of manufacture for sanity */
9697    if(buffer[0x11] > 40) return FALSE;
9698
9699    return TRUE;
9700 }
9701
9702 static BOOLEAN
9703 checkedid2(unsigned char *buffer)
9704 {
9705    USHORT year = buffer[6] | (buffer[7] << 8);
9706
9707    /* Check EDID version */
9708    if((buffer[0] & 0xf0) != 0x20) return FALSE;
9709
9710    /* Check week of manufacture for sanity */
9711    if(buffer[5] > 53) return FALSE;
9712
9713    /* Check year of manufacture for sanity */
9714    if((year != 0) && ((year < 1990) || (year > 2030))) return FALSE;
9715
9716    return TRUE;
9717 }
9718
9719 /* Sense the LCD parameters (CR36, CR37) via DDC */
9720 /* SiS30x(B) only */
9721 USHORT
9722 SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS)
9723 {
9724    USHORT DDCdatatype, paneltype, flag, xres=0, yres=0;
9725    USHORT index, myindex, lumsize, numcodes, panelvendor, panelproduct;
9726    int maxx=0, maxy=0, prefx=0, prefy=0;
9727    unsigned char cr37=0, seekcode;
9728    BOOLEAN checkexpand = FALSE;
9729    BOOLEAN havesync = FALSE;
9730    BOOLEAN indb = FALSE;
9731    int retry, i;
9732    unsigned char buffer[256];
9733
9734    for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE;
9735    SiS_Pr->CP_HaveCustomData = FALSE;
9736    SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0;
9737    SiS_Pr->CP_PreferredX = SiS_Pr->CP_PreferredY = 0;
9738    SiS_Pr->CP_PreferredIndex = -1;
9739    SiS_Pr->CP_PrefClock = 0;
9740    SiS_Pr->PanelSelfDetected = FALSE;
9741
9742    if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
9743    if(pSiS->VBFlags & VB_30xBDH) return 0;
9744   
9745    if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 1, 0, FALSE) == 0xFFFF) return 0;
9746    
9747    SiS_Pr->SiS_DDC_SecAddr = 0x00;
9748    
9749    /* Probe supported DA's */
9750    flag = SiS_ProbeDDC(SiS_Pr);
9751 #ifdef TWDEBUG
9752    xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
9753         "CRT2 DDC capabilities 0x%x\n", flag);
9754 #endif  
9755    if(flag & 0x10) {
9756       SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;        /* EDID V2 (FP) */
9757       DDCdatatype = 4;
9758    } else if(flag & 0x08) {
9759       SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;        /* EDID V2 (P&D-D Monitor) */
9760       DDCdatatype = 3;
9761    } else if(flag & 0x02) {
9762       SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;        /* EDID V1 */
9763       DDCdatatype = 1;
9764    } else return 0;                             /* no DDC support (or no device attached) */
9765    
9766    /* Read the entire EDID */
9767    retry = 2;
9768    do {
9769       if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
9770          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9771                 "CRT2: DDC read failed (attempt %d), %s\n",
9772                 (3-retry), (retry == 1) ? "giving up" : "retrying");
9773          retry--;
9774          if(retry == 0) return 0xFFFF;
9775       } else break;
9776    } while(1);
9777
9778 #ifdef TWDEBUG
9779    for(i=0; i<256; i+=16) {
9780        xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9781         "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
9782         buffer[i],    buffer[i+1], buffer[i+2], buffer[i+3],
9783         buffer[i+4],  buffer[i+5], buffer[i+6], buffer[i+7],
9784         buffer[i+8],  buffer[i+9], buffer[i+10], buffer[i+11],
9785         buffer[i+12], buffer[i+13], buffer[i+14], buffer[i+15]);
9786    }
9787 #endif   
9788    
9789    /* Analyze EDID and retrieve LCD panel information */
9790    paneltype = 0;
9791    switch(DDCdatatype) {
9792    case 1:                                                      /* Analyze EDID V1 */
9793       /* Catch a few clear cases: */
9794       if(!(checkedid1(buffer))) {
9795          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9796                 "LCD sense: EDID corrupt\n");
9797          return 0;
9798       }
9799
9800       if(!(buffer[0x14] & 0x80)) {
9801          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9802                 "LCD sense: Attached display expects analog input (0x%02x)\n",
9803                 buffer[0x14]);
9804          return 0;
9805       }
9806
9807       if((buffer[0x18] & 0x18) != 0x08) {
9808          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
9809                 "LCD sense: Warning: Attached display is not of RGB but of %s type (0x%02x)\n",
9810                 ((buffer[0x18] & 0x18) == 0x00) ? "monochrome/greyscale" :
9811                   ( ((buffer[0x18] & 0x18) == 0x10) ? "non-RGB multicolor" :
9812                      "undefined"),
9813                 buffer[0x18]);
9814       }
9815
9816       /* Now analyze the first Detailed Timing Block and see
9817        * if the preferred timing mode is stored there. If so,
9818        * check if this is a standard panel for which we already
9819        * know the timing.
9820        */
9821
9822       paneltype = Panel_Custom;
9823       checkexpand = FALSE;
9824
9825       panelvendor = buffer[9] | (buffer[8] << 8);
9826       panelproduct = buffer[10] | (buffer[11] << 8);
9827
9828       /* Overrule bogus preferred modes from database */
9829       if((indb = SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
9830          if(prefx) SiS_Pr->CP_PreferredX = xres = prefx;
9831          if(prefy) SiS_Pr->CP_PreferredY = yres = prefy;
9832       }
9833
9834       if(buffer[0x18] & 0x02) {
9835
9836          USHORT pclk = (buffer[0x36] | (buffer[0x37] << 8));
9837          USHORT phb  = (buffer[0x39] | ((buffer[0x3a] & 0x0f) << 8));
9838          USHORT pvb  = (buffer[0x3c] | ((buffer[0x3d] & 0x0f) << 8));
9839
9840          if(!xres) SiS_Pr->CP_PreferredX = xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
9841          if(!yres) SiS_Pr->CP_PreferredY = yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
9842
9843          switch(xres) {
9844 #if 0       /* Treat as custom */
9845             case 800:
9846                 if(yres == 600) {
9847                    paneltype = Panel_800x600;
9848                    checkexpand = TRUE;
9849                 }
9850                 break;
9851 #endif
9852             case 1024:
9853                 if(yres == 768) {
9854                    paneltype = Panel_1024x768;
9855                    checkexpand = TRUE;
9856                 }
9857                 break;
9858             case 1280:
9859                 if(yres == 1024) {
9860                    paneltype = Panel_1280x1024;
9861                    checkexpand = TRUE;
9862                 } else if(yres == 960) {
9863                    if(pSiS->VGAEngine == SIS_300_VGA) {
9864                       paneltype = Panel300_1280x960;
9865                    } else {
9866                       paneltype = Panel310_1280x960;
9867                    }
9868                 } else if(yres == 768) {
9869                    if( (pclk == 8100) &&
9870                        (phb == (1688 - 1280)) &&
9871                        (pvb == (802 - 768)) ) {
9872                       paneltype = Panel_1280x768;
9873                       checkexpand = FALSE;
9874                       cr37 |= 0x10;
9875                    }
9876                 } else if(yres == 800) {
9877                    if( (pclk == 6900) &&
9878                        (phb == (1408 - 1280)) &&
9879                        (pvb == (816 - 800)) ) {
9880                       paneltype = Panel_1280x800;
9881                    }
9882                 }
9883                 break;
9884             case 1400:
9885                 if(pSiS->VGAEngine == SIS_315_VGA) {
9886                    if(yres == 1050) {
9887                       paneltype = Panel310_1400x1050;
9888                       checkexpand = TRUE;
9889                    }
9890                 }
9891                 break;
9892             case 1600:
9893                 if(pSiS->VGAEngine == SIS_315_VGA) {
9894                    if(pSiS->VBFlags & VB_301C) {
9895                       if(yres == 1200) {
9896                          paneltype = Panel310_1600x1200;
9897                          checkexpand = TRUE;
9898                       }
9899                    }
9900                 }
9901                 break;
9902          }
9903
9904          /* Save sync: This is used if "Pass 1:1" is off; in this case
9905           * we always use the panel's native mode = this "preferred mode"
9906           * we just have been analysing. Hence, we also need its sync.
9907           */
9908          if((buffer[0x47] & 0x18) == 0x18) {
9909             cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
9910             havesync = TRUE;
9911          } else {
9912             /* What now? There is no digital separate output timing... */
9913             xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
9914                    "LCD sense: Unable to retrieve Sync polarity information\n");
9915             cr37 |= 0xc0;  /* Default */
9916          }
9917
9918       }
9919
9920       /* Check against our database; eg. Sanyo Z2 projector reports
9921        * 1024x768 as preferred mode, although it supports 1280x720
9922        * natively in non-HDCP mode. Treat such wrongly reporting
9923        * panels as custom and fixup actual maximum resolutions.
9924        */
9925       if(paneltype != Panel_Custom) {
9926          if(indb) {
9927             paneltype = Panel_Custom;
9928             SiS_Pr->CP_MaxX = maxx;
9929             SiS_Pr->CP_MaxY = maxy;
9930             /* Leave preferred unchanged (MUST contain a valid mode!) */
9931          }
9932       }
9933
9934       /* If we still don't know what panel this is, we take it
9935        * as a custom panel and derive the timing data from the
9936        * detailed timing blocks
9937        */
9938       if(paneltype == Panel_Custom) {
9939
9940          int i, temp, base = 0x36;
9941          unsigned long estpack;
9942          const unsigned short estx[] = {
9943                 720, 720, 640, 640, 640, 640, 800, 800,
9944                 800, 800, 832,1024,1024,1024,1024,1280,
9945                 1152
9946          };
9947          const unsigned short esty[] = {
9948                 400, 400, 480, 480, 480, 480, 600, 600,
9949                 600, 600, 624, 768, 768, 768, 768,1024,
9950                 870
9951          };
9952          const int estclk[] = {
9953                     0,     0, 25100,   0, 31500, 31500, 36100, 40000,
9954                 50100, 49500,     0,   0, 65100, 75200, 78700,135200,
9955                 0
9956          };
9957
9958          paneltype = 0;
9959          SiS_Pr->CP_Supports64048075 = TRUE;
9960
9961          /* Find the maximum resolution */
9962
9963          /* 1. From Established timings */
9964          estpack = (buffer[0x23] << 9) | (buffer[0x24] << 1) | ((buffer[0x25] >> 7) & 0x01);
9965          for(i=16; i>=0; i--) {
9966              if(estpack & (1 << i)) {
9967                 if(estx[16 - i] > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = estx[16 - i];
9968                 if(esty[16 - i] > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = esty[16 - i];
9969                 if(estclk[16 - i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = estclk[16 - i];
9970              }
9971          }
9972
9973          /* By default we drive the LCD at 75Hz in 640x480 mode; if
9974           * the panel does not provide this mode, use 60hz
9975           */
9976          if(!(buffer[0x23] & 0x04)) SiS_Pr->CP_Supports64048075 = FALSE;
9977
9978          /* 2. From Standard Timings */
9979          for(i=0x26; i < 0x36; i+=2) {
9980             if((buffer[i] != 0x01) && (buffer[i+1] != 0x01)) {
9981                temp = (buffer[i] + 31) * 8;
9982                if(temp > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = temp;
9983                switch((buffer[i+1] & 0xc0) >> 6) {
9984                case 0x03: temp = temp * 9 / 16; break;
9985                case 0x02: temp = temp * 4 / 5;  break;
9986                case 0x01: temp = temp * 3 / 4;  break;
9987                }
9988                if(temp > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = temp;
9989             }
9990          }
9991
9992          /* Now extract the Detailed Timings and convert them into modes */
9993
9994          for(i = 0; i < 4; i++, base += 18) {
9995
9996             /* Is this a detailed timing block or a monitor descriptor? */
9997             if(buffer[base] || buffer[base+1] || buffer[base+2]) {
9998
9999                xres = buffer[base+2] | ((buffer[base+4] & 0xf0) << 4);
10000                yres = buffer[base+5] | ((buffer[base+7] & 0xf0) << 4);
10001
10002                SiS_Pr->CP_HDisplay[i] = xres;
10003                SiS_Pr->CP_HSyncStart[i] = xres + (buffer[base+8] | ((buffer[base+11] & 0xc0) << 2));
10004                SiS_Pr->CP_HSyncEnd[i]   = SiS_Pr->CP_HSyncStart[i] + (buffer[base+9] | ((buffer[base+11] & 0x30) << 4));
10005                SiS_Pr->CP_HTotal[i] = xres + (buffer[base+3] | ((buffer[base+4] & 0x0f) << 8));
10006                SiS_Pr->CP_HBlankStart[i] = xres + 1;
10007                SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
10008
10009                SiS_Pr->CP_VDisplay[i] = yres;
10010                SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[base+10] & 0xf0) >> 4) | ((buffer[base+11] & 0x0c) << 2));
10011                SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[base+10] & 0x0f) | ((buffer[base+11] & 0x03) << 4));
10012                SiS_Pr->CP_VTotal[i] = yres + (buffer[base+6] | ((buffer[base+7] & 0x0f) << 8));
10013                SiS_Pr->CP_VBlankStart[i] = yres + 1;
10014                SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
10015
10016                SiS_Pr->CP_Clock[i] = (buffer[base] | (buffer[base+1] << 8)) * 10;
10017
10018                SiS_Pr->CP_DataValid[i] = TRUE;
10019
10020                /* Sort out invalid timings, interlace and too high clocks */
10021                if((SiS_Pr->CP_HDisplay[i] & 7)                                            ||
10022                   (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i])                     ||
10023                   (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i])                      ||
10024                   (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i])                        ||
10025                   (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i])                    ||
10026                   (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i])                       ||
10027                   (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i])                         ||
10028                   (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i])                     ||
10029                   (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i])                      ||
10030                   (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i])                        ||
10031                   (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i])                     ||
10032                   (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i])                       ||
10033                   (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i])                         ||
10034                   (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
10035                    ((!(pSiS->VBFlags & VB_301C)) &&
10036                     ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024) ||
10037                      (SiS_Pr->CP_HDisplay[i] > 1600))))                                   ||
10038                   (buffer[base+17] & 0x80)) {
10039
10040                   SiS_Pr->CP_DataValid[i] = FALSE;
10041
10042                } else {
10043
10044                   SiS_Pr->CP_HaveCustomData = TRUE;
10045
10046                   if(xres > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = xres;
10047                   if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres;
10048                   if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
10049
10050                   if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
10051                      SiS_Pr->CP_PreferredIndex = i;
10052                      SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
10053                      SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
10054                   }
10055
10056                   /* Extract the sync polarisation information. This only works
10057                    * if the Flags indicate a digital separate output.
10058                    */
10059                   if((buffer[base+17] & 0x18) == 0x18) {
10060                      SiS_Pr->CP_HSync_P[i] = (buffer[base+17] & 0x02) ? TRUE : FALSE;
10061                      SiS_Pr->CP_VSync_P[i] = (buffer[base+17] & 0x04) ? TRUE : FALSE;
10062                      SiS_Pr->CP_SyncValid[i] = TRUE;
10063                      if((i == SiS_Pr->CP_PreferredIndex) && (!havesync)) {
10064                         cr37 |= ((((buffer[base+17] & 0x06) ^ 0x06) << 5) | 0x20);
10065                         havesync = TRUE;
10066                      }
10067                   } else {
10068                      SiS_Pr->CP_SyncValid[i] = FALSE;
10069                   }
10070
10071                }
10072
10073             } else if((!buffer[base]) && (!buffer[base+1]) && (!buffer[base+2]) && (!buffer[base+4])) {
10074
10075                /* Maximum pixclock from Monitor Range Limits */
10076                if((buffer[base+3] == 0xfd) && (buffer[base+9] != 0xff)) {
10077                   int maxclk = buffer[base+9] * 10;
10078                   /* More than 170 is not supported anyway */
10079                   if(maxclk <= 170) SiS_Pr->CP_MaxClock = maxclk * 1000;
10080                }
10081
10082             }
10083
10084          }
10085
10086          if(SiS_Pr->CP_MaxX && SiS_Pr->CP_MaxY) {
10087             paneltype = Panel_Custom;
10088             checkexpand = FALSE;
10089             cr37 |= 0x10;
10090             SiS_Pr->CP_Vendor = panelvendor;
10091             SiS_Pr->CP_Product = panelproduct;
10092          }
10093
10094       }
10095
10096       if(paneltype && checkexpand) {
10097          /* If any of the Established low-res modes is supported, the
10098           * panel can scale automatically. For 800x600 panels, we only 
10099           * check the even lower ones.
10100           */
10101          if(paneltype == Panel_800x600) {
10102             if(buffer[0x23] & 0xfc) cr37 |= 0x10;
10103          } else {
10104             if(buffer[0x23])        cr37 |= 0x10;
10105          }
10106       }
10107        
10108       break;
10109       
10110    case 3:                                                      /* Analyze EDID V2 */
10111    case 4:
10112       index = 0;
10113
10114       if(!(checkedid2(buffer))) {
10115          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10116                 "LCD sense: EDID corrupt\n");
10117          return 0;
10118       }
10119
10120       if((buffer[0x41] & 0x0f) == 0x03) {
10121          index = 0x42 + 3;
10122          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10123                 "LCD sense: Display supports TMDS input on primary interface\n");
10124       } else if((buffer[0x41] & 0xf0) == 0x30) {
10125          index = 0x46 + 3;
10126          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10127                 "LCD sense: Display supports TMDS input on secondary interface\n");
10128       } else {
10129          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10130                 "LCD sense: Display does not support TMDS video interface (0x%02x)\n",
10131                 buffer[0x41]);
10132          return 0;
10133       }
10134
10135       SiS_Pr->CP_Vendor = panelvendor = buffer[2] | (buffer[1] << 8);
10136       SiS_Pr->CP_Product = panelproduct = buffer[3] | (buffer[4] << 8);
10137
10138       paneltype = Panel_Custom;
10139       SiS_Pr->CP_MaxX = SiS_Pr->CP_PreferredX = xres = buffer[0x76] | (buffer[0x77] << 8);
10140       SiS_Pr->CP_MaxY = SiS_Pr->CP_PreferredY = yres = buffer[0x78] | (buffer[0x79] << 8);
10141
10142       switch(xres) {
10143 #if 0
10144          case 800:
10145              if(yres == 600) {
10146                 paneltype = Panel_800x600;
10147                 checkexpand = TRUE;
10148              }
10149              break;
10150 #endif
10151          case 1024:
10152              if(yres == 768) {
10153                 paneltype = Panel_1024x768;
10154                 checkexpand = TRUE;
10155              }
10156              break;
10157          case 1280:
10158              if(yres == 960) {
10159                 if(pSiS->VGAEngine == SIS_315_VGA) {
10160                    paneltype = Panel310_1280x960;
10161                 } else {
10162                    paneltype = Panel300_1280x960;
10163                 }
10164              } else if(yres == 1024) {
10165                 paneltype = Panel_1280x1024;
10166                 checkexpand = TRUE;
10167              }
10168              /* 1280x768 treated as custom here */
10169              break;
10170          case 1400:
10171              if(pSiS->VGAEngine == SIS_315_VGA) {
10172                 if(yres == 1050) {
10173                    paneltype = Panel310_1400x1050;
10174                    checkexpand = TRUE;
10175                 }
10176              }
10177              break;
10178          case 1600:
10179              if(pSiS->VGAEngine == SIS_315_VGA) {
10180                 if(pSiS->VBFlags & VB_301C) {
10181                    if(yres == 1200) {
10182                       paneltype = Panel310_1600x1200;
10183                       checkexpand = TRUE;
10184                    }
10185                 }
10186              }
10187              break;
10188       }
10189
10190       /* Determine if RGB18 or RGB24 */
10191       if(index) {
10192          if((buffer[index] == 0x20) || (buffer[index] == 0x34)) {
10193             cr37 |= 0x01;
10194          }
10195       }
10196
10197       if(checkexpand) {
10198          /* TODO - for now, we let the panel scale */
10199          cr37 |= 0x10;
10200       }
10201
10202       /* Now seek 4-Byte Timing codes and extract sync pol info */
10203       index = 0x80;
10204       if(buffer[0x7e] & 0x20) {                     /* skip Luminance Table (if provided) */
10205          lumsize = buffer[0x80] & 0x1f;
10206          if(buffer[0x80] & 0x80) lumsize *= 3;
10207          lumsize++;  /* luminance header byte */
10208          index += lumsize;
10209       }
10210 #if 0 /* "pixel rate" = pixel clock? */
10211       if(buffer[0x7e] & 0x1c) {
10212          for(i=0; i<((buffer[0x7e] & 0x1c) >> 2); i++) {
10213             if(buffer[index + (i*8) + 6] && (buffer[index + (i*8) + 7] & 0x0f)) {
10214                int clk = (buffer[index + (i*8) + 6] | ((buffer[index + (i*8) + 7] & 0x0f) << 4)) * 1000;
10215                if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
10216             }
10217          }
10218       }
10219 #endif
10220       index += (((buffer[0x7e] & 0x1c) >> 2) * 8);   /* skip Frequency Ranges */
10221       if(buffer[0x7e] & 0x03) {
10222          for(i=0; i<(buffer[0x7e] & 0x03); i++) {
10223             if((buffer[index + (i*27) + 9]) || (buffer[index + (i*27) + 10])) {
10224                int clk = ((buffer[index + (i*27) + 9]) | ((buffer[index + (i*27) + 9]) << 8)) * 10;
10225                if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
10226             }
10227          }
10228       }
10229       index += ((buffer[0x7e] & 0x03) * 27);         /* skip Detailed Range Limits */
10230       numcodes = (buffer[0x7f] & 0xf8) >> 3;
10231       if(numcodes) {
10232          myindex = index;
10233          seekcode = (xres - 256) / 16;
10234          for(i=0; i<numcodes; i++) {
10235             if(buffer[myindex] == seekcode) break;
10236             myindex += 4;
10237          }
10238          if(buffer[myindex] == seekcode) {
10239             cr37 |= ((((buffer[myindex + 1] & 0x0c) ^ 0x0c) << 4) | 0x20);
10240             havesync = TRUE;
10241          } else {
10242             xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
10243                 "LCD sense: Unable to retrieve Sync polarity information\n");
10244          }
10245       } else {
10246          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
10247              "LCD sense: Unable to retrieve Sync polarity information\n");
10248       }
10249
10250       /* Check against our database; Eg. Sanyo projector reports
10251        * 1024x768 in non-HDPC mode, although it supports 1280x720.
10252        * Treat such wrongly reporting panels as custom.
10253        */
10254       if(paneltype != Panel_Custom) {
10255          int maxx, maxy, prefx, prefy;
10256          if((SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
10257             paneltype = Panel_Custom;
10258             SiS_Pr->CP_MaxX = maxx;
10259             SiS_Pr->CP_MaxY = maxy;
10260             cr37 |= 0x10;
10261             /* Leave preferred unchanged (MUST be a valid mode!) */
10262          }
10263       }
10264
10265       /* Now seek the detailed timing descriptions for custom panels */
10266       if(paneltype == Panel_Custom) {
10267
10268          SiS_Pr->CP_Supports64048075 = TRUE;
10269
10270          index += (numcodes * 4);
10271          numcodes = buffer[0x7f] & 0x07;
10272          for(i=0; i<numcodes; i++, index += 18) {
10273             xres = buffer[index+2] | ((buffer[index+4] & 0xf0) << 4);
10274             yres = buffer[index+5] | ((buffer[index+7] & 0xf0) << 4);
10275
10276             SiS_Pr->CP_HDisplay[i] = xres;
10277             SiS_Pr->CP_HSyncStart[i] = xres + (buffer[index+8] | ((buffer[index+11] & 0xc0) << 2));
10278             SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[index+9] | ((buffer[index+11] & 0x30) << 4));
10279             SiS_Pr->CP_HTotal[i] = xres + (buffer[index+3] | ((buffer[index+4] & 0x0f) << 8));
10280             SiS_Pr->CP_HBlankStart[i] = xres + 1;
10281             SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
10282
10283             SiS_Pr->CP_VDisplay[i] = yres;
10284             SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[index+10] & 0xf0) >> 4) | ((buffer[index+11] & 0x0c) << 2));
10285             SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[index+10] & 0x0f) | ((buffer[index+11] & 0x03) << 4));
10286             SiS_Pr->CP_VTotal[i] = yres + (buffer[index+6] | ((buffer[index+7] & 0x0f) << 8));
10287             SiS_Pr->CP_VBlankStart[i] = yres + 1;
10288             SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
10289
10290             SiS_Pr->CP_Clock[i] = (buffer[index] | (buffer[index+1] << 8)) * 10;
10291
10292             SiS_Pr->CP_DataValid[i] = TRUE;
10293
10294             if((SiS_Pr->CP_HDisplay[i] & 7)                                             ||
10295                (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i])                      ||
10296                (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i])                       ||
10297                (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i])                         ||
10298                (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i])                     ||
10299                (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i])                        ||
10300                (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i])                          ||
10301                (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i])                      ||
10302                (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i])                       ||
10303                (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i])                         ||
10304                (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i])                      ||
10305                (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i])                        ||
10306                (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i])                          ||
10307                (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
10308                 ((!(pSiS->VBFlags & VB_301C)) &&
10309                  ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024))))  ||
10310                (buffer[index + 17] & 0x80)) {
10311
10312                SiS_Pr->CP_DataValid[i] = FALSE;
10313
10314             } else {
10315
10316                SiS_Pr->CP_HaveCustomData = TRUE;
10317
10318                if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
10319
10320                if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
10321                   SiS_Pr->CP_PreferredIndex = i;
10322                   SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
10323                   SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
10324                   if(!havesync) {
10325                      cr37 |= ((((buffer[index + 17] & 0x06) ^ 0x06) << 5) | 0x20);
10326                      havesync = TRUE;
10327                   }
10328                }
10329
10330                SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE;
10331                SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE;
10332                SiS_Pr->CP_SyncValid[i] = TRUE;
10333
10334             }
10335          }
10336
10337          cr37 |= 0x10;
10338
10339       }
10340
10341       break;
10342
10343    }
10344
10345    /* 1280x960 panels are always RGB24, unable to scale and use
10346     * high active sync polarity
10347     */
10348    if(pSiS->VGAEngine == SIS_315_VGA) {
10349       if(paneltype == Panel310_1280x960) cr37 &= 0x0e;
10350    } else {
10351       if(paneltype == Panel300_1280x960) cr37 &= 0x0e;
10352    }
10353
10354    for(i = 0; i < 7; i++) {
10355       if(SiS_Pr->CP_DataValid[i]) {
10356          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10357             "Non-standard LCD/DVI-D timing data no. %d:\n", i);
10358          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10359             "   HDisplay %d HSync %d HSyncEnd %d HTotal %d\n",
10360             SiS_Pr->CP_HDisplay[i], SiS_Pr->CP_HSyncStart[i],
10361             SiS_Pr->CP_HSyncEnd[i], SiS_Pr->CP_HTotal[i]);
10362          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10363             "   VDisplay %d VSync %d VSyncEnd %d VTotal %d\n",
10364             SiS_Pr->CP_VDisplay[i], SiS_Pr->CP_VSyncStart[i],
10365             SiS_Pr->CP_VSyncEnd[i], SiS_Pr->CP_VTotal[i]);
10366          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10367             "   Pixel clock: %3.3fMhz\n", (float)SiS_Pr->CP_Clock[i] / 1000);
10368          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
10369             "   To use this, add \"%dx%d\" to the list of Modes in the Screen section\n",
10370             SiS_Pr->CP_HDisplay[i],
10371             SiS_Pr->CP_VDisplay[i]);
10372       }
10373    }
10374
10375    if(paneltype) {
10376        if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
10377        if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
10378        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
10379        SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,paneltype);
10380        cr37 &= 0xf1;
10381        SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0x0c,cr37);
10382        SiS_Pr->PanelSelfDetected = TRUE;
10383 #ifdef TWDEBUG
10384        xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3, 
10385            "LCD sense: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
10386 #endif  
10387    } else {
10388        SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x32,~0x08);
10389        SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,0x00);
10390    }
10391    return 0;
10392 }
10393    
10394 USHORT
10395 SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS)
10396 {
10397    USHORT DDCdatatype,flag;
10398    BOOLEAN foundcrt = FALSE;
10399    int retry;
10400    unsigned char buffer[256];
10401
10402    if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
10403
10404    if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2, 0, FALSE) == 0xFFFF) return 0;
10405    
10406    SiS_Pr->SiS_DDC_SecAddr = 0x00;
10407    
10408    /* Probe supported DA's */
10409    flag = SiS_ProbeDDC(SiS_Pr);
10410    if(flag & 0x10) {
10411       SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;        /* EDID V2 (FP) */
10412       DDCdatatype = 4;
10413    } else if(flag & 0x08) {
10414       SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;        /* EDID V2 (P&D-D Monitor) */
10415       DDCdatatype = 3;
10416    } else if(flag & 0x02) {
10417       SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;        /* EDID V1 */
10418       DDCdatatype = 1;
10419    } else {
10420         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10421                 "VGA2 sense: Do DDC answer\n");
10422         return 0;                               /* no DDC support (or no device attached) */
10423    }
10424
10425    /* Read the entire EDID */
10426    retry = 2;
10427    do {
10428       if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
10429          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
10430                 "VGA2 sense: DDC read failed (attempt %d), %s\n",
10431                 (3-retry), (retry == 1) ? "giving up" : "retrying");
10432          retry--;
10433          if(retry == 0) return 0xFFFF;
10434       } else break;
10435    } while(1);
10436
10437    /* Analyze EDID. We don't have many chances to
10438     * distinguish a flat panel from a CRT...
10439     */
10440    switch(DDCdatatype) {
10441    case 1:
10442       if(!(checkedid1(buffer))) {
10443           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
10444                 "VGA2 sense: EDID corrupt\n");
10445           return 0;
10446       }
10447       if(buffer[0x14] & 0x80) {                 /* Display uses digital input */
10448           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
10449                 "VGA2 sense: Attached display expects digital input\n");
10450           return 0;
10451       }
10452       SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
10453       SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
10454       foundcrt = TRUE;
10455       break;
10456    case 3:
10457    case 4:
10458       if(!(checkedid2(buffer))) {
10459           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
10460                 "VGA2 sense: EDID corrupt\n");
10461           return 0;
10462       }
10463       if( ((buffer[0x41] & 0x0f) != 0x01) &&    /* Display does not support analog input */
10464           ((buffer[0x41] & 0x0f) != 0x02) &&
10465           ((buffer[0x41] & 0xf0) != 0x10) &&
10466           ((buffer[0x41] & 0xf0) != 0x20) ) {
10467           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
10468                 "VGA2 sense: Attached display does not support analog input (0x%02x)\n",
10469                 buffer[0x41]);
10470           return 0;
10471       }
10472       SiS_Pr->CP_Vendor = buffer[2] | (buffer[1] << 8);
10473       SiS_Pr->CP_Product = buffer[3] | (buffer[4] << 8);
10474       foundcrt = TRUE;
10475       break;
10476    }
10477
10478    if(foundcrt) {
10479       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
10480    }
10481    return(0);
10482 }
10483
10484 #endif
10485
10486 void
10487 SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh)
10488 {
10489   USHORT tempbl;
10490
10491   tempbl = SiS_GetCH70xx(SiS_Pr,(tempax & 0x00FF));
10492   tempbl = (((tempbl & tempbh) << 8) | tempax);
10493   SiS_SetCH70xx(SiS_Pr,tempbl);
10494 }
10495
10496 /* Generic I2C functions for Chrontel & DDC --------- */
10497
10498 static void
10499 SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
10500 {
10501   SiS_SetSCLKHigh(SiS_Pr);
10502   SiS_WaitRetrace1(SiS_Pr);
10503
10504   SiS_SetSCLKLow(SiS_Pr);
10505   SiS_WaitRetrace1(SiS_Pr);
10506 }
10507
10508 USHORT
10509 SiS_ReadDDC1Bit(SiS_Private *SiS_Pr)
10510 {
10511    SiS_WaitRetrace1(SiS_Pr);
10512    return((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
10513 }
10514
10515 /* Set I2C start condition */
10516 /* This is done by a SD high-to-low transition while SC is high */
10517 static USHORT
10518 SiS_SetStart(SiS_Private *SiS_Pr)
10519 {
10520   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                                /* (SC->low)  */
10521   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10522                   SiS_Pr->SiS_DDC_Index,
10523                   SiS_Pr->SiS_DDC_NData,
10524                   SiS_Pr->SiS_DDC_Data);                                   /* SD->high */
10525   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                               /* SC->high */
10526   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10527                   SiS_Pr->SiS_DDC_Index,
10528                   SiS_Pr->SiS_DDC_NData,
10529                   0x00);                                                   /* SD->low = start condition */
10530   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                               /* (SC->low) */
10531   return 0;
10532 }
10533
10534 /* Set I2C stop condition */
10535 /* This is done by a SD low-to-high transition while SC is high */
10536 static USHORT
10537 SiS_SetStop(SiS_Private *SiS_Pr)
10538 {
10539   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                                /* (SC->low) */
10540   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10541                   SiS_Pr->SiS_DDC_Index,
10542                   SiS_Pr->SiS_DDC_NData,
10543                   0x00);                                                   /* SD->low   */
10544   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                               /* SC->high  */
10545   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10546                   SiS_Pr->SiS_DDC_Index,
10547                   SiS_Pr->SiS_DDC_NData,
10548                   SiS_Pr->SiS_DDC_Data);                                   /* SD->high = stop condition */
10549   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                               /* (SC->high) */
10550   return 0;
10551 }
10552
10553 /* Write 8 bits of data */
10554 static USHORT
10555 SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
10556 {
10557   USHORT i,flag,temp;
10558
10559   flag = 0x80;
10560   for(i=0; i<8; i++) {
10561     SiS_SetSCLKLow(SiS_Pr);                                                   /* SC->low */
10562     if(tempax & flag) {
10563       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10564                       SiS_Pr->SiS_DDC_Index,
10565                       SiS_Pr->SiS_DDC_NData,
10566                       SiS_Pr->SiS_DDC_Data);                                  /* Write bit (1) to SD */
10567     } else {
10568       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10569                       SiS_Pr->SiS_DDC_Index,
10570                       SiS_Pr->SiS_DDC_NData,
10571                       0x00);                                                  /* Write bit (0) to SD */
10572     }
10573     SiS_SetSCLKHigh(SiS_Pr);                                                  /* SC->high */
10574     flag >>= 1;
10575   }
10576   temp = SiS_CheckACK(SiS_Pr);                                                /* Check acknowledge */
10577   return(temp);
10578 }
10579
10580 static USHORT
10581 SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
10582 {
10583   USHORT i,temp,getdata;
10584
10585   getdata=0;
10586   for(i=0; i<8; i++) {
10587     getdata <<= 1;
10588     SiS_SetSCLKLow(SiS_Pr);
10589     SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10590                     SiS_Pr->SiS_DDC_Index,
10591                     SiS_Pr->SiS_DDC_NData,
10592                     SiS_Pr->SiS_DDC_Data);
10593     SiS_SetSCLKHigh(SiS_Pr);
10594     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
10595     if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
10596   }
10597   return(getdata);
10598 }
10599
10600 static USHORT
10601 SiS_SetSCLKLow(SiS_Private *SiS_Pr)
10602 {
10603   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10604                   SiS_Pr->SiS_DDC_Index,
10605                   SiS_Pr->SiS_DDC_NClk,
10606                   0x00);                                        /* SetSCLKLow()  */
10607   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
10608   return 0;
10609 }
10610
10611 static USHORT
10612 SiS_SetSCLKHigh(SiS_Private *SiS_Pr)
10613 {
10614   USHORT temp, watchdog=1000;
10615
10616   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10617                   SiS_Pr->SiS_DDC_Index,
10618                   SiS_Pr->SiS_DDC_NClk,
10619                   SiS_Pr->SiS_DDC_Clk);                         /* SetSCLKHigh()  */
10620   do {
10621     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
10622   } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
10623   if (!watchdog) {
10624 #ifdef TWDEBUG
10625         xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n");
10626 #endif
10627         return 0xFFFF;
10628   }
10629   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
10630   return 0;
10631 }
10632
10633 /* Check I2C acknowledge */
10634 /* Returns 0 if ack ok, non-0 if ack not ok */
10635 static USHORT
10636 SiS_CheckACK(SiS_Private *SiS_Pr)
10637 {
10638   USHORT tempah;
10639
10640   SiS_SetSCLKLow(SiS_Pr);                                          /* (SC->low) */
10641   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
10642                   SiS_Pr->SiS_DDC_Index,
10643                   SiS_Pr->SiS_DDC_NData,
10644                   SiS_Pr->SiS_DDC_Data);                           /* (SD->high) */
10645   SiS_SetSCLKHigh(SiS_Pr);                                         /* SC->high = clock impulse for ack */
10646   tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
10647   SiS_SetSCLKLow(SiS_Pr);                                          /* SC->low = end of clock impulse */
10648   if(tempah & SiS_Pr->SiS_DDC_Data) return(1);                     /* Ack OK if bit = 0 */
10649   else return(0);
10650 }
10651
10652 /* End of I2C functions ----------------------- */
10653
10654
10655 /* =============== SiS 315/330 O.E.M. ================= */
10656
10657 #ifdef SIS315H
10658
10659 static USHORT
10660 GetRAMDACromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
10661 {
10662   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
10663   USHORT romptr;
10664
10665   if(HwInfo->jChipType < SIS_330) {
10666      romptr = SISGETROMW(0x128);
10667      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
10668         romptr = SISGETROMW(0x12a);
10669   } else {
10670      romptr = SISGETROMW(0x1a8);
10671      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
10672         romptr = SISGETROMW(0x1aa);
10673   }
10674   return(romptr);
10675 }
10676
10677 static USHORT
10678 GetLCDromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
10679 {
10680   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
10681   USHORT romptr;
10682
10683   if(HwInfo->jChipType < SIS_330) {
10684      romptr = SISGETROMW(0x120);
10685      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
10686         romptr = SISGETROMW(0x122);
10687   } else {
10688      romptr = SISGETROMW(0x1a0);
10689      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
10690         romptr = SISGETROMW(0x1a2);
10691   }
10692   return(romptr);
10693 }
10694
10695 static USHORT
10696 GetTVromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
10697 {
10698   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
10699   USHORT romptr;
10700
10701   if(HwInfo->jChipType < SIS_330) {
10702      romptr = SISGETROMW(0x114);
10703      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
10704         romptr = SISGETROMW(0x11a);
10705   } else {
10706      romptr = SISGETROMW(0x194);
10707      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
10708         romptr = SISGETROMW(0x19a);
10709   }
10710   return(romptr);
10711 }
10712
10713 static USHORT
10714 GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
10715 {
10716   USHORT index;
10717
10718   if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
10719      if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
10720         if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
10721            index >>= 4;
10722            index *= 3;
10723            if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
10724            else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
10725            return index;
10726         }
10727      }
10728   }
10729
10730   index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
10731   if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
10732   else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
10733   index--;
10734   index *= 3;
10735   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
10736   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
10737   return index;
10738 }
10739
10740 static USHORT
10741 GetLCDPtrIndex(SiS_Private *SiS_Pr)
10742 {
10743   USHORT index;
10744
10745   index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
10746   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
10747   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
10748   return index;
10749 }
10750
10751 static USHORT
10752 GetTVPtrIndex(SiS_Private *SiS_Pr)
10753 {
10754   USHORT index;
10755
10756   index = 0;
10757   if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
10758   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
10759
10760   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
10761
10762   index <<= 1;
10763
10764   if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) &&
10765      (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
10766      index++;
10767   }
10768
10769   return index;
10770 }
10771
10772 static ULONG
10773 GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
10774 {
10775    USHORT index = 0, temp = 0;
10776
10777    if(SiS_Pr->SiS_TVMode & TVSetPAL)   index = 1;
10778    if(SiS_Pr->SiS_TVMode & TVSetPALM)  index = 2;
10779    if(SiS_Pr->SiS_TVMode & TVSetPALN)  index = 3;
10780    if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 6;
10781    if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
10782       index = 4;
10783       if(SiS_Pr->SiS_TVMode & TVSetPALM)  index++;
10784       if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
10785    }
10786
10787    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
10788       if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
10789          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
10790          index += addme;
10791          temp++;
10792       }
10793       temp += 0x0100;
10794    }
10795    return(ULONG)(index | (temp << 16));
10796 }
10797
10798 static ULONG
10799 GetOEMTVPtr661_2_OLD(SiS_Private *SiS_Pr)
10800 {
10801    return(GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
10802 }
10803
10804 #if 0
10805 static ULONG
10806 GetOEMTVPtr661_2_NEW(SiS_Private *SiS_Pr)
10807 {
10808    return(GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
10809 }
10810 #endif
10811
10812 static int
10813 GetOEMTVPtr661(SiS_Private *SiS_Pr)
10814 {
10815    int index = 0;
10816
10817    if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
10818    if(SiS_Pr->SiS_ROMNew) {
10819       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
10820       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
10821       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
10822       if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
10823    } else {
10824       if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
10825       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
10826       if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
10827       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
10828    }
10829
10830    if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
10831
10832    return index;
10833 }
10834
10835 static void
10836 SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
10837 {
10838   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
10839   USHORT delay=0,index,myindex,temp,romptr=0;
10840   BOOLEAN dochiptest = TRUE;
10841
10842   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10843      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
10844   } else {
10845      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
10846   }
10847
10848   /* Find delay (from ROM, internal tables, PCI subsystem) */
10849
10850   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {                    /* ------------ VGA */
10851      
10852      if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10853         romptr = GetRAMDACromptr(SiS_Pr, HwInfo);
10854      }
10855      if(romptr) delay = ROMAddr[romptr];
10856      else {
10857         delay = 0x04;
10858         if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
10859            if(IS_SIS650) {
10860               delay = 0x0a;
10861            } else if(IS_SIS740) {
10862               delay = 0x00;
10863            } else if(HwInfo->jChipType < SIS_330) {
10864               delay = 0x0c;
10865            } else {
10866               delay = 0x0c;
10867            }
10868         } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
10869            delay = 0x00;
10870         }
10871      }
10872
10873   } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {  /* ---------- LCD/LCDA */
10874
10875      BOOLEAN gotitfrompci = FALSE;
10876
10877      /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
10878
10879      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
10880         if(SiS_Pr->PDC != -1) {
10881            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
10882            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
10883            return;
10884         }
10885      } else {
10886         if(SiS_Pr->PDCA != -1) {
10887            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
10888            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
10889            return;
10890         }
10891      }
10892
10893      /* Custom Panel? */
10894
10895      if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
10896         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
10897            delay = 0x00;
10898            if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
10899               delay = 0x20;
10900            }
10901            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
10902         } else {
10903            delay = 0x0c;
10904            if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x03;
10905            else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
10906               if(IS_SIS740) delay = 0x01;
10907               else          delay = 0x03;
10908            }
10909            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
10910         }
10911         return;
10912      }
10913
10914      /* This is a piece of typical SiS crap: They code the OEM LCD
10915       * delay into the code, at no defined place in the BIOS.
10916       * We now have to start doing a PCI subsystem check here.
10917       */
10918
10919      switch(SiS_Pr->SiS_CustomT) {
10920      case CUT_COMPAQ1280:
10921      case CUT_COMPAQ12802:
10922         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
10923            gotitfrompci = TRUE;
10924            dochiptest = FALSE;
10925            delay = 0x03;
10926         }
10927         break;
10928      case CUT_CLEVO1400:
10929      case CUT_CLEVO14002:
10930         gotitfrompci = TRUE;
10931         dochiptest = FALSE;
10932         delay = 0x02;
10933         break;
10934      case CUT_CLEVO1024:
10935      case CUT_CLEVO10242:
10936         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
10937            gotitfrompci = TRUE;
10938            dochiptest = FALSE;
10939            delay = 0x33;
10940            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
10941            delay &= 0x0f;
10942         }
10943         break;
10944      }
10945
10946      /* Could we find it through the PCI ID? If no, use ROM or table */
10947
10948      if(!gotitfrompci) {
10949
10950         index = GetLCDPtrIndexBIOS(SiS_Pr, HwInfo);
10951         myindex = GetLCDPtrIndex(SiS_Pr);
10952
10953         if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
10954
10955            if(SiS_IsNotM650orLater(SiS_Pr, HwInfo)) {
10956
10957               if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
10958                  /* Always use the second pointer on 650; some BIOSes */
10959                  /* still carry old 301 data at the first location    */
10960                  /* romptr = SISGETROMW(0x120);                       */
10961                  /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
10962                  romptr = SISGETROMW(0x122);
10963                  if(!romptr) return;
10964                  delay = ROMAddr[(romptr + index)];
10965               } else {
10966                  delay = SiS310_LCDDelayCompensation_650301LV[myindex];
10967               }
10968
10969           } else {
10970
10971              delay = SiS310_LCDDelayCompensation_651301LV[myindex];
10972              if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV))
10973                 delay = SiS310_LCDDelayCompensation_651302LV[myindex];
10974
10975           }
10976
10977         } else if(SiS_Pr->SiS_UseROM                          &&
10978                   (!(SiS_Pr->SiS_ROMNew))                     &&
10979                   (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
10980                   (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
10981                   (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)) {
10982
10983            /* Data for 1280x1024 wrong in 301B BIOS */
10984            romptr = GetLCDromptr(SiS_Pr, HwInfo);
10985            if(!romptr) return;
10986            delay = ROMAddr[(romptr + index)];
10987
10988         } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
10989
10990            if(IS_SIS740) delay = 0x03;
10991            else          delay = 0x00;
10992
10993         } else {
10994
10995            delay = SiS310_LCDDelayCompensation_301[myindex];
10996            if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
10997               if(IS_SIS740) delay = 0x01;
10998               else if(HwInfo->jChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
10999               else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
11000            } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
11001               if(IS_SIS740) delay = 0x01;  /* ? */
11002               else          delay = 0x03;
11003            } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
11004               if(IS_SIS740) delay = 0x01;
11005               else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
11006            }
11007
11008         }
11009
11010      }  /* got it from PCI */
11011
11012      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
11013         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
11014         dochiptest = FALSE;
11015      }
11016      
11017   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 /* ------------ TV */
11018
11019      index = GetTVPtrIndex(SiS_Pr);
11020      
11021      if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
11022
11023         if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
11024
11025            if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
11026               /* Always use the second pointer on 650; some BIOSes */
11027               /* still carry old 301 data at the first location    */
11028               /* romptr = SISGETROMW(0x114);                       */
11029               /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
11030               romptr = SISGETROMW(0x11a);
11031               if(!romptr) return;
11032               delay = ROMAddr[romptr + index];
11033
11034            } else {
11035
11036               delay = SiS310_TVDelayCompensation_301B[index];
11037
11038            }
11039
11040         } else {
11041
11042            switch(SiS_Pr->SiS_CustomT) {
11043            case CUT_COMPAQ1280:
11044            case CUT_COMPAQ12802:
11045            case CUT_CLEVO1400:
11046            case CUT_CLEVO14002:
11047               delay = 0x02;
11048               dochiptest = FALSE;
11049               break;
11050            case CUT_CLEVO1024:
11051            case CUT_CLEVO10242:
11052               delay = 0x03;
11053               dochiptest = FALSE;
11054               break;
11055            default:
11056               delay = SiS310_TVDelayCompensation_651301LV[index];
11057               if(SiS_Pr->SiS_VBType & VB_SIS302LV) {
11058                  delay = SiS310_TVDelayCompensation_651302LV[index];
11059               }
11060            }
11061         }
11062
11063      } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
11064
11065         romptr = GetTVromptr(SiS_Pr, HwInfo);
11066         if(!romptr) return;
11067         delay = ROMAddr[romptr + index];
11068
11069      } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
11070
11071         delay = SiS310_TVDelayCompensation_LVDS[index];
11072
11073      } else {
11074
11075         delay = SiS310_TVDelayCompensation_301[index];
11076         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
11077            if(IS_SIS740) {
11078               delay = SiS310_TVDelayCompensation_740301B[index];
11079               /* LV: use 301 data? BIOS bug? */
11080            } else {
11081               delay = SiS310_TVDelayCompensation_301B[index];
11082               if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
11083            }
11084         }
11085
11086      }
11087
11088      if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
11089         delay &= 0x0f;
11090         dochiptest = FALSE;
11091      }
11092     
11093   } else return;
11094
11095   /* Write delay */
11096
11097   if(SiS_Pr->SiS_VBType & VB_SISVB) {
11098
11099      if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && dochiptest) {
11100
11101         temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
11102         if(temp == 8) {         /* 1400x1050 BIOS (COMPAL) */
11103            delay &= 0x0f;
11104            delay |= 0xb0;
11105         } else if(temp == 6) {
11106            delay &= 0x0f;
11107            delay |= 0xc0;
11108         } else if(temp > 7) {   /* 1280x1024 BIOS (which one?) */
11109            delay = 0x35;
11110         }
11111         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
11112
11113      } else {
11114
11115         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
11116
11117      }
11118
11119   } else {  /* LVDS */
11120
11121      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
11122         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
11123      } else {
11124         if(IS_SIS650 && (SiS_Pr->SiS_IF_DEF_CH70xx != 0)) {
11125            delay <<= 4;
11126            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,delay);
11127         } else {
11128            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
11129         }
11130      }
11131
11132   }
11133
11134 }
11135
11136 static void
11137 SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11138                USHORT ModeNo,USHORT ModeIdIndex)
11139 {
11140   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11141   USHORT index,temp,temp1,romptr=0;
11142
11143   if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
11144
11145   if(ModeNo<=0x13)
11146      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
11147   else
11148      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
11149
11150   temp = GetTVPtrIndex(SiS_Pr);
11151   temp >>= 1;     /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
11152   temp1 = temp;
11153
11154   if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
11155      if(HwInfo->jChipType >= SIS_661) {
11156         temp1 = GetOEMTVPtr661(SiS_Pr);
11157         temp1 >>= 1;
11158         romptr = SISGETROMW(0x260);
11159         if(HwInfo->jChipType >= SIS_760) {
11160            romptr = SISGETROMW(0x360);
11161         }
11162      } else if(HwInfo->jChipType >= SIS_330) {
11163         romptr = SISGETROMW(0x192);
11164      } else {
11165         romptr = SISGETROMW(0x112);
11166      }
11167   }
11168
11169   if(romptr) {
11170      temp1 <<= 1;
11171      temp = ROMAddr[romptr + temp1 + index];
11172   } else {
11173      temp = SiS310_TVAntiFlick1[temp][index];
11174   }
11175   temp <<= 4;
11176
11177   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8f,temp);  /* index 0A D[6:4] */
11178 }
11179
11180 static void
11181 SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11182                USHORT ModeNo,USHORT ModeIdIndex)
11183 {
11184   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11185   USHORT index,temp,temp1,romptr=0;
11186
11187   temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1;    /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
11188
11189   if(ModeNo <= 0x13)
11190      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
11191   else
11192      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
11193
11194   if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
11195      if(HwInfo->jChipType >= SIS_661) {
11196         romptr = SISGETROMW(0x26c);
11197         if(HwInfo->jChipType >= SIS_760) {
11198            romptr = SISGETROMW(0x36c);
11199         }
11200         temp1 = GetOEMTVPtr661(SiS_Pr);
11201         temp1 >>= 1;
11202      } else if(HwInfo->jChipType >= SIS_330) {
11203         romptr = SISGETROMW(0x1a4);
11204      } else {
11205         romptr = SISGETROMW(0x124);
11206      }
11207   }
11208
11209   if(romptr) {
11210      temp1 <<= 1;
11211      temp = ROMAddr[romptr + temp1 + index];
11212   } else {
11213      temp = SiS310_TVEdge1[temp][index];
11214   }
11215   temp <<= 5;
11216   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x3A,0x1F,temp);  /* index 0A D[7:5] */
11217 }
11218
11219 static void
11220 SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11221            USHORT ModeNo,USHORT ModeIdIndex)
11222 {
11223   USHORT index, temp, i, j;
11224
11225   if(ModeNo <= 0x13) {
11226      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
11227   } else {
11228      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
11229   }
11230
11231   temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
11232
11233   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)        temp = 1;  /* NTSC-J uses PAL */
11234   else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
11235   else if(SiS_Pr->SiS_TVMode & TVSetPALN)    temp = 4;  /* PAL-N */
11236   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1;  /* HiVision uses PAL */
11237
11238   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
11239      for(i=0x35, j=0; i<=0x38; i++, j++) {
11240         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
11241      }
11242      for(i=0x48; i<=0x4A; i++, j++) {
11243         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
11244      }
11245   } else {
11246      for(i=0x35, j=0; i<=0x38; i++, j++) {
11247         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter1[temp][index][j]);
11248      }
11249   }
11250 }
11251
11252 static void
11253 SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11254              USHORT ModeNo,USHORT ModeIdIndex)
11255 {
11256   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11257   USHORT index,temp,i,j,resinfo,romptr=0;
11258   ULONG  lindex;
11259
11260   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
11261
11262   /* NTSC-J data not in BIOS, and already set in SetGroup2 */
11263   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
11264
11265   if((HwInfo->jChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
11266      lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
11267      lindex <<= 2;
11268      for(j=0, i=0x31; i<=0x34; i++, j++) {
11269         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
11270      }
11271      return;
11272   }
11273
11274   /* PAL-M, PAL-N not in BIOS, and already set in SetGroup2 */
11275   if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) return;
11276
11277   if(ModeNo<=0x13) {
11278      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
11279   } else {
11280      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
11281   }
11282
11283   temp = GetTVPtrIndex(SiS_Pr);
11284   /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
11285    * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
11286    */
11287   if(SiS_Pr->SiS_UseROM) {
11288      romptr = SISGETROMW(0x116);
11289      if(HwInfo->jChipType >= SIS_330) {
11290         romptr = SISGETROMW(0x196);
11291      }
11292      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
11293         romptr = SISGETROMW(0x11c);
11294         if(HwInfo->jChipType >= SIS_330) {
11295            romptr = SISGETROMW(0x19c);
11296         }
11297         if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
11298            romptr = SISGETROMW(0x116);
11299            if(HwInfo->jChipType >= SIS_330) {
11300               romptr = SISGETROMW(0x196);
11301            }
11302         }
11303      }
11304   }
11305   if(romptr) {
11306      romptr += (temp << 2);
11307      for(j=0, i=0x31; i<=0x34; i++, j++) {
11308         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
11309      }
11310   } else {
11311      index = temp % 2;
11312      temp >>= 1;          /* 0:NTSC, 1:PAL, 2:HiTV */
11313      for(j=0, i=0x31; i<=0x34; i++, j++) {
11314         if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV))
11315            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
11316         else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
11317            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
11318         else
11319            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
11320      }
11321   }
11322
11323   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
11324      if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
11325         if((resinfo == SIS_RI_640x480) ||
11326            (resinfo == SIS_RI_800x600)) {
11327            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
11328            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
11329            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
11330            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
11331         } else if(resinfo == SIS_RI_1024x768) {
11332            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
11333            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
11334            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
11335            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
11336         }
11337      }
11338   }
11339 }
11340
11341 static void
11342 SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
11343                 USHORT ModeIdIndex, USHORT RTI)
11344 {
11345    USHORT delay = 0, romptr = 0, index, lcdpdcindex;
11346    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11347
11348    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
11349       return;
11350
11351    /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
11352    /* (If a custom mode is used, Pass1:1 is always set; hence we do this:) */
11353
11354    if(SiS_Pr->SiS_ROMNew) {
11355       if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)                         ||
11356          ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
11357           (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
11358          index = 25;
11359          if(SiS_Pr->UseCustomMode) {
11360             index = SiS_Pr->CSRClock;
11361          } else if(ModeNo > 0x13) {
11362             index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI,HwInfo);
11363             index = SiS_Pr->SiS_VCLKData[index].CLOCK;
11364          }
11365          if(index < 25) index = 25;
11366          index = ((index / 25) - 1) << 1;
11367          if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
11368             index++;
11369          }
11370          romptr = SISGETROMW(0x104);
11371          delay = ROMAddr[romptr + index];
11372          if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
11373             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
11374             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
11375          } else {
11376             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
11377             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
11378          }
11379          return;
11380       }
11381    }
11382
11383    /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
11384
11385    if(SiS_Pr->UseCustomMode) delay = 0x04;
11386    else if(ModeNo <= 0x13)   delay = 0x04;
11387    else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
11388    delay |= (delay << 8);
11389
11390    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
11391
11392       /* 3. TV */
11393
11394       index = GetOEMTVPtr661(SiS_Pr);
11395       if(SiS_Pr->SiS_ROMNew) {
11396          romptr = SISGETROMW(0x106);
11397          if(SiS_Pr->SiS_VBType & VB_UMC) romptr += 12;
11398          delay = ROMAddr[romptr + index];
11399       } else {
11400          delay = 0x04;
11401          if(index > 3) delay = 0;
11402       }
11403
11404    } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11405
11406       /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
11407
11408       if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
11409           ((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) ) {
11410
11411          lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
11412
11413          /* For LVDS (and sometimes TMDS), the BIOS must know about the correct value */
11414          delay = ROMAddr[romptr + lcdpdcindex + 1];     /* LCD  */
11415          delay |= (ROMAddr[romptr + lcdpdcindex] << 8); /* LCDA */
11416
11417       } else {
11418
11419          /* TMDS: Set our own, since BIOS has no idea */
11420          /* (This is done on >=661 only, since <661 is calling this only for LVDS) */
11421          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
11422             switch(SiS_Pr->SiS_LCDResInfo) {
11423             case Panel_1024x768:  delay = 0x0008; break;
11424             case Panel_1280x720:  delay = 0x0004; break;
11425             case Panel_1280x768:
11426             case Panel_1280x768_2:delay = 0x0004; break;
11427             case Panel_1280x800:
11428             case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
11429             case Panel_1280x1024: delay = 0x1e04; break;
11430             case Panel_1400x1050: delay = 0x0004; break;
11431             case Panel_1600x1200: delay = 0x0400; break;
11432             case Panel_1680x1050: delay = 0x0e04; break;
11433             default:
11434                if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
11435                   delay = 0x0008;
11436                } else if((SiS_Pr->PanelXRes == 1280) && (SiS_Pr->PanelYRes == 1024)) {
11437                   delay = 0x1e04;
11438                } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
11439                   delay = 0x0004;
11440                } else if((SiS_Pr->PanelXRes <= 1600) && (SiS_Pr->PanelYRes <= 1200)) {
11441                   delay = 0x0400;
11442                } else
11443                   delay = 0x0e04;
11444                break;
11445             }
11446          }
11447
11448          /* Override by detected or user-set values */
11449          /* (but only if, for some reason, we can't read value from BIOS) */
11450          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
11451             delay = SiS_Pr->PDC & 0x1f;
11452          }
11453          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
11454             delay = (SiS_Pr->PDCA & 0x1f) << 8;
11455          }
11456
11457       }
11458
11459    }
11460
11461    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
11462       delay >>= 8;
11463       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
11464       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
11465    } else {
11466       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
11467       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
11468    }
11469 }
11470
11471 static void
11472 SetCRT2SyncDither661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT RTI)
11473 {
11474    USHORT infoflag;
11475    UCHAR temp;
11476
11477    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11478
11479       if(ModeNo <= 0x13) {
11480          infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
11481       } else if(SiS_Pr->UseCustomMode) {
11482          infoflag = SiS_Pr->CInfoFlag;
11483       } else {
11484          infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
11485       }
11486
11487       if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
11488          infoflag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37); /* No longer check D5 */
11489       }
11490
11491       infoflag &= 0xc0;
11492
11493       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
11494          temp = (infoflag >> 6) | 0x0c;
11495          if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
11496             temp ^= 0x04;
11497             if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x10;
11498          }
11499          SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
11500       } else {
11501          temp = 0x30;
11502          if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp = 0x20;
11503          temp |= infoflag;
11504          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
11505          temp = 0;
11506          if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
11507             if(SiS_Pr->SiS_ModeType >= Mode24Bpp) temp |= 0x80;
11508          }
11509          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
11510       }
11511
11512    }
11513 }
11514
11515 static void
11516 SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
11517 {
11518    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11519    USHORT romptr, temp1, temp2;
11520
11521    if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
11522       if(SiS_Pr->LVDSHL != -1) {
11523          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
11524       }
11525    }
11526
11527    if(SiS_Pr->SiS_ROMNew) {
11528
11529       if((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) {
11530          if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
11531             temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
11532             temp2 = 0xfc;
11533             if(SiS_Pr->LVDSHL != -1) {
11534               temp1 &= 0xfc;
11535               temp2 = 0xf3;
11536             }
11537             SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
11538          }
11539          if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
11540             temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
11541             SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
11542          }
11543       }
11544
11545    }
11546 }
11547
11548 static void
11549 SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11550                   USHORT ModeNo,USHORT ModeIdIndex,USHORT RRTI)
11551 {
11552    if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
11553       SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
11554       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11555          SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
11556          SetPanelParms661(SiS_Pr,HwInfo);
11557       }
11558    } else {
11559       SetDelayComp(SiS_Pr,HwInfo,ModeNo);
11560    }
11561
11562    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
11563       SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11564       SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11565       SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11566       if(SiS_Pr->SiS_VBType & VB_SIS301) {
11567          SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11568       }
11569    }
11570 }
11571
11572 static void
11573 SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11574                   USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI)
11575 {
11576    if(SiS_Pr->SiS_VBType & VB_SISVB) {
11577
11578       SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
11579
11580       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11581          SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
11582          SetPanelParms661(SiS_Pr,HwInfo);
11583       }
11584
11585       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
11586          SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11587          SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11588          SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11589          if(SiS_Pr->SiS_VBType & VB_SIS301) {
11590             SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
11591          }
11592       }
11593    }
11594 }
11595
11596 /* FinalizeLCD
11597  * This finalizes some CRT2 registers for the very panel used.
11598  * If we have a backup if these registers, we use it; otherwise
11599  * we set the register according to most BIOSes. However, this
11600  * function looks quite different in every BIOS, so you better
11601  * pray that we have a backup...
11602  */
11603 static void
11604 SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
11605                 PSIS_HW_INFO HwInfo)
11606 {
11607   USHORT tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
11608   USHORT resinfo,modeflag;
11609
11610   if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) return;
11611   if(SiS_Pr->SiS_ROMNew) return;
11612
11613   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11614      if(SiS_Pr->LVDSHL != -1) {
11615         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
11616      }
11617   }
11618
11619   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
11620   if(SiS_Pr->UseCustomMode) return;
11621
11622   switch(SiS_Pr->SiS_CustomT) {
11623   case CUT_COMPAQ1280:
11624   case CUT_COMPAQ12802:
11625   case CUT_CLEVO1400:
11626   case CUT_CLEVO14002:
11627      return;
11628   }
11629
11630   if(ModeNo <= 0x13) {
11631      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
11632      modeflag =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
11633   } else {
11634      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
11635      modeflag =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
11636   }
11637
11638   if(IS_SIS650) {
11639      if(!(SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
11640         if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
11641            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x02);
11642         } else {
11643            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
11644         }
11645      }
11646   }
11647
11648   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
11649      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11650         /* Maybe all panels? */
11651         if(SiS_Pr->LVDSHL == -1) {
11652            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
11653         }
11654         return;
11655      }
11656   }
11657
11658   if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
11659      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11660         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11661            if(SiS_Pr->LVDSHL == -1) {
11662               /* Maybe all panels? */
11663               SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
11664            }
11665            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
11666               tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
11667               if(tempch == 3) {
11668                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
11669                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
11670                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
11671                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
11672               }
11673            }
11674            return;
11675         }
11676      }
11677   }
11678
11679   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
11680      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11681         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
11682            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
11683 #ifdef SET_EMI
11684            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
11685 #endif
11686            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
11687         }
11688      } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
11689         if(SiS_Pr->LVDSHL == -1) {
11690            /* Maybe ACER only? */
11691            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
11692         }
11693      }
11694      tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
11695      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
11696         if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
11697            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
11698         } else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11699            if(tempch == 0x03) {
11700               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
11701               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
11702               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
11703               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
11704            }
11705            if((SiS_Pr->Backup == TRUE) && (SiS_Pr->Backup_Mode == ModeNo)) {
11706               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
11707               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
11708               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
11709               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,SiS_Pr->Backup_17);
11710               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,SiS_Pr->Backup_18);
11711               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,SiS_Pr->Backup_19);
11712               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,SiS_Pr->Backup_1a);
11713               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,SiS_Pr->Backup_1b);
11714               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,SiS_Pr->Backup_1c);
11715               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,SiS_Pr->Backup_1d);
11716            } else if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {  /* 1.10.8w */
11717               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x90);
11718               if(ModeNo <= 0x13) {
11719                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x11);
11720                  if((resinfo == 0) || (resinfo == 2)) return;
11721                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x18);
11722                  if((resinfo == 1) || (resinfo == 3)) return;
11723               }
11724               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
11725               if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
11726                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);  /* 1.10.7u */
11727 #if 0
11728                  tempbx = 806;  /* 0x326 */                      /* other older BIOSes */
11729                  tempbx--;
11730                  temp = tempbx & 0xff;
11731                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
11732                  temp = (tempbx >> 8) & 0x03;
11733                  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1d,0xf8,temp);
11734 #endif
11735               }
11736            } else if(ModeNo <= 0x13) {
11737               if(ModeNo <= 1) {
11738                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x70);
11739                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xff);
11740                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
11741                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
11742               }
11743               if(!(modeflag & HalfDCLK)) {
11744                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,0x20);
11745                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,0x1a);
11746                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,0x28);
11747                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,0x00);
11748                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x4c);
11749                  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
11750                  if(ModeNo == 0x12) {
11751                     switch(tempch) {
11752                        case 0:
11753                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
11754                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x19,0xdc);
11755                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1a,0x10);
11756                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
11757                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x48);
11758                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x12);
11759                           break;
11760                        case 2:
11761                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x95);
11762                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x48);
11763                           break;
11764                        case 3:
11765                           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x95);
11766                           break;
11767                     }
11768                  }
11769               }
11770            }
11771         }
11772      } else {
11773         tempcl = tempbh = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
11774         tempcl &= 0x0f;
11775         tempbh &= 0x70;
11776         tempbh >>= 4;
11777         tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
11778         tempbx = (tempbh << 8) | tempbl;
11779         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11780            if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
11781               if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
11782                  tempbx = 770;
11783               } else {
11784                  if(tempbx > 770) tempbx = 770;
11785                  if(SiS_Pr->SiS_VGAVDE < 600) {
11786                     tempax = 768 - SiS_Pr->SiS_VGAVDE;
11787                     tempax >>= 4;                                /* 1.10.7w; 1.10.6s: 3;  */
11788                     if(SiS_Pr->SiS_VGAVDE <= 480)  tempax >>= 4; /* 1.10.7w; 1.10.6s: < 480; >>=1; */
11789                     tempbx -= tempax;
11790                  }
11791               }
11792            } else return;
11793         }
11794         temp = tempbx & 0xff;
11795         SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
11796         temp = ((tempbx & 0xff00) >> 4) | tempcl;
11797         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,temp);
11798      }
11799   }
11800 }
11801
11802 #endif
11803
11804 /*  =================  SiS 300 O.E.M. ================== */
11805
11806 #ifdef SIS300
11807
11808 static void
11809 SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11810                USHORT ModeNo,USHORT ModeIdIndex, USHORT RefTabIndex)
11811 {
11812   USHORT crt2crtc=0, modeflag, myindex=0;
11813   UCHAR  temp;
11814   int i;
11815
11816   if(ModeNo <= 0x13) {
11817      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
11818      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
11819   } else {
11820      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
11821      crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
11822   }
11823
11824   crt2crtc &= 0x3f;
11825
11826   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
11827      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
11828   }
11829
11830   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
11831      if(modeflag & HalfDCLK) myindex = 1;
11832
11833      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
11834         for(i=0; i<7; i++) {
11835            if(barco_p1[myindex][crt2crtc][i][0]) {
11836               SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
11837                               barco_p1[myindex][crt2crtc][i][0],
11838                               barco_p1[myindex][crt2crtc][i][2],
11839                               barco_p1[myindex][crt2crtc][i][1]);
11840            }
11841         }
11842      }
11843      temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
11844      if(temp & 0x80) {
11845         temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x18);
11846         temp++;
11847         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
11848      }
11849   }
11850 }
11851
11852 static USHORT
11853 GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int Flag)
11854 {
11855   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11856   USHORT tempbx=0,romptr=0;
11857   UCHAR customtable300[] = {
11858         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
11859         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
11860   };
11861   UCHAR customtable630[] = {
11862         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
11863         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
11864   };
11865
11866   if(HwInfo->jChipType == SIS_300) {
11867
11868     tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
11869     if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
11870     tempbx -= 2;
11871     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
11872     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
11873        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
11874     }
11875     if(SiS_Pr->SiS_UseROM) {
11876        if(ROMAddr[0x235] & 0x80) {
11877           tempbx = SiS_Pr->SiS_LCDTypeInfo;
11878           if(Flag) {
11879              romptr = SISGETROMW(0x255);
11880              if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
11881              else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
11882              if(tempbx == 0xFF) return 0xFFFF;
11883           }
11884           tempbx <<= 1;
11885           if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
11886        }
11887     }
11888
11889   } else {
11890
11891     if(Flag) {
11892        if(SiS_Pr->SiS_UseROM) {
11893           romptr = SISGETROMW(0x255);
11894           if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
11895           else       tempbx = 0xff;
11896        } else {
11897           tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
11898        }
11899        if(tempbx == 0xFF) return 0xFFFF;
11900        tempbx <<= 2;
11901        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
11902        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
11903        return tempbx;
11904     }
11905     tempbx = SiS_Pr->SiS_LCDTypeInfo << 2;
11906     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempbx += 2;
11907     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
11908
11909   }
11910
11911   return tempbx;
11912 }
11913
11914 static void
11915 SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11916                USHORT ModeNo,USHORT ModeIdIndex)
11917 {
11918   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11919   USHORT index,temp,romptr=0;
11920
11921   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
11922
11923   if(SiS_Pr->SiS_UseROM) {
11924      if(!(ROMAddr[0x237] & 0x01)) return;
11925      if(!(ROMAddr[0x237] & 0x02)) return;
11926      romptr = SISGETROMW(0x24b);
11927   }
11928
11929   /* The Panel Compensation Delay should be set according to tables
11930    * here. Unfortunately, various BIOS versions don't case about
11931    * a uniform way using eg. ROM byte 0x220, but use different
11932    * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
11933    * Thus we don't set this if the user select a custom pdc or if
11934    * we otherwise detected a valid pdc.
11935    */
11936   if(SiS_Pr->PDC != -1) return;
11937
11938   temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 0);
11939
11940   if(SiS_Pr->UseCustomMode)
11941      index = 0;
11942   else
11943      index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
11944
11945   if(HwInfo->jChipType != SIS_300) {
11946      if(romptr) {
11947         romptr += (temp * 2);
11948         romptr = SISGETROMW(romptr);
11949         romptr += index;
11950         temp = ROMAddr[romptr];
11951      } else {
11952         if(SiS_Pr->SiS_VBType & VB_SISVB) {
11953            temp = SiS300_OEMLCDDelay2[temp][index];
11954         } else {
11955            temp = SiS300_OEMLCDDelay3[temp][index];
11956         }
11957      }
11958   } else {
11959      if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
11960         if(romptr) {
11961            romptr += (temp * 2);
11962            romptr = SISGETROMW(romptr);
11963            romptr += index;
11964            temp = ROMAddr[romptr];
11965         } else {
11966            temp = SiS300_OEMLCDDelay5[temp][index];
11967         }
11968      } else {
11969         if(SiS_Pr->SiS_UseROM) {
11970            romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
11971            if(romptr) {
11972               romptr += (temp * 2);
11973               romptr = SISGETROMW(romptr);
11974               romptr += index;
11975               temp = ROMAddr[romptr];
11976            } else {
11977               temp = SiS300_OEMLCDDelay4[temp][index];
11978            }
11979         } else {
11980            temp = SiS300_OEMLCDDelay4[temp][index];
11981         }
11982      }
11983   }
11984   temp &= 0x3c;
11985   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
11986 }
11987
11988 static void
11989 SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
11990               USHORT ModeNo,USHORT ModeIdIndex)
11991 {
11992 #if 0  /* Unfinished; Data table missing */
11993   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
11994   USHORT index,temp;
11995
11996   if((SiS_Pr->SiS_UseROM) {
11997      if(!(ROMAddr[0x237] & 0x01)) return;
11998      if(!(ROMAddr[0x237] & 0x04)) return;
11999      /* No rom pointer in BIOS header! */
12000   }
12001
12002   temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 1);
12003   if(temp = 0xFFFF) return;
12004
12005   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
12006   for(i=0x14, j=0; i<=0x17; i++, j++) {
12007       SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDHData[temp][index][j]);
12008   }
12009   SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1a, 0xf8, (SiS300_LCDHData[temp][index][j] & 0x07));
12010
12011   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDVIndex;
12012   SiS_SetReg(SiS_SiS_Part1Port,0x18, SiS300_LCDVData[temp][index][0]);
12013   SiS_SetRegANDOR(SiS_SiS_Part1Port,0x19, 0xF0, SiS300_LCDVData[temp][index][1]);
12014   SiS_SetRegANDOR(SiS_SiS_Part1Port,0x1A, 0xC7, (SiS300_LCDVData[temp][index][2] & 0x38));
12015   for(i=0x1b, j=3; i<=0x1d; i++, j++) {
12016       SiS_SetReg(SiS_Pr->SiS_Part1Port,i,SiS300_LCDVData[temp][index][j]);
12017   }
12018 #endif
12019 }
12020
12021 static USHORT
12022 GetOEMTVPtr(SiS_Private *SiS_Pr)
12023 {
12024   USHORT index;
12025
12026   index = 0;
12027   if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  index += 4;
12028   if(SiS_Pr->SiS_VBType & VB_SISVB) {
12029      if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)  index += 2;
12030      else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index += 3;
12031      else if(SiS_Pr->SiS_TVMode & TVSetPAL)   index += 1;
12032   } else {
12033      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) index += 2;
12034      if(SiS_Pr->SiS_TVMode & TVSetPAL)        index += 1;
12035   }
12036   return index;
12037 }
12038
12039 static void
12040 SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12041               USHORT ModeNo,USHORT ModeIdIndex)
12042 {
12043   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
12044   USHORT index,temp,romptr=0;
12045
12046   if(SiS_Pr->SiS_UseROM) {
12047      if(!(ROMAddr[0x238] & 0x01)) return;
12048      if(!(ROMAddr[0x238] & 0x02)) return;
12049      romptr = SISGETROMW(0x241);
12050   }
12051
12052   temp = GetOEMTVPtr(SiS_Pr);
12053
12054   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVDelayIndex;
12055
12056   if(romptr) {
12057      romptr += (temp * 2);
12058      romptr = SISGETROMW(romptr);
12059      romptr += index;
12060      temp = ROMAddr[romptr];
12061   } else {
12062      if(SiS_Pr->SiS_VBType & VB_SISVB) {
12063         temp = SiS300_OEMTVDelay301[temp][index];
12064      } else {
12065         temp = SiS300_OEMTVDelayLVDS[temp][index];
12066      }
12067   }
12068   temp &= 0x3c;
12069   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
12070 }
12071
12072 static void
12073 SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12074                   USHORT ModeNo, USHORT ModeIdIndex)
12075 {
12076   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
12077   USHORT index,temp,romptr=0;
12078
12079   if(SiS_Pr->SiS_UseROM) {
12080      if(!(ROMAddr[0x238] & 0x01)) return;
12081      if(!(ROMAddr[0x238] & 0x04)) return;
12082      romptr = SISGETROMW(0x243);
12083   }
12084
12085   temp = GetOEMTVPtr(SiS_Pr);
12086
12087   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVFlickerIndex;
12088
12089   if(romptr) {
12090      romptr += (temp * 2);
12091      romptr = SISGETROMW(romptr);
12092      romptr += index;
12093      temp = ROMAddr[romptr];
12094   } else {
12095      temp = SiS300_OEMTVFlicker[temp][index];
12096   }
12097   temp &= 0x70;
12098   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
12099 }
12100
12101 static void
12102 SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12103                 USHORT ModeNo,USHORT ModeIdIndex)
12104 {
12105   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
12106   USHORT index,i,j,temp,romptr=0;
12107
12108   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
12109
12110   if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
12111
12112   if(SiS_Pr->SiS_UseROM) {
12113      if(!(ROMAddr[0x238] & 0x01)) return;
12114      if(!(ROMAddr[0x238] & 0x08)) return;
12115      romptr = SISGETROMW(0x245);
12116   }
12117
12118   temp = GetOEMTVPtr(SiS_Pr);
12119
12120   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
12121
12122   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
12123      for(i=0x31, j=0; i<=0x34; i++, j++) {
12124         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
12125      }
12126   } else {
12127      if(romptr) {
12128         romptr += (temp * 2);
12129         romptr = SISGETROMW(romptr);
12130         romptr += (index * 4);
12131         for(i=0x31, j=0; i<=0x34; i++, j++) {
12132            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
12133         }
12134      } else {
12135         for(i=0x31, j=0; i<=0x34; i++, j++) {
12136            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase1[temp][index][j]);
12137         }
12138      }
12139   }
12140 }
12141
12142 static void
12143 SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12144               USHORT ModeNo,USHORT ModeIdIndex)
12145 {
12146   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
12147   USHORT index,temp,i,j,romptr=0;
12148
12149   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
12150
12151   if(SiS_Pr->SiS_UseROM) {
12152      if(!(ROMAddr[0x238] & 0x01)) return;
12153      if(!(ROMAddr[0x238] & 0x10)) return;
12154      romptr = SISGETROMW(0x247);
12155   }
12156
12157   temp = GetOEMTVPtr(SiS_Pr);
12158
12159   if(SiS_Pr->SiS_TVMode & TVSetPALM)      temp = 8;
12160   else if(SiS_Pr->SiS_TVMode & TVSetPALN) temp = 9;
12161   /* NTSCJ uses NTSC filters */
12162
12163   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
12164
12165   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
12166       for(i=0x35, j=0; i<=0x38; i++, j++) {
12167         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
12168       }
12169       for(i=0x48; i<=0x4A; i++, j++) {
12170         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
12171       }
12172   } else {
12173       if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
12174          romptr += (temp * 2);
12175          romptr = SISGETROMW(romptr);
12176          romptr += (index * 4);
12177          for(i=0x35, j=0; i<=0x38; i++, j++) {
12178             SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
12179          }
12180       } else {
12181          for(i=0x35, j=0; i<=0x38; i++, j++) {
12182             SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter1[temp][index][j]);
12183          }
12184       }
12185   }
12186 }
12187
12188 static USHORT
12189 SiS_SearchVBModeID(SiS_Private *SiS_Pr, USHORT *ModeNo)
12190 {
12191    USHORT ModeIdIndex;
12192    UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO;
12193
12194    if(*ModeNo <= 5) *ModeNo |= 1;
12195
12196    for(ModeIdIndex=0; ; ModeIdIndex++) {
12197       if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == *ModeNo) break;
12198       if(SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].ModeID == 0xFF)    return 0;
12199    }
12200
12201    if(*ModeNo != 0x07) {
12202       if(*ModeNo > 0x03) return ModeIdIndex;
12203       if(VGAINFO & 0x80) return ModeIdIndex;
12204       ModeIdIndex++;
12205    }
12206
12207    if(VGAINFO & 0x10) ModeIdIndex++;   /* 400 lines */
12208                                        /* else 350 lines */
12209    return ModeIdIndex;
12210 }
12211
12212 static void
12213 SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
12214                   USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTableIndex)
12215 {
12216   USHORT OEMModeIdIndex=0;
12217
12218   if(!SiS_Pr->UseCustomMode) {
12219      OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
12220      if(!(OEMModeIdIndex)) return;
12221   }
12222
12223   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
12224      SetOEMLCDDelay(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12225      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
12226         SetOEMLCDData(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12227      }
12228   }
12229   if(SiS_Pr->UseCustomMode) return;
12230   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
12231      SetOEMTVDelay(SiS_Pr, HwInfo, ModeNo,OEMModeIdIndex);
12232      if(SiS_Pr->SiS_VBType & VB_SISVB) {
12233         SetOEMAntiFlicker(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12234         SetOEMPhaseIncr(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12235         SetOEMYFilter(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
12236      }
12237   }
12238 }
12239 #endif
12240