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