Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
init.c
Go to the documentation of this file.
1 /* $XFree86$ */
2 /* $XdotOrg$ */
3 /*
4  * Mode initializing code (CRT1 section) for
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 Volari 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 #include "init.h"
60 
61 #ifdef CONFIG_FB_SIS_300
62 #include "300vtbl.h"
63 #endif
64 
65 #ifdef CONFIG_FB_SIS_315
66 #include "310vtbl.h"
67 #endif
68 
69 #if defined(ALLOC_PRAGMA)
70 #pragma alloc_text(PAGE,SiSSetMode)
71 #endif
72 
73 /*********************************************/
74 /* POINTER INITIALIZATION */
75 /*********************************************/
76 
77 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
78 static void
79 InitCommonPointer(struct SiS_Private *SiS_Pr)
80 {
81  SiS_Pr->SiS_SModeIDTable = SiS_SModeIDTable;
82  SiS_Pr->SiS_StResInfo = SiS_StResInfo;
85 
86  SiS_Pr->SiS_NTSCTiming = SiS_NTSCTiming;
87  SiS_Pr->SiS_PALTiming = SiS_PALTiming;
88  SiS_Pr->SiS_HiTVSt1Timing = SiS_HiTVSt1Timing;
89  SiS_Pr->SiS_HiTVSt2Timing = SiS_HiTVSt2Timing;
90 
91  SiS_Pr->SiS_HiTVExtTiming = SiS_HiTVExtTiming;
92  SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
93  SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
94 #if 0
95  SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
96  SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
97 #endif
98 
99  SiS_Pr->SiS_StPALData = SiS_StPALData;
100  SiS_Pr->SiS_ExtPALData = SiS_ExtPALData;
101  SiS_Pr->SiS_StNTSCData = SiS_StNTSCData;
102  SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;
103  SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData;
104  SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
105  SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
106  SiS_Pr->SiS_St525iData = SiS_StNTSCData;
107  SiS_Pr->SiS_St525pData = SiS_St525pData;
108  SiS_Pr->SiS_St750pData = SiS_St750pData;
109  SiS_Pr->SiS_Ext525iData = SiS_ExtNTSCData;
110  SiS_Pr->SiS_Ext525pData = SiS_ExtNTSCData;
111  SiS_Pr->SiS_Ext750pData = SiS_Ext750pData;
112 
113  SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
114  SiS_Pr->pSiS_SoftSetting = &SiS_SoftSetting;
115 
116  SiS_Pr->SiS_LCD1280x720Data = SiS_LCD1280x720Data;
117  SiS_Pr->SiS_StLCD1280x768_2Data = SiS_StLCD1280x768_2Data;
118  SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
119  SiS_Pr->SiS_LCD1280x800Data = SiS_LCD1280x800Data;
120  SiS_Pr->SiS_LCD1280x800_2Data = SiS_LCD1280x800_2Data;
121  SiS_Pr->SiS_LCD1280x854Data = SiS_LCD1280x854Data;
122  SiS_Pr->SiS_LCD1280x960Data = SiS_LCD1280x960Data;
123  SiS_Pr->SiS_StLCD1400x1050Data = SiS_StLCD1400x1050Data;
124  SiS_Pr->SiS_ExtLCD1400x1050Data = SiS_ExtLCD1400x1050Data;
125  SiS_Pr->SiS_LCD1680x1050Data = SiS_LCD1680x1050Data;
126  SiS_Pr->SiS_StLCD1600x1200Data = SiS_StLCD1600x1200Data;
127  SiS_Pr->SiS_ExtLCD1600x1200Data = SiS_ExtLCD1600x1200Data;
128  SiS_Pr->SiS_NoScaleData = SiS_NoScaleData;
129 
130  SiS_Pr->SiS_LVDS320x240Data_1 = SiS_LVDS320x240Data_1;
131  SiS_Pr->SiS_LVDS320x240Data_2 = SiS_LVDS320x240Data_2;
132  SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1;
133  SiS_Pr->SiS_LVDS800x600Data_1 = SiS_LVDS800x600Data_1;
134  SiS_Pr->SiS_LVDS1024x600Data_1 = SiS_LVDS1024x600Data_1;
135  SiS_Pr->SiS_LVDS1024x768Data_1 = SiS_LVDS1024x768Data_1;
136 
137  SiS_Pr->SiS_LVDSCRT1320x240_1 = SiS_LVDSCRT1320x240_1;
138  SiS_Pr->SiS_LVDSCRT1320x240_2 = SiS_LVDSCRT1320x240_2;
139  SiS_Pr->SiS_LVDSCRT1320x240_2_H = SiS_LVDSCRT1320x240_2_H;
140  SiS_Pr->SiS_LVDSCRT1320x240_3 = SiS_LVDSCRT1320x240_3;
141  SiS_Pr->SiS_LVDSCRT1320x240_3_H = SiS_LVDSCRT1320x240_3_H;
142  SiS_Pr->SiS_LVDSCRT1640x480_1 = SiS_LVDSCRT1640x480_1;
143  SiS_Pr->SiS_LVDSCRT1640x480_1_H = SiS_LVDSCRT1640x480_1_H;
144 #if 0
145  SiS_Pr->SiS_LVDSCRT11024x600_1 = SiS_LVDSCRT11024x600_1;
146  SiS_Pr->SiS_LVDSCRT11024x600_1_H = SiS_LVDSCRT11024x600_1_H;
147  SiS_Pr->SiS_LVDSCRT11024x600_2 = SiS_LVDSCRT11024x600_2;
148  SiS_Pr->SiS_LVDSCRT11024x600_2_H = SiS_LVDSCRT11024x600_2_H;
149 #endif
150 
151  SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
152  SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
153 
154  SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* lowest value LVDS/LCDA */
155  SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* lowest value 301 */
156 }
157 #endif
158 
159 #ifdef CONFIG_FB_SIS_300
160 static void
161 InitTo300Pointer(struct SiS_Private *SiS_Pr)
162 {
163  InitCommonPointer(SiS_Pr);
164 
165  SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
166  SiS_Pr->SiS_EModeIDTable = SiS300_EModeIDTable;
167  SiS_Pr->SiS_RefIndex = SiS300_RefIndex;
168  SiS_Pr->SiS_CRT1Table = SiS300_CRT1Table;
169  if(SiS_Pr->ChipType == SIS_300) {
170  SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
171  } else {
172  SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
173  }
174  SiS_Pr->SiS_VCLKData = SiS300_VCLKData;
175  SiS_Pr->SiS_VBVCLKData = (struct SiS_VBVCLKData *)SiS300_VCLKData;
176 
177  SiS_Pr->SiS_SR15 = SiS300_SR15;
178 
179  SiS_Pr->SiS_PanelDelayTbl = SiS300_PanelDelayTbl;
180  SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
181 
182  SiS_Pr->SiS_ExtLCD1024x768Data = SiS300_ExtLCD1024x768Data;
183  SiS_Pr->SiS_St2LCD1024x768Data = SiS300_St2LCD1024x768Data;
184  SiS_Pr->SiS_ExtLCD1280x1024Data = SiS300_ExtLCD1280x1024Data;
185  SiS_Pr->SiS_St2LCD1280x1024Data = SiS300_St2LCD1280x1024Data;
186 
187  SiS_Pr->SiS_CRT2Part2_1024x768_1 = SiS300_CRT2Part2_1024x768_1;
188  SiS_Pr->SiS_CRT2Part2_1024x768_2 = SiS300_CRT2Part2_1024x768_2;
189  SiS_Pr->SiS_CRT2Part2_1024x768_3 = SiS300_CRT2Part2_1024x768_3;
190 
191  SiS_Pr->SiS_CHTVUPALData = SiS300_CHTVUPALData;
192  SiS_Pr->SiS_CHTVOPALData = SiS300_CHTVOPALData;
193  SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData; /* not supported on 300 series */
194  SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData; /* not supported on 300 series */
195  SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData; /* not supported on 300 series */
196  SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData; /* not supported on 300 series */
197  SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
198 
199  SiS_Pr->SiS_LVDS848x480Data_1 = SiS300_LVDS848x480Data_1;
200  SiS_Pr->SiS_LVDS848x480Data_2 = SiS300_LVDS848x480Data_2;
201  SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;
202  SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;
203  SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;
204 
205  SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;
206  SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;
207  SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;
208  SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;
209 
210  SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
211  SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
212  SiS_Pr->SiS_CHTVCRT1UPAL = SiS300_CHTVCRT1UPAL;
213  SiS_Pr->SiS_CHTVCRT1OPAL = SiS300_CHTVCRT1OPAL;
214  SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;
215  SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;
216  SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;
217  SiS_Pr->SiS_CHTVReg_UPAL = SiS300_CHTVReg_UPAL;
218  SiS_Pr->SiS_CHTVReg_OPAL = SiS300_CHTVReg_OPAL;
219  SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC; /* not supported on 300 series */
220  SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC; /* not supported on 300 series */
221  SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL; /* not supported on 300 series */
222  SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL; /* not supported on 300 series */
223  SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;
224  SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
225  SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
226  SiS_Pr->SiS_CHTVVCLKUPAL = SiS300_CHTVVCLKUPAL;
227  SiS_Pr->SiS_CHTVVCLKOPAL = SiS300_CHTVVCLKOPAL;
228  SiS_Pr->SiS_CHTVVCLKUPALM = SiS300_CHTVVCLKUNTSC; /* not supported on 300 series */
229  SiS_Pr->SiS_CHTVVCLKOPALM = SiS300_CHTVVCLKONTSC; /* not supported on 300 series */
230  SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL; /* not supported on 300 series */
231  SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL; /* not supported on 300 series */
232  SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
233 }
234 #endif
235 
236 #ifdef CONFIG_FB_SIS_315
237 static void
238 InitTo310Pointer(struct SiS_Private *SiS_Pr)
239 {
240  InitCommonPointer(SiS_Pr);
241 
242  SiS_Pr->SiS_EModeIDTable = SiS310_EModeIDTable;
243  SiS_Pr->SiS_RefIndex = SiS310_RefIndex;
244  SiS_Pr->SiS_CRT1Table = SiS310_CRT1Table;
245  if(SiS_Pr->ChipType >= SIS_340) {
246  SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340; /* 340 + XGI */
247  } else if(SiS_Pr->ChipType >= SIS_761) {
248  SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761; /* 761 - preliminary */
249  } else if(SiS_Pr->ChipType >= SIS_760) {
250  SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760; /* 760 */
251  } else if(SiS_Pr->ChipType >= SIS_661) {
252  SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660; /* 661/741 */
253  } else if(SiS_Pr->ChipType == SIS_330) {
254  SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330; /* 330 */
255  } else if(SiS_Pr->ChipType > SIS_315PRO) {
256  SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650; /* 550, 650, 740 */
257  } else {
258  SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315; /* 315 */
259  }
260  if(SiS_Pr->ChipType >= SIS_340) {
261  SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
262  } else {
263  SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
264  }
265  SiS_Pr->SiS_VCLKData = SiS310_VCLKData;
266  SiS_Pr->SiS_VBVCLKData = SiS310_VBVCLKData;
267 
268  SiS_Pr->SiS_SR15 = SiS310_SR15;
269 
270  SiS_Pr->SiS_PanelDelayTbl = SiS310_PanelDelayTbl;
271  SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
272 
273  SiS_Pr->SiS_St2LCD1024x768Data = SiS310_St2LCD1024x768Data;
274  SiS_Pr->SiS_ExtLCD1024x768Data = SiS310_ExtLCD1024x768Data;
275  SiS_Pr->SiS_St2LCD1280x1024Data = SiS310_St2LCD1280x1024Data;
276  SiS_Pr->SiS_ExtLCD1280x1024Data = SiS310_ExtLCD1280x1024Data;
277 
278  SiS_Pr->SiS_CRT2Part2_1024x768_1 = SiS310_CRT2Part2_1024x768_1;
279 
280  SiS_Pr->SiS_CHTVUPALData = SiS310_CHTVUPALData;
281  SiS_Pr->SiS_CHTVOPALData = SiS310_CHTVOPALData;
282  SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
283  SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;
284  SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;
285  SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
286  SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
287 
288  SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
289  SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
290  SiS_Pr->SiS_CHTVCRT1UPAL = SiS310_CHTVCRT1UPAL;
291  SiS_Pr->SiS_CHTVCRT1OPAL = SiS310_CHTVCRT1OPAL;
292  SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
293 
294  SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
295  SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
296  SiS_Pr->SiS_CHTVReg_UPAL = SiS310_CHTVReg_UPAL;
297  SiS_Pr->SiS_CHTVReg_OPAL = SiS310_CHTVReg_OPAL;
298  SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;
299  SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;
300  SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;
301  SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;
302  SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;
303 
304  SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
305  SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
306  SiS_Pr->SiS_CHTVVCLKUPAL = SiS310_CHTVVCLKUPAL;
307  SiS_Pr->SiS_CHTVVCLKOPAL = SiS310_CHTVVCLKOPAL;
308  SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;
309  SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;
310  SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;
311  SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;
312  SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;
313 }
314 #endif
315 
316 bool
317 SiSInitPtr(struct SiS_Private *SiS_Pr)
318 {
319  if(SiS_Pr->ChipType < SIS_315H) {
320 #ifdef CONFIG_FB_SIS_300
321  InitTo300Pointer(SiS_Pr);
322 #else
323  return false;
324 #endif
325  } else {
326 #ifdef CONFIG_FB_SIS_315
327  InitTo310Pointer(SiS_Pr);
328 #else
329  return false;
330 #endif
331  }
332  return true;
333 }
334 
335 /*********************************************/
336 /* HELPER: Get ModeID */
337 /*********************************************/
338 
339 static
340 unsigned short
341 SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
342  int Depth, bool FSTN, int LCDwidth, int LCDheight)
343 {
344  unsigned short ModeIndex = 0;
345 
346  switch(HDisplay)
347  {
348  case 320:
349  if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
350  else if(VDisplay == 240) {
351  if((VBFlags & CRT2_LCD) && (FSTN))
352  ModeIndex = ModeIndex_320x240_FSTN[Depth];
353  else
354  ModeIndex = ModeIndex_320x240[Depth];
355  }
356  break;
357  case 400:
358  if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
359  if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
360  }
361  break;
362  case 512:
363  if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
364  if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
365  }
366  break;
367  case 640:
368  if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
369  else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
370  break;
371  case 720:
372  if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
373  else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
374  break;
375  case 768:
376  if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
377  break;
378  case 800:
379  if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
380  else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
381  break;
382  case 848:
383  if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
384  break;
385  case 856:
386  if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
387  break;
388  case 960:
389  if(VGAEngine == SIS_315_VGA) {
390  if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
391  else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
392  }
393  break;
394  case 1024:
395  if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
396  else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
397  else if(VGAEngine == SIS_300_VGA) {
398  if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
399  }
400  break;
401  case 1152:
402  if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
403  if(VGAEngine == SIS_300_VGA) {
404  if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
405  }
406  break;
407  case 1280:
408  switch(VDisplay) {
409  case 720:
410  ModeIndex = ModeIndex_1280x720[Depth];
411  break;
412  case 768:
413  if(VGAEngine == SIS_300_VGA) {
414  ModeIndex = ModeIndex_300_1280x768[Depth];
415  } else {
416  ModeIndex = ModeIndex_310_1280x768[Depth];
417  }
418  break;
419  case 800:
420  if(VGAEngine == SIS_315_VGA) {
421  ModeIndex = ModeIndex_1280x800[Depth];
422  }
423  break;
424  case 854:
425  if(VGAEngine == SIS_315_VGA) {
426  ModeIndex = ModeIndex_1280x854[Depth];
427  }
428  break;
429  case 960:
430  ModeIndex = ModeIndex_1280x960[Depth];
431  break;
432  case 1024:
433  ModeIndex = ModeIndex_1280x1024[Depth];
434  break;
435  }
436  break;
437  case 1360:
438  if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
439  if(VGAEngine == SIS_300_VGA) {
440  if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
441  }
442  break;
443  case 1400:
444  if(VGAEngine == SIS_315_VGA) {
445  if(VDisplay == 1050) {
446  ModeIndex = ModeIndex_1400x1050[Depth];
447  }
448  }
449  break;
450  case 1600:
451  if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
452  break;
453  case 1680:
454  if(VGAEngine == SIS_315_VGA) {
455  if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
456  }
457  break;
458  case 1920:
459  if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
460  else if(VGAEngine == SIS_315_VGA) {
461  if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
462  }
463  break;
464  case 2048:
465  if(VDisplay == 1536) {
466  if(VGAEngine == SIS_300_VGA) {
467  ModeIndex = ModeIndex_300_2048x1536[Depth];
468  } else {
469  ModeIndex = ModeIndex_310_2048x1536[Depth];
470  }
471  }
472  break;
473  }
474 
475  return ModeIndex;
476 }
477 
478 unsigned short
479 SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
480  int Depth, bool FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
481  unsigned int VBFlags2)
482 {
483  unsigned short ModeIndex = 0;
484 
485  if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
486 
487  switch(HDisplay)
488  {
489  case 320:
490  if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
491  if(VDisplay == 200) {
492  if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];
493  } else if(VDisplay == 240) {
494  if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];
495  else if(VGAEngine == SIS_315_VGA) {
496  ModeIndex = ModeIndex_320x240_FSTN[Depth];
497  }
498  }
499  }
500  break;
501  case 400:
502  if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
503  if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
504  if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
505  }
506  }
507  break;
508  case 512:
509  if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
510  if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
511  if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {
512  if(VDisplay == 384) {
513  ModeIndex = ModeIndex_512x384[Depth];
514  }
515  }
516  }
517  }
518  break;
519  case 640:
520  if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
521  else if(VDisplay == 400) {
522  if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))
523  ModeIndex = ModeIndex_640x400[Depth];
524  }
525  break;
526  case 800:
527  if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
528  break;
529  case 848:
530  if(CustomT == CUT_PANEL848) {
531  if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
532  }
533  break;
534  case 856:
535  if(CustomT == CUT_PANEL856) {
536  if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
537  }
538  break;
539  case 1024:
540  if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
541  else if(VGAEngine == SIS_300_VGA) {
542  if((VDisplay == 600) && (LCDheight == 600)) {
543  ModeIndex = ModeIndex_1024x600[Depth];
544  }
545  }
546  break;
547  case 1152:
548  if(VGAEngine == SIS_300_VGA) {
549  if((VDisplay == 768) && (LCDheight == 768)) {
550  ModeIndex = ModeIndex_1152x768[Depth];
551  }
552  }
553  break;
554  case 1280:
555  if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
556  else if(VGAEngine == SIS_315_VGA) {
557  if((VDisplay == 768) && (LCDheight == 768)) {
558  ModeIndex = ModeIndex_310_1280x768[Depth];
559  }
560  }
561  break;
562  case 1360:
563  if(VGAEngine == SIS_300_VGA) {
564  if(CustomT == CUT_BARCO1366) {
565  if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
566  }
567  }
568  if(CustomT == CUT_PANEL848) {
569  if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
570  }
571  break;
572  case 1400:
573  if(VGAEngine == SIS_315_VGA) {
574  if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
575  }
576  break;
577  case 1600:
578  if(VGAEngine == SIS_315_VGA) {
579  if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
580  }
581  break;
582  }
583 
584  } else if(VBFlags2 & VB2_SISBRIDGE) {
585 
586  switch(HDisplay)
587  {
588  case 320:
589  if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
590  else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
591  break;
592  case 400:
593  if(LCDwidth >= 800 && LCDheight >= 600) {
594  if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
595  }
596  break;
597  case 512:
598  if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {
599  if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
600  }
601  break;
602  case 640:
603  if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
604  else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
605  break;
606  case 720:
607  if(VGAEngine == SIS_315_VGA) {
608  if(VDisplay == 480) ModeIndex = ModeIndex_720x480[Depth];
609  else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
610  }
611  break;
612  case 768:
613  if(VGAEngine == SIS_315_VGA) {
614  if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
615  }
616  break;
617  case 800:
618  if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
619  if(VGAEngine == SIS_315_VGA) {
620  if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
621  }
622  break;
623  case 848:
624  if(VGAEngine == SIS_315_VGA) {
625  if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
626  }
627  break;
628  case 856:
629  if(VGAEngine == SIS_315_VGA) {
630  if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
631  }
632  break;
633  case 960:
634  if(VGAEngine == SIS_315_VGA) {
635  if(VDisplay == 540) ModeIndex = ModeIndex_960x540[Depth];
636  else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
637  }
638  break;
639  case 1024:
640  if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
641  if(VGAEngine == SIS_315_VGA) {
642  if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
643  }
644  break;
645  case 1152:
646  if(VGAEngine == SIS_315_VGA) {
647  if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
648  }
649  break;
650  case 1280:
651  switch(VDisplay) {
652  case 720:
653  ModeIndex = ModeIndex_1280x720[Depth];
654  case 768:
655  if(VGAEngine == SIS_300_VGA) {
656  ModeIndex = ModeIndex_300_1280x768[Depth];
657  } else {
658  ModeIndex = ModeIndex_310_1280x768[Depth];
659  }
660  break;
661  case 800:
662  if(VGAEngine == SIS_315_VGA) {
663  ModeIndex = ModeIndex_1280x800[Depth];
664  }
665  break;
666  case 854:
667  if(VGAEngine == SIS_315_VGA) {
668  ModeIndex = ModeIndex_1280x854[Depth];
669  }
670  break;
671  case 960:
672  ModeIndex = ModeIndex_1280x960[Depth];
673  break;
674  case 1024:
675  ModeIndex = ModeIndex_1280x1024[Depth];
676  break;
677  }
678  break;
679  case 1360:
680  if(VGAEngine == SIS_315_VGA) { /* OVER1280 only? */
681  if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
682  }
683  break;
684  case 1400:
685  if(VGAEngine == SIS_315_VGA) {
686  if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
687  if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
688  }
689  }
690  break;
691  case 1600:
692  if(VGAEngine == SIS_315_VGA) {
693  if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
694  if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
695  }
696  }
697  break;
698 #ifndef VB_FORBID_CRT2LCD_OVER_1600
699  case 1680:
700  if(VGAEngine == SIS_315_VGA) {
701  if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
702  if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
703  }
704  }
705  break;
706  case 1920:
707  if(VGAEngine == SIS_315_VGA) {
708  if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
709  if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
710  }
711  }
712  break;
713  case 2048:
714  if(VGAEngine == SIS_315_VGA) {
715  if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
716  if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
717  }
718  }
719  break;
720 #endif
721  }
722  }
723 
724  return ModeIndex;
725 }
726 
727 unsigned short
728 SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
729  unsigned int VBFlags2)
730 {
731  unsigned short ModeIndex = 0;
732 
733  if(VBFlags2 & VB2_CHRONTEL) {
734 
735  switch(HDisplay)
736  {
737  case 512:
738  if(VGAEngine == SIS_315_VGA) {
739  if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
740  }
741  break;
742  case 640:
743  if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
744  else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
745  break;
746  case 800:
747  if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
748  break;
749  case 1024:
750  if(VGAEngine == SIS_315_VGA) {
751  if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
752  }
753  break;
754  }
755 
756  } else if(VBFlags2 & VB2_SISTVBRIDGE) {
757 
758  switch(HDisplay)
759  {
760  case 320:
761  if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
762  else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
763  break;
764  case 400:
765  if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
766  break;
767  case 512:
768  if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
769  (VBFlags & TV_HIVISION) ||
770  ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
771  if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
772  }
773  break;
774  case 640:
775  if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
776  else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
777  break;
778  case 720:
779  if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
780  if(VDisplay == 480) {
781  ModeIndex = ModeIndex_720x480[Depth];
782  } else if(VDisplay == 576) {
783  if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
784  ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
785  ModeIndex = ModeIndex_720x576[Depth];
786  }
787  }
788  break;
789  case 768:
790  if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
791  if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
792  ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
793  if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
794  }
795  }
796  break;
797  case 800:
798  if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
799  else if(VDisplay == 480) {
800  if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {
801  ModeIndex = ModeIndex_800x480[Depth];
802  }
803  }
804  break;
805  case 960:
806  if(VGAEngine == SIS_315_VGA) {
807  if(VDisplay == 600) {
808  if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
809  ModeIndex = ModeIndex_960x600[Depth];
810  }
811  }
812  }
813  break;
814  case 1024:
815  if(VDisplay == 768) {
816  if(VBFlags2 & VB2_30xBLV) {
817  ModeIndex = ModeIndex_1024x768[Depth];
818  }
819  } else if(VDisplay == 576) {
820  if( (VBFlags & TV_HIVISION) ||
821  ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||
822  ((VBFlags2 & VB2_30xBLV) &&
823  ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {
824  ModeIndex = ModeIndex_1024x576[Depth];
825  }
826  }
827  break;
828  case 1280:
829  if(VDisplay == 720) {
830  if((VBFlags & TV_HIVISION) ||
831  ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
832  ModeIndex = ModeIndex_1280x720[Depth];
833  }
834  } else if(VDisplay == 1024) {
835  if((VBFlags & TV_HIVISION) ||
836  ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
837  ModeIndex = ModeIndex_1280x1024[Depth];
838  }
839  }
840  break;
841  }
842  }
843  return ModeIndex;
844 }
845 
846 unsigned short
847 SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
848  unsigned int VBFlags2)
849 {
850  if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;
851 
852  if(HDisplay >= 1920) return 0;
853 
854  switch(HDisplay)
855  {
856  case 1600:
857  if(VDisplay == 1200) {
858  if(VGAEngine != SIS_315_VGA) return 0;
859  if(!(VBFlags2 & VB2_30xB)) return 0;
860  }
861  break;
862  case 1680:
863  if(VDisplay == 1050) {
864  if(VGAEngine != SIS_315_VGA) return 0;
865  if(!(VBFlags2 & VB2_30xB)) return 0;
866  }
867  break;
868  }
869 
870  return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, false, 0, 0);
871 }
872 
873 
874 /*********************************************/
875 /* HELPER: SetReg, GetReg */
876 /*********************************************/
877 
878 void
880 {
881  outb(index, port);
882  outb(data, port + 1);
883 }
884 
885 void
887 {
888  outb(data, port);
889 }
890 
891 void
893 {
894  outw(data, port);
895 }
896 
897 void
899 {
900  outl(data, port);
901 }
902 
903 u8
905 {
906  outb(index, port);
907  return inb(port + 1);
908 }
909 
910 u8
912 {
913  return inb(port);
914 }
915 
916 u16
918 {
919  return inw(port);
920 }
921 
922 u32
924 {
925  return inl(port);
926 }
927 
928 void
929 SiS_SetRegANDOR(SISIOADDRESS Port, u8 Index, u8 DataAND, u8 DataOR)
930 {
931  u8 temp;
932 
933  temp = SiS_GetReg(Port, Index);
934  temp = (temp & (DataAND)) | DataOR;
935  SiS_SetReg(Port, Index, temp);
936 }
937 
938 void
939 SiS_SetRegAND(SISIOADDRESS Port, u8 Index, u8 DataAND)
940 {
941  u8 temp;
942 
943  temp = SiS_GetReg(Port, Index);
944  temp &= DataAND;
945  SiS_SetReg(Port, Index, temp);
946 }
947 
948 void
949 SiS_SetRegOR(SISIOADDRESS Port, u8 Index, u8 DataOR)
950 {
951  u8 temp;
952 
953  temp = SiS_GetReg(Port, Index);
954  temp |= DataOR;
955  SiS_SetReg(Port, Index, temp);
956 }
957 
958 /*********************************************/
959 /* HELPER: DisplayOn, DisplayOff */
960 /*********************************************/
961 
962 void
963 SiS_DisplayOn(struct SiS_Private *SiS_Pr)
964 {
965  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
966 }
967 
968 void
970 {
971  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
972 }
973 
974 
975 /*********************************************/
976 /* HELPER: Init Port Addresses */
977 /*********************************************/
978 
979 void
980 SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
981 {
982  SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
983  SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
984  SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
985  SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
986  SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
987  SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
988  SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
989  SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
990  SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
991  SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
992  SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
993  SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
994  SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
995  SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
996  SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
997  SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
998  SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
999  SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
1000  SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
1001  SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14;
1002  SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE;
1003  SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK;
1004 }
1005 
1006 /*********************************************/
1007 /* HELPER: GetSysFlags */
1008 /*********************************************/
1009 
1010 static void
1011 SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
1012 {
1013  unsigned char cr5f, temp1, temp2;
1014 
1015  /* 661 and newer: NEVER write non-zero to SR11[7:4] */
1016  /* (SR11 is used for DDC and in enable/disablebridge) */
1017  SiS_Pr->SiS_SensibleSR11 = false;
1018  SiS_Pr->SiS_MyCR63 = 0x63;
1019  if(SiS_Pr->ChipType >= SIS_330) {
1020  SiS_Pr->SiS_MyCR63 = 0x53;
1021  if(SiS_Pr->ChipType >= SIS_661) {
1022  SiS_Pr->SiS_SensibleSR11 = true;
1023  }
1024  }
1025 
1026  /* You should use the macros, not these flags directly */
1027 
1028  SiS_Pr->SiS_SysFlags = 0;
1029  if(SiS_Pr->ChipType == SIS_650) {
1030  cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
1031  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
1032  temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
1033  SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
1034  temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
1035  if((!temp1) || (temp2)) {
1036  switch(cr5f) {
1037  case 0x80:
1038  case 0x90:
1039  case 0xc0:
1040  SiS_Pr->SiS_SysFlags |= SF_IsM650;
1041  break;
1042  case 0xa0:
1043  case 0xb0:
1044  case 0xe0:
1045  SiS_Pr->SiS_SysFlags |= SF_Is651;
1046  break;
1047  }
1048  } else {
1049  switch(cr5f) {
1050  case 0x90:
1051  temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
1052  switch(temp1) {
1053  case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
1054  case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
1055  default: SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
1056  }
1057  break;
1058  case 0xb0:
1059  SiS_Pr->SiS_SysFlags |= SF_Is652;
1060  break;
1061  default:
1062  SiS_Pr->SiS_SysFlags |= SF_IsM650;
1063  break;
1064  }
1065  }
1066  }
1067 
1068  if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
1069  if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
1070  SiS_Pr->SiS_SysFlags |= SF_760LFB;
1071  }
1072  if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
1073  SiS_Pr->SiS_SysFlags |= SF_760UMA;
1074  }
1075  }
1076 }
1077 
1078 /*********************************************/
1079 /* HELPER: Init PCI & Engines */
1080 /*********************************************/
1081 
1082 static void
1083 SiSInitPCIetc(struct SiS_Private *SiS_Pr)
1084 {
1085  switch(SiS_Pr->ChipType) {
1086 #ifdef CONFIG_FB_SIS_300
1087  case SIS_300:
1088  case SIS_540:
1089  case SIS_630:
1090  case SIS_730:
1091  /* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
1092  * - RELOCATED VGA IO ENABLED (0x20)
1093  * - MMIO ENABLED (0x01)
1094  * Leave other bits untouched.
1095  */
1096  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
1097  /* - Enable 2D (0x40)
1098  * - Enable 3D (0x02)
1099  * - Enable 3D Vertex command fetch (0x10) ?
1100  * - Enable 3D command parser (0x08) ?
1101  */
1102  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
1103  break;
1104 #endif
1105 #ifdef CONFIG_FB_SIS_315
1106  case SIS_315H:
1107  case SIS_315:
1108  case SIS_315PRO:
1109  case SIS_650:
1110  case SIS_740:
1111  case SIS_330:
1112  case SIS_661:
1113  case SIS_741:
1114  case SIS_660:
1115  case SIS_760:
1116  case SIS_761:
1117  case SIS_340:
1118  case XGI_40:
1119  /* See above */
1120  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
1121  /* - Enable 3D G/L transformation engine (0x80)
1122  * - Enable 2D (0x40)
1123  * - Enable 3D vertex command fetch (0x10)
1124  * - Enable 3D command parser (0x08)
1125  * - Enable 3D (0x02)
1126  */
1127  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
1128  break;
1129  case XGI_20:
1130  case SIS_550:
1131  /* See above */
1132  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
1133  /* No 3D engine ! */
1134  /* - Enable 2D (0x40)
1135  * - disable 3D
1136  */
1137  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
1138  break;
1139 #endif
1140  default:
1141  break;
1142  }
1143 }
1144 
1145 /*********************************************/
1146 /* HELPER: SetLVDSetc */
1147 /*********************************************/
1148 
1149 static
1150 void
1151 SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
1152 {
1153  unsigned short temp;
1154 
1155  SiS_Pr->SiS_IF_DEF_LVDS = 0;
1156  SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
1157  SiS_Pr->SiS_IF_DEF_CH70xx = 0;
1158  SiS_Pr->SiS_IF_DEF_CONEX = 0;
1159 
1160  SiS_Pr->SiS_ChrontelInit = 0;
1161 
1162  if(SiS_Pr->ChipType == XGI_20) return;
1163 
1164  /* Check for SiS30x first */
1165  temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
1166  if((temp == 1) || (temp == 2)) return;
1167 
1168  switch(SiS_Pr->ChipType) {
1169 #ifdef CONFIG_FB_SIS_300
1170  case SIS_540:
1171  case SIS_630:
1172  case SIS_730:
1173  temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
1174  if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
1175  if(temp == 3) SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
1176  if((temp == 4) || (temp == 5)) {
1177  /* Save power status (and error check) - UNUSED */
1178  SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
1179  SiS_Pr->SiS_IF_DEF_CH70xx = 1;
1180  }
1181  break;
1182 #endif
1183 #ifdef CONFIG_FB_SIS_315
1184  case SIS_550:
1185  case SIS_650:
1186  case SIS_740:
1187  case SIS_330:
1188  temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
1189  if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
1190  if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
1191  break;
1192  case SIS_661:
1193  case SIS_741:
1194  case SIS_660:
1195  case SIS_760:
1196  case SIS_761:
1197  case SIS_340:
1198  case XGI_20:
1199  case XGI_40:
1200  temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
1201  if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
1202  if(temp == 3) SiS_Pr->SiS_IF_DEF_CH70xx = 2;
1203  if(temp == 4) SiS_Pr->SiS_IF_DEF_CONEX = 1; /* Not yet supported */
1204  break;
1205 #endif
1206  default:
1207  break;
1208  }
1209 }
1210 
1211 /*********************************************/
1212 /* HELPER: Enable DSTN/FSTN */
1213 /*********************************************/
1214 
1215 void
1217 {
1218  SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
1219 }
1220 
1221 void
1223 {
1224  SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
1225 }
1226 
1227 /*********************************************/
1228 /* HELPER: Get modeflag */
1229 /*********************************************/
1230 
1231 unsigned short
1232 SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1233  unsigned short ModeIdIndex)
1234 {
1235  if(SiS_Pr->UseCustomMode) {
1236  return SiS_Pr->CModeFlag;
1237  } else if(ModeNo <= 0x13) {
1238  return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
1239  } else {
1240  return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1241  }
1242 }
1243 
1244 /*********************************************/
1245 /* HELPER: Determine ROM usage */
1246 /*********************************************/
1247 
1248 bool
1250 {
1251  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1252  unsigned short romversoffs, romvmaj = 1, romvmin = 0;
1253 
1254  if(SiS_Pr->ChipType >= XGI_20) {
1255  /* XGI ROMs don't qualify */
1256  return false;
1257  } else if(SiS_Pr->ChipType >= SIS_761) {
1258  /* I very much assume 761, 340 and newer will use new layout */
1259  return true;
1260  } else if(SiS_Pr->ChipType >= SIS_661) {
1261  if((ROMAddr[0x1a] == 'N') &&
1262  (ROMAddr[0x1b] == 'e') &&
1263  (ROMAddr[0x1c] == 'w') &&
1264  (ROMAddr[0x1d] == 'V')) {
1265  return true;
1266  }
1267  romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
1268  if(romversoffs) {
1269  if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
1270  romvmaj = ROMAddr[romversoffs] - '0';
1271  romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
1272  }
1273  }
1274  if((romvmaj != 0) || (romvmin >= 92)) {
1275  return true;
1276  }
1277  } else if(IS_SIS650740) {
1278  if((ROMAddr[0x1a] == 'N') &&
1279  (ROMAddr[0x1b] == 'e') &&
1280  (ROMAddr[0x1c] == 'w') &&
1281  (ROMAddr[0x1d] == 'V')) {
1282  return true;
1283  }
1284  }
1285  return false;
1286 }
1287 
1288 static void
1289 SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
1290 {
1291  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1292  unsigned short romptr = 0;
1293 
1294  SiS_Pr->SiS_UseROM = false;
1295  SiS_Pr->SiS_ROMNew = false;
1296  SiS_Pr->SiS_PWDOffset = 0;
1297 
1298  if(SiS_Pr->ChipType >= XGI_20) return;
1299 
1300  if((ROMAddr) && (SiS_Pr->UseROM)) {
1301  if(SiS_Pr->ChipType == SIS_300) {
1302  /* 300: We check if the code starts below 0x220 by
1303  * checking the jmp instruction at the beginning
1304  * of the BIOS image.
1305  */
1306  if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
1307  SiS_Pr->SiS_UseROM = true;
1308  } else if(SiS_Pr->ChipType < SIS_315H) {
1309  /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
1310  * the others do as well
1311  */
1312  SiS_Pr->SiS_UseROM = true;
1313  } else {
1314  /* 315/330 series stick to the standard(s) */
1315  SiS_Pr->SiS_UseROM = true;
1316  if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
1317  SiS_Pr->SiS_EMIOffset = 14;
1318  SiS_Pr->SiS_PWDOffset = 17;
1319  SiS_Pr->SiS661LCD2TableSize = 36;
1320  /* Find out about LCD data table entry size */
1321  if((romptr = SISGETROMW(0x0102))) {
1322  if(ROMAddr[romptr + (32 * 16)] == 0xff)
1323  SiS_Pr->SiS661LCD2TableSize = 32;
1324  else if(ROMAddr[romptr + (34 * 16)] == 0xff)
1325  SiS_Pr->SiS661LCD2TableSize = 34;
1326  else if(ROMAddr[romptr + (36 * 16)] == 0xff) /* 0.94, 2.05.00+ */
1327  SiS_Pr->SiS661LCD2TableSize = 36;
1328  else if( (ROMAddr[romptr + (38 * 16)] == 0xff) || /* 2.00.00 - 2.02.00 */
1329  (ROMAddr[0x6F] & 0x01) ) { /* 2.03.00 - <2.05.00 */
1330  SiS_Pr->SiS661LCD2TableSize = 38; /* UMC data layout abandoned at 2.05.00 */
1331  SiS_Pr->SiS_EMIOffset = 16;
1332  SiS_Pr->SiS_PWDOffset = 19;
1333  }
1334  }
1335  }
1336  }
1337  }
1338 }
1339 
1340 /*********************************************/
1341 /* HELPER: SET SEGMENT REGISTERS */
1342 /*********************************************/
1343 
1344 static void
1345 SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
1346 {
1347  unsigned short temp;
1348 
1349  value &= 0x00ff;
1350  temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
1351  temp |= (value >> 4);
1352  SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
1353  temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0xf0;
1354  temp |= (value & 0x0f);
1355  SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
1356 }
1357 
1358 static void
1359 SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
1360 {
1361  unsigned short temp;
1362 
1363  value &= 0x00ff;
1364  temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
1365  temp |= (value & 0xf0);
1366  SiS_SetRegByte(SiS_Pr->SiS_P3cb, temp);
1367  temp = SiS_GetRegByte(SiS_Pr->SiS_P3cd) & 0x0f;
1368  temp |= (value << 4);
1369  SiS_SetRegByte(SiS_Pr->SiS_P3cd, temp);
1370 }
1371 
1372 static void
1373 SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
1374 {
1375  SiS_SetSegRegLower(SiS_Pr, value);
1376  SiS_SetSegRegUpper(SiS_Pr, value);
1377 }
1378 
1379 static void
1380 SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
1381 {
1382  SiS_SetSegmentReg(SiS_Pr, 0);
1383 }
1384 
1385 static void
1386 SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
1387 {
1388  unsigned short temp = value >> 8;
1389 
1390  temp &= 0x07;
1391  temp |= (temp << 4);
1392  SiS_SetReg(SiS_Pr->SiS_P3c4,0x1d,temp);
1393  SiS_SetSegmentReg(SiS_Pr, value);
1394 }
1395 
1396 static void
1397 SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
1398 {
1399  SiS_SetSegmentRegOver(SiS_Pr, 0);
1400 }
1401 
1402 static void
1403 SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
1404 {
1405  if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
1406  SiS_ResetSegmentReg(SiS_Pr);
1407  SiS_ResetSegmentRegOver(SiS_Pr);
1408  }
1409 }
1410 
1411 /*********************************************/
1412 /* HELPER: GetVBType */
1413 /*********************************************/
1414 
1415 static
1416 void
1417 SiS_GetVBType(struct SiS_Private *SiS_Pr)
1418 {
1419  unsigned short flag = 0, rev = 0, nolcd = 0;
1420  unsigned short p4_0f, p4_25, p4_27;
1421 
1422  SiS_Pr->SiS_VBType = 0;
1423 
1424  if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
1425  return;
1426 
1427  if(SiS_Pr->ChipType == XGI_20)
1428  return;
1429 
1430  flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
1431 
1432  if(flag > 3)
1433  return;
1434 
1435  rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
1436 
1437  if(flag >= 2) {
1438  SiS_Pr->SiS_VBType = VB_SIS302B;
1439  } else if(flag == 1) {
1440  if(rev >= 0xC0) {
1441  SiS_Pr->SiS_VBType = VB_SIS301C;
1442  } else if(rev >= 0xB0) {
1443  SiS_Pr->SiS_VBType = VB_SIS301B;
1444  /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
1445  nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
1446  if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
1447  } else {
1448  SiS_Pr->SiS_VBType = VB_SIS301;
1449  }
1450  }
1451  if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
1452  if(rev >= 0xE0) {
1453  flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
1454  if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
1455  else SiS_Pr->SiS_VBType = VB_SIS301C; /* VB_SIS302ELV; */
1456  } else if(rev >= 0xD0) {
1457  SiS_Pr->SiS_VBType = VB_SIS301LV;
1458  }
1459  }
1460  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
1461  p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
1462  p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
1463  p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
1464  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
1465  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
1466  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
1467  if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
1468  SiS_Pr->SiS_VBType |= VB_UMC;
1469  }
1470  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
1471  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
1472  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
1473  }
1474 }
1475 
1476 /*********************************************/
1477 /* HELPER: Check RAM size */
1478 /*********************************************/
1479 
1480 static bool
1481 SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1482  unsigned short ModeIdIndex)
1483 {
1484  unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
1485  unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
1486  unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
1487 
1488  if(!AdapterMemSize) return true;
1489 
1490  if(AdapterMemSize < memorysize) return false;
1491  return true;
1492 }
1493 
1494 /*********************************************/
1495 /* HELPER: Get DRAM type */
1496 /*********************************************/
1497 
1498 #ifdef CONFIG_FB_SIS_315
1499 static unsigned char
1500 SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
1501 {
1502  unsigned char data;
1503 
1504  if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
1505  data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
1506  } else {
1507  if(SiS_Pr->ChipType >= XGI_20) {
1508  /* Do I need this? SR17 seems to be zero anyway... */
1509  data = 0;
1510  } else if(SiS_Pr->ChipType >= SIS_340) {
1511  /* TODO */
1512  data = 0;
1513  } if(SiS_Pr->ChipType >= SIS_661) {
1514  if(SiS_Pr->SiS_ROMNew) {
1515  data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
1516  } else {
1517  data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
1518  }
1519  } else if(IS_SIS550650740) {
1520  data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
1521  } else { /* 315, 330 */
1522  data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
1523  if(SiS_Pr->ChipType == SIS_330) {
1524  if(data > 1) {
1525  switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
1526  case 0x00: data = 1; break;
1527  case 0x10: data = 3; break;
1528  case 0x20: data = 3; break;
1529  case 0x30: data = 2; break;
1530  }
1531  } else {
1532  data = 0;
1533  }
1534  }
1535  }
1536  }
1537 
1538  return data;
1539 }
1540 
1541 static unsigned short
1542 SiS_GetMCLK(struct SiS_Private *SiS_Pr)
1543 {
1544  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
1545  unsigned short index;
1546 
1547  index = SiS_Get310DRAMType(SiS_Pr);
1548  if(SiS_Pr->ChipType >= SIS_661) {
1549  if(SiS_Pr->SiS_ROMNew) {
1550  return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
1551  }
1552  return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
1553  } else if(index >= 4) {
1554  return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
1555  } else {
1556  return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
1557  }
1558 }
1559 #endif
1560 
1561 /*********************************************/
1562 /* HELPER: ClearBuffer */
1563 /*********************************************/
1564 
1565 static void
1566 SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1567 {
1568  unsigned char SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
1569  unsigned int memsize = SiS_Pr->VideoMemorySize;
1570  unsigned short SISIOMEMTYPE *pBuffer;
1571  int i;
1572 
1573  if(!memaddr || !memsize) return;
1574 
1575  if(SiS_Pr->SiS_ModeType >= ModeEGA) {
1576  if(ModeNo > 0x13) {
1577  memset_io(memaddr, 0, memsize);
1578  } else {
1579  pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
1580  for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
1581  }
1582  } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
1583  pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
1584  for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
1585  } else {
1586  memset_io(memaddr, 0, 0x8000);
1587  }
1588 }
1589 
1590 /*********************************************/
1591 /* HELPER: SearchModeID */
1592 /*********************************************/
1593 
1594 bool
1595 SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
1596  unsigned short *ModeIdIndex)
1597 {
1598  unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
1599 
1600  if((*ModeNo) <= 0x13) {
1601 
1602  if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;
1603 
1604  for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
1605  if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
1606  if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return false;
1607  }
1608 
1609  if((*ModeNo) == 0x07) {
1610  if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
1611  /* else 350 lines */
1612  }
1613  if((*ModeNo) <= 0x03) {
1614  if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
1615  if(VGAINFO & 0x10) (*ModeIdIndex)++; /* 400 lines */
1616  /* else 350 lines */
1617  }
1618  /* else 200 lines */
1619 
1620  } else {
1621 
1622  for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
1623  if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
1624  if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return false;
1625  }
1626 
1627  }
1628  return true;
1629 }
1630 
1631 /*********************************************/
1632 /* HELPER: GetModePtr */
1633 /*********************************************/
1634 
1635 unsigned short
1636 SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
1637 {
1638  unsigned short index;
1639 
1640  if(ModeNo <= 0x13) {
1641  index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
1642  } else {
1643  if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;
1644  else index = 0x0F;
1645  }
1646  return index;
1647 }
1648 
1649 /*********************************************/
1650 /* HELPERS: Get some indices */
1651 /*********************************************/
1652 
1653 unsigned short
1654 SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
1655 {
1656  if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
1657  if(UseWide == 1) {
1658  return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;
1659  } else {
1660  return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
1661  }
1662  } else {
1663  return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
1664  }
1665 }
1666 
1667 unsigned short
1668 SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
1669 {
1670  if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
1671  if(UseWide == 1) {
1672  return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
1673  } else {
1674  return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
1675  }
1676  } else {
1677  return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
1678  }
1679 }
1680 
1681 /*********************************************/
1682 /* HELPER: LowModeTests */
1683 /*********************************************/
1684 
1685 static bool
1686 SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1687 {
1688  unsigned short temp, temp1, temp2;
1689 
1690  if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
1691  return true;
1692  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
1693  SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
1694  temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
1695  SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
1696  temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
1697  SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
1698  SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
1699  if((SiS_Pr->ChipType >= SIS_315H) ||
1700  (SiS_Pr->ChipType == SIS_300)) {
1701  if(temp2 == 0x55) return false;
1702  else return true;
1703  } else {
1704  if(temp2 != 0x55) return true;
1705  else {
1706  SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
1707  return false;
1708  }
1709  }
1710 }
1711 
1712 static void
1713 SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
1714 {
1715  if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
1716  SiS_Pr->SiS_SetFlag |= LowModeTests;
1717  }
1718 }
1719 
1720 /*********************************************/
1721 /* HELPER: OPEN/CLOSE CRT1 CRTC */
1722 /*********************************************/
1723 
1724 static void
1725 SiS_OpenCRTC(struct SiS_Private *SiS_Pr)
1726 {
1727  if(IS_SIS650) {
1728  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
1729  if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
1730  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
1731  } else if(IS_SIS661741660760) {
1732  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
1733  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
1734  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
1735  if(!SiS_Pr->SiS_ROMNew) {
1736  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
1737  }
1738  }
1739 }
1740 
1741 static void
1742 SiS_CloseCRTC(struct SiS_Private *SiS_Pr)
1743 {
1744 #if 0 /* This locks some CRTC registers. We don't want that. */
1745  unsigned short temp1 = 0, temp2 = 0;
1746 
1747  if(IS_SIS661741660760) {
1748  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1749  temp1 = 0xa0; temp2 = 0x08;
1750  }
1751  SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
1752  SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
1753  }
1754 #endif
1755 }
1756 
1757 static void
1758 SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
1759 {
1760  /* Enable CRT1 gating */
1761  SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
1762 #if 0
1763  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
1764  if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
1765  (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
1766  SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
1767  }
1768  }
1769 #endif
1770 }
1771 
1772 /*********************************************/
1773 /* HELPER: GetColorDepth */
1774 /*********************************************/
1775 
1776 unsigned short
1777 SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1778  unsigned short ModeIdIndex)
1779 {
1780  static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
1781  unsigned short modeflag;
1782  short index;
1783 
1784  /* Do NOT check UseCustomMode, will skrew up FIFO */
1785  if(ModeNo == 0xfe) {
1786  modeflag = SiS_Pr->CModeFlag;
1787  } else if(ModeNo <= 0x13) {
1788  modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
1789  } else {
1790  modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
1791  }
1792 
1793  index = (modeflag & ModeTypeMask) - ModeEGA;
1794  if(index < 0) index = 0;
1795  return ColorDepth[index];
1796 }
1797 
1798 /*********************************************/
1799 /* HELPER: GetOffset */
1800 /*********************************************/
1801 
1802 unsigned short
1803 SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
1804  unsigned short ModeIdIndex, unsigned short RRTI)
1805 {
1806  unsigned short xres, temp, colordepth, infoflag;
1807 
1808  if(SiS_Pr->UseCustomMode) {
1809  infoflag = SiS_Pr->CInfoFlag;
1810  xres = SiS_Pr->CHDisplay;
1811  } else {
1812  infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
1813  xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
1814  }
1815 
1816  colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
1817 
1818  temp = xres / 16;
1819  if(infoflag & InterlaceMode) temp <<= 1;
1820  temp *= colordepth;
1821  if(xres % 16) temp += (colordepth >> 1);
1822 
1823  return temp;
1824 }
1825 
1826 /*********************************************/
1827 /* SEQ */
1828 /*********************************************/
1829 
1830 static void
1831 SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1832 {
1833  unsigned char SRdata;
1834  int i;
1835 
1836  SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
1837 
1838  /* or "display off" */
1839  SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
1840 
1841  /* determine whether to force x8 dotclock */
1842  if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {
1843 
1844  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
1845  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) SRdata |= 0x01;
1846  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;
1847 
1848  }
1849 
1850  SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);
1851 
1852  for(i = 2; i <= 4; i++) {
1853  SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
1854  SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
1855  }
1856 }
1857 
1858 /*********************************************/
1859 /* MISC */
1860 /*********************************************/
1861 
1862 static void
1863 SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1864 {
1865  unsigned char Miscdata;
1866 
1867  Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
1868 
1869  if(SiS_Pr->ChipType < SIS_661) {
1870  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1871  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
1872  Miscdata |= 0x0C;
1873  }
1874  }
1875  }
1876 
1877  SiS_SetRegByte(SiS_Pr->SiS_P3c2,Miscdata);
1878 }
1879 
1880 /*********************************************/
1881 /* CRTC */
1882 /*********************************************/
1883 
1884 static void
1885 SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1886 {
1887  unsigned char CRTCdata;
1888  unsigned short i;
1889 
1890  /* Unlock CRTC */
1891  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
1892 
1893  for(i = 0; i <= 0x18; i++) {
1894  CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
1895  SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
1896  }
1897 
1898  if(SiS_Pr->ChipType >= SIS_661) {
1899  SiS_OpenCRTC(SiS_Pr);
1900  for(i = 0x13; i <= 0x14; i++) {
1901  CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
1902  SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
1903  }
1904  } else if( ( (SiS_Pr->ChipType == SIS_630) ||
1905  (SiS_Pr->ChipType == SIS_730) ) &&
1906  (SiS_Pr->ChipRevision >= 0x30) ) {
1907  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
1908  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
1909  SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
1910  }
1911  }
1912  }
1913 }
1914 
1915 /*********************************************/
1916 /* ATT */
1917 /*********************************************/
1918 
1919 static void
1920 SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1921 {
1922  unsigned char ARdata;
1923  unsigned short i;
1924 
1925  for(i = 0; i <= 0x13; i++) {
1926  ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
1927 
1928  if(i == 0x13) {
1929  /* Pixel shift. If screen on LCD or TV is shifted left or right,
1930  * this might be the cause.
1931  */
1932  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
1933  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
1934  }
1935  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
1936  if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
1937  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
1938  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1939  }
1940  }
1941  }
1942  if(SiS_Pr->ChipType >= SIS_661) {
1943  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
1944  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1945  }
1946  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
1947  if(SiS_Pr->ChipType >= SIS_315H) {
1948  if(IS_SIS550650740660) {
1949  /* 315, 330 don't do this */
1950  if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
1951  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1952  } else {
1953  ARdata = 0;
1954  }
1955  }
1956  } else {
1957  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
1958  }
1959  }
1960  }
1961  SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
1962  SiS_SetRegByte(SiS_Pr->SiS_P3c0,i); /* set index */
1963  SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata); /* set data */
1964  }
1965 
1966  SiS_GetRegByte(SiS_Pr->SiS_P3da); /* reset 3da */
1967  SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14); /* set index */
1968  SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00); /* set data */
1969 
1970  SiS_GetRegByte(SiS_Pr->SiS_P3da);
1971  SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20); /* Enable Attribute */
1972  SiS_GetRegByte(SiS_Pr->SiS_P3da);
1973 }
1974 
1975 /*********************************************/
1976 /* GRC */
1977 /*********************************************/
1978 
1979 static void
1980 SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
1981 {
1982  unsigned char GRdata;
1983  unsigned short i;
1984 
1985  for(i = 0; i <= 0x08; i++) {
1986  GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
1987  SiS_SetReg(SiS_Pr->SiS_P3ce,i,GRdata);
1988  }
1989 
1990  if(SiS_Pr->SiS_ModeType > ModeVGA) {
1991  /* 256 color disable */
1992  SiS_SetRegAND(SiS_Pr->SiS_P3ce,0x05,0xBF);
1993  }
1994 }
1995 
1996 /*********************************************/
1997 /* CLEAR EXTENDED REGISTERS */
1998 /*********************************************/
1999 
2000 static void
2001 SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
2002 {
2003  unsigned short i;
2004 
2005  for(i = 0x0A; i <= 0x0E; i++) {
2006  SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
2007  }
2008 
2009  if(SiS_Pr->ChipType >= SIS_315H) {
2010  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
2011  if(ModeNo <= 0x13) {
2012  if(ModeNo == 0x06 || ModeNo >= 0x0e) {
2013  SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
2014  }
2015  }
2016  }
2017 }
2018 
2019 /*********************************************/
2020 /* RESET VCLK */
2021 /*********************************************/
2022 
2023 static void
2024 SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
2025 {
2026  if(SiS_Pr->ChipType >= SIS_315H) {
2027  if(SiS_Pr->ChipType < SIS_661) {
2028  if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
2029  }
2030  } else {
2031  if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
2032  (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
2033  return;
2034  }
2035  }
2036 
2037  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
2038  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
2039  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
2040  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2041  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
2042  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
2043  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
2044  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2045 }
2046 
2047 /*********************************************/
2048 /* SYNC */
2049 /*********************************************/
2050 
2051 static void
2052 SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
2053 {
2054  unsigned short sync;
2055 
2056  if(SiS_Pr->UseCustomMode) {
2057  sync = SiS_Pr->CInfoFlag >> 8;
2058  } else {
2059  sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
2060  }
2061 
2062  sync &= 0xC0;
2063  sync |= 0x2f;
2064  SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
2065 }
2066 
2067 /*********************************************/
2068 /* CRTC/2 */
2069 /*********************************************/
2070 
2071 static void
2072 SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2073  unsigned short ModeIdIndex, unsigned short RRTI)
2074 {
2075  unsigned short temp, i, j, modeflag;
2076  unsigned char *crt1data = NULL;
2077 
2078  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2079 
2080  if(SiS_Pr->UseCustomMode) {
2081 
2082  crt1data = &SiS_Pr->CCRT1CRTC[0];
2083 
2084  } else {
2085 
2086  temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);
2087 
2088  /* Alternate for 1600x1200 LCDA */
2089  if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;
2090 
2091  crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];
2092 
2093  }
2094 
2095  /* unlock cr0-7 */
2096  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
2097 
2098  for(i = 0, j = 0; i <= 7; i++, j++) {
2099  SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
2100  }
2101  for(j = 0x10; i <= 10; i++, j++) {
2102  SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
2103  }
2104  for(j = 0x15; i <= 12; i++, j++) {
2105  SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
2106  }
2107  for(j = 0x0A; i <= 15; i++, j++) {
2108  SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
2109  }
2110 
2111  SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);
2112 
2113  temp = (crt1data[16] & 0x01) << 5;
2114  if(modeflag & DoubleScanMode) temp |= 0x80;
2115  SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
2116 
2117  if(SiS_Pr->SiS_ModeType > ModeVGA) {
2118  SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
2119  }
2120 
2121 #ifdef CONFIG_FB_SIS_315
2122  if(SiS_Pr->ChipType == XGI_20) {
2123  SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
2124  if(!(temp = crt1data[5] & 0x1f)) {
2125  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
2126  }
2127  SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
2128  temp = (crt1data[16] >> 5) + 3;
2129  if(temp > 7) temp -= 7;
2130  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
2131  }
2132 #endif
2133 }
2134 
2135 /*********************************************/
2136 /* OFFSET & PITCH */
2137 /*********************************************/
2138 /* (partly overruled by SetPitch() in XF86) */
2139 /*********************************************/
2140 
2141 static void
2142 SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2143  unsigned short ModeIdIndex, unsigned short RRTI)
2144 {
2145  unsigned short temp, DisplayUnit, infoflag;
2146 
2147  if(SiS_Pr->UseCustomMode) {
2148  infoflag = SiS_Pr->CInfoFlag;
2149  } else {
2150  infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
2151  }
2152 
2153  DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2154 
2155  temp = (DisplayUnit >> 8) & 0x0f;
2156  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);
2157 
2158  SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);
2159 
2160  if(infoflag & InterlaceMode) DisplayUnit >>= 1;
2161 
2162  DisplayUnit <<= 5;
2163  temp = (DisplayUnit >> 8) + 1;
2164  if(DisplayUnit & 0xff) temp++;
2165  if(SiS_Pr->ChipType == XGI_20) {
2166  if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
2167  }
2168  SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
2169 }
2170 
2171 /*********************************************/
2172 /* VCLK */
2173 /*********************************************/
2174 
2175 static void
2176 SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2177  unsigned short ModeIdIndex, unsigned short RRTI)
2178 {
2179  unsigned short index = 0, clka, clkb;
2180 
2181  if(SiS_Pr->UseCustomMode) {
2182  clka = SiS_Pr->CSR2B;
2183  clkb = SiS_Pr->CSR2C;
2184  } else {
2185  index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2186  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
2187  (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2188  /* Alternate for 1600x1200 LCDA */
2189  if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;
2190  clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
2191  clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
2192  } else {
2193  clka = SiS_Pr->SiS_VCLKData[index].SR2B;
2194  clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
2195  }
2196  }
2197 
2198  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
2199 
2200  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);
2201  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
2202 
2203  if(SiS_Pr->ChipType >= SIS_315H) {
2204 #ifdef CONFIG_FB_SIS_315
2205  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
2206  if(SiS_Pr->ChipType == XGI_20) {
2207  unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2208  if(mf & HalfDCLK) {
2209  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));
2210  clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);
2211  clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);
2212  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
2213  }
2214  }
2215 #endif
2216  } else {
2217  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
2218  }
2219 }
2220 
2221 /*********************************************/
2222 /* FIFO */
2223 /*********************************************/
2224 
2225 #ifdef CONFIG_FB_SIS_300
2226 void
2227 SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
2228  unsigned short *idx2)
2229 {
2230  unsigned short temp1, temp2;
2231  static const unsigned char ThTiming[8] = {
2232  1, 2, 2, 3, 0, 1, 1, 2
2233  };
2234 
2235  temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;
2236  (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);
2237  (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;
2238  (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));
2239  (*idx1) <<= 1;
2240 }
2241 
2242 static unsigned short
2243 SiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)
2244 {
2245  static const unsigned char ThLowA[8 * 3] = {
2246  61, 3,52, 5,68, 7,100,11,
2247  43, 3,42, 5,54, 7, 78,11,
2248  34, 3,37, 5,47, 7, 67,11
2249  };
2250 
2251  return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
2252 }
2253 
2254 unsigned short
2255 SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)
2256 {
2257  static const unsigned char ThLowB[8 * 3] = {
2258  81, 4,72, 6,88, 8,120,12,
2259  55, 4,54, 6,66, 8, 90,12,
2260  42, 4,45, 6,55, 8, 75,12
2261  };
2262 
2263  return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
2264 }
2265 
2266 static unsigned short
2267 SiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,
2268  unsigned short colordepth, unsigned short key)
2269 {
2270  unsigned short idx1, idx2;
2271  unsigned int longtemp = VCLK * colordepth;
2272 
2273  SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);
2274 
2275  if(key == 0) {
2276  longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);
2277  } else {
2278  longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);
2279  }
2280  idx1 = longtemp % (MCLK * 16);
2281  longtemp /= (MCLK * 16);
2282  if(idx1) longtemp++;
2283  return (unsigned short)longtemp;
2284 }
2285 
2286 static unsigned short
2287 SiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,
2288  unsigned short colordepth, unsigned short MCLK)
2289 {
2290  unsigned short temp1, temp2;
2291 
2292  temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
2293  temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
2294  if(temp1 < 4) temp1 = 4;
2295  temp1 -= 4;
2296  if(temp2 < temp1) temp2 = temp1;
2297  return temp2;
2298 }
2299 
2300 static void
2301 SiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2302  unsigned short RefreshRateTableIndex)
2303 {
2304  unsigned short ThresholdLow = 0;
2305  unsigned short temp, index, VCLK, MCLK, colorth;
2306  static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };
2307 
2308  if(ModeNo > 0x13) {
2309 
2310  /* Get VCLK */
2311  if(SiS_Pr->UseCustomMode) {
2312  VCLK = SiS_Pr->CSRClock;
2313  } else {
2314  index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
2315  VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
2316  }
2317 
2318  /* Get half colordepth */
2319  colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
2320 
2321  /* Get MCLK */
2322  index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;
2323  MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
2324 
2325  temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;
2326  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);
2327 
2328  do {
2329  ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;
2330  if(ThresholdLow < 0x13) break;
2331  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
2332  ThresholdLow = 0x13;
2333  temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;
2334  if(!temp) break;
2335  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));
2336  } while(0);
2337 
2338  } else ThresholdLow = 2;
2339 
2340  /* Write CRT/CPU threshold low, CRT/Engine threshold high */
2341  temp = (ThresholdLow << 4) | 0x0f;
2342  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
2343 
2344  temp = (ThresholdLow & 0x10) << 1;
2345  if(ModeNo > 0x13) temp |= 0x40;
2346  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
2347 
2348  /* What is this? */
2349  SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
2350 
2351  /* Write CRT/CPU threshold high */
2352  temp = ThresholdLow + 3;
2353  if(temp > 0x0f) temp = 0x0f;
2354  SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
2355 }
2356 
2357 unsigned short
2358 SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)
2359 {
2360  static const unsigned char LatencyFactor[] = {
2361  97, 88, 86, 79, 77, 0, /* 64 bit BQ=2 */
2362  0, 87, 85, 78, 76, 54, /* 64 bit BQ=1 */
2363  97, 88, 86, 79, 77, 0, /* 128 bit BQ=2 */
2364  0, 79, 77, 70, 68, 48, /* 128 bit BQ=1 */
2365  80, 72, 69, 63, 61, 0, /* 64 bit BQ=2 */
2366  0, 70, 68, 61, 59, 37, /* 64 bit BQ=1 */
2367  86, 77, 75, 68, 66, 0, /* 128 bit BQ=2 */
2368  0, 68, 66, 59, 57, 37 /* 128 bit BQ=1 */
2369  };
2370  static const unsigned char LatencyFactor730[] = {
2371  69, 63, 61,
2372  86, 79, 77,
2373  103, 96, 94,
2374  120,113,111,
2375  137,130,128
2376  };
2377 
2378  if(SiS_Pr->ChipType == SIS_730) {
2379  return (unsigned short)LatencyFactor730[index];
2380  } else {
2381  return (unsigned short)LatencyFactor[index];
2382  }
2383 }
2384 
2385 static unsigned short
2386 SiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)
2387 {
2388  unsigned short index;
2389 
2390  if(SiS_Pr->ChipType == SIS_730) {
2391  index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);
2392  } else {
2393  index = (key & 0xe0) >> 5;
2394  if(key & 0x10) index += 6;
2395  if(!(key & 0x01)) index += 24;
2396  if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
2397  }
2398  return SiS_GetLatencyFactor630(SiS_Pr, index);
2399 }
2400 
2401 static void
2402 SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2403  unsigned short RefreshRateTableIndex)
2404 {
2405  unsigned short ThresholdLow = 0;
2406  unsigned short i, data, VCLK, MCLK16, colorth = 0;
2407  unsigned int templ, datal;
2408  const unsigned char *queuedata = NULL;
2409  static const unsigned char FQBQData[21] = {
2410  0x01,0x21,0x41,0x61,0x81,
2411  0x31,0x51,0x71,0x91,0xb1,
2412  0x00,0x20,0x40,0x60,0x80,
2413  0x30,0x50,0x70,0x90,0xb0,
2414  0xff
2415  };
2416  static const unsigned char FQBQData730[16] = {
2417  0x34,0x74,0xb4,
2418  0x23,0x63,0xa3,
2419  0x12,0x52,0x92,
2420  0x01,0x41,0x81,
2421  0x00,0x40,0x80,
2422  0xff
2423  };
2424  static const unsigned short colortharray[6] = {
2425  1, 1, 2, 2, 3, 4
2426  };
2427 
2428  i = 0;
2429 
2430  if(ModeNo > 0x13) {
2431 
2432  /* Get VCLK */
2433  if(SiS_Pr->UseCustomMode) {
2434  VCLK = SiS_Pr->CSRClock;
2435  } else {
2436  data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
2437  VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
2438  }
2439 
2440  /* Get MCLK * 16 */
2441  data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
2442  MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
2443 
2444  /* Get half colordepth */
2445  colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
2446 
2447  if(SiS_Pr->ChipType == SIS_730) {
2448  queuedata = &FQBQData730[0];
2449  } else {
2450  queuedata = &FQBQData[0];
2451  }
2452 
2453  do {
2454  templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
2455 
2456  datal = templ % MCLK16;
2457  templ = (templ / MCLK16) + 1;
2458  if(datal) templ++;
2459 
2460  if(templ > 0x13) {
2461  if(queuedata[i + 1] == 0xFF) {
2462  ThresholdLow = 0x13;
2463  break;
2464  }
2465  i++;
2466  } else {
2467  ThresholdLow = templ;
2468  break;
2469  }
2470  } while(queuedata[i] != 0xFF);
2471 
2472  } else {
2473 
2474  if(SiS_Pr->ChipType != SIS_730) i = 9;
2475  ThresholdLow = 0x02;
2476 
2477  }
2478 
2479  /* Write CRT/CPU threshold low, CRT/Engine threshold high */
2480  data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
2481  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
2482 
2483  data = (ThresholdLow & 0x10) << 1;
2484  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
2485 
2486  /* What is this? */
2487  SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
2488 
2489  /* Write CRT/CPU threshold high (gap = 3) */
2490  data = ThresholdLow + 3;
2491  if(data > 0x0f) data = 0x0f;
2492  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
2493 
2494  /* Write foreground and background queue */
2495  templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
2496 
2497  if(SiS_Pr->ChipType == SIS_730) {
2498 
2499  templ &= 0xfffff9ff;
2500  templ |= ((queuedata[i] & 0xc0) << 3);
2501 
2502  } else {
2503 
2504  templ &= 0xf0ffffff;
2505  if( (ModeNo <= 0x13) &&
2506  (SiS_Pr->ChipType == SIS_630) &&
2507  (SiS_Pr->ChipRevision >= 0x30) ) {
2508  templ |= 0x0b000000;
2509  } else {
2510  templ |= ((queuedata[i] & 0xf0) << 20);
2511  }
2512 
2513  }
2514 
2515  sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
2516  templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
2517 
2518  /* GUI grant timer (PCI config 0xA3) */
2519  if(SiS_Pr->ChipType == SIS_730) {
2520 
2521  templ &= 0x00ffffff;
2522  datal = queuedata[i] << 8;
2523  templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
2524 
2525  } else {
2526 
2527  templ &= 0xf0ffffff;
2528  templ |= ((queuedata[i] & 0x0f) << 24);
2529 
2530  }
2531 
2532  sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
2533 }
2534 #endif /* CONFIG_FB_SIS_300 */
2535 
2536 #ifdef CONFIG_FB_SIS_315
2537 static void
2538 SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2539 {
2540  unsigned short modeflag;
2541 
2542  /* disable auto-threshold */
2543  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
2544 
2545  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2546 
2547  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
2548  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
2549  if(ModeNo > 0x13) {
2550  if(SiS_Pr->ChipType >= XGI_20) {
2551  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2552  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2553  } else if(SiS_Pr->ChipType >= SIS_661) {
2554  if(!(modeflag & HalfDCLK)) {
2555  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2556  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2557  }
2558  } else {
2559  if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
2560  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
2561  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
2562  }
2563  }
2564  }
2565 }
2566 #endif
2567 
2568 /*********************************************/
2569 /* MODE REGISTERS */
2570 /*********************************************/
2571 
2572 static void
2573 SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2574  unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
2575 {
2576  unsigned short data = 0, VCLK = 0, index = 0;
2577 
2578  if(ModeNo > 0x13) {
2579  if(SiS_Pr->UseCustomMode) {
2580  VCLK = SiS_Pr->CSRClock;
2581  } else {
2582  index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2583  VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
2584  }
2585  }
2586 
2587  if(SiS_Pr->ChipType < SIS_315H) {
2588 #ifdef CONFIG_FB_SIS_300
2589  if(VCLK > 150) data |= 0x80;
2590  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
2591 
2592  data = 0x00;
2593  if(VCLK >= 150) data |= 0x08;
2594  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
2595 #endif
2596  } else if(SiS_Pr->ChipType < XGI_20) {
2597 #ifdef CONFIG_FB_SIS_315
2598  if(VCLK >= 166) data |= 0x0c;
2599  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
2600 
2601  if(VCLK >= 166) {
2602  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
2603  }
2604 #endif
2605  } else {
2606 #ifdef CONFIG_FB_SIS_315
2607  if(VCLK >= 200) data |= 0x0c;
2608  if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
2609  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
2610  if(SiS_Pr->ChipType != XGI_20) {
2611  data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
2612  if(VCLK < 200) data |= 0x10;
2613  SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
2614  }
2615 #endif
2616  }
2617 
2618  /* DAC speed */
2619  if(SiS_Pr->ChipType >= SIS_661) {
2620 
2621  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
2622 
2623  } else {
2624 
2625  data = 0x03;
2626  if(VCLK >= 260) data = 0x00;
2627  else if(VCLK >= 160) data = 0x01;
2628  else if(VCLK >= 135) data = 0x02;
2629 
2630  if(SiS_Pr->ChipType == SIS_540) {
2631  /* Was == 203 or < 234 which made no sense */
2632  if (VCLK < 234) data = 0x02;
2633  }
2634 
2635  if(SiS_Pr->ChipType < SIS_315H) {
2636  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
2637  } else {
2638  if(SiS_Pr->ChipType > SIS_315PRO) {
2639  if(ModeNo > 0x13) data &= 0xfc;
2640  }
2641  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
2642  }
2643 
2644  }
2645 }
2646 
2647 static void
2648 SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
2649  unsigned short ModeIdIndex, unsigned short RRTI)
2650 {
2651  unsigned short data, infoflag = 0, modeflag, resindex;
2652 #ifdef CONFIG_FB_SIS_315
2653  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
2654  unsigned short data2, data3;
2655 #endif
2656 
2657  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
2658 
2659  if(SiS_Pr->UseCustomMode) {
2660  infoflag = SiS_Pr->CInfoFlag;
2661  } else {
2662  resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
2663  if(ModeNo > 0x13) {
2664  infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
2665  }
2666  }
2667 
2668  /* Disable DPMS */
2669  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
2670 
2671  data = 0;
2672  if(ModeNo > 0x13) {
2673  if(SiS_Pr->SiS_ModeType > ModeEGA) {
2674  data |= 0x02;
2675  data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
2676  }
2677  if(infoflag & InterlaceMode) data |= 0x20;
2678  }
2679  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
2680 
2681  if(SiS_Pr->ChipType != SIS_300) {
2682  data = 0;
2683  if(infoflag & InterlaceMode) {
2684  /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
2685  int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
2686  ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
2687  int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
2688  ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
2689  data = hrs - (hto >> 1) + 3;
2690  }
2691  SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
2692  SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
2693  }
2694 
2695  if(modeflag & HalfDCLK) {
2696  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
2697  }
2698 
2699  data = 0;
2700  if(modeflag & LineCompareOff) data = 0x08;
2701  if(SiS_Pr->ChipType == SIS_300) {
2702  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
2703  } else {
2704  if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
2705  if(SiS_Pr->SiS_ModeType == ModeEGA) {
2706  if(ModeNo > 0x13) {
2707  data |= 0x40;
2708  }
2709  }
2710  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
2711  }
2712 
2713 #ifdef CONFIG_FB_SIS_315
2714  if(SiS_Pr->ChipType >= SIS_315H) {
2715  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
2716  }
2717 
2718  if(SiS_Pr->ChipType == SIS_315PRO) {
2719 
2720  data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
2721  if(SiS_Pr->SiS_ModeType == ModeText) {
2722  data &= 0xc7;
2723  } else {
2724  data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
2725  if(infoflag & InterlaceMode) data2 >>= 1;
2726  data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
2727  if(data3) data2 /= data3;
2728  if(data2 >= 0x50) {
2729  data &= 0x0f;
2730  data |= 0x50;
2731  }
2732  }
2733  SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
2734 
2735  } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
2736 
2737  data = SiS_Get310DRAMType(SiS_Pr);
2738  if(SiS_Pr->ChipType == SIS_330) {
2739  data = SiS_Pr->SiS_SR15[(2 * 4) + data];
2740  } else {
2741  if(SiS_Pr->SiS_ROMNew) data = ROMAddr[0xf6];
2742  else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
2743  else data = 0xba;
2744  }
2745  if(SiS_Pr->SiS_ModeType <= ModeEGA) {
2746  data &= 0xc7;
2747  } else {
2748  if(SiS_Pr->UseCustomMode) {
2749  data2 = SiS_Pr->CSRClock;
2750  } else {
2751  data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
2752  data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
2753  }
2754 
2755  data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
2756  if(data3) data2 *= data3;
2757 
2758  data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
2759 
2760  if(SiS_Pr->ChipType == SIS_330) {
2761  if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
2762  if (data2 >= 0x19c) data = 0xba;
2763  else if(data2 >= 0x140) data = 0x7a;
2764  else if(data2 >= 0x101) data = 0x3a;
2765  else if(data2 >= 0xf5) data = 0x32;
2766  else if(data2 >= 0xe2) data = 0x2a;
2767  else if(data2 >= 0xc4) data = 0x22;
2768  else if(data2 >= 0xac) data = 0x1a;
2769  else if(data2 >= 0x9e) data = 0x12;
2770  else if(data2 >= 0x8e) data = 0x0a;
2771  else data = 0x02;
2772  } else {
2773  if(data2 >= 0x127) data = 0xba;
2774  else data = 0x7a;
2775  }
2776  } else { /* 76x+LFB */
2777  if (data2 >= 0x190) data = 0xba;
2778  else if(data2 >= 0xff) data = 0x7a;
2779  else if(data2 >= 0xd3) data = 0x3a;
2780  else if(data2 >= 0xa9) data = 0x1a;
2781  else if(data2 >= 0x93) data = 0x0a;
2782  else data = 0x02;
2783  }
2784  }
2785  SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
2786 
2787  }
2788  /* XGI: Nothing. */
2789  /* TODO: Check SiS340 */
2790 #endif
2791 
2792  data = 0x60;
2793  if(SiS_Pr->SiS_ModeType != ModeText) {
2794  data ^= 0x60;
2795  if(SiS_Pr->SiS_ModeType != ModeEGA) {
2796  data ^= 0xA0;
2797  }
2798  }
2799  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
2800 
2801  SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
2802 
2803 #ifdef CONFIG_FB_SIS_315
2804  if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
2805  (SiS_Pr->ChipType == XGI_40)) {
2806  if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
2807  SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
2808  } else {
2809  SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
2810  }
2811  } else if(SiS_Pr->ChipType == XGI_20) {
2812  if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
2813  SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
2814  } else {
2815  SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
2816  }
2817  SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
2818  }
2819 #endif
2820 }
2821 
2822 #ifdef CONFIG_FB_SIS_315
2823 static void
2824 SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
2825 {
2826 #if 0
2827  /* TODO: Find out about IOAddress2 */
2828  SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
2829  SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
2830  SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
2831  int i;
2832 
2833  if((SiS_Pr->ChipRevision != 0) ||
2834  (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
2835  return;
2836 
2837  for(i = 0; i <= 4; i++) { /* SR00 - SR04 */
2838  SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
2839  }
2840  for(i = 0; i <= 8; i++) { /* GR00 - GR08 */
2841  SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
2842  }
2843  SiS_SetReg(P2_3c4,0x05,0x86);
2844  SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06)); /* SR06 */
2845  SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21)); /* SR21 */
2846  SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc)); /* MISC */
2847  SiS_SetReg(P2_3c4,0x05,0x00);
2848 #endif
2849 }
2850 #endif
2851 
2852 /*********************************************/
2853 /* LOAD DAC */
2854 /*********************************************/
2855 
2856 static void
2857 SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
2858  unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
2859 {
2860  unsigned short d1, d2, d3;
2861 
2862  switch(dl) {
2863  case 0: d1 = dh; d2 = ah; d3 = al; break;
2864  case 1: d1 = ah; d2 = al; d3 = dh; break;
2865  default: d1 = al; d2 = dh; d3 = ah;
2866  }
2867  SiS_SetRegByte(DACData, (d1 << shiftflag));
2868  SiS_SetRegByte(DACData, (d2 << shiftflag));
2869  SiS_SetRegByte(DACData, (d3 << shiftflag));
2870 }
2871 
2872 void
2873 SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2874 {
2875  unsigned short data, data2, time, i, j, k, m, n, o;
2876  unsigned short si, di, bx, sf;
2877  SISIOADDRESS DACAddr, DACData;
2878  const unsigned char *table = NULL;
2879 
2880  data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
2881 
2882  j = time = 64;
2883  if(data == 0x00) table = SiS_MDA_DAC;
2884  else if(data == 0x08) table = SiS_CGA_DAC;
2885  else if(data == 0x10) table = SiS_EGA_DAC;
2886  else if(data == 0x18) {
2887  j = 16;
2888  time = 256;
2889  table = SiS_VGA_DAC;
2890  }
2891 
2892  if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && /* 301B-DH LCD */
2893  (SiS_Pr->SiS_VBType & VB_NoLCD) ) ||
2894  (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) || /* LCDA */
2895  (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) { /* Programming CRT1 */
2896  SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
2897  DACAddr = SiS_Pr->SiS_P3c8;
2898  DACData = SiS_Pr->SiS_P3c9;
2899  sf = 0;
2900  } else {
2901  DACAddr = SiS_Pr->SiS_Part5Port;
2902  DACData = SiS_Pr->SiS_Part5Port + 1;
2903  sf = 2;
2904  }
2905 
2906  SiS_SetRegByte(DACAddr,0x00);
2907 
2908  for(i = 0; i < j; i++) {
2909  data = table[i];
2910  for(k = 0; k < 3; k++) {
2911  data2 = 0;
2912  if(data & 0x01) data2 += 0x2A;
2913  if(data & 0x02) data2 += 0x15;
2914  SiS_SetRegByte(DACData, (data2 << sf));
2915  data >>= 2;
2916  }
2917  }
2918 
2919  if(time == 256) {
2920  for(i = 16; i < 32; i++) {
2921  data = table[i] << sf;
2922  for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
2923  }
2924  si = 32;
2925  for(m = 0; m < 9; m++) {
2926  di = si;
2927  bx = si + 4;
2928  for(n = 0; n < 3; n++) {
2929  for(o = 0; o < 5; o++) {
2930  SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
2931  si++;
2932  }
2933  si -= 2;
2934  for(o = 0; o < 3; o++) {
2935  SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
2936  si--;
2937  }
2938  } /* for n < 3 */
2939  si += 5;
2940  } /* for m < 9 */
2941  }
2942 }
2943 
2944 /*********************************************/
2945 /* SET CRT1 REGISTER GROUP */
2946 /*********************************************/
2947 
2948 static void
2949 SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
2950 {
2951  unsigned short StandTableIndex, RefreshRateTableIndex;
2952 
2953  SiS_Pr->SiS_CRT1Mode = ModeNo;
2954 
2955  StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
2956 
2957  if(SiS_Pr->SiS_SetFlag & LowModeTests) {
2958  if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
2959  SiS_DisableBridge(SiS_Pr);
2960  }
2961  }
2962 
2963  SiS_ResetSegmentRegisters(SiS_Pr);
2964 
2965  SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
2966  SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
2967  SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
2968  SiS_SetATTRegs(SiS_Pr, StandTableIndex);
2969  SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
2970  SiS_ClearExt1Regs(SiS_Pr, ModeNo);
2971  SiS_ResetCRT1VCLK(SiS_Pr);
2972 
2973  SiS_Pr->SiS_SelectCRT2Rate = 0;
2974  SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
2975 
2976  if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
2977  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
2978  SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
2979  }
2980  }
2981 
2982  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
2983  SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
2984  }
2985 
2986  RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
2987 
2988  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
2989  SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
2990  }
2991 
2992  if(RefreshRateTableIndex != 0xFFFF) {
2993  SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
2994  SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2995  SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2996  SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
2997  }
2998 
2999  switch(SiS_Pr->ChipType) {
3000 #ifdef CONFIG_FB_SIS_300
3001  case SIS_300:
3002  SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
3003  break;
3004  case SIS_540:
3005  case SIS_630:
3006  case SIS_730:
3007  SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
3008  break;
3009 #endif
3010  default:
3011 #ifdef CONFIG_FB_SIS_315
3012  if(SiS_Pr->ChipType == XGI_20) {
3013  unsigned char sr2b = 0, sr2c = 0;
3014  switch(ModeNo) {
3015  case 0x00:
3016  case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
3017  case 0x04:
3018  case 0x05:
3019  case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
3020  }
3021  if(sr2b) {
3022  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
3023  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
3024  SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
3025  }
3026  }
3027  SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
3028 #endif
3029  break;
3030  }
3031 
3032  SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
3033 
3034 #ifdef CONFIG_FB_SIS_315
3035  if(SiS_Pr->ChipType == XGI_40) {
3036  SiS_SetupDualChip(SiS_Pr);
3037  }
3038 #endif
3039 
3040  SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
3041 
3042  if(SiS_Pr->SiS_flag_clearbuffer) {
3043  SiS_ClearBuffer(SiS_Pr, ModeNo);
3044  }
3045 
3046  if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
3047  SiS_WaitRetrace1(SiS_Pr);
3048  SiS_DisplayOn(SiS_Pr);
3049  }
3050 }
3051 
3052 /*********************************************/
3053 /* HELPER: VIDEO BRIDGE PROG CLK */
3054 /*********************************************/
3055 
3056 static void
3057 SiS_InitVB(struct SiS_Private *SiS_Pr)
3058 {
3059  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3060 
3061  SiS_Pr->Init_P4_0E = 0;
3062  if(SiS_Pr->SiS_ROMNew) {
3063  SiS_Pr->Init_P4_0E = ROMAddr[0x82];
3064  } else if(SiS_Pr->ChipType >= XGI_40) {
3065  if(SiS_Pr->SiS_XGIROM) {
3066  SiS_Pr->Init_P4_0E = ROMAddr[0x80];
3067  }
3068  }
3069 }
3070 
3071 static void
3072 SiS_ResetVB(struct SiS_Private *SiS_Pr)
3073 {
3074 #ifdef CONFIG_FB_SIS_315
3075  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
3076  unsigned short temp;
3077 
3078  /* VB programming clock */
3079  if(SiS_Pr->SiS_UseROM) {
3080  if(SiS_Pr->ChipType < SIS_330) {
3081  temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
3082  if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
3083  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3084  } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
3085  temp = ROMAddr[0x7e] | 0x40;
3086  if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
3087  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3088  }
3089  } else if(SiS_Pr->ChipType >= XGI_40) {
3090  temp = 0x40;
3091  if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
3092  /* Can we do this on any chipset? */
3093  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
3094  }
3095 #endif
3096 }
3097 
3098 /*********************************************/
3099 /* HELPER: SET VIDEO/CAPTURE REGISTERS */
3100 /*********************************************/
3101 
3102 static void
3103 SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
3104 {
3105  /* SiS65x and XGI set up some sort of "lock mode" for text
3106  * which locks CRT2 in some way to CRT1 timing. Disable
3107  * this here.
3108  */
3109 #ifdef CONFIG_FB_SIS_315
3110  if((IS_SIS651) || (IS_SISM650) ||
3111  SiS_Pr->ChipType == SIS_340 ||
3112  SiS_Pr->ChipType == XGI_40) {
3113  SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00); /* Fiddle with capture regs */
3114  SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
3115  SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86); /* (BIOS does NOT unlock) */
3116  SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */
3117  SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
3118  }
3119  /* !!! This does not support modes < 0x13 !!! */
3120 #endif
3121 }
3122 
3123 /*********************************************/
3124 /* HELPER: SET AGP TIMING FOR SiS760 */
3125 /*********************************************/
3126 
3127 static void
3128 SiS_Handle760(struct SiS_Private *SiS_Pr)
3129 {
3130 #ifdef CONFIG_FB_SIS_315
3131  unsigned int somebase;
3132  unsigned char temp1, temp2, temp3;
3133 
3134  if( (SiS_Pr->ChipType != SIS_760) ||
3135  ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
3136  (!(SiS_Pr->SiS_SysFlags & SF_760LFB)) ||
3137  (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
3138  return;
3139 
3140  somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
3141  somebase &= 0xffff;
3142 
3143  if(somebase == 0) return;
3144 
3145  temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
3146 
3147  if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
3148  temp1 = 0x21;
3149  temp2 = 0x03;
3150  temp3 |= 0x08;
3151  } else {
3152  temp1 = 0x25;
3153  temp2 = 0x0b;
3154  }
3155 
3156  sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
3157  sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
3158 
3159  SiS_SetRegByte((somebase + 0x85), temp3);
3160 #endif
3161 }
3162 
3163 /*********************************************/
3164 /* SiSSetMode() */
3165 /*********************************************/
3166 
3167 bool
3168 SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
3169 {
3170  SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
3171  unsigned short RealModeNo, ModeIdIndex;
3172  unsigned char backupreg = 0;
3173  unsigned short KeepLockReg;
3174 
3175  SiS_Pr->UseCustomMode = false;
3176  SiS_Pr->CRT1UsesCustomMode = false;
3177 
3178  SiS_Pr->SiS_flag_clearbuffer = 0;
3179 
3180  if(SiS_Pr->UseCustomMode) {
3181  ModeNo = 0xfe;
3182  } else {
3183  if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
3184  ModeNo &= 0x7f;
3185  }
3186 
3187  /* Don't use FSTN mode for CRT1 */
3188  RealModeNo = ModeNo;
3189  if(ModeNo == 0x5b) ModeNo = 0x56;
3190 
3191  SiSInitPtr(SiS_Pr);
3192  SiSRegInit(SiS_Pr, BaseAddr);
3193  SiS_GetSysFlags(SiS_Pr);
3194 
3195  SiS_Pr->SiS_VGAINFO = 0x11;
3196 
3197  KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
3198  SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
3199 
3200  SiSInitPCIetc(SiS_Pr);
3201  SiSSetLVDSetc(SiS_Pr);
3202  SiSDetermineROMUsage(SiS_Pr);
3203 
3204  SiS_UnLockCRT2(SiS_Pr);
3205 
3206  if(!SiS_Pr->UseCustomMode) {
3207  if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
3208  } else {
3209  ModeIdIndex = 0;
3210  }
3211 
3212  SiS_GetVBType(SiS_Pr);
3213 
3214  /* Init/restore some VB registers */
3215  SiS_InitVB(SiS_Pr);
3216  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3217  if(SiS_Pr->ChipType >= SIS_315H) {
3218  SiS_ResetVB(SiS_Pr);
3219  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
3220  SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
3221  backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
3222  } else {
3223  backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
3224  }
3225  }
3226 
3227  /* Get VB information (connectors, connected devices) */
3228  SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
3229  SiS_SetYPbPr(SiS_Pr);
3230  SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
3231  SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
3232  SiS_SetLowModeTest(SiS_Pr, ModeNo);
3233 
3234  /* Check memory size (kernel framebuffer driver only) */
3235  if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
3236  return false;
3237  }
3238 
3239  SiS_OpenCRTC(SiS_Pr);
3240 
3241  if(SiS_Pr->UseCustomMode) {
3242  SiS_Pr->CRT1UsesCustomMode = true;
3243  SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
3244  SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
3245  } else {
3246  SiS_Pr->CRT1UsesCustomMode = false;
3247  }
3248 
3249  /* Set mode on CRT1 */
3250  if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
3251  (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
3252  SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
3253  }
3254 
3255  /* Set mode on CRT2 */
3256  if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
3257  if( (SiS_Pr->SiS_VBType & VB_SISVB) ||
3258  (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
3259  (SiS_Pr->SiS_IF_DEF_CH70xx != 0) ||
3260  (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
3261  SiS_SetCRT2Group(SiS_Pr, RealModeNo);
3262  }
3263  }
3264 
3265  SiS_HandleCRT1(SiS_Pr);
3266 
3267  SiS_StrangeStuff(SiS_Pr);
3268 
3269  SiS_DisplayOn(SiS_Pr);
3270  SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
3271 
3272 #ifdef CONFIG_FB_SIS_315
3273  if(SiS_Pr->ChipType >= SIS_315H) {
3274  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
3275  if(!(SiS_IsDualEdge(SiS_Pr))) {
3276  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
3277  }
3278  }
3279  }
3280 #endif
3281 
3282  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
3283  if(SiS_Pr->ChipType >= SIS_315H) {
3284 #ifdef CONFIG_FB_SIS_315
3285  if(!SiS_Pr->SiS_ROMNew) {
3286  if(SiS_IsVAMode(SiS_Pr)) {
3287  SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
3288  } else {
3289  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
3290  }
3291  }
3292 
3293  SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
3294 
3295  if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {
3296  if((ModeNo == 0x03) || (ModeNo == 0x10)) {
3297  SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
3298  SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
3299  }
3300  }
3301 
3302  if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
3303  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
3304  }
3305 #endif
3306  } else if((SiS_Pr->ChipType == SIS_630) ||
3307  (SiS_Pr->ChipType == SIS_730)) {
3308  SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
3309  }
3310  }
3311 
3312  SiS_CloseCRTC(SiS_Pr);
3313 
3314  SiS_Handle760(SiS_Pr);
3315 
3316  /* We never lock registers in XF86 */
3317  if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
3318 
3319  return true;
3320 }
3321 
3322 #ifndef GETBITSTR
3323 #define BITMASK(h,l) (((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
3324 #define GENMASK(mask) BITMASK(1?mask,0?mask)
3325 #define GETBITS(var,mask) (((var) & GENMASK(mask)) >> (0?mask))
3326 #define GETBITSTR(val,from,to) ((GETBITS(val,from)) << (0?to))
3327 #endif
3328 
3329 void
3331 {
3332  int x = 1; /* Fix sync */
3333 
3334  SiS_Pr->CCRT1CRTC[0] = ((SiS_Pr->CHTotal >> 3) - 5) & 0xff; /* CR0 */
3335  SiS_Pr->CCRT1CRTC[1] = (SiS_Pr->CHDisplay >> 3) - 1; /* CR1 */
3336  SiS_Pr->CCRT1CRTC[2] = (SiS_Pr->CHBlankStart >> 3) - 1; /* CR2 */
3337  SiS_Pr->CCRT1CRTC[3] = (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80; /* CR3 */
3338  SiS_Pr->CCRT1CRTC[4] = (SiS_Pr->CHSyncStart >> 3) + 3; /* CR4 */
3339  SiS_Pr->CCRT1CRTC[5] = ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) | /* CR5 */
3340  (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
3341 
3342  SiS_Pr->CCRT1CRTC[6] = (SiS_Pr->CVTotal - 2) & 0xFF; /* CR6 */
3343  SiS_Pr->CCRT1CRTC[7] = (((SiS_Pr->CVTotal - 2) & 0x100) >> 8) /* CR7 */
3344  | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
3345  | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)
3346  | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)
3347  | 0x10
3348  | (((SiS_Pr->CVTotal - 2) & 0x200) >> 4)
3349  | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
3350  | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);
3351 
3352  SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); /* CR9 */
3353 
3354  if(depth != 8) {
3355  if(SiS_Pr->CHDisplay >= 1600) SiS_Pr->CCRT1CRTC[16] |= 0x60; /* SRE */
3356  else if(SiS_Pr->CHDisplay >= 640) SiS_Pr->CCRT1CRTC[16] |= 0x40;
3357  }
3358 
3359  SiS_Pr->CCRT1CRTC[8] = (SiS_Pr->CVSyncStart - x) & 0xFF; /* CR10 */
3360  SiS_Pr->CCRT1CRTC[9] = ((SiS_Pr->CVSyncEnd - x) & 0x0F) | 0x80; /* CR11 */
3361  SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay - 1) & 0xFF; /* CR12 */
3362  SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF; /* CR15 */
3363  SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd - 1) & 0xFF; /* CR16 */
3364 
3365  SiS_Pr->CCRT1CRTC[13] = /* SRA */
3366  GETBITSTR((SiS_Pr->CVTotal -2), 10:10, 0:0) |
3367  GETBITSTR((SiS_Pr->CVDisplay -1), 10:10, 1:1) |
3368  GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
3369  GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |
3370  GETBITSTR((SiS_Pr->CVBlankEnd -1), 8:8, 4:4) |
3371  GETBITSTR((SiS_Pr->CVSyncEnd ), 4:4, 5:5) ;
3372 
3373  SiS_Pr->CCRT1CRTC[14] = /* SRB */
3374  GETBITSTR((SiS_Pr->CHTotal >> 3) - 5, 9:8, 1:0) |
3375  GETBITSTR((SiS_Pr->CHDisplay >> 3) - 1, 9:8, 3:2) |
3376  GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
3377  GETBITSTR((SiS_Pr->CHSyncStart >> 3) + 3, 9:8, 7:6) ;
3378 
3379 
3380  SiS_Pr->CCRT1CRTC[15] = /* SRC */
3381  GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
3382  GETBITSTR((SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ;
3383 }
3384 
3385 void
3386 SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
3387  unsigned short ModeIdIndex)
3388 {
3389  unsigned short modeflag, tempax, tempbx = 0, remaining = 0;
3390  unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;
3391  int i, j;
3392 
3393  /* 1:1 data: use data set by setcrt1crtc() */
3394  if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
3395 
3396  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
3397 
3398  if(modeflag & HalfDCLK) VGAHDE >>= 1;
3399 
3400  SiS_Pr->CHDisplay = VGAHDE;
3401  SiS_Pr->CHBlankStart = VGAHDE;
3402 
3403  SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
3404  SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
3405 
3406  if(SiS_Pr->ChipType < SIS_315H) {
3407 #ifdef CONFIG_FB_SIS_300
3408  tempbx = SiS_Pr->SiS_VGAHT;
3409  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3410  tempbx = SiS_Pr->PanelHT;
3411  }
3412  if(modeflag & HalfDCLK) tempbx >>= 1;
3413  remaining = tempbx % 8;
3414 #endif
3415  } else {
3416 #ifdef CONFIG_FB_SIS_315
3417  /* OK for LCDA, LVDS */
3418  tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
3419  tempax = SiS_Pr->SiS_VGAHDE; /* not /2 ! */
3420  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3421  tempax = SiS_Pr->PanelXRes;
3422  }
3423  tempbx += tempax;
3424  if(modeflag & HalfDCLK) tempbx -= VGAHDE;
3425 #endif
3426  }
3427  SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
3428 
3429  if(SiS_Pr->ChipType < SIS_315H) {
3430 #ifdef CONFIG_FB_SIS_300
3431  if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
3432  SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
3433  SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
3434  if(modeflag & HalfDCLK) {
3435  SiS_Pr->CHSyncStart >>= 1;
3436  SiS_Pr->CHSyncEnd >>= 1;
3437  }
3438  } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3439  tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;
3440  tempbx = (SiS_Pr->PanelHRS + 1) & ~1;
3441  if(modeflag & HalfDCLK) {
3442  tempax >>= 1;
3443  tempbx >>= 1;
3444  }
3445  SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;
3446  tempax = SiS_Pr->PanelHRE + 7;
3447  if(modeflag & HalfDCLK) tempax >>= 1;
3448  SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;
3449  } else {
3450  SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;
3451  if(modeflag & HalfDCLK) {
3452  SiS_Pr->CHSyncStart >>= 1;
3453  tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;
3454  SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;
3455  } else {
3456  SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;
3457  SiS_Pr->CHSyncStart += 8;
3458  }
3459  }
3460 #endif
3461  } else {
3462 #ifdef CONFIG_FB_SIS_315
3463  tempax = VGAHDE;
3464  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3465  tempbx = SiS_Pr->PanelXRes;
3466  if(modeflag & HalfDCLK) tempbx >>= 1;
3467  tempax += ((tempbx - tempax) >> 1);
3468  }
3469  tempax += SiS_Pr->PanelHRS;
3470  SiS_Pr->CHSyncStart = tempax;
3471  tempax += SiS_Pr->PanelHRE;
3472  SiS_Pr->CHSyncEnd = tempax;
3473 #endif
3474  }
3475 
3476  tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
3477  tempax = SiS_Pr->SiS_VGAVDE;
3478  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3479  tempax = SiS_Pr->PanelYRes;
3480  } else if(SiS_Pr->ChipType < SIS_315H) {
3481 #ifdef CONFIG_FB_SIS_300
3482  /* Stupid hack for 640x400/320x200 */
3483  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
3484  if((tempax + tempbx) == 438) tempbx += 16;
3485  } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||
3486  (SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {
3487  tempax = 0;
3488  tempbx = SiS_Pr->SiS_VGAVT;
3489  }
3490 #endif
3491  }
3492  SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
3493 
3494  tempax = SiS_Pr->SiS_VGAVDE;
3495  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
3496  tempax += (SiS_Pr->PanelYRes - tempax) >> 1;
3497  }
3498  tempax += SiS_Pr->PanelVRS;
3499  SiS_Pr->CVSyncStart = tempax;
3500  tempax += SiS_Pr->PanelVRE;
3501  SiS_Pr->CVSyncEnd = tempax;
3502  if(SiS_Pr->ChipType < SIS_315H) {
3503  SiS_Pr->CVSyncStart--;
3504  SiS_Pr->CVSyncEnd--;
3505  }
3506 
3507  SiS_CalcCRRegisters(SiS_Pr, 8);
3508  SiS_Pr->CCRT1CRTC[15] &= ~0xF8;
3509  SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);
3510  SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
3511 
3512  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
3513 
3514  for(i = 0, j = 0; i <= 7; i++, j++) {
3515  SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
3516  }
3517  for(j = 0x10; i <= 10; i++, j++) {
3518  SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
3519  }
3520  for(j = 0x15; i <= 12; i++, j++) {
3521  SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
3522  }
3523  for(j = 0x0A; i <= 15; i++, j++) {
3524  SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
3525  }
3526 
3527  tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;
3528  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);
3529 
3530  tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
3531  if(modeflag & DoubleScanMode) tempax |= 0x80;
3532  SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
3533 
3534 }
3535 
3536 void
3537 SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
3538  int xres, int yres,
3539  struct fb_var_screeninfo *var, bool writeres
3540 )
3541 {
3542  unsigned short HRE, HBE, HRS, HBS, HDE, HT;
3543  unsigned short VRE, VBE, VRS, VBS, VDE, VT;
3544  unsigned char sr_data, cr_data, cr_data2;
3545  int A, B, C, D, E, F, temp;
3546 
3547  sr_data = crdata[14];
3548 
3549  /* Horizontal total */
3550  HT = crdata[0] | ((unsigned short)(sr_data & 0x03) << 8);
3551  A = HT + 5;
3552 
3553  /* Horizontal display enable end */
3554  HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);
3555  E = HDE + 1;
3556 
3557  /* Horizontal retrace (=sync) start */
3558  HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);
3559  F = HRS - E - 3;
3560 
3561  /* Horizontal blank start */
3562  HBS = crdata[2] | ((unsigned short)(sr_data & 0x30) << 4);
3563 
3564  sr_data = crdata[15];
3565  cr_data = crdata[5];
3566 
3567  /* Horizontal blank end */
3568  HBE = (crdata[3] & 0x1f) |
3569  ((unsigned short)(cr_data & 0x80) >> 2) |
3570  ((unsigned short)(sr_data & 0x03) << 6);
3571 
3572  /* Horizontal retrace (=sync) end */
3573  HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);
3574 
3575  temp = HBE - ((E - 1) & 255);
3576  B = (temp > 0) ? temp : (temp + 256);
3577 
3578  temp = HRE - ((E + F + 3) & 63);
3579  C = (temp > 0) ? temp : (temp + 64);
3580 
3581  D = B - F - C;
3582 
3583  if(writeres) var->xres = xres = E * 8;
3584  var->left_margin = D * 8;
3585  var->right_margin = F * 8;
3586  var->hsync_len = C * 8;
3587 
3588  /* Vertical */
3589  sr_data = crdata[13];
3590  cr_data = crdata[7];
3591 
3592  /* Vertical total */
3593  VT = crdata[6] |
3594  ((unsigned short)(cr_data & 0x01) << 8) |
3595  ((unsigned short)(cr_data & 0x20) << 4) |
3596  ((unsigned short)(sr_data & 0x01) << 10);
3597  A = VT + 2;
3598 
3599  /* Vertical display enable end */
3600  VDE = crdata[10] |
3601  ((unsigned short)(cr_data & 0x02) << 7) |
3602  ((unsigned short)(cr_data & 0x40) << 3) |
3603  ((unsigned short)(sr_data & 0x02) << 9);
3604  E = VDE + 1;
3605 
3606  /* Vertical retrace (=sync) start */
3607  VRS = crdata[8] |
3608  ((unsigned short)(cr_data & 0x04) << 6) |
3609  ((unsigned short)(cr_data & 0x80) << 2) |
3610  ((unsigned short)(sr_data & 0x08) << 7);
3611  F = VRS + 1 - E;
3612 
3613  cr_data2 = (crdata[16] & 0x01) << 5;
3614 
3615  /* Vertical blank start */
3616  VBS = crdata[11] |
3617  ((unsigned short)(cr_data & 0x08) << 5) |
3618  ((unsigned short)(cr_data2 & 0x20) << 4) |
3619  ((unsigned short)(sr_data & 0x04) << 8);
3620 
3621  /* Vertical blank end */
3622  VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);
3623  temp = VBE - ((E - 1) & 511);
3624  B = (temp > 0) ? temp : (temp + 512);
3625 
3626  /* Vertical retrace (=sync) end */
3627  VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);
3628  temp = VRE - ((E + F - 1) & 31);
3629  C = (temp > 0) ? temp : (temp + 32);
3630 
3631  D = B - F - C;
3632 
3633  if(writeres) var->yres = yres = E;
3634  var->upper_margin = D;
3635  var->lower_margin = F;
3636  var->vsync_len = C;
3637 
3638  if((xres == 320) && ((yres == 200) || (yres == 240))) {
3639  /* Terrible hack, but correct CRTC data for
3640  * these modes only produces a black screen...
3641  * (HRE is 0, leading into a too large C and
3642  * a negative D. The CRT controller does not
3643  * seem to like correcting HRE to 50)
3644  */
3645  var->left_margin = (400 - 376);
3646  var->right_margin = (328 - 320);
3647  var->hsync_len = (376 - 328);
3648 
3649  }
3650 
3651 }
3652 
3653 
3654 
3655