aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/sis/sis_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/sis/sis_main.c')
-rw-r--r--drivers/video/sis/sis_main.c7525
1 files changed, 4314 insertions, 3211 deletions
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 698266036819..42c54b69726e 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1,9 +1,10 @@
1/* 1/*
2 * SiS 300/305/540/630(S)/730(S) 2 * SiS 300/540/630[S]/730[S],
3 * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760 3 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
4 * XGI V3XT/V5/V8, Z7
4 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3 5 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
5 * 6 *
6 * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria. 7 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
7 * 8 *
8 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -19,11 +20,11 @@
19 * along with this program; if not, write to the Free Software 20 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
21 * 22 *
22 * Author: Thomas Winischhofer <thomas@winischhofer.net> 23 * Author: Thomas Winischhofer <thomas@winischhofer.net>
23 * 24 *
24 * Author of (practically wiped) code base: 25 * Author of (practically wiped) code base:
25 * SiS (www.sis.com) 26 * SiS (www.sis.com)
26 * Copyright (C) 1999 Silicon Integrated Systems, Inc. 27 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
27 * 28 *
28 * See http://www.winischhofer.net/ for more information and updates 29 * See http://www.winischhofer.net/ for more information and updates
29 * 30 *
@@ -46,16 +47,15 @@
46#include <linux/mm.h> 47#include <linux/mm.h>
47#include <linux/tty.h> 48#include <linux/tty.h>
48#include <linux/slab.h> 49#include <linux/slab.h>
49#include <linux/delay.h>
50#include <linux/fb.h> 50#include <linux/fb.h>
51#include <linux/console.h>
52#include <linux/selection.h> 51#include <linux/selection.h>
53#include <linux/smp_lock.h>
54#include <linux/ioport.h> 52#include <linux/ioport.h>
55#include <linux/init.h> 53#include <linux/init.h>
56#include <linux/pci.h> 54#include <linux/pci.h>
57#include <linux/vmalloc.h> 55#include <linux/vmalloc.h>
56#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
58#include <linux/vt_kern.h> 57#include <linux/vt_kern.h>
58#endif
59#include <linux/capability.h> 59#include <linux/capability.h>
60#include <linux/fs.h> 60#include <linux/fs.h>
61#include <linux/types.h> 61#include <linux/types.h>
@@ -94,71 +94,75 @@ extern struct display_switch fbcon_sis32;
94#endif 94#endif
95#endif 95#endif
96 96
97static void sisfb_handle_command(struct sis_video_info *ivideo,
98 struct sisfb_cmd *sisfb_command);
99
97/* ------------------ Internal helper routines ----------------- */ 100/* ------------------ Internal helper routines ----------------- */
98 101
99static void __init 102static void __init
100sisfb_setdefaultparms(void) 103sisfb_setdefaultparms(void)
101{ 104{
102 sisfb_off = 0; 105 sisfb_off = 0;
103 sisfb_parm_mem = 0; 106 sisfb_parm_mem = 0;
104 sisfb_accel = -1; 107 sisfb_accel = -1;
105 sisfb_ypan = -1; 108 sisfb_ypan = -1;
106 sisfb_max = -1; 109 sisfb_max = -1;
107 sisfb_userom = -1; 110 sisfb_userom = -1;
108 sisfb_useoem = -1; 111 sisfb_useoem = -1;
109#ifdef MODULE 112#ifdef MODULE
110 /* Module: "None" for 2.4, default mode for 2.5+ */ 113 /* Module: "None" for 2.4, default mode for 2.5+ */
111#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 114#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
112 sisfb_mode_idx = -1; 115 sisfb_mode_idx = -1;
113#else 116#else
114 sisfb_mode_idx = MODE_INDEX_NONE; 117 sisfb_mode_idx = MODE_INDEX_NONE;
115#endif 118#endif
116#else 119#else
117 /* Static: Default mode */ 120 /* Static: Default mode */
118 sisfb_mode_idx = -1; 121 sisfb_mode_idx = -1;
119#endif 122#endif
120 sisfb_parm_rate = -1; 123 sisfb_parm_rate = -1;
121 sisfb_crt1off = 0; 124 sisfb_crt1off = 0;
122 sisfb_forcecrt1 = -1; 125 sisfb_forcecrt1 = -1;
123 sisfb_crt2type = -1; 126 sisfb_crt2type = -1;
124 sisfb_crt2flags = 0; 127 sisfb_crt2flags = 0;
125 sisfb_pdc = 0xff; 128 sisfb_pdc = 0xff;
126 sisfb_pdca = 0xff; 129 sisfb_pdca = 0xff;
127 sisfb_scalelcd = -1; 130 sisfb_scalelcd = -1;
128 sisfb_specialtiming = CUT_NONE; 131 sisfb_specialtiming = CUT_NONE;
129 sisfb_lvdshl = -1; 132 sisfb_lvdshl = -1;
130 sisfb_dstn = 0; 133 sisfb_dstn = 0;
131 sisfb_fstn = 0; 134 sisfb_fstn = 0;
132 sisfb_tvplug = -1; 135 sisfb_tvplug = -1;
133 sisfb_tvstd = -1; 136 sisfb_tvstd = -1;
134 sisfb_tvxposoffset = 0; 137 sisfb_tvxposoffset = 0;
135 sisfb_tvyposoffset = 0; 138 sisfb_tvyposoffset = 0;
136 sisfb_filter = -1; 139 sisfb_nocrt2rate = 0;
137 sisfb_nocrt2rate = 0;
138#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 140#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
139 sisfb_inverse = 0; 141 sisfb_inverse = 0;
140 sisfb_fontname[0] = 0; 142 sisfb_fontname[0] = 0;
141#endif 143#endif
142#if !defined(__i386__) && !defined(__x86_64__) 144#if !defined(__i386__) && !defined(__x86_64__)
143 sisfb_resetcard = 0; 145 sisfb_resetcard = 0;
144 sisfb_videoram = 0; 146 sisfb_videoram = 0;
145#endif 147#endif
146} 148}
147 149
150/* ------------- Parameter parsing -------------- */
151
148static void __devinit 152static void __devinit
149sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet) 153sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
150{ 154{
151 int i = 0, j = 0; 155 int i = 0, j = 0;
152 156
153 /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ 157 /* We don't know the hardware specs yet and there is no ivideo */
154 158
155 if(vesamode == 0) { 159 if(vesamode == 0) {
156#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 160#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
157 sisfb_mode_idx = MODE_INDEX_NONE; 161 sisfb_mode_idx = MODE_INDEX_NONE;
158#else 162#else
159 if(!quiet) { 163 if(!quiet)
160 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n"); 164 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
161 } 165
162 sisfb_mode_idx = DEFAULT_MODE; 166 sisfb_mode_idx = DEFAULT_MODE;
163#endif 167#endif
164 return; 168 return;
@@ -169,95 +173,102 @@ sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
169 while(sisbios_mode[i++].mode_no[0] != 0) { 173 while(sisbios_mode[i++].mode_no[0] != 0) {
170 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) || 174 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
171 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) { 175 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
172 if(sisfb_fstn) { 176 if(sisfb_fstn) {
173 if(sisbios_mode[i-1].mode_no[1] == 0x50 || 177 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
174 sisbios_mode[i-1].mode_no[1] == 0x56 || 178 sisbios_mode[i-1].mode_no[1] == 0x56 ||
175 sisbios_mode[i-1].mode_no[1] == 0x53) continue; 179 sisbios_mode[i-1].mode_no[1] == 0x53)
176 } else { 180 continue;
177 if(sisbios_mode[i-1].mode_no[1] == 0x5a || 181 } else {
178 sisbios_mode[i-1].mode_no[1] == 0x5b) continue; 182 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
179 } 183 sisbios_mode[i-1].mode_no[1] == 0x5b)
180 sisfb_mode_idx = i - 1; 184 continue;
181 j = 1; 185 }
182 break; 186 sisfb_mode_idx = i - 1;
187 j = 1;
188 break;
183 } 189 }
184 } 190 }
185 if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode); 191 if((!j) && !quiet)
192 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
186} 193}
187 194
188static void 195static void __devinit
189sisfb_search_mode(char *name, BOOLEAN quiet) 196sisfb_search_mode(char *name, BOOLEAN quiet)
190{ 197{
191 int i = 0;
192 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0; 198 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
199 int i = 0;
193 char strbuf[16], strbuf1[20]; 200 char strbuf[16], strbuf1[20];
194 char *nameptr = name; 201 char *nameptr = name;
195 202
196 /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ 203 /* We don't know the hardware specs yet and there is no ivideo */
197 204
198 if(name == NULL) { 205 if(name == NULL) {
199 if(!quiet) { 206 if(!quiet)
200 printk(KERN_ERR "sisfb: Internal error, using default mode.\n"); 207 printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
201 } 208
202 sisfb_mode_idx = DEFAULT_MODE; 209 sisfb_mode_idx = DEFAULT_MODE;
203 return; 210 return;
204 } 211 }
205 212
206#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 213#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
207 if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) { 214 if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
208 if(!quiet) { 215 if(!quiet)
209 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n"); 216 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
210 } 217
211 sisfb_mode_idx = DEFAULT_MODE; 218 sisfb_mode_idx = DEFAULT_MODE;
212 return; 219 return;
213 } 220 }
214#endif 221#endif
215 if(strlen(name) <= 19) { 222 if(strlen(name) <= 19) {
216 strcpy(strbuf1, name); 223 strcpy(strbuf1, name);
217 for(i=0; i<strlen(strbuf1); i++) { 224 for(i = 0; i < strlen(strbuf1); i++) {
218 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' '; 225 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
219 } 226 }
220 227
221 /* This does some fuzzy mode naming detection */ 228 /* This does some fuzzy mode naming detection */
222 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) { 229 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
223 if((rate <= 32) || (depth > 32)) { 230 if((rate <= 32) || (depth > 32)) {
224 j = rate; rate = depth; depth = j; 231 j = rate; rate = depth; depth = j;
225 } 232 }
226 sprintf(strbuf, "%ux%ux%u", xres, yres, depth); 233 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
227 nameptr = strbuf; 234 nameptr = strbuf;
228 sisfb_parm_rate = rate; 235 sisfb_parm_rate = rate;
229 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) { 236 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
230 sprintf(strbuf, "%ux%ux%u", xres, yres, depth); 237 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
231 nameptr = strbuf; 238 nameptr = strbuf;
232 } else { 239 } else {
233 xres = 0; 240 xres = 0;
234 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) { 241 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
235 sprintf(strbuf, "%ux%ux8", xres, yres); 242 sprintf(strbuf, "%ux%ux8", xres, yres);
236 nameptr = strbuf; 243 nameptr = strbuf;
237 } else { 244 } else {
238 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet); 245 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
239 return; 246 return;
240 } 247 }
241 } 248 }
242 } 249 }
243 250
244 i = 0; j = 0; 251 i = 0; j = 0;
245 while(sisbios_mode[i].mode_no[0] != 0) { 252 while(sisbios_mode[i].mode_no[0] != 0) {
246 if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) { 253 if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
247 if(sisfb_fstn) { 254 if(sisfb_fstn) {
248 if(sisbios_mode[i-1].mode_no[1] == 0x50 || 255 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
249 sisbios_mode[i-1].mode_no[1] == 0x56 || 256 sisbios_mode[i-1].mode_no[1] == 0x56 ||
250 sisbios_mode[i-1].mode_no[1] == 0x53) continue; 257 sisbios_mode[i-1].mode_no[1] == 0x53)
251 } else { 258 continue;
252 if(sisbios_mode[i-1].mode_no[1] == 0x5a || 259 } else {
253 sisbios_mode[i-1].mode_no[1] == 0x5b) continue; 260 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
254 } 261 sisbios_mode[i-1].mode_no[1] == 0x5b)
255 sisfb_mode_idx = i - 1; 262 continue;
256 j = 1; 263 }
257 break; 264 sisfb_mode_idx = i - 1;
258 } 265 j = 1;
259 } 266 break;
260 if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr); 267 }
268 }
269
270 if((!j) && !quiet)
271 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
261} 272}
262 273
263#ifndef MODULE 274#ifndef MODULE
@@ -265,7 +276,7 @@ static void __devinit
265sisfb_get_vga_mode_from_kernel(void) 276sisfb_get_vga_mode_from_kernel(void)
266{ 277{
267#if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT) 278#if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT)
268 char mymode[32]; 279 char mymode[32];
269 int mydepth = screen_info.lfb_depth; 280 int mydepth = screen_info.lfb_depth;
270 281
271 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return; 282 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
@@ -274,15 +285,17 @@ sisfb_get_vga_mode_from_kernel(void)
274 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) && 285 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
275 (mydepth >= 8) && (mydepth <= 32) ) { 286 (mydepth >= 8) && (mydepth <= 32) ) {
276 287
277 if(mydepth == 24) mydepth = 32; 288 if(mydepth == 24) mydepth = 32;
278 289
279 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width, 290 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
280 screen_info.lfb_height, 291 screen_info.lfb_height,
281 mydepth); 292 mydepth);
282 293
283 printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode); 294 printk(KERN_DEBUG
295 "sisfb: Using vga mode %s pre-set by kernel as default\n",
296 mymode);
284 297
285 sisfb_search_mode(mymode, TRUE); 298 sisfb_search_mode(mymode, TRUE);
286 } 299 }
287#endif 300#endif
288 return; 301 return;
@@ -294,26 +307,25 @@ sisfb_search_crt2type(const char *name)
294{ 307{
295 int i = 0; 308 int i = 0;
296 309
297 /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ 310 /* We don't know the hardware specs yet and there is no ivideo */
298 311
299 if(name == NULL) return; 312 if(name == NULL) return;
300 313
301 while(sis_crt2type[i].type_no != -1) { 314 while(sis_crt2type[i].type_no != -1) {
302 if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) { 315 if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
303 sisfb_crt2type = sis_crt2type[i].type_no; 316 sisfb_crt2type = sis_crt2type[i].type_no;
304 sisfb_tvplug = sis_crt2type[i].tvplug_no; 317 sisfb_tvplug = sis_crt2type[i].tvplug_no;
305 sisfb_crt2flags = sis_crt2type[i].flags; 318 sisfb_crt2flags = sis_crt2type[i].flags;
306 break; 319 break;
307 } 320 }
308 i++; 321 i++;
309 } 322 }
310 323
311 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0; 324 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
312 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0; 325 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
313 326
314 if(sisfb_crt2type < 0) { 327 if(sisfb_crt2type < 0)
315 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name); 328 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
316 }
317} 329}
318 330
319static void __init 331static void __init
@@ -321,16 +333,17 @@ sisfb_search_tvstd(const char *name)
321{ 333{
322 int i = 0; 334 int i = 0;
323 335
324 /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ 336 /* We don't know the hardware specs yet and there is no ivideo */
325 337
326 if(name == NULL) return; 338 if(name == NULL)
339 return;
327 340
328 while(sis_tvtype[i].type_no != -1) { 341 while(sis_tvtype[i].type_no != -1) {
329 if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) { 342 if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
330 sisfb_tvstd = sis_tvtype[i].type_no; 343 sisfb_tvstd = sis_tvtype[i].type_no;
331 break; 344 break;
332 } 345 }
333 i++; 346 i++;
334 } 347 }
335} 348}
336 349
@@ -340,38 +353,101 @@ sisfb_search_specialtiming(const char *name)
340 int i = 0; 353 int i = 0;
341 BOOLEAN found = FALSE; 354 BOOLEAN found = FALSE;
342 355
343 /* BEWARE: We don't know the hardware specs yet and there is no ivideo */ 356 /* We don't know the hardware specs yet and there is no ivideo */
344 357
345 if(name == NULL) return; 358 if(name == NULL)
359 return;
346 360
347 if(!strnicmp(name, "none", 4)) { 361 if(!strnicmp(name, "none", 4)) {
348 sisfb_specialtiming = CUT_FORCENONE; 362 sisfb_specialtiming = CUT_FORCENONE;
349 printk(KERN_DEBUG "sisfb: Special timing disabled\n"); 363 printk(KERN_DEBUG "sisfb: Special timing disabled\n");
350 } else { 364 } else {
351 while(mycustomttable[i].chipID != 0) { 365 while(mycustomttable[i].chipID != 0) {
352 if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) { 366 if(!strnicmp(name,mycustomttable[i].optionName,
353 sisfb_specialtiming = mycustomttable[i].SpecialID; 367 strlen(mycustomttable[i].optionName))) {
354 found = TRUE; 368 sisfb_specialtiming = mycustomttable[i].SpecialID;
355 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n", 369 found = TRUE;
356 mycustomttable[i].vendorName, mycustomttable[i].cardName, 370 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
357 mycustomttable[i].optionName); 371 mycustomttable[i].vendorName,
358 break; 372 mycustomttable[i].cardName,
359 } 373 mycustomttable[i].optionName);
360 i++; 374 break;
361 } 375 }
362 if(!found) { 376 i++;
363 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:"); 377 }
364 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n"); 378 if(!found) {
365 i = 0; 379 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
366 while(mycustomttable[i].chipID != 0) { 380 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
367 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n", 381 i = 0;
368 mycustomttable[i].optionName, 382 while(mycustomttable[i].chipID != 0) {
369 mycustomttable[i].vendorName, 383 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
370 mycustomttable[i].cardName); 384 mycustomttable[i].optionName,
371 i++; 385 mycustomttable[i].vendorName,
372 } 386 mycustomttable[i].cardName);
373 } 387 i++;
374 } 388 }
389 }
390 }
391}
392
393/* ----------- Various detection routines ----------- */
394
395static void __devinit
396sisfb_detect_custom_timing(struct sis_video_info *ivideo)
397{
398 unsigned char *biosver = NULL;
399 unsigned char *biosdate = NULL;
400 BOOLEAN footprint;
401 u32 chksum = 0;
402 int i, j;
403
404 if(ivideo->SiS_Pr.UseROM) {
405 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
406 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
407 for(i = 0; i < 32768; i++)
408 chksum += ivideo->SiS_Pr.VirtualRomBase[i];
409 }
410
411 i = 0;
412 do {
413 if( (mycustomttable[i].chipID == ivideo->chip) &&
414 ((!strlen(mycustomttable[i].biosversion)) ||
415 (ivideo->SiS_Pr.UseROM &&
416 (!strncmp(mycustomttable[i].biosversion, biosver,
417 strlen(mycustomttable[i].biosversion))))) &&
418 ((!strlen(mycustomttable[i].biosdate)) ||
419 (ivideo->SiS_Pr.UseROM &&
420 (!strncmp(mycustomttable[i].biosdate, biosdate,
421 strlen(mycustomttable[i].biosdate))))) &&
422 ((!mycustomttable[i].bioschksum) ||
423 (ivideo->SiS_Pr.UseROM &&
424 (mycustomttable[i].bioschksum == chksum))) &&
425 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
426 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
427 footprint = TRUE;
428 for(j = 0; j < 5; j++) {
429 if(mycustomttable[i].biosFootprintAddr[j]) {
430 if(ivideo->SiS_Pr.UseROM) {
431 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
432 mycustomttable[i].biosFootprintData[j]) {
433 footprint = FALSE;
434 }
435 } else
436 footprint = FALSE;
437 }
438 }
439 if(footprint) {
440 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
441 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
442 mycustomttable[i].vendorName,
443 mycustomttable[i].cardName);
444 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
445 mycustomttable[i].optionName);
446 break;
447 }
448 }
449 i++;
450 } while(mycustomttable[i].chipID);
375} 451}
376 452
377static BOOLEAN __devinit 453static BOOLEAN __devinit
@@ -384,22 +460,23 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
384 buffer[2] != 0xff || buffer[3] != 0xff || 460 buffer[2] != 0xff || buffer[3] != 0xff ||
385 buffer[4] != 0xff || buffer[5] != 0xff || 461 buffer[4] != 0xff || buffer[5] != 0xff ||
386 buffer[6] != 0xff || buffer[7] != 0x00) { 462 buffer[6] != 0xff || buffer[7] != 0x00) {
387 printk(KERN_DEBUG "sisfb: Bad EDID header\n"); 463 printk(KERN_DEBUG "sisfb: Bad EDID header\n");
388 return FALSE; 464 return FALSE;
389 } 465 }
390 466
391 if(buffer[0x12] != 0x01) { 467 if(buffer[0x12] != 0x01) {
392 printk(KERN_INFO "sisfb: EDID version %d not supported\n", 468 printk(KERN_INFO "sisfb: EDID version %d not supported\n",
393 buffer[0x12]); 469 buffer[0x12]);
394 return FALSE; 470 return FALSE;
395 } 471 }
396 472
397 monitor->feature = buffer[0x18]; 473 monitor->feature = buffer[0x18];
398 474
399 if(!buffer[0x14] & 0x80) { 475 if(!buffer[0x14] & 0x80) {
400 if(!(buffer[0x14] & 0x08)) { 476 if(!(buffer[0x14] & 0x08)) {
401 printk(KERN_INFO "sisfb: WARNING: Monitor does not support separate syncs\n"); 477 printk(KERN_INFO
402 } 478 "sisfb: WARNING: Monitor does not support separate syncs\n");
479 }
403 } 480 }
404 481
405 if(buffer[0x13] >= 0x01) { 482 if(buffer[0x13] >= 0x01) {
@@ -409,7 +486,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
409 j = 0x36; 486 j = 0x36;
410 for(i=0; i<4; i++) { 487 for(i=0; i<4; i++) {
411 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 && 488 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
412 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd && 489 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
413 buffer[j + 4] == 0x00) { 490 buffer[j + 4] == 0x00) {
414 monitor->hmin = buffer[j + 7]; 491 monitor->hmin = buffer[j + 7];
415 monitor->hmax = buffer[j + 8]; 492 monitor->hmax = buffer[j + 8];
@@ -435,7 +512,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
435 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16); 512 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
436 for(i = 0; i < 13; i++) { 513 for(i = 0; i < 13; i++) {
437 if(emodes & sisfb_ddcsmodes[i].mask) { 514 if(emodes & sisfb_ddcsmodes[i].mask) {
438 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h; 515 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
439 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1; 516 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
440 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v; 517 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
441 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v; 518 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
@@ -446,80 +523,81 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
446 for(i = 0; i < 8; i++) { 523 for(i = 0; i < 8; i++) {
447 xres = (buffer[index] + 31) * 8; 524 xres = (buffer[index] + 31) * 8;
448 switch(buffer[index + 1] & 0xc0) { 525 switch(buffer[index + 1] & 0xc0) {
449 case 0xc0: yres = (xres * 9) / 16; break; 526 case 0xc0: yres = (xres * 9) / 16; break;
450 case 0x80: yres = (xres * 4) / 5; break; 527 case 0x80: yres = (xres * 4) / 5; break;
451 case 0x40: yres = (xres * 3) / 4; break; 528 case 0x40: yres = (xres * 3) / 4; break;
452 default: yres = xres; break; 529 default: yres = xres; break;
453 } 530 }
454 refresh = (buffer[index + 1] & 0x3f) + 60; 531 refresh = (buffer[index + 1] & 0x3f) + 60;
455 if((xres >= 640) && (yres >= 480)) { 532 if((xres >= 640) && (yres >= 480)) {
456 for(j = 0; j < 8; j++) { 533 for(j = 0; j < 8; j++) {
457 if((xres == sisfb_ddcfmodes[j].x) && 534 if((xres == sisfb_ddcfmodes[j].x) &&
458 (yres == sisfb_ddcfmodes[j].y) && 535 (yres == sisfb_ddcfmodes[j].y) &&
459 (refresh == sisfb_ddcfmodes[j].v)) { 536 (refresh == sisfb_ddcfmodes[j].v)) {
460 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h; 537 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
461 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1; 538 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
462 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v; 539 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
463 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v; 540 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
464 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[i].d; 541 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
465 } 542 }
466 } 543 }
467 } 544 }
468 index += 2; 545 index += 2;
469 } 546 }
470 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) { 547 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
471 monitor->datavalid = TRUE; 548 monitor->datavalid = TRUE;
472 } 549 }
473 } 550 }
474 551
475 return(monitor->datavalid); 552 return monitor->datavalid;
476} 553}
477 554
478static void __devinit 555static void __devinit
479sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno) 556sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
480{ 557{
481 USHORT temp, i, realcrtno = crtno; 558 unsigned short temp, i, realcrtno = crtno;
482 u8 buffer[256]; 559 unsigned char buffer[256];
483 560
484 monitor->datavalid = FALSE; 561 monitor->datavalid = FALSE;
485 562
486 if(crtno) { 563 if(crtno) {
487 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1; 564 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
488 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2; 565 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
489 else return; 566 else return;
490 } 567 }
491 568
492 if((ivideo->sisfb_crt1off) && (!crtno)) return; 569 if((ivideo->sisfb_crt1off) && (!crtno))
570 return;
493 571
494 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 572 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
495 realcrtno, 0, &buffer[0]); 573 realcrtno, 0, &buffer[0], ivideo->vbflags2);
496 if((!temp) || (temp == 0xffff)) { 574 if((!temp) || (temp == 0xffff)) {
497 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1); 575 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
498 return; 576 return;
499 } else { 577 } else {
500 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1); 578 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
501 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n", 579 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
502 crtno + 1, 580 crtno + 1,
503 (temp & 0x1a) ? "" : "[none of the supported]", 581 (temp & 0x1a) ? "" : "[none of the supported]",
504 (temp & 0x02) ? "2 " : "", 582 (temp & 0x02) ? "2 " : "",
505 (temp & 0x08) ? "D&P" : "", 583 (temp & 0x08) ? "D&P" : "",
506 (temp & 0x10) ? "FPDI-2" : ""); 584 (temp & 0x10) ? "FPDI-2" : "");
507 if(temp & 0x02) { 585 if(temp & 0x02) {
508 i = 3; /* Number of retrys */ 586 i = 3; /* Number of retrys */
509 do { 587 do {
510 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 588 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
511 realcrtno, 1, &buffer[0]); 589 realcrtno, 1, &buffer[0], ivideo->vbflags2);
512 } while((temp) && i--); 590 } while((temp) && i--);
513 if(!temp) { 591 if(!temp) {
514 if(sisfb_interpret_edid(monitor, &buffer[0])) { 592 if(sisfb_interpret_edid(monitor, &buffer[0])) {
515 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n", 593 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
516 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax, 594 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
517 monitor->dclockmax / 1000); 595 monitor->dclockmax / 1000);
518 } else { 596 } else {
519 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1); 597 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
520 } 598 }
521 } else { 599 } else {
522 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1); 600 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
523 } 601 }
524 } else { 602 } else {
525 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n"); 603 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
@@ -527,6 +605,8 @@ sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, i
527 } 605 }
528} 606}
529 607
608/* -------------- Mode validation --------------- */
609
530static BOOLEAN 610static BOOLEAN
531sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, 611sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
532 int mode_idx, int rate_idx, int rate) 612 int mode_idx, int rate_idx, int rate)
@@ -534,42 +614,49 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
534 int htotal, vtotal; 614 int htotal, vtotal;
535 unsigned int dclock, hsync; 615 unsigned int dclock, hsync;
536 616
537 if(!monitor->datavalid) return TRUE; 617 if(!monitor->datavalid)
618 return TRUE;
538 619
539 if(mode_idx < 0) return FALSE; 620 if(mode_idx < 0)
621 return FALSE;
540 622
541 /* Skip for 320x200, 320x240, 640x400 */ 623 /* Skip for 320x200, 320x240, 640x400 */
542 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) { 624 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
543 case 0x59: 625 case 0x59:
544 case 0x41: 626 case 0x41:
545 case 0x4f: 627 case 0x4f:
546 case 0x50: 628 case 0x50:
547 case 0x56: 629 case 0x56:
548 case 0x53: 630 case 0x53:
549 case 0x2f: 631 case 0x2f:
550 case 0x5d: 632 case 0x5d:
551 case 0x5e: 633 case 0x5e:
552 return TRUE; 634 return TRUE;
553#ifdef CONFIG_FB_SIS_315 635#ifdef CONFIG_FB_SIS_315
554 case 0x5a: 636 case 0x5a:
555 case 0x5b: 637 case 0x5b:
556 if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE; 638 if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE;
557#endif 639#endif
558 } 640 }
559 641
560 if(rate < (monitor->vmin - 1)) return FALSE; 642 if(rate < (monitor->vmin - 1))
561 if(rate > (monitor->vmax + 1)) return FALSE; 643 return FALSE;
644 if(rate > (monitor->vmax + 1))
645 return FALSE;
562 646
563 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext, 647 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
564 sisbios_mode[mode_idx].mode_no[ivideo->mni], 648 sisbios_mode[mode_idx].mode_no[ivideo->mni],
565 &htotal, &vtotal, rate_idx)) { 649 &htotal, &vtotal, rate_idx)) {
566 dclock = (htotal * vtotal * rate) / 1000; 650 dclock = (htotal * vtotal * rate) / 1000;
567 if(dclock > (monitor->dclockmax + 1000)) return FALSE; 651 if(dclock > (monitor->dclockmax + 1000))
652 return FALSE;
568 hsync = dclock / htotal; 653 hsync = dclock / htotal;
569 if(hsync < (monitor->hmin - 1)) return FALSE; 654 if(hsync < (monitor->hmin - 1))
570 if(hsync > (monitor->hmax + 1)) return FALSE; 655 return FALSE;
656 if(hsync > (monitor->hmax + 1))
657 return FALSE;
571 } else { 658 } else {
572 return FALSE; 659 return FALSE;
573 } 660 }
574 return TRUE; 661 return TRUE;
575} 662}
@@ -577,82 +664,79 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
577static int 664static int
578sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags) 665sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
579{ 666{
580 u16 xres=0, yres, myres; 667 u16 xres=0, yres, myres;
581 668
582#ifdef CONFIG_FB_SIS_300 669#ifdef CONFIG_FB_SIS_300
583 if(ivideo->sisvga_engine == SIS_300_VGA) { 670 if(ivideo->sisvga_engine == SIS_300_VGA) {
584 if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1); 671 if(!(sisbios_mode[myindex].chipset & MD_SIS300))
585 } 672 return -1 ;
673 }
586#endif 674#endif
587#ifdef CONFIG_FB_SIS_315 675#ifdef CONFIG_FB_SIS_315
588 if(ivideo->sisvga_engine == SIS_315_VGA) { 676 if(ivideo->sisvga_engine == SIS_315_VGA) {
589 if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1); 677 if(!(sisbios_mode[myindex].chipset & MD_SIS315))
590 } 678 return -1;
679 }
591#endif 680#endif
592 681
593 myres = sisbios_mode[myindex].yres; 682 myres = sisbios_mode[myindex].yres;
594
595 switch(vbflags & VB_DISPTYPE_DISP2) {
596 683
597 case CRT2_LCD: 684 switch(vbflags & VB_DISPTYPE_DISP2) {
598 685
599 xres = ivideo->lcdxres; yres = ivideo->lcdyres; 686 case CRT2_LCD:
687 xres = ivideo->lcdxres; yres = ivideo->lcdyres;
600 688
601 if(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) { 689 if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
602 if(sisbios_mode[myindex].xres > xres) return(-1); 690 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
603 if(myres > yres) return(-1); 691 if(sisbios_mode[myindex].xres > xres)
604 } 692 return -1;
693 if(myres > yres)
694 return -1;
695 }
605 696
606 if(vbflags & (VB_LVDS | VB_30xBDH)) { 697 if(ivideo->sisfb_fstn) {
607 if(sisbios_mode[myindex].xres == 320) { 698 if(sisbios_mode[myindex].xres == 320) {
608 if((myres == 240) || (myres == 480)) { 699 if(myres == 240) {
609 if(!ivideo->sisfb_fstn) { 700 switch(sisbios_mode[myindex].mode_no[1]) {
610 if(sisbios_mode[myindex].mode_no[1] == 0x5a || 701 case 0x50: myindex = MODE_FSTN_8; break;
611 sisbios_mode[myindex].mode_no[1] == 0x5b) 702 case 0x56: myindex = MODE_FSTN_16; break;
612 return(-1); 703 case 0x53: return -1;
613 } else { 704 }
614 if(sisbios_mode[myindex].mode_no[1] == 0x50 || 705 }
615 sisbios_mode[myindex].mode_no[1] == 0x56 || 706 }
616 sisbios_mode[myindex].mode_no[1] == 0x53) 707 }
617 return(-1);
618 }
619 }
620 }
621 }
622 708
623 if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, 709 if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
624 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn, 710 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
625 ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) { 711 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
626 return(-1); 712 return -1;
627 } 713 }
628 break; 714 break;
629 715
630 case CRT2_TV: 716 case CRT2_TV:
631 if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, 717 if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
632 sisbios_mode[myindex].yres, 0) < 0x14) { 718 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
633 return(-1); 719 return -1;
634 } 720 }
635 break; 721 break;
636 722
637 case CRT2_VGA: 723 case CRT2_VGA:
638 if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, 724 if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
639 sisbios_mode[myindex].yres, 0) < 0x14) { 725 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
640 return(-1); 726 return -1;
727 }
728 break;
641 } 729 }
642 break;
643 }
644 730
645 return(myindex); 731 return myindex;
646} 732}
647 733
648static u8 734static u8
649sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx) 735sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
650{ 736{
651 u16 xres, yres;
652 int i = 0; 737 int i = 0;
653 738 u16 xres = sisbios_mode[mode_idx].xres;
654 xres = sisbios_mode[mode_idx].xres; 739 u16 yres = sisbios_mode[mode_idx].yres;
655 yres = sisbios_mode[mode_idx].yres;
656 740
657 ivideo->rate_idx = 0; 741 ivideo->rate_idx = 0;
658 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) { 742 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
@@ -672,14 +756,14 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int
672 rate, sisfb_vrate[i-1].refresh); 756 rate, sisfb_vrate[i-1].refresh);
673 ivideo->rate_idx = sisfb_vrate[i-1].idx; 757 ivideo->rate_idx = sisfb_vrate[i-1].idx;
674 ivideo->refresh_rate = sisfb_vrate[i-1].refresh; 758 ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
675 } 759 }
676 break; 760 break;
677 } else if((rate - sisfb_vrate[i].refresh) <= 2) { 761 } else if((rate - sisfb_vrate[i].refresh) <= 2) {
678 DPRINTK("sisfb: Adjusting rate from %d down to %d\n", 762 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
679 rate, sisfb_vrate[i].refresh); 763 rate, sisfb_vrate[i].refresh);
680 ivideo->rate_idx = sisfb_vrate[i].idx; 764 ivideo->rate_idx = sisfb_vrate[i].idx;
681 break; 765 break;
682 } 766 }
683 } 767 }
684 i++; 768 i++;
685 } 769 }
@@ -695,252 +779,321 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int
695static BOOLEAN 779static BOOLEAN
696sisfb_bridgeisslave(struct sis_video_info *ivideo) 780sisfb_bridgeisslave(struct sis_video_info *ivideo)
697{ 781{
698 unsigned char P1_00; 782 unsigned char P1_00;
699 783
700 if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE; 784 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
785 return FALSE;
701 786
702 inSISIDXREG(SISPART1,0x00,P1_00); 787 inSISIDXREG(SISPART1,0x00,P1_00);
703 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) || 788 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
704 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) { 789 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
705 return TRUE; 790 return TRUE;
706 } else { 791 } else {
707 return FALSE; 792 return FALSE;
708 } 793 }
709} 794}
710 795
711static BOOLEAN 796static BOOLEAN
712sisfballowretracecrt1(struct sis_video_info *ivideo) 797sisfballowretracecrt1(struct sis_video_info *ivideo)
713{ 798{
714 u8 temp; 799 u8 temp;
715 800
716 inSISIDXREG(SISCR,0x17,temp); 801 inSISIDXREG(SISCR,0x17,temp);
717 if(!(temp & 0x80)) return FALSE; 802 if(!(temp & 0x80))
803 return FALSE;
718 804
719 inSISIDXREG(SISSR,0x1f,temp); 805 inSISIDXREG(SISSR,0x1f,temp);
720 if(temp & 0xc0) return FALSE; 806 if(temp & 0xc0)
807 return FALSE;
721 808
722 return TRUE; 809 return TRUE;
723} 810}
724 811
725static BOOLEAN 812static BOOLEAN
726sisfbcheckvretracecrt1(struct sis_video_info *ivideo) 813sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
727{ 814{
728 if(!sisfballowretracecrt1(ivideo)) return FALSE; 815 if(!sisfballowretracecrt1(ivideo))
816 return FALSE;
729 817
730 if(inSISREG(SISINPSTAT) & 0x08) return TRUE; 818 if(inSISREG(SISINPSTAT) & 0x08)
731 else return FALSE; 819 return TRUE;
820 else
821 return FALSE;
732} 822}
733 823
734static void 824static void
735sisfbwaitretracecrt1(struct sis_video_info *ivideo) 825sisfbwaitretracecrt1(struct sis_video_info *ivideo)
736{ 826{
737 int watchdog; 827 int watchdog;
738 828
739 if(!sisfballowretracecrt1(ivideo)) return; 829 if(!sisfballowretracecrt1(ivideo))
830 return;
740 831
741 watchdog = 65536; 832 watchdog = 65536;
742 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog); 833 while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
743 watchdog = 65536; 834 watchdog = 65536;
744 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog); 835 while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
745} 836}
746 837
747static BOOLEAN 838static BOOLEAN
748sisfbcheckvretracecrt2(struct sis_video_info *ivideo) 839sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
749{ 840{
750 unsigned char temp, reg; 841 unsigned char temp, reg;
751 842
752 switch(ivideo->sisvga_engine) { 843 switch(ivideo->sisvga_engine) {
753 case SIS_300_VGA: reg = 0x25; break; 844 case SIS_300_VGA: reg = 0x25; break;
754 case SIS_315_VGA: reg = 0x30; break; 845 case SIS_315_VGA: reg = 0x30; break;
755 default: return FALSE; 846 default: return FALSE;
756 } 847 }
757 848
758 inSISIDXREG(SISPART1, reg, temp); 849 inSISIDXREG(SISPART1, reg, temp);
759 if(temp & 0x02) return TRUE; 850 if(temp & 0x02)
760 else return FALSE; 851 return TRUE;
852 else
853 return FALSE;
761} 854}
762 855
763static BOOLEAN 856static BOOLEAN
764sisfb_CheckVBRetrace(struct sis_video_info *ivideo) 857sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
765{ 858{
766 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 859 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
767 if(sisfb_bridgeisslave(ivideo)) { 860 if(!sisfb_bridgeisslave(ivideo)) {
768 return(sisfbcheckvretracecrt1(ivideo)); 861 return sisfbcheckvretracecrt2(ivideo);
769 } else { 862 }
770 return(sisfbcheckvretracecrt2(ivideo)); 863 }
771 } 864 return sisfbcheckvretracecrt1(ivideo);
772 }
773 return(sisfbcheckvretracecrt1(ivideo));
774} 865}
775 866
776static u32 867static u32
777sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount) 868sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
778{ 869{
779 u8 idx, reg1, reg2, reg3, reg4; 870 u8 idx, reg1, reg2, reg3, reg4;
780 u32 ret = 0; 871 u32 ret = 0;
781 872
782 (*vcount) = (*hcount) = 0; 873 (*vcount) = (*hcount) = 0;
783 874
784 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) { 875 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
785 ret |= (FB_VBLANK_HAVE_VSYNC | 876
786 FB_VBLANK_HAVE_HBLANK | 877 ret |= (FB_VBLANK_HAVE_VSYNC |
787 FB_VBLANK_HAVE_VBLANK | 878 FB_VBLANK_HAVE_HBLANK |
788 FB_VBLANK_HAVE_VCOUNT | 879 FB_VBLANK_HAVE_VBLANK |
789 FB_VBLANK_HAVE_HCOUNT); 880 FB_VBLANK_HAVE_VCOUNT |
790 switch(ivideo->sisvga_engine) { 881 FB_VBLANK_HAVE_HCOUNT);
791 case SIS_300_VGA: idx = 0x25; break; 882 switch(ivideo->sisvga_engine) {
792 default: 883 case SIS_300_VGA: idx = 0x25; break;
793 case SIS_315_VGA: idx = 0x30; break; 884 default:
794 } 885 case SIS_315_VGA: idx = 0x30; break;
795 inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */ 886 }
796 inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */ 887 inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
797 inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */ 888 inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
798 inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */ 889 inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
799 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; 890 inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
800 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING; 891 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
801 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING; 892 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
802 (*vcount) = reg3 | ((reg4 & 0x70) << 4); 893 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
803 (*hcount) = reg2 | ((reg4 & 0x0f) << 8); 894 (*vcount) = reg3 | ((reg4 & 0x70) << 4);
804 } else if(sisfballowretracecrt1(ivideo)) { 895 (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
805 ret |= (FB_VBLANK_HAVE_VSYNC | 896
806 FB_VBLANK_HAVE_VBLANK | 897 } else if(sisfballowretracecrt1(ivideo)) {
807 FB_VBLANK_HAVE_VCOUNT | 898
808 FB_VBLANK_HAVE_HCOUNT); 899 ret |= (FB_VBLANK_HAVE_VSYNC |
809 reg1 = inSISREG(SISINPSTAT); 900 FB_VBLANK_HAVE_VBLANK |
810 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING; 901 FB_VBLANK_HAVE_VCOUNT |
811 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING; 902 FB_VBLANK_HAVE_HCOUNT);
812 inSISIDXREG(SISCR,0x20,reg1); 903 reg1 = inSISREG(SISINPSTAT);
813 inSISIDXREG(SISCR,0x1b,reg1); 904 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
814 inSISIDXREG(SISCR,0x1c,reg2); 905 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
815 inSISIDXREG(SISCR,0x1d,reg3); 906 inSISIDXREG(SISCR,0x20,reg1);
816 (*vcount) = reg2 | ((reg3 & 0x07) << 8); 907 inSISIDXREG(SISCR,0x1b,reg1);
817 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3; 908 inSISIDXREG(SISCR,0x1c,reg2);
818 } 909 inSISIDXREG(SISCR,0x1d,reg3);
819 return ret; 910 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
911 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
912 }
913
914 return ret;
820} 915}
821 916
822static int 917static int
823sisfb_myblank(struct sis_video_info *ivideo, int blank) 918sisfb_myblank(struct sis_video_info *ivideo, int blank)
824{ 919{
825 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13; 920 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
826 BOOLEAN backlight = TRUE; 921 BOOLEAN backlight = TRUE;
827 922
828 switch(blank) { 923 switch(blank) {
829 case FB_BLANK_UNBLANK: /* on */ 924 case FB_BLANK_UNBLANK: /* on */
830 sr01 = 0x00; 925 sr01 = 0x00;
831 sr11 = 0x00; 926 sr11 = 0x00;
832 sr1f = 0x00; 927 sr1f = 0x00;
833 cr63 = 0x00; 928 cr63 = 0x00;
834 p2_0 = 0x20; 929 p2_0 = 0x20;
835 p1_13 = 0x00; 930 p1_13 = 0x00;
836 backlight = TRUE; 931 backlight = TRUE;
837 break; 932 break;
838 case FB_BLANK_NORMAL: /* blank */ 933 case FB_BLANK_NORMAL: /* blank */
839 sr01 = 0x20; 934 sr01 = 0x20;
840 sr11 = 0x00; 935 sr11 = 0x00;
841 sr1f = 0x00; 936 sr1f = 0x00;
842 cr63 = 0x00; 937 cr63 = 0x00;
843 p2_0 = 0x20; 938 p2_0 = 0x20;
844 p1_13 = 0x00; 939 p1_13 = 0x00;
845 backlight = TRUE; 940 backlight = TRUE;
846 break; 941 break;
847 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */ 942 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
848 sr01 = 0x20; 943 sr01 = 0x20;
849 sr11 = 0x08; 944 sr11 = 0x08;
850 sr1f = 0x80; 945 sr1f = 0x80;
851 cr63 = 0x40; 946 cr63 = 0x40;
852 p2_0 = 0x40; 947 p2_0 = 0x40;
853 p1_13 = 0x80; 948 p1_13 = 0x80;
854 backlight = FALSE; 949 backlight = FALSE;
855 break; 950 break;
856 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */ 951 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
857 sr01 = 0x20; 952 sr01 = 0x20;
858 sr11 = 0x08; 953 sr11 = 0x08;
859 sr1f = 0x40; 954 sr1f = 0x40;
860 cr63 = 0x40; 955 cr63 = 0x40;
861 p2_0 = 0x80; 956 p2_0 = 0x80;
862 p1_13 = 0x40; 957 p1_13 = 0x40;
863 backlight = FALSE; 958 backlight = FALSE;
864 break; 959 break;
865 case FB_BLANK_POWERDOWN: /* off */ 960 case FB_BLANK_POWERDOWN: /* off */
866 sr01 = 0x20; 961 sr01 = 0x20;
867 sr11 = 0x08; 962 sr11 = 0x08;
868 sr1f = 0xc0; 963 sr1f = 0xc0;
869 cr63 = 0x40; 964 cr63 = 0x40;
870 p2_0 = 0xc0; 965 p2_0 = 0xc0;
871 p1_13 = 0xc0; 966 p1_13 = 0xc0;
872 backlight = FALSE; 967 backlight = FALSE;
873 break; 968 break;
874 default: 969 default:
875 return 1; 970 return 1;
876 } 971 }
877 972
878 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) { 973 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
879 974
880 if( (!ivideo->sisfb_thismonitor.datavalid) || 975 if( (!ivideo->sisfb_thismonitor.datavalid) ||
881 ((ivideo->sisfb_thismonitor.datavalid) && 976 ((ivideo->sisfb_thismonitor.datavalid) &&
882 (ivideo->sisfb_thismonitor.feature & 0xe0))) { 977 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
883 978
884 if(ivideo->sisvga_engine == SIS_315_VGA) { 979 if(ivideo->sisvga_engine == SIS_315_VGA) {
885 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63); 980 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
886 } 981 }
887 982
888 if(!(sisfb_bridgeisslave(ivideo))) { 983 if(!(sisfb_bridgeisslave(ivideo))) {
889 setSISIDXREG(SISSR, 0x01, ~0x20, sr01); 984 setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
890 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f); 985 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
891 } 986 }
892 } 987 }
893 988
894 } 989 }
895 990
896 if(ivideo->currentvbflags & CRT2_LCD) { 991 if(ivideo->currentvbflags & CRT2_LCD) {
897 992
898 if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) { 993 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
899 if(backlight) { 994 if(backlight) {
900 SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext); 995 SiS_SiS30xBLOn(&ivideo->SiS_Pr);
901 } else { 996 } else {
902 SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext); 997 SiS_SiS30xBLOff(&ivideo->SiS_Pr);
903 } 998 }
904 } else if(ivideo->sisvga_engine == SIS_315_VGA) { 999 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
905 if(ivideo->vbflags & VB_CHRONTEL) { 1000#ifdef CONFIG_FB_SIS_315
906 if(backlight) { 1001 if(ivideo->vbflags2 & VB2_CHRONTEL) {
907 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext); 1002 if(backlight) {
908 } else { 1003 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
909 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr); 1004 } else {
910 } 1005 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
911 } 1006 }
912 } 1007 }
913 1008#endif
914 if(((ivideo->sisvga_engine == SIS_300_VGA) && 1009 }
915 (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) || 1010
916 ((ivideo->sisvga_engine == SIS_315_VGA) && 1011 if(((ivideo->sisvga_engine == SIS_300_VGA) &&
917 ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) { 1012 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
918 setSISIDXREG(SISSR, 0x11, ~0x0c, sr11); 1013 ((ivideo->sisvga_engine == SIS_315_VGA) &&
919 } 1014 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
920 1015 setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
921 if(ivideo->sisvga_engine == SIS_300_VGA) { 1016 }
922 if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) && 1017
923 (!(ivideo->vbflags & VB_30xBDH))) { 1018 if(ivideo->sisvga_engine == SIS_300_VGA) {
924 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); 1019 if((ivideo->vbflags2 & VB2_30xB) &&
925 } 1020 (!(ivideo->vbflags2 & VB2_30xBDH))) {
926 } else if(ivideo->sisvga_engine == SIS_315_VGA) { 1021 setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
927 if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) && 1022 }
928 (!(ivideo->vbflags & VB_30xBDH))) { 1023 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
929 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 1024 if((ivideo->vbflags2 & VB2_30xB) &&
930 } 1025 (!(ivideo->vbflags2 & VB2_30xBDH))) {
931 } 1026 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
932 1027 }
933 } else if(ivideo->currentvbflags & CRT2_VGA) { 1028 }
934 1029
935 if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) { 1030 } else if(ivideo->currentvbflags & CRT2_VGA) {
936 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); 1031
937 } 1032 if(ivideo->vbflags2 & VB2_30xB) {
938 1033 setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
939 } 1034 }
940 1035
941 return(0); 1036 }
1037
1038 return 0;
1039}
1040
1041/* ------------- Callbacks from init.c/init301.c -------------- */
1042
1043#ifdef CONFIG_FB_SIS_300
1044unsigned int
1045sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1046{
1047 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1048 u32 val = 0;
1049
1050 pci_read_config_dword(ivideo->nbridge, reg, &val);
1051 return (unsigned int)val;
1052}
1053
1054void
1055sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1056{
1057 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1058
1059 pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
942} 1060}
943 1061
1062unsigned int
1063sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1064{
1065 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1066 u32 val = 0;
1067
1068 if(!ivideo->lpcdev) return 0;
1069
1070 pci_read_config_dword(ivideo->lpcdev, reg, &val);
1071 return (unsigned int)val;
1072}
1073#endif
1074
1075#ifdef CONFIG_FB_SIS_315
1076void
1077sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1078{
1079 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1080
1081 pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1082}
1083
1084unsigned int
1085sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1086{
1087 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1088 u16 val = 0;
1089
1090 if(!ivideo->lpcdev) return 0;
1091
1092 pci_read_config_word(ivideo->lpcdev, reg, &val);
1093 return (unsigned int)val;
1094}
1095#endif
1096
944/* ----------- FBDev related routines for all series ----------- */ 1097/* ----------- FBDev related routines for all series ----------- */
945 1098
946static int 1099static int
@@ -952,7 +1105,7 @@ sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
952static void 1105static void
953sisfb_set_vparms(struct sis_video_info *ivideo) 1106sisfb_set_vparms(struct sis_video_info *ivideo)
954{ 1107{
955 switch(ivideo->video_bpp) { 1108 switch(ivideo->video_bpp) {
956 case 8: 1109 case 8:
957 ivideo->DstColor = 0x0000; 1110 ivideo->DstColor = 0x0000;
958 ivideo->SiS310_AccelDepth = 0x00000000; 1111 ivideo->SiS310_AccelDepth = 0x00000000;
@@ -972,14 +1125,13 @@ sisfb_set_vparms(struct sis_video_info *ivideo)
972 ivideo->video_cmap_len = 16; 1125 ivideo->video_cmap_len = 16;
973 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp); 1126 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
974 ivideo->accel = 0; 1127 ivideo->accel = 0;
975 break; 1128 }
976 }
977} 1129}
978 1130
979static int 1131static int
980sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) 1132sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
981{ 1133{
982 int maxyres = ivideo->heapstart / (var->xres_virtual * (var->bits_per_pixel >> 3)); 1134 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
983 1135
984 if(maxyres > 32767) maxyres = 32767; 1136 if(maxyres > 32767) maxyres = 32767;
985 1137
@@ -996,30 +1148,29 @@ sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
996 ivideo->scrnpitchCRT1 <<= 1; 1148 ivideo->scrnpitchCRT1 <<= 1;
997 } 1149 }
998 } 1150 }
999
1000} 1151}
1001 1152
1002static void 1153static void
1003sisfb_set_pitch(struct sis_video_info *ivideo) 1154sisfb_set_pitch(struct sis_video_info *ivideo)
1004{ 1155{
1005 BOOLEAN isslavemode = FALSE; 1156 BOOLEAN isslavemode = FALSE;
1006 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3; 1157 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1007 unsigned short HDisplay2 = ivideo->video_linelength >> 3; 1158 unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1008 1159
1009 if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE; 1160 if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
1010 1161
1011 /* We need to set pitch for CRT1 if bridge is in slave mode, too */ 1162 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1012 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) { 1163 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1013 outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF)); 1164 outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
1014 setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8)); 1165 setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
1015 } 1166 }
1016 1167
1017 /* We must not set the pitch for CRT2 if bridge is in slave mode */ 1168 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1018 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) { 1169 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1019 orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01); 1170 orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
1020 outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF)); 1171 outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
1021 setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8)); 1172 setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
1022 } 1173 }
1023} 1174}
1024 1175
1025static void 1176static void
@@ -1056,12 +1207,41 @@ sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1056} 1207}
1057 1208
1058static int 1209static int
1210sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1211{
1212 unsigned short modeno = ivideo->mode_no;
1213
1214 /* >=2.6.12's fbcon clears the screen anyway */
1215#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
1216 if(!clrscrn) modeno |= 0x80;
1217#else
1218 modeno |= 0x80;
1219#endif
1220
1221 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1222
1223 sisfb_pre_setmode(ivideo);
1224
1225 if(SiSSetMode(&ivideo->SiS_Pr, modeno) == 0) {
1226 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1227 return -EINVAL;
1228 }
1229
1230 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1231
1232 sisfb_post_setmode(ivideo);
1233
1234 return 0;
1235}
1236
1237
1238static int
1059sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info) 1239sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1060{ 1240{
1061 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1241 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1062 unsigned int htotal = 0, vtotal = 0; 1242 unsigned int htotal = 0, vtotal = 0;
1063 unsigned int drate = 0, hrate = 0; 1243 unsigned int drate = 0, hrate = 0;
1064 int found_mode = 0; 1244 int found_mode = 0, ret;
1065 int old_mode; 1245 int old_mode;
1066 u32 pixclock; 1246 u32 pixclock;
1067 1247
@@ -1088,11 +1268,11 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
1088 } 1268 }
1089 1269
1090 if(pixclock && htotal && vtotal) { 1270 if(pixclock && htotal && vtotal) {
1091 drate = 1000000000 / pixclock; 1271 drate = 1000000000 / pixclock;
1092 hrate = (drate * 1000) / htotal; 1272 hrate = (drate * 1000) / htotal;
1093 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal); 1273 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1094 } else { 1274 } else {
1095 ivideo->refresh_rate = 60; 1275 ivideo->refresh_rate = 60;
1096 } 1276 }
1097 1277
1098 old_mode = ivideo->sisfb_mode_idx; 1278 old_mode = ivideo->sisfb_mode_idx;
@@ -1113,6 +1293,7 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
1113 if(found_mode) { 1293 if(found_mode) {
1114 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, 1294 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1115 ivideo->sisfb_mode_idx, ivideo->currentvbflags); 1295 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1296 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1116 } else { 1297 } else {
1117 ivideo->sisfb_mode_idx = -1; 1298 ivideo->sisfb_mode_idx = -1;
1118 } 1299 }
@@ -1131,10 +1312,10 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
1131 1312
1132#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 1313#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
1133 if(ivideo->sisfb_thismonitor.datavalid) { 1314 if(ivideo->sisfb_thismonitor.datavalid) {
1134 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx, 1315 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
1135 ivideo->rate_idx, ivideo->refresh_rate)) { 1316 ivideo->rate_idx, ivideo->refresh_rate)) {
1136 printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); 1317 printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1137 } 1318 }
1138 } 1319 }
1139#endif 1320#endif
1140 1321
@@ -1143,24 +1324,9 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
1143#else 1324#else
1144 if(isactive) { 1325 if(isactive) {
1145#endif 1326#endif
1146 sisfb_pre_setmode(ivideo); 1327 /* If acceleration to be used? Need to know
1147 1328 * before pre/post_set_mode()
1148 if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) { 1329 */
1149 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1150 return -EINVAL;
1151 }
1152
1153 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1154
1155 sisfb_post_setmode(ivideo);
1156
1157 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1158 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1159 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1160
1161 sisfb_calc_pitch(ivideo, var);
1162 sisfb_set_pitch(ivideo);
1163
1164 ivideo->accel = 0; 1330 ivideo->accel = 0;
1165#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN) 1331#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1166#ifdef STUPID_ACCELF_TEXT_SHIT 1332#ifdef STUPID_ACCELF_TEXT_SHIT
@@ -1175,6 +1341,17 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
1175 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1; 1341 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1176#endif 1342#endif
1177 1343
1344 if((ret = sisfb_set_mode(ivideo, 1))) {
1345 return ret;
1346 }
1347
1348 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1349 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1350 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1351
1352 sisfb_calc_pitch(ivideo, var);
1353 sisfb_set_pitch(ivideo);
1354
1178 sisfb_set_vparms(ivideo); 1355 sisfb_set_vparms(ivideo);
1179 1356
1180 ivideo->current_width = ivideo->video_width; 1357 ivideo->current_width = ivideo->video_width;
@@ -1186,572 +1363,79 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
1186 ivideo->current_pixclock = var->pixclock; 1363 ivideo->current_pixclock = var->pixclock;
1187 ivideo->current_refresh_rate = ivideo->refresh_rate; 1364 ivideo->current_refresh_rate = ivideo->refresh_rate;
1188#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 1365#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1189 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate; 1366 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1190#endif 1367#endif
1191 } 1368 }
1192 1369
1193 return 0; 1370 return 0;
1194} 1371}
1195 1372
1196static int 1373static void
1197sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) 1374sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1198{ 1375{
1199 unsigned int base;
1200
1201 if(var->xoffset > (var->xres_virtual - var->xres)) {
1202 return -EINVAL;
1203 }
1204 if(var->yoffset > (var->yres_virtual - var->yres)) {
1205 return -EINVAL;
1206 }
1207
1208 base = (var->yoffset * var->xres_virtual) + var->xoffset;
1209
1210 /* calculate base bpp dep. */
1211 switch(var->bits_per_pixel) {
1212 case 32:
1213 break;
1214 case 16:
1215 base >>= 1;
1216 break;
1217 case 8:
1218 default:
1219 base >>= 2;
1220 break;
1221 }
1222
1223 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); 1376 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1224 1377
1225 outSISIDXREG(SISCR, 0x0D, base & 0xFF); 1378 outSISIDXREG(SISCR, 0x0D, base & 0xFF);
1226 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); 1379 outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
1227 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); 1380 outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
1228 if(ivideo->sisvga_engine == SIS_315_VGA) { 1381 if(ivideo->sisvga_engine == SIS_315_VGA) {
1229 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); 1382 setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1230 } 1383 }
1231 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1232 orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
1233 outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
1234 outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
1235 outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
1236 if(ivideo->sisvga_engine == SIS_315_VGA) {
1237 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1238 }
1239 }
1240 return 0;
1241} 1384}
1242 1385
1243/* ------------ FBDev related routines for 2.4 series ----------- */
1244
1245#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
1246
1247static void 1386static void
1248sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) 1387sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1249{
1250 u16 VRE, VBE, VRS, VBS, VDE, VT;
1251 u16 HRE, HBE, HRS, HBS, HDE, HT;
1252 u8 sr_data, cr_data, cr_data2, cr_data3, mr_data;
1253 int A, B, C, D, E, F, temp;
1254 unsigned int hrate, drate, maxyres;
1255
1256 inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data);
1257
1258 if(sr_data & SIS_INTERLACED_MODE)
1259 var->vmode = FB_VMODE_INTERLACED;
1260 else
1261 var->vmode = FB_VMODE_NONINTERLACED;
1262
1263 switch((sr_data & 0x1C) >> 2) {
1264 case SIS_8BPP_COLOR_MODE:
1265 var->bits_per_pixel = 8;
1266 break;
1267 case SIS_16BPP_COLOR_MODE:
1268 var->bits_per_pixel = 16;
1269 break;
1270 case SIS_32BPP_COLOR_MODE:
1271 var->bits_per_pixel = 32;
1272 break;
1273 }
1274
1275 sisfb_bpp_to_var(ivideo, var);
1276
1277 inSISIDXREG(SISSR, 0x0A, sr_data);
1278 inSISIDXREG(SISCR, 0x06, cr_data);
1279 inSISIDXREG(SISCR, 0x07, cr_data2);
1280
1281 VT = (cr_data & 0xFF) |
1282 ((u16) (cr_data2 & 0x01) << 8) |
1283 ((u16) (cr_data2 & 0x20) << 4) |
1284 ((u16) (sr_data & 0x01) << 10);
1285 A = VT + 2;
1286
1287 inSISIDXREG(SISCR, 0x12, cr_data);
1288
1289 VDE = (cr_data & 0xff) |
1290 ((u16) (cr_data2 & 0x02) << 7) |
1291 ((u16) (cr_data2 & 0x40) << 3) |
1292 ((u16) (sr_data & 0x02) << 9);
1293 E = VDE + 1;
1294
1295 inSISIDXREG(SISCR, 0x10, cr_data);
1296
1297 VRS = (cr_data & 0xff) |
1298 ((u16) (cr_data2 & 0x04) << 6) |
1299 ((u16) (cr_data2 & 0x80) << 2) |
1300 ((u16) (sr_data & 0x08) << 7);
1301 F = VRS + 1 - E;
1302
1303 inSISIDXREG(SISCR, 0x15, cr_data);
1304 inSISIDXREG(SISCR, 0x09, cr_data3);
1305
1306 if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE;
1307
1308 VBS = (cr_data & 0xff) |
1309 ((u16) (cr_data2 & 0x08) << 5) |
1310 ((u16) (cr_data3 & 0x20) << 4) |
1311 ((u16) (sr_data & 0x04) << 8);
1312
1313 inSISIDXREG(SISCR, 0x16, cr_data);
1314
1315 VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
1316 temp = VBE - ((E - 1) & 511);
1317 B = (temp > 0) ? temp : (temp + 512);
1318
1319 inSISIDXREG(SISCR, 0x11, cr_data);
1320
1321 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
1322 temp = VRE - ((E + F - 1) & 31);
1323 C = (temp > 0) ? temp : (temp + 32);
1324
1325 D = B - F - C;
1326
1327 var->yres = E;
1328 var->upper_margin = D;
1329 var->lower_margin = F;
1330 var->vsync_len = C;
1331
1332 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1333 var->yres <<= 1;
1334 var->upper_margin <<= 1;
1335 var->lower_margin <<= 1;
1336 var->vsync_len <<= 1;
1337 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1338 var->yres >>= 1;
1339 var->upper_margin >>= 1;
1340 var->lower_margin >>= 1;
1341 var->vsync_len >>= 1;
1342 }
1343
1344 inSISIDXREG(SISSR, 0x0b, sr_data);
1345 inSISIDXREG(SISCR, 0x00, cr_data);
1346
1347 HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
1348 A = HT + 5;
1349
1350 inSISIDXREG(SISCR, 0x01, cr_data);
1351
1352 HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
1353 E = HDE + 1;
1354
1355 inSISIDXREG(SISCR, 0x04, cr_data);
1356
1357 HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
1358 F = HRS - E - 3;
1359
1360 inSISIDXREG(SISCR, 0x02, cr_data);
1361
1362 HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
1363
1364 inSISIDXREG(SISSR, 0x0c, sr_data);
1365 inSISIDXREG(SISCR, 0x03, cr_data);
1366 inSISIDXREG(SISCR, 0x05, cr_data2);
1367
1368 HBE = (cr_data & 0x1f) |
1369 ((u16) (cr_data2 & 0x80) >> 2) |
1370 ((u16) (sr_data & 0x03) << 6);
1371 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
1372
1373 temp = HBE - ((E - 1) & 255);
1374 B = (temp > 0) ? temp : (temp + 256);
1375
1376 temp = HRE - ((E + F + 3) & 63);
1377 C = (temp > 0) ? temp : (temp + 64);
1378
1379 D = B - F - C;
1380
1381 var->xres = E * 8;
1382 if(var->xres_virtual < var->xres) {
1383 var->xres_virtual = var->xres;
1384 }
1385
1386 if((var->xres == 320) &&
1387 (var->yres == 200 || var->yres == 240)) {
1388 /* Terrible hack, but the correct CRTC data for
1389 * these modes only produces a black screen...
1390 */
1391 var->left_margin = (400 - 376);
1392 var->right_margin = (328 - 320);
1393 var->hsync_len = (376 - 328);
1394 } else {
1395 var->left_margin = D * 8;
1396 var->right_margin = F * 8;
1397 var->hsync_len = C * 8;
1398 }
1399 var->activate = FB_ACTIVATE_NOW;
1400
1401 var->sync = 0;
1402
1403 mr_data = inSISREG(SISMISCR);
1404 if(mr_data & 0x80)
1405 var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
1406 else
1407 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1408
1409 if(mr_data & 0x40)
1410 var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
1411 else
1412 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1413
1414 VT += 2;
1415 VT <<= 1;
1416 HT = (HT + 5) * 8;
1417
1418 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1419 VT <<= 1;
1420 }
1421 hrate = ivideo->refresh_rate * VT / 2;
1422 drate = (hrate * HT) / 1000;
1423 var->pixclock = (u32) (1000000000 / drate);
1424
1425 if(ivideo->sisfb_ypan) {
1426 maxyres = sisfb_calc_maxyres(ivideo, var);
1427 if(ivideo->sisfb_max) {
1428 var->yres_virtual = maxyres;
1429 } else {
1430 if(var->yres_virtual > maxyres) {
1431 var->yres_virtual = maxyres;
1432 }
1433 }
1434 if(var->yres_virtual <= var->yres) {
1435 var->yres_virtual = var->yres;
1436 }
1437 } else {
1438 var->yres_virtual = var->yres;
1439 }
1440
1441}
1442
1443static int
1444sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
1445 unsigned *transp, struct fb_info *info)
1446{ 1388{
1447 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1389 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1448 1390 orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
1449 if(regno >= ivideo->video_cmap_len) return 1; 1391 outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
1450 1392 outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
1451 *red = ivideo->sis_palette[regno].red; 1393 outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
1452 *green = ivideo->sis_palette[regno].green; 1394 if(ivideo->sisvga_engine == SIS_315_VGA) {
1453 *blue = ivideo->sis_palette[regno].blue; 1395 setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1454 *transp = 0;
1455
1456 return 0;
1457}
1458
1459static int
1460sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1461 unsigned transp, struct fb_info *info)
1462{
1463 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1464
1465 if(regno >= ivideo->video_cmap_len) return 1;
1466
1467 ivideo->sis_palette[regno].red = red;
1468 ivideo->sis_palette[regno].green = green;
1469 ivideo->sis_palette[regno].blue = blue;
1470
1471 switch(ivideo->video_bpp) {
1472#ifdef FBCON_HAS_CFB8
1473 case 8:
1474 outSISREG(SISDACA, regno);
1475 outSISREG(SISDACD, (red >> 10));
1476 outSISREG(SISDACD, (green >> 10));
1477 outSISREG(SISDACD, (blue >> 10));
1478 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1479 outSISREG(SISDAC2A, regno);
1480 outSISREG(SISDAC2D, (red >> 8));
1481 outSISREG(SISDAC2D, (green >> 8));
1482 outSISREG(SISDAC2D, (blue >> 8));
1483 } 1396 }
1484 break;
1485#endif
1486#ifdef FBCON_HAS_CFB16
1487 case 16:
1488 ivideo->sis_fbcon_cmap.cfb16[regno] =
1489 ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
1490 break;
1491#endif
1492#ifdef FBCON_HAS_CFB32
1493 case 32:
1494 red >>= 8;
1495 green >>= 8;
1496 blue >>= 8;
1497 ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
1498 break;
1499#endif
1500 }
1501
1502 return 0;
1503}
1504
1505static void
1506sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info)
1507{
1508 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1509 struct display *display;
1510 struct display_switch *sw;
1511 struct fb_fix_screeninfo fix;
1512 long flags;
1513
1514 display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
1515
1516 sisfb_get_fix(&fix, con, info);
1517
1518 display->var = *var;
1519 display->screen_base = (char *)ivideo->video_vbase;
1520 display->visual = fix.visual;
1521 display->type = fix.type;
1522 display->type_aux = fix.type_aux;
1523 display->ypanstep = fix.ypanstep;
1524 display->ywrapstep = fix.ywrapstep;
1525 display->line_length = fix.line_length;
1526 display->can_soft_blank = 1;
1527 display->inverse = ivideo->sisfb_inverse;
1528 display->next_line = fix.line_length;
1529
1530 save_flags(flags);
1531
1532 switch(ivideo->video_bpp) {
1533#ifdef FBCON_HAS_CFB8
1534 case 8: sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8;
1535 break;
1536#endif
1537#ifdef FBCON_HAS_CFB16
1538 case 16:sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16;
1539 display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16;
1540 break;
1541#endif
1542#ifdef FBCON_HAS_CFB32
1543 case 32:sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32;
1544 display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32;
1545 break;
1546#endif
1547 default:sw = &fbcon_dummy;
1548 break;
1549 }
1550 memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw));
1551 display->dispsw = &ivideo->sisfb_sw;
1552
1553 restore_flags(flags);
1554
1555 if(ivideo->sisfb_ypan) {
1556 /* display->scrollmode = 0; */
1557 } else {
1558 display->scrollmode = SCROLL_YREDRAW;
1559 ivideo->sisfb_sw.bmove = fbcon_redraw_bmove;
1560 }
1561}
1562
1563static void
1564sisfb_do_install_cmap(int con, struct fb_info *info)
1565{
1566 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1567
1568 if(con != ivideo->currcon) return;
1569
1570 if(fb_display[con].cmap.len) {
1571 fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
1572 } else {
1573 int size = sisfb_get_cmap_len(&fb_display[con].var);
1574 fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info);
1575 } 1397 }
1576} 1398}
1577 1399
1578static int 1400static int
1579sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) 1401sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1580{
1581 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1582
1583 if(con == -1) {
1584 memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo));
1585 } else {
1586 *var = fb_display[con].var;
1587 }
1588
1589 if(ivideo->sisfb_fstn) {
1590 if(var->xres == 320 && var->yres == 480) var->yres = 240;
1591 }
1592
1593 return 0;
1594}
1595
1596static int
1597sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
1598{ 1402{
1599 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1403 if(var->xoffset > (var->xres_virtual - var->xres)) {
1600 int err;
1601
1602 fb_display[con].var.activate = FB_ACTIVATE_NOW;
1603
1604 if(sisfb_do_set_var(var, con == ivideo->currcon, info)) {
1605 sisfb_crtc_to_var(ivideo, var);
1606 return -EINVAL; 1404 return -EINVAL;
1607 } 1405 }
1608 1406 if(var->yoffset > (var->yres_virtual - var->yres)) {
1609 sisfb_crtc_to_var(ivideo, var); 1407 return -EINVAL;
1610
1611 sisfb_set_disp(con, var, info);
1612
1613 if(info->changevar) {
1614 (*info->changevar)(con);
1615 }
1616
1617 if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) {
1618 return err;
1619 }
1620
1621 sisfb_do_install_cmap(con, info);
1622
1623#if 0 /* Why was this called here? */
1624 unsigned int cols, rows;
1625 cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
1626 rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
1627 vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
1628#endif
1629 return 0;
1630}
1631
1632static int
1633sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
1634{
1635 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1636 struct display *display;
1637
1638 display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
1639
1640 if(con == ivideo->currcon) {
1641
1642 return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
1643
1644 } else if(display->cmap.len) {
1645
1646 fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2);
1647
1648 } else {
1649
1650 int size = sisfb_get_cmap_len(&display->var);
1651 fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
1652
1653 } 1408 }
1654 1409
1655 return 0; 1410 ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
1656}
1657 1411
1658static int 1412 /* calculate base bpp dep. */
1659sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) 1413 switch(var->bits_per_pixel) {
1660{ 1414 case 32:
1661 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1415 break;
1662 struct display *display; 1416 case 16:
1663 int err, size; 1417 ivideo->current_base >>= 1;
1664 1418 break;
1665 display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; 1419 case 8:
1666 1420 default:
1667 size = sisfb_get_cmap_len(&display->var); 1421 ivideo->current_base >>= 2;
1668 if(display->cmap.len != size) { 1422 break;
1669 err = fb_alloc_cmap(&display->cmap, size, 0);
1670 if(err) return err;
1671 }
1672
1673 if(con == ivideo->currcon) {
1674 return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
1675 } else {
1676 fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1);
1677 }
1678
1679 return 0;
1680}
1681
1682static int
1683sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info)
1684{
1685 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1686 int err;
1687
1688 if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
1689
1690 if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) ||
1691 (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) {
1692 return -EINVAL;
1693 } 1423 }
1694 1424
1695 if(con == ivideo->currcon) { 1425 ivideo->current_base += (ivideo->video_offset >> 2);
1696 if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
1697 }
1698 1426
1699 fb_display[con].var.xoffset = var->xoffset; 1427 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1700 fb_display[con].var.yoffset = var->yoffset; 1428 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1701 1429
1702 return 0; 1430 return 0;
1703} 1431}
1704 1432
1705static int 1433/* ------------ FBDev related routines for 2.4 series ----------- */
1706sisfb_update_var(int con, struct fb_info *info)
1707{
1708 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1709
1710 return(sisfb_pan_var(ivideo, &fb_display[con].var));
1711}
1712
1713static int
1714sisfb_switch(int con, struct fb_info *info)
1715{
1716 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1717 int cols, rows;
1718
1719 if(fb_display[ivideo->currcon].cmap.len) {
1720 fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info);
1721 }
1722
1723 fb_display[con].var.activate = FB_ACTIVATE_NOW;
1724
1725 if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var,
1726 sizeof(struct fb_var_screeninfo))) {
1727 ivideo->currcon = con;
1728 return 1;
1729 }
1730
1731 ivideo->currcon = con;
1732
1733 sisfb_do_set_var(&fb_display[con].var, 1, info);
1734
1735 sisfb_set_disp(con, &fb_display[con].var, info);
1736
1737 sisfb_do_install_cmap(con, info);
1738
1739 cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
1740 rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
1741 vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
1742
1743 sisfb_update_var(con, info);
1744 1434
1745 return 1; 1435#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
1746}
1747 1436
1748static void 1437#include "sisfb_fbdev_2_4.h"
1749sisfb_blank(int blank, struct fb_info *info)
1750{
1751 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1752 1438
1753 sisfb_myblank(ivideo, blank);
1754}
1755#endif 1439#endif
1756 1440
1757/* ------------ FBDev related routines for 2.6 series ----------- */ 1441/* ------------ FBDev related routines for 2.6 series ----------- */
@@ -1761,13 +1445,13 @@ sisfb_blank(int blank, struct fb_info *info)
1761static int 1445static int
1762sisfb_open(struct fb_info *info, int user) 1446sisfb_open(struct fb_info *info, int user)
1763{ 1447{
1764 return 0; 1448 return 0;
1765} 1449}
1766 1450
1767static int 1451static int
1768sisfb_release(struct fb_info *info, int user) 1452sisfb_release(struct fb_info *info, int user)
1769{ 1453{
1770 return 0; 1454 return 0;
1771} 1455}
1772 1456
1773static int 1457static int
@@ -1776,16 +1460,17 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1776{ 1460{
1777 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1461 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1778 1462
1779 if(regno >= sisfb_get_cmap_len(&info->var)) return 1; 1463 if(regno >= sisfb_get_cmap_len(&info->var))
1464 return 1;
1780 1465
1781 switch(info->var.bits_per_pixel) { 1466 switch(info->var.bits_per_pixel) {
1782 case 8: 1467 case 8:
1783 outSISREG(SISDACA, regno); 1468 outSISREG(SISDACA, regno);
1784 outSISREG(SISDACD, (red >> 10)); 1469 outSISREG(SISDACD, (red >> 10));
1785 outSISREG(SISDACD, (green >> 10)); 1470 outSISREG(SISDACD, (green >> 10));
1786 outSISREG(SISDACD, (blue >> 10)); 1471 outSISREG(SISDACD, (blue >> 10));
1787 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 1472 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1788 outSISREG(SISDAC2A, regno); 1473 outSISREG(SISDAC2A, regno);
1789 outSISREG(SISDAC2D, (red >> 8)); 1474 outSISREG(SISDAC2D, (red >> 8));
1790 outSISREG(SISDAC2D, (green >> 8)); 1475 outSISREG(SISDAC2D, (green >> 8));
1791 outSISREG(SISDAC2D, (blue >> 8)); 1476 outSISREG(SISDAC2D, (blue >> 8));
@@ -1793,7 +1478,9 @@ sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1793 break; 1478 break;
1794 case 16: 1479 case 16:
1795 ((u32 *)(info->pseudo_palette))[regno] = 1480 ((u32 *)(info->pseudo_palette))[regno] =
1796 ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); 1481 (red & 0xf800) |
1482 ((green & 0xfc00) >> 5) |
1483 ((blue & 0xf800) >> 11);
1797 break; 1484 break;
1798 case 32: 1485 case 32:
1799 red >>= 8; 1486 red >>= 8;
@@ -1811,13 +1498,13 @@ sisfb_set_par(struct fb_info *info)
1811{ 1498{
1812 int err; 1499 int err;
1813 1500
1814 if((err = sisfb_do_set_var(&info->var, 1, info))) { 1501 if((err = sisfb_do_set_var(&info->var, 1, info)))
1815 return err; 1502 return err;
1816 } 1503
1817#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) 1504#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
1818 sisfb_get_fix(&info->fix, info->currcon, info); 1505 sisfb_get_fix(&info->fix, info->currcon, info);
1819#else 1506#else
1820 sisfb_get_fix(&info->fix, -1, info); 1507 sisfb_get_fix(&info->fix, -1, info);
1821#endif 1508#endif
1822 return 0; 1509 return 0;
1823} 1510}
@@ -1829,7 +1516,7 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1829 unsigned int htotal = 0, vtotal = 0, myrateindex = 0; 1516 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1830 unsigned int drate = 0, hrate = 0, maxyres; 1517 unsigned int drate = 0, hrate = 0, maxyres;
1831 int found_mode = 0; 1518 int found_mode = 0;
1832 int refresh_rate, search_idx; 1519 int refresh_rate, search_idx, tidx;
1833 BOOLEAN recalc_clock = FALSE; 1520 BOOLEAN recalc_clock = FALSE;
1834 u32 pixclock; 1521 u32 pixclock;
1835 1522
@@ -1848,7 +1535,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1848 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { 1535 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1849 vtotal += var->yres; 1536 vtotal += var->yres;
1850 vtotal <<= 1; 1537 vtotal <<= 1;
1851 } else vtotal += var->yres; 1538 } else
1539 vtotal += var->yres;
1852 1540
1853 if(!(htotal) || !(vtotal)) { 1541 if(!(htotal) || !(vtotal)) {
1854 SISFAIL("sisfb: no valid timing data"); 1542 SISFAIL("sisfb: no valid timing data");
@@ -1860,60 +1548,68 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1860 if( (sisbios_mode[search_idx].xres == var->xres) && 1548 if( (sisbios_mode[search_idx].xres == var->xres) &&
1861 (sisbios_mode[search_idx].yres == var->yres) && 1549 (sisbios_mode[search_idx].yres == var->yres) &&
1862 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) { 1550 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1863 if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) { 1551 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1864 found_mode = 1; 1552 ivideo->currentvbflags)) > 0) {
1865 break; 1553 found_mode = 1;
1554 search_idx = tidx;
1555 break;
1866 } 1556 }
1867 } 1557 }
1868 search_idx++; 1558 search_idx++;
1869 } 1559 }
1870 1560
1871 if(!found_mode) { 1561 if(!found_mode) {
1872 search_idx = 0; 1562 search_idx = 0;
1873 while(sisbios_mode[search_idx].mode_no[0] != 0) { 1563 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1874 if( (var->xres <= sisbios_mode[search_idx].xres) && 1564 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1875 (var->yres <= sisbios_mode[search_idx].yres) && 1565 (var->yres <= sisbios_mode[search_idx].yres) &&
1876 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) { 1566 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1877 if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) { 1567 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1878 found_mode = 1; 1568 ivideo->currentvbflags)) > 0) {
1879 break; 1569 found_mode = 1;
1880 } 1570 search_idx = tidx;
1571 break;
1572 }
1881 } 1573 }
1882 search_idx++; 1574 search_idx++;
1883 } 1575 }
1884 if(found_mode) { 1576 if(found_mode) {
1885 printk(KERN_DEBUG "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n", 1577 printk(KERN_DEBUG
1886 var->xres, var->yres, var->bits_per_pixel, 1578 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1579 var->xres, var->yres, var->bits_per_pixel,
1887 sisbios_mode[search_idx].xres, 1580 sisbios_mode[search_idx].xres,
1888 sisbios_mode[search_idx].yres, 1581 sisbios_mode[search_idx].yres,
1889 var->bits_per_pixel); 1582 var->bits_per_pixel);
1890 var->xres = sisbios_mode[search_idx].xres; 1583 var->xres = sisbios_mode[search_idx].xres;
1891 var->yres = sisbios_mode[search_idx].yres; 1584 var->yres = sisbios_mode[search_idx].yres;
1892
1893
1894 } else { 1585 } else {
1895 printk(KERN_ERR "sisfb: Failed to find supported mode near %dx%dx%d\n", 1586 printk(KERN_ERR
1587 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1896 var->xres, var->yres, var->bits_per_pixel); 1588 var->xres, var->yres, var->bits_per_pixel);
1897 return -EINVAL; 1589 return -EINVAL;
1898 } 1590 }
1899 } 1591 }
1900 1592
1901 if( ((ivideo->vbflags & VB_LVDS) || /* Slave modes on LVDS and 301B-DH */ 1593 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1902 ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) && 1594 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1903 (var->bits_per_pixel == 8) ) { 1595 (var->bits_per_pixel == 8) ) {
1904 refresh_rate = 60; 1596 /* Slave modes on LVDS and 301B-DH */
1597 refresh_rate = 60;
1905 recalc_clock = TRUE; 1598 recalc_clock = TRUE;
1906 } else if( (ivideo->current_htotal == htotal) && /* x=x & y=y & c=c -> assume depth change */ 1599 } else if( (ivideo->current_htotal == htotal) &&
1907 (ivideo->current_vtotal == vtotal) && 1600 (ivideo->current_vtotal == vtotal) &&
1908 (ivideo->current_pixclock == pixclock) ) { 1601 (ivideo->current_pixclock == pixclock) ) {
1602 /* x=x & y=y & c=c -> assume depth change */
1909 drate = 1000000000 / pixclock; 1603 drate = 1000000000 / pixclock;
1910 hrate = (drate * 1000) / htotal; 1604 hrate = (drate * 1000) / htotal;
1911 refresh_rate = (unsigned int) (hrate * 2 / vtotal); 1605 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1912 } else if( ( (ivideo->current_htotal != htotal) || /* x!=x | y!=y & c=c -> invalid pixclock */ 1606 } else if( ( (ivideo->current_htotal != htotal) ||
1913 (ivideo->current_vtotal != vtotal) ) && 1607 (ivideo->current_vtotal != vtotal) ) &&
1914 (ivideo->current_pixclock == var->pixclock) ) { 1608 (ivideo->current_pixclock == var->pixclock) ) {
1609 /* x!=x | y!=y & c=c -> invalid pixclock */
1915 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) { 1610 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1916 refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]; 1611 refresh_rate =
1612 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1917 } else if(ivideo->sisfb_parm_rate != -1) { 1613 } else if(ivideo->sisfb_parm_rate != -1) {
1918 /* Sic, sisfb_parm_rate - want to know originally desired rate here */ 1614 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1919 refresh_rate = ivideo->sisfb_parm_rate; 1615 refresh_rate = ivideo->sisfb_parm_rate;
@@ -1923,8 +1619,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1923 recalc_clock = TRUE; 1619 recalc_clock = TRUE;
1924 } else if((pixclock) && (htotal) && (vtotal)) { 1620 } else if((pixclock) && (htotal) && (vtotal)) {
1925 drate = 1000000000 / pixclock; 1621 drate = 1000000000 / pixclock;
1926 hrate = (drate * 1000) / htotal; 1622 hrate = (drate * 1000) / htotal;
1927 refresh_rate = (unsigned int) (hrate * 2 / vtotal); 1623 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1928 } else if(ivideo->current_refresh_rate) { 1624 } else if(ivideo->current_refresh_rate) {
1929 refresh_rate = ivideo->current_refresh_rate; 1625 refresh_rate = ivideo->current_refresh_rate;
1930 recalc_clock = TRUE; 1626 recalc_clock = TRUE;
@@ -1937,72 +1633,72 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1937 1633
1938 /* Eventually recalculate timing and clock */ 1634 /* Eventually recalculate timing and clock */
1939 if(recalc_clock) { 1635 if(recalc_clock) {
1940 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx; 1636 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1941 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, 1637 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1942 &ivideo->sishw_ext,
1943 sisbios_mode[search_idx].mode_no[ivideo->mni], 1638 sisbios_mode[search_idx].mode_no[ivideo->mni],
1944 myrateindex)); 1639 myrateindex));
1945 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext, 1640 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1946 sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex, var); 1641 sisbios_mode[search_idx].mode_no[ivideo->mni],
1947 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { 1642 myrateindex, var);
1948 var->pixclock <<= 1; 1643 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1949 } 1644 var->pixclock <<= 1;
1645 }
1950 } 1646 }
1951 1647
1952 if(ivideo->sisfb_thismonitor.datavalid) { 1648 if(ivideo->sisfb_thismonitor.datavalid) {
1953 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx, 1649 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1954 myrateindex, refresh_rate)) { 1650 myrateindex, refresh_rate)) {
1955 printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); 1651 printk(KERN_INFO
1956 } 1652 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1653 }
1957 } 1654 }
1958 1655
1959 /* Adapt RGB settings */ 1656 /* Adapt RGB settings */
1960 sisfb_bpp_to_var(ivideo, var); 1657 sisfb_bpp_to_var(ivideo, var);
1961 1658
1962 /* Sanity check for offsets */ 1659 /* Sanity check for offsets */
1963 if(var->xoffset < 0) var->xoffset = 0; 1660 if(var->xoffset < 0) var->xoffset = 0;
1964 if(var->yoffset < 0) var->yoffset = 0; 1661 if(var->yoffset < 0) var->yoffset = 0;
1965 1662
1966 if(var->xres > var->xres_virtual) { 1663 if(var->xres > var->xres_virtual)
1967 var->xres_virtual = var->xres; 1664 var->xres_virtual = var->xres;
1968 }
1969 1665
1970 if(ivideo->sisfb_ypan) { 1666 if(ivideo->sisfb_ypan) {
1971 maxyres = sisfb_calc_maxyres(ivideo, var); 1667 maxyres = sisfb_calc_maxyres(ivideo, var);
1972 if(ivideo->sisfb_max) { 1668 if(ivideo->sisfb_max) {
1973 var->yres_virtual = maxyres; 1669 var->yres_virtual = maxyres;
1974 } else { 1670 } else {
1975 if(var->yres_virtual > maxyres) { 1671 if(var->yres_virtual > maxyres) {
1976 var->yres_virtual = maxyres; 1672 var->yres_virtual = maxyres;
1977 } 1673 }
1978 } 1674 }
1979 if(var->yres_virtual <= var->yres) { 1675 if(var->yres_virtual <= var->yres) {
1980 var->yres_virtual = var->yres; 1676 var->yres_virtual = var->yres;
1981 } 1677 }
1982 } else { 1678 } else {
1983 if(var->yres != var->yres_virtual) { 1679 if(var->yres != var->yres_virtual) {
1984 var->yres_virtual = var->yres; 1680 var->yres_virtual = var->yres;
1985 } 1681 }
1986 var->xoffset = 0; 1682 var->xoffset = 0;
1987 var->yoffset = 0; 1683 var->yoffset = 0;
1988 } 1684 }
1989 1685
1990 /* Truncate offsets to maximum if too high */ 1686 /* Truncate offsets to maximum if too high */
1991 if(var->xoffset > var->xres_virtual - var->xres) { 1687 if(var->xoffset > var->xres_virtual - var->xres) {
1992 var->xoffset = var->xres_virtual - var->xres - 1; 1688 var->xoffset = var->xres_virtual - var->xres - 1;
1993 } 1689 }
1994 1690
1995 if(var->yoffset > var->yres_virtual - var->yres) { 1691 if(var->yoffset > var->yres_virtual - var->yres) {
1996 var->yoffset = var->yres_virtual - var->yres - 1; 1692 var->yoffset = var->yres_virtual - var->yres - 1;
1997 } 1693 }
1998 1694
1999 /* Set everything else to 0 */ 1695 /* Set everything else to 0 */
2000 var->red.msb_right = 1696 var->red.msb_right =
2001 var->green.msb_right = 1697 var->green.msb_right =
2002 var->blue.msb_right = 1698 var->blue.msb_right =
2003 var->transp.offset = 1699 var->transp.offset =
2004 var->transp.length = 1700 var->transp.length =
2005 var->transp.msb_right = 0; 1701 var->transp.msb_right = 0;
2006 1702
2007 return 0; 1703 return 0;
2008} 1704}
@@ -2013,21 +1709,21 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
2013 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1709 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
2014 int err; 1710 int err;
2015 1711
2016 if(var->xoffset > (var->xres_virtual - var->xres)) { 1712 if(var->xoffset > (var->xres_virtual - var->xres))
2017 return -EINVAL; 1713 return -EINVAL;
2018 } 1714
2019 if(var->yoffset > (var->yres_virtual - var->yres)) { 1715 if(var->yoffset > (var->yres_virtual - var->yres))
2020 return -EINVAL; 1716 return -EINVAL;
2021 }
2022 1717
2023 if(var->vmode & FB_VMODE_YWRAP) return -EINVAL; 1718 if(var->vmode & FB_VMODE_YWRAP)
1719 return -EINVAL;
2024 1720
2025 if(var->xoffset + info->var.xres > info->var.xres_virtual || 1721 if(var->xoffset + info->var.xres > info->var.xres_virtual ||
2026 var->yoffset + info->var.yres > info->var.yres_virtual) { 1722 var->yoffset + info->var.yres > info->var.yres_virtual)
2027 return -EINVAL; 1723 return -EINVAL;
2028 }
2029 1724
2030 if((err = sisfb_pan_var(ivideo, var)) < 0) return err; 1725 if((err = sisfb_pan_var(ivideo, var)) < 0)
1726 return err;
2031 1727
2032 info->var.xoffset = var->xoffset; 1728 info->var.xoffset = var->xoffset;
2033 info->var.yoffset = var->yoffset; 1729 info->var.yoffset = var->yoffset;
@@ -2040,7 +1736,7 @@ sisfb_blank(int blank, struct fb_info *info)
2040{ 1736{
2041 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1737 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
2042 1738
2043 return(sisfb_myblank(ivideo, blank)); 1739 return sisfb_myblank(ivideo, blank);
2044} 1740}
2045 1741
2046#endif 1742#endif
@@ -2056,153 +1752,184 @@ sisfb_ioctl(struct inode *inode, struct file *file,
2056 struct fb_info *info) 1752 struct fb_info *info)
2057{ 1753{
2058 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1754 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
2059 struct sis_memreq sismemreq; 1755 struct sis_memreq sismemreq;
2060 struct fb_vblank sisvbblank; 1756 struct fb_vblank sisvbblank;
2061 sisfb_info x;
2062 u32 gpu32 = 0; 1757 u32 gpu32 = 0;
2063#ifndef __user 1758#ifndef __user
2064#define __user 1759#define __user
2065#endif 1760#endif
2066 u32 __user *argp = (u32 __user *)arg; 1761 u32 __user *argp = (u32 __user *)arg;
2067 1762
2068 switch (cmd) { 1763 switch(cmd) {
2069 case FBIO_ALLOC: 1764 case FBIO_ALLOC:
2070 if(!capable(CAP_SYS_RAWIO)) { 1765 if(!capable(CAP_SYS_RAWIO))
2071 return -EPERM; 1766 return -EPERM;
2072 } 1767
2073 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq))) { 1768 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
2074 return -EFAULT; 1769 return -EFAULT;
2075 } 1770
2076 sis_malloc(&sismemreq); 1771 sis_malloc(&sismemreq);
1772
2077 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) { 1773 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
2078 sis_free((u32)sismemreq.offset); 1774 sis_free((u32)sismemreq.offset);
2079 return -EFAULT; 1775 return -EFAULT;
2080 } 1776 }
2081 break; 1777 break;
2082 1778
2083 case FBIO_FREE: 1779 case FBIO_FREE:
2084 if(!capable(CAP_SYS_RAWIO)) { 1780 if(!capable(CAP_SYS_RAWIO))
2085 return -EPERM; 1781 return -EPERM;
2086 } 1782
2087 if(get_user(gpu32, argp)) { 1783 if(get_user(gpu32, argp))
2088 return -EFAULT; 1784 return -EFAULT;
2089 } 1785
2090 sis_free(gpu32); 1786 sis_free(gpu32);
2091 break; 1787 break;
2092 1788
2093 case FBIOGET_VBLANK: 1789 case FBIOGET_VBLANK:
2094 sisvbblank.count = 0; 1790 sisvbblank.count = 0;
2095 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount); 1791 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
2096 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank))) { 1792
1793 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
2097 return -EFAULT; 1794 return -EFAULT;
2098 } 1795
2099 break; 1796 break;
2100 1797
2101 case SISFB_GET_INFO_SIZE: 1798 case SISFB_GET_INFO_SIZE:
2102 return put_user(sizeof(sisfb_info), argp); 1799 return put_user(sizeof(struct sisfb_info), argp);
2103 1800
2104 case SISFB_GET_INFO_OLD: 1801 case SISFB_GET_INFO_OLD:
2105 if(ivideo->warncount++ < 50) { 1802 if(ivideo->warncount++ < 10)
2106 printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); 1803 printk(KERN_INFO
2107 } 1804 "sisfb: Deprecated ioctl call received - update your application!\n");
2108 case SISFB_GET_INFO: /* For communication with X driver */ 1805 case SISFB_GET_INFO: /* For communication with X driver */
2109 x.sisfb_id = SISFB_ID; 1806 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
2110 x.sisfb_version = VER_MAJOR; 1807 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
2111 x.sisfb_revision = VER_MINOR; 1808 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
2112 x.sisfb_patchlevel = VER_LEVEL; 1809 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
2113 x.chip_id = ivideo->chip_id; 1810 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
2114 x.memory = ivideo->video_size / 1024; 1811 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
2115 x.heapstart = ivideo->heapstart / 1024; 1812 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1813 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
2116 if(ivideo->modechanged) { 1814 if(ivideo->modechanged) {
2117 x.fbvidmode = ivideo->mode_no; 1815 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
2118 } else { 1816 } else {
2119 x.fbvidmode = ivideo->modeprechange; 1817 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
2120 }
2121 x.sisfb_caps = ivideo->caps;
2122 x.sisfb_tqlen = 512; /* yet fixed */
2123 x.sisfb_pcibus = ivideo->pcibus;
2124 x.sisfb_pcislot = ivideo->pcislot;
2125 x.sisfb_pcifunc = ivideo->pcifunc;
2126 x.sisfb_lcdpdc = ivideo->detectedpdc;
2127 x.sisfb_lcdpdca = ivideo->detectedpdca;
2128 x.sisfb_lcda = ivideo->detectedlcda;
2129 x.sisfb_vbflags = ivideo->vbflags;
2130 x.sisfb_currentvbflags = ivideo->currentvbflags;
2131 x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
2132 x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
2133 x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
2134 x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
2135 x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
2136 x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
2137 x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
2138 x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
2139 x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
2140 x.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
2141
2142 if(copy_to_user((void __user *)arg, &x, sizeof(x))) {
2143 return -EFAULT;
2144 } 1818 }
1819 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1820 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1821 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1822 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1823 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1824 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1825 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1826 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1827 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1828 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1829 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1830 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1831 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1832 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1833 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1834 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1835 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1836 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1837 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1838 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1839 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1840 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1841 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1842 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1843 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1844 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1845 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1846 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1847
1848 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1849 sizeof(ivideo->sisfb_infoblock)))
1850 return -EFAULT;
1851
2145 break; 1852 break;
2146 1853
2147 case SISFB_GET_VBRSTATUS_OLD: 1854 case SISFB_GET_VBRSTATUS_OLD:
2148 if(ivideo->warncount++ < 50) { 1855 if(ivideo->warncount++ < 10)
2149 printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); 1856 printk(KERN_INFO
2150 } 1857 "sisfb: Deprecated ioctl call received - update your application!\n");
2151 case SISFB_GET_VBRSTATUS: 1858 case SISFB_GET_VBRSTATUS:
2152 if(sisfb_CheckVBRetrace(ivideo)) { 1859 if(sisfb_CheckVBRetrace(ivideo))
2153 return put_user((u32)1, argp); 1860 return put_user((u32)1, argp);
2154 } else { 1861 else
2155 return put_user((u32)0, argp); 1862 return put_user((u32)0, argp);
2156 }
2157 1863
2158 case SISFB_GET_AUTOMAXIMIZE_OLD: 1864 case SISFB_GET_AUTOMAXIMIZE_OLD:
2159 if(ivideo->warncount++ < 50) { 1865 if(ivideo->warncount++ < 10)
2160 printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); 1866 printk(KERN_INFO
2161 } 1867 "sisfb: Deprecated ioctl call received - update your application!\n");
2162 case SISFB_GET_AUTOMAXIMIZE: 1868 case SISFB_GET_AUTOMAXIMIZE:
2163 if(ivideo->sisfb_max) return put_user((u32)1, argp); 1869 if(ivideo->sisfb_max)
2164 else return put_user((u32)0, argp); 1870 return put_user((u32)1, argp);
1871 else
1872 return put_user((u32)0, argp);
2165 1873
2166 case SISFB_SET_AUTOMAXIMIZE_OLD: 1874 case SISFB_SET_AUTOMAXIMIZE_OLD:
2167 if(ivideo->warncount++ < 50) { 1875 if(ivideo->warncount++ < 10)
2168 printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); 1876 printk(KERN_INFO
2169 } 1877 "sisfb: Deprecated ioctl call received - update your application!\n");
2170 case SISFB_SET_AUTOMAXIMIZE: 1878 case SISFB_SET_AUTOMAXIMIZE:
2171 if(copy_from_user(&gpu32, argp, sizeof(gpu32))) { 1879 if(get_user(gpu32, argp))
2172 return -EFAULT; 1880 return -EFAULT;
2173 } 1881
2174 ivideo->sisfb_max = (gpu32) ? 1 : 0; 1882 ivideo->sisfb_max = (gpu32) ? 1 : 0;
2175 break; 1883 break;
2176 1884
2177 case SISFB_SET_TVPOSOFFSET: 1885 case SISFB_SET_TVPOSOFFSET:
2178 if(copy_from_user(&gpu32, argp, sizeof(gpu32))) { 1886 if(get_user(gpu32, argp))
2179 return -EFAULT; 1887 return -EFAULT;
2180 } 1888
2181 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32); 1889 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
2182 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32); 1890 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
2183 break; 1891 break;
2184 1892
2185 case SISFB_GET_TVPOSOFFSET: 1893 case SISFB_GET_TVPOSOFFSET:
2186 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)), 1894 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
2187 argp); 1895 argp);
1896
1897 case SISFB_COMMAND:
1898 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1899 sizeof(struct sisfb_cmd)))
1900 return -EFAULT;
1901
1902 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1903
1904 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1905 sizeof(struct sisfb_cmd)))
1906 return -EFAULT;
1907
1908 break;
2188 1909
2189 case SISFB_SET_LOCK: 1910 case SISFB_SET_LOCK:
2190 if(copy_from_user(&gpu32, argp, sizeof(gpu32))) { 1911 if(get_user(gpu32, argp))
2191 return -EFAULT; 1912 return -EFAULT;
2192 } 1913
2193 ivideo->sisfblocked = (gpu32) ? 1 : 0; 1914 ivideo->sisfblocked = (gpu32) ? 1 : 0;
2194 break; 1915 break;
2195 1916
2196 default: 1917 default:
1918#ifdef SIS_NEW_CONFIG_COMPAT
2197 return -ENOIOCTLCMD; 1919 return -ENOIOCTLCMD;
1920#else
1921 return -EINVAL;
1922#endif
2198 } 1923 }
2199 return 0; 1924 return 0;
2200} 1925}
2201 1926
2202#ifdef CONFIG_COMPAT 1927#ifdef SIS_NEW_CONFIG_COMPAT
2203static long sisfb_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg, struct fb_info *info) 1928static long
1929sisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info)
2204{ 1930{
2205 int ret; 1931 int ret;
1932
2206 lock_kernel(); 1933 lock_kernel();
2207 ret = sisfb_ioctl(NULL, f, cmd, arg, info); 1934 ret = sisfb_ioctl(NULL, f, cmd, arg, info);
2208 unlock_kernel(); 1935 unlock_kernel();
@@ -2219,7 +1946,7 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
2219 1946
2220 strcpy(fix->id, ivideo->myid); 1947 strcpy(fix->id, ivideo->myid);
2221 1948
2222 fix->smem_start = ivideo->video_base; 1949 fix->smem_start = ivideo->video_base + ivideo->video_offset;
2223 fix->smem_len = ivideo->sisfb_mem; 1950 fix->smem_len = ivideo->sisfb_mem;
2224 fix->type = FB_TYPE_PACKED_PIXELS; 1951 fix->type = FB_TYPE_PACKED_PIXELS;
2225 fix->type_aux = 0; 1952 fix->type_aux = 0;
@@ -2231,11 +1958,17 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
2231 fix->mmio_start = ivideo->mmio_base; 1958 fix->mmio_start = ivideo->mmio_base;
2232 fix->mmio_len = ivideo->mmio_size; 1959 fix->mmio_len = ivideo->mmio_size;
2233 if(ivideo->sisvga_engine == SIS_300_VGA) { 1960 if(ivideo->sisvga_engine == SIS_300_VGA) {
2234 fix->accel = FB_ACCEL_SIS_GLAMOUR; 1961 fix->accel = FB_ACCEL_SIS_GLAMOUR;
2235 } else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) { 1962 } else if((ivideo->chip == SIS_330) ||
2236 fix->accel = FB_ACCEL_SIS_XABRE; 1963 (ivideo->chip == SIS_760) ||
1964 (ivideo->chip == SIS_761)) {
1965 fix->accel = FB_ACCEL_SIS_XABRE;
1966 } else if(ivideo->chip == XGI_20) {
1967 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1968 } else if(ivideo->chip >= XGI_40) {
1969 fix->accel = FB_ACCEL_XGI_VOLARI_V;
2237 } else { 1970 } else {
2238 fix->accel = FB_ACCEL_SIS_GLAMOUR_2; 1971 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
2239 } 1972 }
2240 1973
2241 return 0; 1974 return 0;
@@ -2251,40 +1984,41 @@ static struct fb_ops sisfb_ops = {
2251 .fb_set_var = sisfb_set_var, 1984 .fb_set_var = sisfb_set_var,
2252 .fb_get_cmap = sisfb_get_cmap, 1985 .fb_get_cmap = sisfb_get_cmap,
2253 .fb_set_cmap = sisfb_set_cmap, 1986 .fb_set_cmap = sisfb_set_cmap,
2254 .fb_pan_display = sisfb_pan_display, 1987 .fb_pan_display = sisfb_pan_display,
2255 .fb_ioctl = sisfb_ioctl 1988 .fb_ioctl = sisfb_ioctl
2256}; 1989};
2257#endif 1990#endif
2258 1991
2259#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 1992#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
2260static struct fb_ops sisfb_ops = { 1993static struct fb_ops sisfb_ops = {
2261 .owner = THIS_MODULE, 1994 .owner = THIS_MODULE,
2262 .fb_open = sisfb_open, 1995 .fb_open = sisfb_open,
2263 .fb_release = sisfb_release, 1996 .fb_release = sisfb_release,
2264 .fb_check_var = sisfb_check_var, 1997 .fb_check_var = sisfb_check_var,
2265 .fb_set_par = sisfb_set_par, 1998 .fb_set_par = sisfb_set_par,
2266 .fb_setcolreg = sisfb_setcolreg, 1999 .fb_setcolreg = sisfb_setcolreg,
2267 .fb_pan_display = sisfb_pan_display, 2000 .fb_pan_display = sisfb_pan_display,
2268 .fb_blank = sisfb_blank, 2001 .fb_blank = sisfb_blank,
2269 .fb_fillrect = fbcon_sis_fillrect, 2002 .fb_fillrect = fbcon_sis_fillrect,
2270 .fb_copyarea = fbcon_sis_copyarea, 2003 .fb_copyarea = fbcon_sis_copyarea,
2271 .fb_imageblit = cfb_imageblit, 2004 .fb_imageblit = cfb_imageblit,
2272 .fb_cursor = soft_cursor, 2005 .fb_cursor = soft_cursor,
2273 .fb_sync = fbcon_sis_sync, 2006 .fb_sync = fbcon_sis_sync,
2274 .fb_ioctl = sisfb_ioctl, 2007#ifdef SIS_NEW_CONFIG_COMPAT
2275#ifdef CONFIG_COMPAT 2008 .fb_compat_ioctl= sisfb_compat_ioctl,
2276 .fb_compat_ioctl = sisfb_compat_ioctl,
2277#endif 2009#endif
2010 .fb_ioctl = sisfb_ioctl
2278}; 2011};
2279#endif 2012#endif
2280 2013
2281/* ---------------- Chip generation dependent routines ---------------- */ 2014/* ---------------- Chip generation dependent routines ---------------- */
2282 2015
2283static struct pci_dev * sisfb_get_northbridge(int basechipid) 2016static struct pci_dev * __devinit
2017sisfb_get_northbridge(int basechipid)
2284{ 2018{
2285 struct pci_dev *pdev = NULL; 2019 struct pci_dev *pdev = NULL;
2286 int nbridgenum, nbridgeidx, i; 2020 int nbridgenum, nbridgeidx, i;
2287 const unsigned short nbridgeids[] = { 2021 static const unsigned short nbridgeids[] = {
2288 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */ 2022 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
2289 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */ 2023 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
2290 PCI_DEVICE_ID_SI_730, 2024 PCI_DEVICE_ID_SI_730,
@@ -2292,13 +2026,14 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid)
2292 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */ 2026 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
2293 PCI_DEVICE_ID_SI_651, 2027 PCI_DEVICE_ID_SI_651,
2294 PCI_DEVICE_ID_SI_740, 2028 PCI_DEVICE_ID_SI_740,
2295 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760 VGA */ 2029 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
2296 PCI_DEVICE_ID_SI_741, 2030 PCI_DEVICE_ID_SI_741,
2297 PCI_DEVICE_ID_SI_660, 2031 PCI_DEVICE_ID_SI_660,
2298 PCI_DEVICE_ID_SI_760 2032 PCI_DEVICE_ID_SI_760,
2033 PCI_DEVICE_ID_SI_761
2299 }; 2034 };
2300 2035
2301 switch(basechipid) { 2036 switch(basechipid) {
2302#ifdef CONFIG_FB_SIS_300 2037#ifdef CONFIG_FB_SIS_300
2303 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break; 2038 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
2304 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break; 2039 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
@@ -2306,35 +2041,40 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid)
2306#ifdef CONFIG_FB_SIS_315 2041#ifdef CONFIG_FB_SIS_315
2307 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break; 2042 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
2308 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break; 2043 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
2309 case SIS_660: nbridgeidx = 7; nbridgenum = 4; break; 2044 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
2310#endif 2045#endif
2311 default: return NULL; 2046 default: return NULL;
2312 } 2047 }
2313 for(i = 0; i < nbridgenum; i++) { 2048 for(i = 0; i < nbridgenum; i++) {
2314 if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break; 2049 if((pdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI,
2050 nbridgeids[nbridgeidx+i], NULL)))
2051 break;
2315 } 2052 }
2316 return pdev; 2053 return pdev;
2317} 2054}
2318 2055
2319static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo) 2056static int __devinit
2057sisfb_get_dram_size(struct sis_video_info *ivideo)
2320{ 2058{
2321#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) 2059#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2322 u8 reg; 2060 u8 reg;
2323#endif 2061#endif
2324 2062
2325 ivideo->video_size = 0; 2063 ivideo->video_size = 0;
2064 ivideo->UMAsize = ivideo->LFBsize = 0;
2326 2065
2327 switch(ivideo->chip) { 2066 switch(ivideo->chip) {
2328#ifdef CONFIG_FB_SIS_300 2067#ifdef CONFIG_FB_SIS_300
2329 case SIS_300: 2068 case SIS_300:
2330 inSISIDXREG(SISSR, 0x14, reg); 2069 inSISIDXREG(SISSR, 0x14, reg);
2331 ivideo->video_size = ((reg & 0x3F) + 1) << 20; 2070 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
2332 break; 2071 break;
2333 case SIS_540: 2072 case SIS_540:
2334 case SIS_630: 2073 case SIS_630:
2335 case SIS_730: 2074 case SIS_730:
2336 if(!ivideo->nbridge) return -1; 2075 if(!ivideo->nbridge)
2337 pci_read_config_byte(ivideo->nbridge, 0x63, &reg); 2076 return -1;
2077 pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
2338 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21); 2078 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
2339 break; 2079 break;
2340#endif 2080#endif
@@ -2342,45 +2082,68 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
2342 case SIS_315H: 2082 case SIS_315H:
2343 case SIS_315PRO: 2083 case SIS_315PRO:
2344 case SIS_315: 2084 case SIS_315:
2345 inSISIDXREG(SISSR, 0x14, reg); 2085 inSISIDXREG(SISSR, 0x14, reg);
2346 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 2086 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2347 switch((reg >> 2) & 0x03) { 2087 switch((reg >> 2) & 0x03) {
2348 case 0x01: 2088 case 0x01:
2349 case 0x03: 2089 case 0x03:
2350 ivideo->video_size <<= 1; 2090 ivideo->video_size <<= 1;
2351 break; 2091 break;
2352 case 0x02: 2092 case 0x02:
2353 ivideo->video_size += (ivideo->video_size/2); 2093 ivideo->video_size += (ivideo->video_size/2);
2354 } 2094 }
2355 break; 2095 break;
2356 case SIS_330: 2096 case SIS_330:
2357 inSISIDXREG(SISSR, 0x14, reg); 2097 inSISIDXREG(SISSR, 0x14, reg);
2358 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 2098 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2359 if(reg & 0x0c) ivideo->video_size <<= 1; 2099 if(reg & 0x0c) ivideo->video_size <<= 1;
2360 break; 2100 break;
2361 case SIS_550: 2101 case SIS_550:
2362 case SIS_650: 2102 case SIS_650:
2363 case SIS_740: 2103 case SIS_740:
2364 inSISIDXREG(SISSR, 0x14, reg); 2104 inSISIDXREG(SISSR, 0x14, reg);
2365 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20; 2105 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
2366 break; 2106 break;
2367 case SIS_661: 2107 case SIS_661:
2368 case SIS_741: 2108 case SIS_741:
2369 inSISIDXREG(SISCR, 0x79, reg); 2109 inSISIDXREG(SISCR, 0x79, reg);
2370 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; 2110 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2371 break; 2111 break;
2372 case SIS_660: 2112 case SIS_660:
2373 case SIS_760: 2113 case SIS_760:
2114 case SIS_761:
2374 inSISIDXREG(SISCR, 0x79, reg); 2115 inSISIDXREG(SISCR, 0x79, reg);
2375 reg = (reg & 0xf0) >> 4; 2116 reg = (reg & 0xf0) >> 4;
2376 if(reg) ivideo->video_size = (1 << reg) << 20; 2117 if(reg) {
2118 ivideo->video_size = (1 << reg) << 20;
2119 ivideo->UMAsize = ivideo->video_size;
2120 }
2377 inSISIDXREG(SISCR, 0x78, reg); 2121 inSISIDXREG(SISCR, 0x78, reg);
2378 reg &= 0x30; 2122 reg &= 0x30;
2379 if(reg) { 2123 if(reg) {
2380 if(reg == 0x10) ivideo->video_size += (32 << 20); 2124 if(reg == 0x10) {
2381 else ivideo->video_size += (64 << 20); 2125 ivideo->LFBsize = (32 << 20);
2126 } else {
2127 ivideo->LFBsize = (64 << 20);
2128 }
2129 ivideo->video_size += ivideo->LFBsize;
2382 } 2130 }
2383 break; 2131 break;
2132 case SIS_340:
2133 case XGI_20:
2134 case XGI_40:
2135 inSISIDXREG(SISSR, 0x14, reg);
2136 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2137 if(ivideo->chip != XGI_20) {
2138 reg = (reg & 0x0c) >> 2;
2139 if(ivideo->revision_id == 2) {
2140 if(reg & 0x01) reg = 0x02;
2141 else reg = 0x00;
2142 }
2143 if(reg == 0x02) ivideo->video_size <<= 1;
2144 else if(reg == 0x03) ivideo->video_size <<= 2;
2145 }
2146 break;
2384#endif 2147#endif
2385 default: 2148 default:
2386 return -1; 2149 return -1;
@@ -2390,17 +2153,24 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
2390 2153
2391/* -------------- video bridge device detection --------------- */ 2154/* -------------- video bridge device detection --------------- */
2392 2155
2393static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo) 2156static void __devinit
2157sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2394{ 2158{
2395 u8 cr32, temp; 2159 u8 cr32, temp;
2396 2160
2161 /* No CRT2 on XGI Z7 */
2162 if(ivideo->chip == XGI_20) {
2163 ivideo->sisfb_crt1off = 0;
2164 return;
2165 }
2166
2397#ifdef CONFIG_FB_SIS_300 2167#ifdef CONFIG_FB_SIS_300
2398 if(ivideo->sisvga_engine == SIS_300_VGA) { 2168 if(ivideo->sisvga_engine == SIS_300_VGA) {
2399 inSISIDXREG(SISSR, 0x17, temp); 2169 inSISIDXREG(SISSR, 0x17, temp);
2400 if((temp & 0x0F) && (ivideo->chip != SIS_300)) { 2170 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2401 /* PAL/NTSC is stored on SR16 on such machines */ 2171 /* PAL/NTSC is stored on SR16 on such machines */
2402 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) { 2172 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2403 inSISIDXREG(SISSR, 0x16, temp); 2173 inSISIDXREG(SISSR, 0x16, temp);
2404 if(temp & 0x20) 2174 if(temp & 0x20)
2405 ivideo->vbflags |= TV_PAL; 2175 ivideo->vbflags |= TV_PAL;
2406 else 2176 else
@@ -2435,28 +2205,29 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2435 2205
2436 if(ivideo->sisfb_tvplug != -1) { 2206 if(ivideo->sisfb_tvplug != -1) {
2437 if( (ivideo->sisvga_engine != SIS_315_VGA) || 2207 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2438 (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) { 2208 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2439 if(ivideo->sisfb_tvplug & TV_YPBPR) { 2209 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2440 ivideo->sisfb_tvplug = -1; 2210 ivideo->sisfb_tvplug = -1;
2441 printk(KERN_ERR "sisfb: YPbPr not supported\n"); 2211 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2442 } 2212 }
2443 } 2213 }
2444 } 2214 }
2445 if(ivideo->sisfb_tvplug != -1) { 2215 if(ivideo->sisfb_tvplug != -1) {
2446 if( (ivideo->sisvga_engine != SIS_315_VGA) || 2216 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2447 (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) { 2217 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2448 if(ivideo->sisfb_tvplug & TV_HIVISION) { 2218 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2449 ivideo->sisfb_tvplug = -1; 2219 ivideo->sisfb_tvplug = -1;
2450 printk(KERN_ERR "sisfb: HiVision not supported\n"); 2220 printk(KERN_ERR "sisfb: HiVision not supported\n");
2451 } 2221 }
2452 } 2222 }
2453 } 2223 }
2454 if(ivideo->sisfb_tvstd != -1) { 2224 if(ivideo->sisfb_tvstd != -1) {
2455 if( (!(ivideo->vbflags & VB_SISBRIDGE)) && 2225 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2456 (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) { 2226 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2227 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2457 if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) { 2228 if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
2458 ivideo->sisfb_tvstd = -1; 2229 ivideo->sisfb_tvstd = -1;
2459 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n"); 2230 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2460 } 2231 }
2461 } 2232 }
2462 } 2233 }
@@ -2468,7 +2239,7 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2468 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */ 2239 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2469 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION; 2240 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2470 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART; 2241 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2471 else { 2242 else {
2472 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO; 2243 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2473 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO; 2244 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2474 } 2245 }
@@ -2485,165 +2256,44 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2485 } 2256 }
2486 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) { 2257 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2487 if(ivideo->sisvga_engine == SIS_300_VGA) { 2258 if(ivideo->sisvga_engine == SIS_300_VGA) {
2488 inSISIDXREG(SISSR, 0x38, temp); 2259 inSISIDXREG(SISSR, 0x38, temp);
2489 if(temp & 0x01) ivideo->vbflags |= TV_PAL; 2260 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2490 else ivideo->vbflags |= TV_NTSC; 2261 else ivideo->vbflags |= TV_NTSC;
2491 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) { 2262 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2492 inSISIDXREG(SISSR, 0x38, temp); 2263 inSISIDXREG(SISSR, 0x38, temp);
2493 if(temp & 0x01) ivideo->vbflags |= TV_PAL; 2264 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2494 else ivideo->vbflags |= TV_NTSC; 2265 else ivideo->vbflags |= TV_NTSC;
2495 } else { 2266 } else {
2496 inSISIDXREG(SISCR, 0x79, temp); 2267 inSISIDXREG(SISCR, 0x79, temp);
2497 if(temp & 0x20) ivideo->vbflags |= TV_PAL; 2268 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2498 else ivideo->vbflags |= TV_NTSC; 2269 else ivideo->vbflags |= TV_NTSC;
2499 } 2270 }
2500 } 2271 }
2501 } 2272 }
2502 2273
2503 /* Copy forceCRT1 option to CRT1off if option is given */ 2274 /* Copy forceCRT1 option to CRT1off if option is given */
2504 if(ivideo->sisfb_forcecrt1 != -1) { 2275 if(ivideo->sisfb_forcecrt1 != -1) {
2505 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1; 2276 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2506 }
2507}
2508
2509static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo)
2510{
2511 char stdstr[] = "sisfb: Detected";
2512 char bridgestr[] = "video bridge";
2513 u8 vb_chipid;
2514 u8 reg;
2515
2516 inSISIDXREG(SISPART4, 0x00, vb_chipid);
2517 switch(vb_chipid) {
2518 case 0x01:
2519 inSISIDXREG(SISPART4, 0x01, reg);
2520 if(reg < 0xb0) {
2521 ivideo->vbflags |= VB_301;
2522 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2523 } else if(reg < 0xc0) {
2524 ivideo->vbflags |= VB_301B;
2525 inSISIDXREG(SISPART4,0x23,reg);
2526 if(!(reg & 0x02)) {
2527 ivideo->vbflags |= VB_30xBDH;
2528 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2529 } else {
2530 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2531 }
2532 } else if(reg < 0xd0) {
2533 ivideo->vbflags |= VB_301C;
2534 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2535 } else if(reg < 0xe0) {
2536 ivideo->vbflags |= VB_301LV;
2537 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2538 } else if(reg <= 0xe1) {
2539 inSISIDXREG(SISPART4,0x39,reg);
2540 if(reg == 0xff) {
2541 ivideo->vbflags |= VB_302LV;
2542 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2543 } else {
2544 ivideo->vbflags |= VB_301C;
2545 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2546#if 0
2547 ivideo->vbflags |= VB_302ELV;
2548 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2549#endif
2550 }
2551 }
2552 break;
2553 case 0x02:
2554 ivideo->vbflags |= VB_302B;
2555 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2556 break;
2557 }
2558
2559 if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2560 inSISIDXREG(SISCR, 0x37, reg);
2561 reg &= SIS_EXTERNAL_CHIP_MASK;
2562 reg >>= 1;
2563 if(ivideo->sisvga_engine == SIS_300_VGA) {
2564#ifdef CONFIG_FB_SIS_300
2565 switch(reg) {
2566 case SIS_EXTERNAL_CHIP_LVDS:
2567 ivideo->vbflags |= VB_LVDS;
2568 break;
2569 case SIS_EXTERNAL_CHIP_TRUMPION:
2570 ivideo->vbflags |= VB_TRUMPION;
2571 break;
2572 case SIS_EXTERNAL_CHIP_CHRONTEL:
2573 ivideo->vbflags |= VB_CHRONTEL;
2574 break;
2575 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2576 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
2577 break;
2578 }
2579 if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1;
2580#endif
2581 } else if(ivideo->chip < SIS_661) {
2582#ifdef CONFIG_FB_SIS_315
2583 switch (reg) {
2584 case SIS310_EXTERNAL_CHIP_LVDS:
2585 ivideo->vbflags |= VB_LVDS;
2586 break;
2587 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2588 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
2589 break;
2590 }
2591 if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
2592#endif
2593 } else if(ivideo->chip >= SIS_661) {
2594#ifdef CONFIG_FB_SIS_315
2595 inSISIDXREG(SISCR, 0x38, reg);
2596 reg >>= 5;
2597 switch(reg) {
2598 case 0x02:
2599 ivideo->vbflags |= VB_LVDS;
2600 break;
2601 case 0x03:
2602 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
2603 break;
2604 case 0x04:
2605 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);
2606 break;
2607 }
2608 if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
2609#endif
2610 }
2611 if(ivideo->vbflags & VB_LVDS) {
2612 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2613 }
2614 if(ivideo->vbflags & VB_TRUMPION) {
2615 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2616 }
2617 if(ivideo->vbflags & VB_CHRONTEL) {
2618 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2619 }
2620 if(ivideo->vbflags & VB_CONEXANT) {
2621 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2622 }
2623 }
2624
2625 if(ivideo->vbflags & VB_SISBRIDGE) {
2626 SiS_Sense30x(ivideo);
2627 } else if(ivideo->vbflags & VB_CHRONTEL) {
2628 SiS_SenseCh(ivideo);
2629 } 2277 }
2630} 2278}
2631 2279
2632/* ------------------ Sensing routines ------------------ */ 2280/* ------------------ Sensing routines ------------------ */
2633 2281
2634static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo) 2282static BOOLEAN __devinit
2283sisfb_test_DDC1(struct sis_video_info *ivideo)
2635{ 2284{
2636 unsigned short old; 2285 unsigned short old;
2637 int count = 48; 2286 int count = 48;
2638 2287
2639 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr); 2288 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2640 do { 2289 do {
2641 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break; 2290 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2642 } while(count--); 2291 } while(count--);
2643 return (count == -1) ? FALSE : TRUE; 2292 return (count == -1) ? FALSE : TRUE;
2644} 2293}
2645 2294
2646static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo) 2295static void __devinit
2296sisfb_sense_crt1(struct sis_video_info *ivideo)
2647{ 2297{
2648 BOOLEAN mustwait = FALSE; 2298 BOOLEAN mustwait = FALSE;
2649 u8 sr1F, cr17; 2299 u8 sr1F, cr17;
@@ -2699,7 +2349,8 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
2699 if(temp == 0xffff) { 2349 if(temp == 0xffff) {
2700 i = 3; 2350 i = 3;
2701 do { 2351 do {
2702 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL); 2352 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2353 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2703 } while(((temp == 0) || (temp == 0xffff)) && i--); 2354 } while(((temp == 0) || (temp == 0xffff)) && i--);
2704 2355
2705 if((temp == 0) || (temp == 0xffff)) { 2356 if((temp == 0) || (temp == 0xffff)) {
@@ -2723,7 +2374,96 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
2723} 2374}
2724 2375
2725/* Determine and detect attached devices on SiS30x */ 2376/* Determine and detect attached devices on SiS30x */
2726static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test) 2377static void __devinit
2378SiS_SenseLCD(struct sis_video_info *ivideo)
2379{
2380 unsigned char buffer[256];
2381 unsigned short temp, realcrtno, i;
2382 u8 reg, cr37 = 0, paneltype = 0;
2383 u16 xres, yres;
2384
2385 ivideo->SiS_Pr.PanelSelfDetected = FALSE;
2386
2387 /* LCD detection only for TMDS bridges */
2388 if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2389 return;
2390 if(ivideo->vbflags2 & VB2_30xBDH)
2391 return;
2392
2393 /* If LCD already set up by BIOS, skip it */
2394 inSISIDXREG(SISCR, 0x32, reg);
2395 if(reg & 0x08)
2396 return;
2397
2398 realcrtno = 1;
2399 if(ivideo->SiS_Pr.DDCPortMixup)
2400 realcrtno = 0;
2401
2402 /* Check DDC capabilities */
2403 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2404 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2405
2406 if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2407 return;
2408
2409 /* Read DDC data */
2410 i = 3; /* Number of retrys */
2411 do {
2412 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2413 ivideo->sisvga_engine, realcrtno, 1,
2414 &buffer[0], ivideo->vbflags2);
2415 } while((temp) && i--);
2416
2417 if(temp)
2418 return;
2419
2420 /* No digital device */
2421 if(!(buffer[0x14] & 0x80))
2422 return;
2423
2424 /* First detailed timing preferred timing? */
2425 if(!(buffer[0x18] & 0x02))
2426 return;
2427
2428 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2429 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2430
2431 switch(xres) {
2432 case 1024:
2433 if(yres == 768)
2434 paneltype = 0x02;
2435 break;
2436 case 1280:
2437 if(yres == 1024)
2438 paneltype = 0x03;
2439 break;
2440 case 1600:
2441 if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2442 paneltype = 0x0b;
2443 break;
2444 }
2445
2446 if(!paneltype)
2447 return;
2448
2449 if(buffer[0x23])
2450 cr37 |= 0x10;
2451
2452 if((buffer[0x47] & 0x18) == 0x18)
2453 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2454 else
2455 cr37 |= 0xc0;
2456
2457 outSISIDXREG(SISCR, 0x36, paneltype);
2458 cr37 &= 0xf1;
2459 setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
2460 orSISIDXREG(SISCR, 0x32, 0x08);
2461
2462 ivideo->SiS_Pr.PanelSelfDetected = TRUE;
2463}
2464
2465static int __devinit
2466SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2727{ 2467{
2728 int temp, mytest, result, i, j; 2468 int temp, mytest, result, i, j;
2729 2469
@@ -2749,10 +2489,11 @@ static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 tes
2749 } 2489 }
2750 if((result == 0) || (result >= 2)) break; 2490 if((result == 0) || (result >= 2)) break;
2751 } 2491 }
2752 return(result); 2492 return result;
2753} 2493}
2754 2494
2755static void __devinit SiS_Sense30x(struct sis_video_info *ivideo) 2495static void __devinit
2496SiS_Sense30x(struct sis_video_info *ivideo)
2756{ 2497{
2757 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0; 2498 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2758 u16 svhs=0, svhs_c=0; 2499 u16 svhs=0, svhs_c=0;
@@ -2762,36 +2503,51 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
2762 char stdstr[] = "sisfb: Detected"; 2503 char stdstr[] = "sisfb: Detected";
2763 char tvstr[] = "TV connected to"; 2504 char tvstr[] = "TV connected to";
2764 2505
2765 if(ivideo->vbflags & VB_301) { 2506 if(ivideo->vbflags2 & VB2_301) {
2766 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1; 2507 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2767 inSISIDXREG(SISPART4,0x01,myflag); 2508 inSISIDXREG(SISPART4,0x01,myflag);
2768 if(myflag & 0x04) { 2509 if(myflag & 0x04) {
2769 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd; 2510 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2770 } 2511 }
2771 } else if(ivideo->vbflags & (VB_301B | VB_302B)) { 2512 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2772 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190; 2513 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2773 } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) { 2514 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2774 svhs = 0x0200; cvbs = 0x0100; 2515 svhs = 0x0200; cvbs = 0x0100;
2775 } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) { 2516 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2776 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190; 2517 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2777 } else return; 2518 } else
2519 return;
2778 2520
2779 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804; 2521 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2780 if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) { 2522 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2781 svhs_c = 0x0408; cvbs_c = 0x0808; 2523 svhs_c = 0x0408; cvbs_c = 0x0808;
2782 } 2524 }
2525
2783 biosflag = 2; 2526 biosflag = 2;
2527 if(ivideo->haveXGIROM) {
2528 biosflag = ivideo->bios_abase[0x58] & 0x03;
2529 } else if(ivideo->newrom) {
2530 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2531 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2532 if(ivideo->bios_abase) {
2533 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2534 }
2535 }
2784 2536
2785 if(ivideo->chip == SIS_300) { 2537 if(ivideo->chip == SIS_300) {
2786 inSISIDXREG(SISSR,0x3b,myflag); 2538 inSISIDXREG(SISSR,0x3b,myflag);
2787 if(!(myflag & 0x01)) vga2 = vga2_c = 0; 2539 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2788 } 2540 }
2789 2541
2542 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2543 vga2 = vga2_c = 0;
2544 }
2545
2790 inSISIDXREG(SISSR,0x1e,backupSR_1e); 2546 inSISIDXREG(SISSR,0x1e,backupSR_1e);
2791 orSISIDXREG(SISSR,0x1e,0x20); 2547 orSISIDXREG(SISSR,0x1e,0x20);
2792 2548
2793 inSISIDXREG(SISPART4,0x0d,backupP4_0d); 2549 inSISIDXREG(SISPART4,0x0d,backupP4_0d);
2794 if(ivideo->vbflags & VB_301C) { 2550 if(ivideo->vbflags2 & VB2_30xC) {
2795 setSISIDXREG(SISPART4,0x0d,~0x07,0x01); 2551 setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
2796 } else { 2552 } else {
2797 orSISIDXREG(SISPART4,0x0d,0x04); 2553 orSISIDXREG(SISPART4,0x0d,0x04);
@@ -2802,11 +2558,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
2802 outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc)); 2558 outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
2803 2559
2804 inSISIDXREG(SISPART2,0x4d,backupP2_4d); 2560 inSISIDXREG(SISPART2,0x4d,backupP2_4d);
2805 if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) { 2561 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2806 outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10)); 2562 outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
2807 } 2563 }
2808 2564
2809 if(!(ivideo->vbflags & VB_301C)) { 2565 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2810 SISDoSense(ivideo, 0, 0); 2566 SISDoSense(ivideo, 0, 0);
2811 } 2567 }
2812 2568
@@ -2826,12 +2582,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
2826 2582
2827 andSISIDXREG(SISCR, 0x32, 0x3f); 2583 andSISIDXREG(SISCR, 0x32, 0x3f);
2828 2584
2829 if(ivideo->vbflags & VB_301C) { 2585 if(ivideo->vbflags2 & VB2_30xCLV) {
2830 orSISIDXREG(SISPART4,0x0d,0x04); 2586 orSISIDXREG(SISPART4,0x0d,0x04);
2831 } 2587 }
2832 2588
2833 if((ivideo->sisvga_engine == SIS_315_VGA) && 2589 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2834 (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) {
2835 outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10)); 2590 outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
2836 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000); 2591 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2837 if((result = SISDoSense(ivideo, svhs, 0x0604))) { 2592 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
@@ -2864,7 +2619,7 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
2864 outSISIDXREG(SISPART4,0x0d,backupP4_0d); 2619 outSISIDXREG(SISPART4,0x0d,backupP4_0d);
2865 outSISIDXREG(SISSR,0x1e,backupSR_1e); 2620 outSISIDXREG(SISSR,0x1e,backupSR_1e);
2866 2621
2867 if(ivideo->vbflags & VB_301C) { 2622 if(ivideo->vbflags2 & VB2_30xCLV) {
2868 inSISIDXREG(SISPART2,0x00,biosflag); 2623 inSISIDXREG(SISPART2,0x00,biosflag);
2869 if(biosflag & 0x20) { 2624 if(biosflag & 0x20) {
2870 for(myflag = 2; myflag > 0; myflag--) { 2625 for(myflag = 2; myflag > 0; myflag--) {
@@ -2878,7 +2633,8 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
2878} 2633}
2879 2634
2880/* Determine and detect attached TV's on Chrontel */ 2635/* Determine and detect attached TV's on Chrontel */
2881static void __devinit SiS_SenseCh(struct sis_video_info *ivideo) 2636static void __devinit
2637SiS_SenseCh(struct sis_video_info *ivideo)
2882{ 2638{
2883#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) 2639#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2884 u8 temp1, temp2; 2640 u8 temp1, temp2;
@@ -2899,7 +2655,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
2899 /* See Chrontel TB31 for explanation */ 2655 /* See Chrontel TB31 for explanation */
2900 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); 2656 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2901 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) { 2657 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2902 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e); 2658 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2903 SiS_DDC2Delay(&ivideo->SiS_Pr, 300); 2659 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2904 } 2660 }
2905 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25); 2661 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
@@ -2909,15 +2665,15 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
2909 /* Read power status */ 2665 /* Read power status */
2910 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e); 2666 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2911 if((temp1 & 0x03) != 0x03) { 2667 if((temp1 & 0x03) != 0x03) {
2912 /* Power all outputs */ 2668 /* Power all outputs */
2913 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E); 2669 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2914 SiS_DDC2Delay(&ivideo->SiS_Pr, 300); 2670 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2915 } 2671 }
2916 /* Sense connected TV devices */ 2672 /* Sense connected TV devices */
2917 for(i = 0; i < 3; i++) { 2673 for(i = 0; i < 3; i++) {
2918 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110); 2674 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2919 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2675 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2920 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010); 2676 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2921 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2677 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2922 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10); 2678 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2923 if(!(temp1 & 0x08)) test[i] = 0x02; 2679 if(!(temp1 & 0x08)) test[i] = 0x02;
@@ -2930,7 +2686,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
2930 else if(test[0] == test[2]) temp1 = test[0]; 2686 else if(test[0] == test[2]) temp1 = test[0];
2931 else if(test[1] == test[2]) temp1 = test[1]; 2687 else if(test[1] == test[2]) temp1 = test[1];
2932 else { 2688 else {
2933 printk(KERN_INFO 2689 printk(KERN_INFO
2934 "sisfb: TV detection unreliable - test results varied\n"); 2690 "sisfb: TV detection unreliable - test results varied\n");
2935 temp1 = test[2]; 2691 temp1 = test[2];
2936 } 2692 }
@@ -2945,11 +2701,11 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
2945 orSISIDXREG(SISCR, 0x32, 0x01); 2701 orSISIDXREG(SISCR, 0x32, 0x01);
2946 andSISIDXREG(SISCR, 0x32, ~0x06); 2702 andSISIDXREG(SISCR, 0x32, ~0x06);
2947 } else { 2703 } else {
2948 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8); 2704 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2949 andSISIDXREG(SISCR, 0x32, ~0x07); 2705 andSISIDXREG(SISCR, 0x32, ~0x07);
2950 } 2706 }
2951 } else if(temp1 == 0) { 2707 } else if(temp1 == 0) {
2952 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8); 2708 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2953 andSISIDXREG(SISCR, 0x32, ~0x07); 2709 andSISIDXREG(SISCR, 0x32, ~0x07);
2954 } 2710 }
2955 /* Set general purpose IO for Chrontel communication */ 2711 /* Set general purpose IO for Chrontel communication */
@@ -2960,19 +2716,19 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
2960 2716
2961#ifdef CONFIG_FB_SIS_315 2717#ifdef CONFIG_FB_SIS_315
2962 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */ 2718 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2963 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49); 2719 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2964 SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049); 2720 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2965 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2721 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2966 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); 2722 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2967 temp2 |= 0x01; 2723 temp2 |= 0x01;
2968 SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20); 2724 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2969 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2725 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2970 temp2 ^= 0x01; 2726 temp2 ^= 0x01;
2971 SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20); 2727 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2972 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96); 2728 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2973 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20); 2729 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2974 SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49); 2730 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2975 temp1 = 0; 2731 temp1 = 0;
2976 if(temp2 & 0x02) temp1 |= 0x01; 2732 if(temp2 & 0x02) temp1 |= 0x01;
2977 if(temp2 & 0x10) temp1 |= 0x01; 2733 if(temp2 & 0x10) temp1 |= 0x01;
2978 if(temp2 & 0x04) temp1 |= 0x02; 2734 if(temp2 & 0x04) temp1 |= 0x02;
@@ -2983,18 +2739,18 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
2983 ivideo->vbflags |= TV_AVIDEO; 2739 ivideo->vbflags |= TV_AVIDEO;
2984 orSISIDXREG(SISCR, 0x32, 0x01); 2740 orSISIDXREG(SISCR, 0x32, 0x01);
2985 andSISIDXREG(SISCR, 0x32, ~0x06); 2741 andSISIDXREG(SISCR, 0x32, ~0x06);
2986 break; 2742 break;
2987 case 0x02: 2743 case 0x02:
2988 printk(KERN_INFO "%s SVIDEO output\n", stdstr); 2744 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2989 ivideo->vbflags |= TV_SVIDEO; 2745 ivideo->vbflags |= TV_SVIDEO;
2990 orSISIDXREG(SISCR, 0x32, 0x02); 2746 orSISIDXREG(SISCR, 0x32, 0x02);
2991 andSISIDXREG(SISCR, 0x32, ~0x05); 2747 andSISIDXREG(SISCR, 0x32, ~0x05);
2992 break; 2748 break;
2993 case 0x04: 2749 case 0x04:
2994 printk(KERN_INFO "%s SCART output\n", stdstr); 2750 printk(KERN_INFO "%s SCART output\n", stdstr);
2995 orSISIDXREG(SISCR, 0x32, 0x04); 2751 orSISIDXREG(SISCR, 0x32, 0x04);
2996 andSISIDXREG(SISCR, 0x32, ~0x03); 2752 andSISIDXREG(SISCR, 0x32, ~0x03);
2997 break; 2753 break;
2998 default: 2754 default:
2999 andSISIDXREG(SISCR, 0x32, ~0x07); 2755 andSISIDXREG(SISCR, 0x32, ~0x07);
3000 } 2756 }
@@ -3002,165 +2758,589 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
3002 } 2758 }
3003} 2759}
3004 2760
3005/* ------------------------ Heap routines -------------------------- */ 2761static void __devinit
3006 2762sisfb_get_VB_type(struct sis_video_info *ivideo)
3007static u32 __devinit
3008sisfb_getheapstart(struct sis_video_info *ivideo)
3009{ 2763{
3010 u32 ret = ivideo->sisfb_parm_mem * 1024; 2764 char stdstr[] = "sisfb: Detected";
3011 u32 max = ivideo->video_size - ivideo->hwcursor_size; 2765 char bridgestr[] = "video bridge";
3012 u32 def; 2766 u8 vb_chipid;
2767 u8 reg;
3013 2768
3014 /* Calculate heap start = end of memory for console 2769 /* No CRT2 on XGI Z7 */
3015 * 2770 if(ivideo->chip == XGI_20)
3016 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ 2771 return;
3017 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3018 *
3019 * Basically given by "mem" parameter
3020 *
3021 * maximum = videosize - cmd_queue - hwcursor
3022 * (results in a heap of size 0)
3023 * default = SiS 300: depends on videosize
3024 * SiS 315/330: 32k below max
3025 */
3026 2772
3027 if(ivideo->sisvga_engine == SIS_300_VGA) { 2773 inSISIDXREG(SISPART4, 0x00, vb_chipid);
3028 max -= TURBO_QUEUE_AREA_SIZE; 2774 switch(vb_chipid) {
3029 if(ivideo->video_size > 0x1000000) { 2775 case 0x01:
3030 def = 0xc00000; 2776 inSISIDXREG(SISPART4, 0x01, reg);
3031 } else if(ivideo->video_size > 0x800000) { 2777 if(reg < 0xb0) {
3032 def = 0x800000; 2778 ivideo->vbflags |= VB_301; /* Deprecated */
3033 } else { 2779 ivideo->vbflags2 |= VB2_301;
3034 def = 0x400000; 2780 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
3035 } 2781 } else if(reg < 0xc0) {
3036 } else { 2782 ivideo->vbflags |= VB_301B; /* Deprecated */
3037 max -= COMMAND_QUEUE_AREA_SIZE; 2783 ivideo->vbflags2 |= VB2_301B;
3038 def = max - 0x8000; 2784 inSISIDXREG(SISPART4,0x23,reg);
2785 if(!(reg & 0x02)) {
2786 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2787 ivideo->vbflags2 |= VB2_30xBDH;
2788 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2789 } else {
2790 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2791 }
2792 } else if(reg < 0xd0) {
2793 ivideo->vbflags |= VB_301C; /* Deprecated */
2794 ivideo->vbflags2 |= VB2_301C;
2795 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2796 } else if(reg < 0xe0) {
2797 ivideo->vbflags |= VB_301LV; /* Deprecated */
2798 ivideo->vbflags2 |= VB2_301LV;
2799 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2800 } else if(reg <= 0xe1) {
2801 inSISIDXREG(SISPART4,0x39,reg);
2802 if(reg == 0xff) {
2803 ivideo->vbflags |= VB_302LV; /* Deprecated */
2804 ivideo->vbflags2 |= VB2_302LV;
2805 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2806 } else {
2807 ivideo->vbflags |= VB_301C; /* Deprecated */
2808 ivideo->vbflags2 |= VB2_301C;
2809 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2810#if 0
2811 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2812 ivideo->vbflags2 |= VB2_302ELV;
2813 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2814#endif
2815 }
2816 }
2817 break;
2818 case 0x02:
2819 ivideo->vbflags |= VB_302B; /* Deprecated */
2820 ivideo->vbflags2 |= VB2_302B;
2821 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2822 break;
3039 } 2823 }
3040 2824
3041 if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) { 2825 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
3042 ret = def; 2826 inSISIDXREG(SISCR, 0x37, reg);
3043 } 2827 reg &= SIS_EXTERNAL_CHIP_MASK;
2828 reg >>= 1;
2829 if(ivideo->sisvga_engine == SIS_300_VGA) {
2830#ifdef CONFIG_FB_SIS_300
2831 switch(reg) {
2832 case SIS_EXTERNAL_CHIP_LVDS:
2833 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2834 ivideo->vbflags2 |= VB2_LVDS;
2835 break;
2836 case SIS_EXTERNAL_CHIP_TRUMPION:
2837 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2838 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2839 break;
2840 case SIS_EXTERNAL_CHIP_CHRONTEL:
2841 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2842 ivideo->vbflags2 |= VB2_CHRONTEL;
2843 break;
2844 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2845 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2846 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2847 break;
2848 }
2849 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2850#endif
2851 } else if(ivideo->chip < SIS_661) {
2852#ifdef CONFIG_FB_SIS_315
2853 switch (reg) {
2854 case SIS310_EXTERNAL_CHIP_LVDS:
2855 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2856 ivideo->vbflags2 |= VB2_LVDS;
2857 break;
2858 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2859 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2860 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2861 break;
2862 }
2863 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2864#endif
2865 } else if(ivideo->chip >= SIS_661) {
2866#ifdef CONFIG_FB_SIS_315
2867 inSISIDXREG(SISCR, 0x38, reg);
2868 reg >>= 5;
2869 switch(reg) {
2870 case 0x02:
2871 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2872 ivideo->vbflags2 |= VB2_LVDS;
2873 break;
2874 case 0x03:
2875 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2876 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2877 break;
2878 case 0x04:
2879 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2880 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2881 break;
2882 }
2883 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2884#endif
2885 }
2886 if(ivideo->vbflags2 & VB2_LVDS) {
2887 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2888 }
2889 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2890 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2891 }
2892 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2893 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2894 }
2895 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2896 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2897 }
2898 }
3044 2899
3045 return ret; 2900 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2901 SiS_SenseLCD(ivideo);
2902 SiS_Sense30x(ivideo);
2903 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2904 SiS_SenseCh(ivideo);
2905 }
3046} 2906}
3047 2907
3048static int __devinit 2908/* ---------- Engine initialization routines ------------ */
3049sisfb_heap_init(struct sis_video_info *ivideo) 2909
2910static void
2911sisfb_engine_init(struct sis_video_info *ivideo)
3050{ 2912{
3051 SIS_OH *poh;
3052 2913
3053 ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo); 2914 /* Initialize command queue (we use MMIO only) */
3054 2915
3055 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart; 2916 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
3056 ivideo->sisfb_heap_end = ivideo->video_vbase + ivideo->video_size;
3057 2917
3058 /* Initialize command queue (We use MMIO only) */ 2918 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2919 MMIO_CMD_QUEUE_CAP |
2920 VM_CMD_QUEUE_CAP |
2921 AGP_CMD_QUEUE_CAP);
2922
2923#ifdef CONFIG_FB_SIS_300
2924 if(ivideo->sisvga_engine == SIS_300_VGA) {
2925 u32 tqueue_pos;
2926 u8 tq_state;
2927
2928 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2929
2930 inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2931 tq_state |= 0xf0;
2932 tq_state &= 0xfc;
2933 tq_state |= (u8)(tqueue_pos >> 8);
2934 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2935
2936 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2937
2938 ivideo->caps |= TURBO_QUEUE_CAP;
2939 }
2940#endif
3059 2941
3060#ifdef CONFIG_FB_SIS_315 2942#ifdef CONFIG_FB_SIS_315
3061 if(ivideo->sisvga_engine == SIS_315_VGA) { 2943 if(ivideo->sisvga_engine == SIS_315_VGA) {
3062 u32 tempq = 0; 2944 u32 tempq = 0, templ;
3063 u8 temp = 0; 2945 u8 temp;
2946
2947 if(ivideo->chip == XGI_20) {
2948 switch(ivideo->cmdQueueSize) {
2949 case (64 * 1024):
2950 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2951 break;
2952 case (128 * 1024):
2953 default:
2954 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2955 }
2956 } else {
2957 switch(ivideo->cmdQueueSize) {
2958 case (4 * 1024 * 1024):
2959 temp = SIS_CMD_QUEUE_SIZE_4M;
2960 break;
2961 case (2 * 1024 * 1024):
2962 temp = SIS_CMD_QUEUE_SIZE_2M;
2963 break;
2964 case (1 * 1024 * 1024):
2965 temp = SIS_CMD_QUEUE_SIZE_1M;
2966 break;
2967 default:
2968 case (512 * 1024):
2969 temp = SIS_CMD_QUEUE_SIZE_512k;
2970 }
2971 }
2972
2973 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2974 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2975
2976 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2977 /* Must disable dual pipe on XGI_40. Can't do
2978 * this in MMIO mode, because it requires
2979 * setting/clearing a bit in the MMIO fire trigger
2980 * register.
2981 */
2982 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2983
2984 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2985
2986 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2987
2988 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2989 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2990
2991 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2992 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2993
2994 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2995 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2996 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2997 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2998
2999 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
3000
3001 sisfb_syncaccel(ivideo);
3002
3003 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
3004
3005 }
3006 }
3007
3008 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
3009 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
3010
3011 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
3012 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
3013
3014 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
3015 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
3064 3016
3065 ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; 3017 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
3018 }
3019#endif
3066 3020
3067 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); 3021 ivideo->engineok = 1;
3068 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET); 3022}
3069 3023
3070 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT); 3024static void __devinit
3071 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq); 3025sisfb_detect_lcd_type(struct sis_video_info *ivideo)
3026{
3027 u8 reg;
3028 int i;
3072 3029
3073 temp = SIS_CMD_QUEUE_SIZE_512k; 3030 inSISIDXREG(SISCR, 0x36, reg);
3074 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR); 3031 reg &= 0x0f;
3075 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp); 3032 if(ivideo->sisvga_engine == SIS_300_VGA) {
3033 ivideo->CRT2LCDType = sis300paneltype[reg];
3034 } else if(ivideo->chip >= SIS_661) {
3035 ivideo->CRT2LCDType = sis661paneltype[reg];
3036 } else {
3037 ivideo->CRT2LCDType = sis310paneltype[reg];
3038 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
3039 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
3040 (ivideo->CRT2LCDType != LCD_320x240_3)) {
3041 ivideo->CRT2LCDType = LCD_320x240;
3042 }
3043 }
3044 }
3076 3045
3077 tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE); 3046 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
3078 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq); 3047 /* For broken BIOSes: Assume 1024x768, RGB18 */
3048 ivideo->CRT2LCDType = LCD_1024x768;
3049 setSISIDXREG(SISCR,0x36,0xf0,0x02);
3050 setSISIDXREG(SISCR,0x37,0xee,0x01);
3051 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
3052 }
3079 3053
3080 ivideo->caps |= MMIO_CMD_QUEUE_CAP; 3054 for(i = 0; i < SIS_LCD_NUMBER; i++) {
3081 } 3055 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
3056 ivideo->lcdxres = sis_lcd_data[i].xres;
3057 ivideo->lcdyres = sis_lcd_data[i].yres;
3058 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
3059 break;
3060 }
3061 }
3062
3063#ifdef CONFIG_FB_SIS_300
3064 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
3065 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
3066 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
3067 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
3068 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
3069 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
3070 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
3071 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
3072 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
3073 }
3082#endif 3074#endif
3083 3075
3076 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
3077 ivideo->lcdxres, ivideo->lcdyres);
3078}
3079
3080static void __devinit
3081sisfb_save_pdc_emi(struct sis_video_info *ivideo)
3082{
3084#ifdef CONFIG_FB_SIS_300 3083#ifdef CONFIG_FB_SIS_300
3085 if(ivideo->sisvga_engine == SIS_300_VGA) { 3084 /* Save the current PanelDelayCompensation if the LCD is currently used */
3086 unsigned long tqueue_pos; 3085 if(ivideo->sisvga_engine == SIS_300_VGA) {
3087 u8 tq_state; 3086 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
3087 int tmp;
3088 inSISIDXREG(SISCR,0x30,tmp);
3089 if(tmp & 0x20) {
3090 /* Currently on LCD? If yes, read current pdc */
3091 inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
3092 ivideo->detectedpdc &= 0x3c;
3093 if(ivideo->SiS_Pr.PDC == -1) {
3094 /* Let option override detection */
3095 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3096 }
3097 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
3098 ivideo->detectedpdc);
3099 }
3100 if((ivideo->SiS_Pr.PDC != -1) &&
3101 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3102 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
3103 ivideo->SiS_Pr.PDC);
3104 }
3105 }
3106 }
3107#endif
3088 3108
3089 ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE; 3109#ifdef CONFIG_FB_SIS_315
3110 if(ivideo->sisvga_engine == SIS_315_VGA) {
3090 3111
3091 tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024); 3112 /* Try to find about LCDA */
3113 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3114 int tmp;
3115 inSISIDXREG(SISPART1,0x13,tmp);
3116 if(tmp & 0x04) {
3117 ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
3118 ivideo->detectedlcda = 0x03;
3119 }
3120 }
3092 3121
3093 inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); 3122 /* Save PDC */
3094 tq_state |= 0xf0; 3123 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3095 tq_state &= 0xfc; 3124 int tmp;
3096 tq_state |= (u8)(tqueue_pos >> 8); 3125 inSISIDXREG(SISCR,0x30,tmp);
3097 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state); 3126 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3127 /* Currently on LCD? If yes, read current pdc */
3128 u8 pdc;
3129 inSISIDXREG(SISPART1,0x2D,pdc);
3130 ivideo->detectedpdc = (pdc & 0x0f) << 1;
3131 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3132 inSISIDXREG(SISPART1,0x35,pdc);
3133 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3134 inSISIDXREG(SISPART1,0x20,pdc);
3135 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3136 if(ivideo->newrom) {
3137 /* New ROM invalidates other PDC resp. */
3138 if(ivideo->detectedlcda != 0xff) {
3139 ivideo->detectedpdc = 0xff;
3140 } else {
3141 ivideo->detectedpdca = 0xff;
3142 }
3143 }
3144 if(ivideo->SiS_Pr.PDC == -1) {
3145 if(ivideo->detectedpdc != 0xff) {
3146 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3147 }
3148 }
3149 if(ivideo->SiS_Pr.PDCA == -1) {
3150 if(ivideo->detectedpdca != 0xff) {
3151 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3152 }
3153 }
3154 if(ivideo->detectedpdc != 0xff) {
3155 printk(KERN_INFO
3156 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3157 ivideo->detectedpdc);
3158 }
3159 if(ivideo->detectedpdca != 0xff) {
3160 printk(KERN_INFO
3161 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3162 ivideo->detectedpdca);
3163 }
3164 }
3098 3165
3099 outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff)); 3166 /* Save EMI */
3167 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3168 inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
3169 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
3170 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
3171 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
3172 ivideo->SiS_Pr.HaveEMI = TRUE;
3173 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3174 ivideo->SiS_Pr.HaveEMILCD = TRUE;
3175 }
3176 }
3177 }
3100 3178
3101 ivideo->caps |= TURBO_QUEUE_CAP; 3179 /* Let user override detected PDCs (all bridges) */
3102 } 3180 if(ivideo->vbflags2 & VB2_30xBLV) {
3181 if((ivideo->SiS_Pr.PDC != -1) &&
3182 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3183 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3184 ivideo->SiS_Pr.PDC);
3185 }
3186 if((ivideo->SiS_Pr.PDCA != -1) &&
3187 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3188 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3189 ivideo->SiS_Pr.PDCA);
3190 }
3191 }
3192
3193 }
3103#endif 3194#endif
3195}
3104 3196
3105 /* Reserve memory for the HWCursor */ 3197/* -------------------- Memory manager routines ---------------------- */
3106 ivideo->sisfb_heap_end -= ivideo->hwcursor_size;
3107 ivideo->hwcursor_vbase = ivideo->sisfb_heap_end;
3108 ivideo->caps |= HW_CURSOR_CAP;
3109 3198
3110 ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start; 3199static u32 __devinit
3200sisfb_getheapstart(struct sis_video_info *ivideo)
3201{
3202 u32 ret = ivideo->sisfb_parm_mem * 1024;
3203 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3204 u32 def;
3111 3205
3112 if(ivideo->cardnumber == 0) { 3206 /* Calculate heap start = end of memory for console
3207 *
3208 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3209 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3210 *
3211 * On 76x in UMA+LFB mode, the layout is as follows:
3212 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3213 * where the heap is the entire UMA area, eventually
3214 * into the LFB area if the given mem parameter is
3215 * higher than the size of the UMA memory.
3216 *
3217 * Basically given by "mem" parameter
3218 *
3219 * maximum = videosize - cmd_queue - hwcursor
3220 * (results in a heap of size 0)
3221 * default = SiS 300: depends on videosize
3222 * SiS 315/330/340/XGI: 32k below max
3223 */
3113 3224
3114 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n", 3225 if(ivideo->sisvga_engine == SIS_300_VGA) {
3115 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024)); 3226 if(ivideo->video_size > 0x1000000) {
3227 def = 0xc00000;
3228 } else if(ivideo->video_size > 0x800000) {
3229 def = 0x800000;
3230 } else {
3231 def = 0x400000;
3232 }
3233 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3234 ret = def = 0;
3235 } else {
3236 def = maxoffs - 0x8000;
3237 }
3116 3238
3117 sisfb_heap.vinfo = ivideo; 3239 /* Use default for secondary card for now (FIXME) */
3240 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3241 ret = def;
3118 3242
3119 sisfb_heap.poha_chain = NULL; 3243 return ret;
3120 sisfb_heap.poh_freelist = NULL; 3244}
3121 3245
3122 poh = sisfb_poh_new_node(); 3246static u32 __devinit
3123 if(poh == NULL) return 1; 3247sisfb_getheapsize(struct sis_video_info *ivideo)
3248{
3249 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3250 u32 ret = 0;
3251
3252 if(ivideo->UMAsize && ivideo->LFBsize) {
3253 if( (!ivideo->sisfb_parm_mem) ||
3254 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3255 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3256 ret = ivideo->UMAsize;
3257 max -= ivideo->UMAsize;
3258 } else {
3259 ret = max - (ivideo->sisfb_parm_mem * 1024);
3260 max = ivideo->sisfb_parm_mem * 1024;
3261 }
3262 ivideo->video_offset = ret;
3263 ivideo->sisfb_mem = max;
3264 } else {
3265 ret = max - ivideo->heapstart;
3266 ivideo->sisfb_mem = ivideo->heapstart;
3267 }
3124 3268
3125 poh->poh_next = &sisfb_heap.oh_free; 3269 return ret;
3126 poh->poh_prev = &sisfb_heap.oh_free; 3270}
3127 poh->size = ivideo->sisfb_heap_size;
3128 poh->offset = ivideo->heapstart;
3129 3271
3130 sisfb_heap.oh_free.poh_next = poh; 3272static int __devinit
3131 sisfb_heap.oh_free.poh_prev = poh; 3273sisfb_heap_init(struct sis_video_info *ivideo)
3132 sisfb_heap.oh_free.size = 0; 3274{
3133 sisfb_heap.max_freesize = poh->size; 3275 struct SIS_OH *poh;
3134 3276
3135 sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used; 3277 ivideo->video_offset = 0;
3136 sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used; 3278 if(ivideo->sisfb_parm_mem) {
3137 sisfb_heap.oh_used.size = SENTINEL; 3279 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3280 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3281 ivideo->sisfb_parm_mem = 0;
3282 }
3283 }
3138 3284
3139 } else { 3285 ivideo->heapstart = sisfb_getheapstart(ivideo);
3286 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3140 3287
3141 printk(KERN_INFO "Skipped heap initialization for secondary cards\n"); 3288 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3289 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3142 3290
3143 } 3291 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3292 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3144 3293
3145 return 0; 3294 ivideo->sisfb_heap.vinfo = ivideo;
3295
3296 ivideo->sisfb_heap.poha_chain = NULL;
3297 ivideo->sisfb_heap.poh_freelist = NULL;
3298
3299 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3300 if(poh == NULL)
3301 return 1;
3302
3303 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3304 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3305 poh->size = ivideo->sisfb_heap_size;
3306 poh->offset = ivideo->heapstart;
3307
3308 ivideo->sisfb_heap.oh_free.poh_next = poh;
3309 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3310 ivideo->sisfb_heap.oh_free.size = 0;
3311 ivideo->sisfb_heap.max_freesize = poh->size;
3312
3313 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3314 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3315 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3316
3317 if(ivideo->cardnumber == 0) {
3318 /* For the first card, make this heap the "global" one
3319 * for old DRM (which could handle only one card)
3320 */
3321 sisfb_heap = &ivideo->sisfb_heap;
3322 }
3323
3324 return 0;
3146} 3325}
3147 3326
3148static SIS_OH * 3327static struct SIS_OH *
3149sisfb_poh_new_node(void) 3328sisfb_poh_new_node(struct SIS_HEAP *memheap)
3150{ 3329{
3151 int i; 3330 struct SIS_OHALLOC *poha;
3152 unsigned long cOhs; 3331 struct SIS_OH *poh;
3153 SIS_OHALLOC *poha; 3332 unsigned long cOhs;
3154 SIS_OH *poh; 3333 int i;
3155 3334
3156 if(sisfb_heap.poh_freelist == NULL) { 3335 if(memheap->poh_freelist == NULL) {
3157 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL); 3336 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3158 if(!poha) return NULL; 3337 if(!poha)
3338 return NULL;
3159 3339
3160 poha->poha_next = sisfb_heap.poha_chain; 3340 poha->poha_next = memheap->poha_chain;
3161 sisfb_heap.poha_chain = poha; 3341 memheap->poha_chain = poha;
3162 3342
3163 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1; 3343 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3164 3344
3165 poh = &poha->aoh[0]; 3345 poh = &poha->aoh[0];
3166 for(i = cOhs - 1; i != 0; i--) { 3346 for(i = cOhs - 1; i != 0; i--) {
@@ -3169,32 +3349,32 @@ sisfb_poh_new_node(void)
3169 } 3349 }
3170 3350
3171 poh->poh_next = NULL; 3351 poh->poh_next = NULL;
3172 sisfb_heap.poh_freelist = &poha->aoh[0]; 3352 memheap->poh_freelist = &poha->aoh[0];
3173 } 3353 }
3174 3354
3175 poh = sisfb_heap.poh_freelist; 3355 poh = memheap->poh_freelist;
3176 sisfb_heap.poh_freelist = poh->poh_next; 3356 memheap->poh_freelist = poh->poh_next;
3177 3357
3178 return (poh); 3358 return poh;
3179} 3359}
3180 3360
3181static SIS_OH * 3361static struct SIS_OH *
3182sisfb_poh_allocate(u32 size) 3362sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3183{ 3363{
3184 SIS_OH *pohThis; 3364 struct SIS_OH *pohThis;
3185 SIS_OH *pohRoot; 3365 struct SIS_OH *pohRoot;
3186 int bAllocated = 0; 3366 int bAllocated = 0;
3187 3367
3188 if(size > sisfb_heap.max_freesize) { 3368 if(size > memheap->max_freesize) {
3189 DPRINTK("sisfb: Can't allocate %dk video memory\n", 3369 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3190 (unsigned int) size / 1024); 3370 (unsigned int) size / 1024);
3191 return (NULL); 3371 return NULL;
3192 } 3372 }
3193 3373
3194 pohThis = sisfb_heap.oh_free.poh_next; 3374 pohThis = memheap->oh_free.poh_next;
3195 3375
3196 while(pohThis != &sisfb_heap.oh_free) { 3376 while(pohThis != &memheap->oh_free) {
3197 if (size <= pohThis->size) { 3377 if(size <= pohThis->size) {
3198 bAllocated = 1; 3378 bAllocated = 1;
3199 break; 3379 break;
3200 } 3380 }
@@ -3204,18 +3384,16 @@ sisfb_poh_allocate(u32 size)
3204 if(!bAllocated) { 3384 if(!bAllocated) {
3205 DPRINTK("sisfb: Can't allocate %dk video memory\n", 3385 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3206 (unsigned int) size / 1024); 3386 (unsigned int) size / 1024);
3207 return (NULL); 3387 return NULL;
3208 } 3388 }
3209 3389
3210 if(size == pohThis->size) { 3390 if(size == pohThis->size) {
3211 pohRoot = pohThis; 3391 pohRoot = pohThis;
3212 sisfb_delete_node(pohThis); 3392 sisfb_delete_node(pohThis);
3213 } else { 3393 } else {
3214 pohRoot = sisfb_poh_new_node(); 3394 pohRoot = sisfb_poh_new_node(memheap);
3215 3395 if(pohRoot == NULL)
3216 if(pohRoot == NULL) { 3396 return NULL;
3217 return (NULL);
3218 }
3219 3397
3220 pohRoot->offset = pohThis->offset; 3398 pohRoot->offset = pohThis->offset;
3221 pohRoot->size = size; 3399 pohRoot->size = size;
@@ -3224,33 +3402,25 @@ sisfb_poh_allocate(u32 size)
3224 pohThis->size -= size; 3402 pohThis->size -= size;
3225 } 3403 }
3226 3404
3227 sisfb_heap.max_freesize -= size; 3405 memheap->max_freesize -= size;
3228 3406
3229 pohThis = &sisfb_heap.oh_used; 3407 pohThis = &memheap->oh_used;
3230 sisfb_insert_node(pohThis, pohRoot); 3408 sisfb_insert_node(pohThis, pohRoot);
3231 3409
3232 return (pohRoot); 3410 return pohRoot;
3233} 3411}
3234 3412
3235static void 3413static void
3236sisfb_delete_node(SIS_OH *poh) 3414sisfb_delete_node(struct SIS_OH *poh)
3237{ 3415{
3238 SIS_OH *poh_prev; 3416 poh->poh_prev->poh_next = poh->poh_next;
3239 SIS_OH *poh_next; 3417 poh->poh_next->poh_prev = poh->poh_prev;
3240
3241 poh_prev = poh->poh_prev;
3242 poh_next = poh->poh_next;
3243
3244 poh_prev->poh_next = poh_next;
3245 poh_next->poh_prev = poh_prev;
3246} 3418}
3247 3419
3248static void 3420static void
3249sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh) 3421sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3250{ 3422{
3251 SIS_OH *pohTemp; 3423 struct SIS_OH *pohTemp = pohList->poh_next;
3252
3253 pohTemp = pohList->poh_next;
3254 3424
3255 pohList->poh_next = poh; 3425 pohList->poh_next = poh;
3256 pohTemp->poh_prev = poh; 3426 pohTemp->poh_prev = poh;
@@ -3259,20 +3429,20 @@ sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
3259 poh->poh_next = pohTemp; 3429 poh->poh_next = pohTemp;
3260} 3430}
3261 3431
3262static SIS_OH * 3432static struct SIS_OH *
3263sisfb_poh_free(u32 base) 3433sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3264{ 3434{
3265 SIS_OH *pohThis; 3435 struct SIS_OH *pohThis;
3266 SIS_OH *poh_freed; 3436 struct SIS_OH *poh_freed;
3267 SIS_OH *poh_prev; 3437 struct SIS_OH *poh_prev;
3268 SIS_OH *poh_next; 3438 struct SIS_OH *poh_next;
3269 u32 ulUpper; 3439 u32 ulUpper;
3270 u32 ulLower; 3440 u32 ulLower;
3271 int foundNode = 0; 3441 int foundNode = 0;
3272 3442
3273 poh_freed = sisfb_heap.oh_used.poh_next; 3443 poh_freed = memheap->oh_used.poh_next;
3274 3444
3275 while(poh_freed != &sisfb_heap.oh_used) { 3445 while(poh_freed != &memheap->oh_used) {
3276 if(poh_freed->offset == base) { 3446 if(poh_freed->offset == base) {
3277 foundNode = 1; 3447 foundNode = 1;
3278 break; 3448 break;
@@ -3281,17 +3451,18 @@ sisfb_poh_free(u32 base)
3281 poh_freed = poh_freed->poh_next; 3451 poh_freed = poh_freed->poh_next;
3282 } 3452 }
3283 3453
3284 if(!foundNode) return(NULL); 3454 if(!foundNode)
3455 return NULL;
3285 3456
3286 sisfb_heap.max_freesize += poh_freed->size; 3457 memheap->max_freesize += poh_freed->size;
3287 3458
3288 poh_prev = poh_next = NULL; 3459 poh_prev = poh_next = NULL;
3289 ulUpper = poh_freed->offset + poh_freed->size; 3460 ulUpper = poh_freed->offset + poh_freed->size;
3290 ulLower = poh_freed->offset; 3461 ulLower = poh_freed->offset;
3291 3462
3292 pohThis = sisfb_heap.oh_free.poh_next; 3463 pohThis = memheap->oh_free.poh_next;
3293 3464
3294 while(pohThis != &sisfb_heap.oh_free) { 3465 while(pohThis != &memheap->oh_free) {
3295 if(pohThis->offset == ulUpper) { 3466 if(pohThis->offset == ulUpper) {
3296 poh_next = pohThis; 3467 poh_next = pohThis;
3297 } else if((pohThis->offset + pohThis->size) == ulLower) { 3468 } else if((pohThis->offset + pohThis->size) == ulLower) {
@@ -3305,70 +3476,88 @@ sisfb_poh_free(u32 base)
3305 if(poh_prev && poh_next) { 3476 if(poh_prev && poh_next) {
3306 poh_prev->size += (poh_freed->size + poh_next->size); 3477 poh_prev->size += (poh_freed->size + poh_next->size);
3307 sisfb_delete_node(poh_next); 3478 sisfb_delete_node(poh_next);
3308 sisfb_free_node(poh_freed); 3479 sisfb_free_node(memheap, poh_freed);
3309 sisfb_free_node(poh_next); 3480 sisfb_free_node(memheap, poh_next);
3310 return(poh_prev); 3481 return poh_prev;
3311 } 3482 }
3312 3483
3313 if(poh_prev) { 3484 if(poh_prev) {
3314 poh_prev->size += poh_freed->size; 3485 poh_prev->size += poh_freed->size;
3315 sisfb_free_node(poh_freed); 3486 sisfb_free_node(memheap, poh_freed);
3316 return(poh_prev); 3487 return poh_prev;
3317 } 3488 }
3318 3489
3319 if(poh_next) { 3490 if(poh_next) {
3320 poh_next->size += poh_freed->size; 3491 poh_next->size += poh_freed->size;
3321 poh_next->offset = poh_freed->offset; 3492 poh_next->offset = poh_freed->offset;
3322 sisfb_free_node(poh_freed); 3493 sisfb_free_node(memheap, poh_freed);
3323 return(poh_next); 3494 return poh_next;
3324 } 3495 }
3325 3496
3326 sisfb_insert_node(&sisfb_heap.oh_free, poh_freed); 3497 sisfb_insert_node(&memheap->oh_free, poh_freed);
3327 3498
3328 return(poh_freed); 3499 return poh_freed;
3329} 3500}
3330 3501
3331static void 3502static void
3332sisfb_free_node(SIS_OH *poh) 3503sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3333{ 3504{
3334 if(poh == NULL) return; 3505 if(poh == NULL)
3506 return;
3335 3507
3336 poh->poh_next = sisfb_heap.poh_freelist; 3508 poh->poh_next = memheap->poh_freelist;
3337 sisfb_heap.poh_freelist = poh; 3509 memheap->poh_freelist = poh;
3338} 3510}
3339 3511
3340void 3512static void
3341sis_malloc(struct sis_memreq *req) 3513sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3342{ 3514{
3343 struct sis_video_info *ivideo = sisfb_heap.vinfo; 3515 struct SIS_OH *poh = NULL;
3344 SIS_OH *poh = NULL;
3345 3516
3346 if((ivideo) && (!ivideo->havenoheap)) { 3517 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3347 poh = sisfb_poh_allocate((u32)req->size); 3518 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3348 }
3349 3519
3350 if(poh == NULL) { 3520 if(poh == NULL) {
3351 req->offset = req->size = 0; 3521 req->offset = req->size = 0;
3352 DPRINTK("sisfb: Video RAM allocation failed\n"); 3522 DPRINTK("sisfb: Video RAM allocation failed\n");
3353 } else { 3523 } else {
3354 req->offset = poh->offset; 3524 req->offset = poh->offset;
3355 req->size = poh->size; 3525 req->size = poh->size;
3356 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n", 3526 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3357 (poh->offset + ivideo->video_vbase)); 3527 (poh->offset + ivideo->video_vbase));
3358 } 3528 }
3359} 3529}
3360 3530
3361/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */ 3531void
3532sis_malloc(struct sis_memreq *req)
3533{
3534 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3535
3536 if(&ivideo->sisfb_heap == sisfb_heap)
3537 sis_int_malloc(ivideo, req);
3538 else
3539 req->offset = req->size = 0;
3540}
3362 3541
3363void 3542void
3364sis_free(u32 base) 3543sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3365{ 3544{
3366 struct sis_video_info *ivideo = sisfb_heap.vinfo; 3545 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3367 SIS_OH *poh; 3546
3547 sis_int_malloc(ivideo, req);
3548}
3549
3550/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3368 3551
3369 if((!ivideo) || (ivideo->havenoheap)) return; 3552static void
3553sis_int_free(struct sis_video_info *ivideo, u32 base)
3554{
3555 struct SIS_OH *poh;
3370 3556
3371 poh = sisfb_poh_free((u32)base); 3557 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3558 return;
3559
3560 poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3372 3561
3373 if(poh == NULL) { 3562 if(poh == NULL) {
3374 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n", 3563 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
@@ -3376,9 +3565,63 @@ sis_free(u32 base)
3376 } 3565 }
3377} 3566}
3378 3567
3568void
3569sis_free(u32 base)
3570{
3571 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3572
3573 sis_int_free(ivideo, base);
3574}
3575
3576void
3577sis_free_new(struct pci_dev *pdev, u32 base)
3578{
3579 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3580
3581 sis_int_free(ivideo, base);
3582}
3583
3379/* --------------------- SetMode routines ------------------------- */ 3584/* --------------------- SetMode routines ------------------------- */
3380 3585
3381static void 3586static void
3587sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3588{
3589 u8 cr30, cr31;
3590
3591 /* Check if MMIO and engines are enabled,
3592 * and sync in case they are. Can't use
3593 * ivideo->accel here, as this might have
3594 * been changed before this is called.
3595 */
3596 inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
3597 inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
3598 /* MMIO and 2D/3D engine enabled? */
3599 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3600#ifdef CONFIG_FB_SIS_300
3601 if(ivideo->sisvga_engine == SIS_300_VGA) {
3602 /* Don't care about TurboQueue. It's
3603 * enough to know that the engines
3604 * are enabled
3605 */
3606 sisfb_syncaccel(ivideo);
3607 }
3608#endif
3609#ifdef CONFIG_FB_SIS_315
3610 if(ivideo->sisvga_engine == SIS_315_VGA) {
3611 /* Check that any queue mode is
3612 * enabled, and that the queue
3613 * is not in the state of "reset"
3614 */
3615 inSISIDXREG(SISSR, 0x26, cr30);
3616 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3617 sisfb_syncaccel(ivideo);
3618 }
3619 }
3620#endif
3621 }
3622}
3623
3624static void
3382sisfb_pre_setmode(struct sis_video_info *ivideo) 3625sisfb_pre_setmode(struct sis_video_info *ivideo)
3383{ 3626{
3384 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0; 3627 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
@@ -3386,6 +3629,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3386 3629
3387 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2); 3630 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3388 3631
3632 outSISIDXREG(SISSR, 0x05, 0x86);
3633
3389 inSISIDXREG(SISCR, 0x31, cr31); 3634 inSISIDXREG(SISCR, 0x31, cr31);
3390 cr31 &= ~0x60; 3635 cr31 &= ~0x60;
3391 cr31 |= 0x04; 3636 cr31 |= 0x04;
@@ -3413,41 +3658,43 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3413 3658
3414 SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE); 3659 SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
3415 SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE); 3660 SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
3661 ivideo->curFSTN = ivideo->curDSTN = 0;
3416 3662
3417 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { 3663 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3418 3664
3419 case CRT2_TV: 3665 case CRT2_TV:
3420 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */ 3666 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3421 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) { 3667 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3422#ifdef CONFIG_FB_SIS_315 3668#ifdef CONFIG_FB_SIS_315
3423 if(ivideo->chip >= SIS_661) { 3669 if(ivideo->chip >= SIS_661) {
3424 cr38 |= 0x04; 3670 cr38 |= 0x04;
3425 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20; 3671 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3426 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40; 3672 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3427 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60; 3673 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3428 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; 3674 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3429 cr35 &= ~0x01; 3675 cr35 &= ~0x01;
3430 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); 3676 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3431 } else if(ivideo->sisvga_engine == SIS_315_VGA) { 3677 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3432 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE); 3678 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3433 cr38 |= 0x08; 3679 cr38 |= 0x08;
3434 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10; 3680 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3435 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20; 3681 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3436 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30; 3682 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3437 cr31 &= ~0x01; 3683 cr31 &= ~0x01;
3438 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL)); 3684 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3439 } 3685 }
3440#endif 3686#endif
3441 } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) { 3687 } else if((ivideo->vbflags & TV_HIVISION) &&
3442 if(ivideo->chip >= SIS_661) { 3688 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3443 cr38 |= 0x04; 3689 if(ivideo->chip >= SIS_661) {
3444 cr35 |= 0x60; 3690 cr38 |= 0x04;
3445 } else { 3691 cr35 |= 0x60;
3446 cr30 |= 0x80; 3692 } else {
3447 } 3693 cr30 |= 0x80;
3694 }
3448 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; 3695 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3449 cr31 |= 0x01; 3696 cr31 |= 0x01;
3450 cr35 |= 0x01; 3697 cr35 |= 0x01;
3451 ivideo->currentvbflags |= TV_HIVISION; 3698 ivideo->currentvbflags |= TV_HIVISION;
3452 } else if(ivideo->vbflags & TV_SCART) { 3699 } else if(ivideo->vbflags & TV_SCART) {
3453 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE); 3700 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
@@ -3466,8 +3713,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3466 } 3713 }
3467 cr31 |= SIS_DRIVER_MODE; 3714 cr31 |= SIS_DRIVER_MODE;
3468 3715
3469 if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) { 3716 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3470 if(ivideo->vbflags & TV_PAL) { 3717 if(ivideo->vbflags & TV_PAL) {
3471 cr31 |= 0x01; cr35 |= 0x01; 3718 cr31 |= 0x01; cr35 |= 0x01;
3472 ivideo->currentvbflags |= TV_PAL; 3719 ivideo->currentvbflags |= TV_PAL;
3473 if(ivideo->vbflags & TV_PALM) { 3720 if(ivideo->vbflags & TV_PALM) {
@@ -3476,14 +3723,14 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3476 } else if(ivideo->vbflags & TV_PALN) { 3723 } else if(ivideo->vbflags & TV_PALN) {
3477 cr38 |= 0x80; cr35 |= 0x08; 3724 cr38 |= 0x80; cr35 |= 0x08;
3478 ivideo->currentvbflags |= TV_PALN; 3725 ivideo->currentvbflags |= TV_PALN;
3479 } 3726 }
3480 } else { 3727 } else {
3481 cr31 &= ~0x01; cr35 &= ~0x01; 3728 cr31 &= ~0x01; cr35 &= ~0x01;
3482 ivideo->currentvbflags |= TV_NTSC; 3729 ivideo->currentvbflags |= TV_NTSC;
3483 if(ivideo->vbflags & TV_NTSCJ) { 3730 if(ivideo->vbflags & TV_NTSCJ) {
3484 cr38 |= 0x40; cr35 |= 0x02; 3731 cr38 |= 0x40; cr35 |= 0x02;
3485 ivideo->currentvbflags |= TV_NTSCJ; 3732 ivideo->currentvbflags |= TV_NTSCJ;
3486 } 3733 }
3487 } 3734 }
3488 } 3735 }
3489 break; 3736 break;
@@ -3493,6 +3740,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3493 cr31 |= SIS_DRIVER_MODE; 3740 cr31 |= SIS_DRIVER_MODE;
3494 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn); 3741 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3495 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn); 3742 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3743 ivideo->curFSTN = ivideo->sisfb_fstn;
3744 ivideo->curDSTN = ivideo->sisfb_dstn;
3496 break; 3745 break;
3497 3746
3498 case CRT2_VGA: 3747 case CRT2_VGA:
@@ -3525,9 +3774,9 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3525 } 3774 }
3526 outSISIDXREG(SISCR, 0x31, cr31); 3775 outSISIDXREG(SISCR, 0x31, cr31);
3527 3776
3528 if(ivideo->accel) sisfb_syncaccel(ivideo);
3529
3530 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem; 3777 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3778
3779 sisfb_check_engine_and_sync(ivideo);
3531} 3780}
3532 3781
3533/* Fix SR11 for 661 and later */ 3782/* Fix SR11 for 661 and later */
@@ -3535,125 +3784,129 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
3535static void 3784static void
3536sisfb_fixup_SR11(struct sis_video_info *ivideo) 3785sisfb_fixup_SR11(struct sis_video_info *ivideo)
3537{ 3786{
3538 u8 tmpreg; 3787 u8 tmpreg;
3539 3788
3540 if(ivideo->chip >= SIS_661) { 3789 if(ivideo->chip >= SIS_661) {
3541 inSISIDXREG(SISSR,0x11,tmpreg); 3790 inSISIDXREG(SISSR,0x11,tmpreg);
3542 if(tmpreg & 0x20) { 3791 if(tmpreg & 0x20) {
3543 inSISIDXREG(SISSR,0x3e,tmpreg); 3792 inSISIDXREG(SISSR,0x3e,tmpreg);
3544 tmpreg = (tmpreg + 1) & 0xff; 3793 tmpreg = (tmpreg + 1) & 0xff;
3545 outSISIDXREG(SISSR,0x3e,tmpreg); 3794 outSISIDXREG(SISSR,0x3e,tmpreg);
3546 inSISIDXREG(SISSR,0x11,tmpreg); 3795 inSISIDXREG(SISSR,0x11,tmpreg);
3547 } 3796 }
3548 if(tmpreg & 0xf0) { 3797 if(tmpreg & 0xf0) {
3549 andSISIDXREG(SISSR,0x11,0x0f); 3798 andSISIDXREG(SISSR,0x11,0x0f);
3550 } 3799 }
3551 } 3800 }
3552} 3801}
3553#endif 3802#endif
3554 3803
3555static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val) 3804static void
3805sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3556{ 3806{
3557 if(val > 32) val = 32; 3807 if(val > 32) val = 32;
3558 if(val < -32) val = -32; 3808 if(val < -32) val = -32;
3559 ivideo->tvxpos = val; 3809 ivideo->tvxpos = val;
3560 3810
3561 if(ivideo->sisfblocked) return; 3811 if(ivideo->sisfblocked) return;
3562 if(!ivideo->modechanged) return; 3812 if(!ivideo->modechanged) return;
3563 3813
3564 if(ivideo->currentvbflags & CRT2_TV) { 3814 if(ivideo->currentvbflags & CRT2_TV) {
3565 3815
3566 if(ivideo->vbflags & VB_CHRONTEL) { 3816 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3567 3817
3568 int x = ivideo->tvx; 3818 int x = ivideo->tvx;
3569 3819
3570 switch(ivideo->chronteltype) { 3820 switch(ivideo->chronteltype) {
3571 case 1: 3821 case 1:
3572 x += val; 3822 x += val;
3573 if(x < 0) x = 0; 3823 if(x < 0) x = 0;
3574 outSISIDXREG(SISSR,0x05,0x86); 3824 outSISIDXREG(SISSR,0x05,0x86);
3575 SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a)); 3825 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3576 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD); 3826 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3577 break; 3827 break;
3578 case 2: 3828 case 2:
3579 /* Not supported by hardware */ 3829 /* Not supported by hardware */
3580 break; 3830 break;
3581 } 3831 }
3582 3832
3583 } else if(ivideo->vbflags & VB_SISBRIDGE) { 3833 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3584 3834
3585 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43; 3835 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3586 unsigned short temp; 3836 unsigned short temp;
3587 3837
3588 p2_1f = ivideo->p2_1f; 3838 p2_1f = ivideo->p2_1f;
3589 p2_20 = ivideo->p2_20; 3839 p2_20 = ivideo->p2_20;
3590 p2_2b = ivideo->p2_2b; 3840 p2_2b = ivideo->p2_2b;
3591 p2_42 = ivideo->p2_42; 3841 p2_42 = ivideo->p2_42;
3592 p2_43 = ivideo->p2_43; 3842 p2_43 = ivideo->p2_43;
3593 3843
3594 temp = p2_1f | ((p2_20 & 0xf0) << 4); 3844 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3595 temp += (val * 2); 3845 temp += (val * 2);
3596 p2_1f = temp & 0xff; 3846 p2_1f = temp & 0xff;
3597 p2_20 = (temp & 0xf00) >> 4; 3847 p2_20 = (temp & 0xf00) >> 4;
3598 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f; 3848 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3599 temp = p2_43 | ((p2_42 & 0xf0) << 4); 3849 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3600 temp += (val * 2); 3850 temp += (val * 2);
3601 p2_43 = temp & 0xff; 3851 p2_43 = temp & 0xff;
3602 p2_42 = (temp & 0xf00) >> 4; 3852 p2_42 = (temp & 0xf00) >> 4;
3603 outSISIDXREG(SISPART2,0x1f,p2_1f); 3853 outSISIDXREG(SISPART2,0x1f,p2_1f);
3604 setSISIDXREG(SISPART2,0x20,0x0F,p2_20); 3854 setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
3605 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b); 3855 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
3606 setSISIDXREG(SISPART2,0x42,0x0F,p2_42); 3856 setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
3607 outSISIDXREG(SISPART2,0x43,p2_43); 3857 outSISIDXREG(SISPART2,0x43,p2_43);
3608 } 3858 }
3609 } 3859 }
3610} 3860}
3611 3861
3612static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val) 3862static void
3863sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3613{ 3864{
3614 if(val > 32) val = 32; 3865 if(val > 32) val = 32;
3615 if(val < -32) val = -32; 3866 if(val < -32) val = -32;
3616 ivideo->tvypos = val; 3867 ivideo->tvypos = val;
3617 3868
3618 if(ivideo->sisfblocked) return; 3869 if(ivideo->sisfblocked) return;
3619 if(!ivideo->modechanged) return; 3870 if(!ivideo->modechanged) return;
3620 3871
3621 if(ivideo->currentvbflags & CRT2_TV) { 3872 if(ivideo->currentvbflags & CRT2_TV) {
3622 3873
3623 if(ivideo->vbflags & VB_CHRONTEL) { 3874 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3624 3875
3625 int y = ivideo->tvy; 3876 int y = ivideo->tvy;
3626 3877
3627 switch(ivideo->chronteltype) { 3878 switch(ivideo->chronteltype) {
3628 case 1: 3879 case 1:
3629 y -= val; 3880 y -= val;
3630 if(y < 0) y = 0; 3881 if(y < 0) y = 0;
3631 outSISIDXREG(SISSR,0x05,0x86); 3882 outSISIDXREG(SISSR,0x05,0x86);
3632 SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b)); 3883 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3633 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE); 3884 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3634 break; 3885 break;
3635 case 2: 3886 case 2:
3636 /* Not supported by hardware */ 3887 /* Not supported by hardware */
3637 break; 3888 break;
3638 } 3889 }
3639 3890
3640 } else if(ivideo->vbflags & VB_SISBRIDGE) { 3891 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3641 3892
3642 char p2_01, p2_02; 3893 char p2_01, p2_02;
3643 val /= 2; 3894 val /= 2;
3644 p2_01 = ivideo->p2_01; 3895 p2_01 = ivideo->p2_01;
3645 p2_02 = ivideo->p2_02; 3896 p2_02 = ivideo->p2_02;
3646 3897
3647 p2_01 += val; 3898 p2_01 += val;
3648 p2_02 += val; 3899 p2_02 += val;
3649 while((p2_01 <= 0) || (p2_02 <= 0)) { 3900 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3650 p2_01 += 2; 3901 while((p2_01 <= 0) || (p2_02 <= 0)) {
3651 p2_02 += 2; 3902 p2_01 += 2;
3652 } 3903 p2_02 += 2;
3653 outSISIDXREG(SISPART2,0x01,p2_01); 3904 }
3654 outSISIDXREG(SISPART2,0x02,p2_02); 3905 }
3655 } 3906 outSISIDXREG(SISPART2,0x01,p2_01);
3656 } 3907 outSISIDXREG(SISPART2,0x02,p2_02);
3908 }
3909 }
3657} 3910}
3658 3911
3659static void 3912static void
@@ -3668,207 +3921,172 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
3668 u8 reg1; 3921 u8 reg1;
3669#endif 3922#endif
3670 3923
3671 outSISIDXREG(SISSR,0x05,0x86); 3924 outSISIDXREG(SISSR, 0x05, 0x86);
3672 3925
3673#ifdef CONFIG_FB_SIS_315 3926#ifdef CONFIG_FB_SIS_315
3674 sisfb_fixup_SR11(ivideo); 3927 sisfb_fixup_SR11(ivideo);
3675#endif 3928#endif
3676 3929
3677 /* Now we actually HAVE changed the display mode */ 3930 /* Now we actually HAVE changed the display mode */
3678 ivideo->modechanged = 1; 3931 ivideo->modechanged = 1;
3679 3932
3680 /* We can't switch off CRT1 if bridge is in slave mode */ 3933 /* We can't switch off CRT1 if bridge is in slave mode */
3681 if(ivideo->vbflags & VB_VIDEOBRIDGE) { 3934 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3682 if(sisfb_bridgeisslave(ivideo)) doit = FALSE; 3935 if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
3683 } else ivideo->sisfb_crt1off = 0; 3936 } else
3937 ivideo->sisfb_crt1off = 0;
3684 3938
3685#ifdef CONFIG_FB_SIS_300 3939#ifdef CONFIG_FB_SIS_300
3686 if(ivideo->sisvga_engine == SIS_300_VGA) { 3940 if(ivideo->sisvga_engine == SIS_300_VGA) {
3687 if((ivideo->sisfb_crt1off) && (doit)) { 3941 if((ivideo->sisfb_crt1off) && (doit)) {
3688 crt1isoff = TRUE; 3942 crt1isoff = TRUE;
3689 reg = 0x00; 3943 reg = 0x00;
3690 } else { 3944 } else {
3691 crt1isoff = FALSE; 3945 crt1isoff = FALSE;
3692 reg = 0x80; 3946 reg = 0x80;
3693 } 3947 }
3694 setSISIDXREG(SISCR, 0x17, 0x7f, reg); 3948 setSISIDXREG(SISCR, 0x17, 0x7f, reg);
3695 } 3949 }
3696#endif 3950#endif
3697#ifdef CONFIG_FB_SIS_315 3951#ifdef CONFIG_FB_SIS_315
3698 if(ivideo->sisvga_engine == SIS_315_VGA) { 3952 if(ivideo->sisvga_engine == SIS_315_VGA) {
3699 if((ivideo->sisfb_crt1off) && (doit)) { 3953 if((ivideo->sisfb_crt1off) && (doit)) {
3700 crt1isoff = TRUE; 3954 crt1isoff = TRUE;
3701 reg = 0x40; 3955 reg = 0x40;
3702 reg1 = 0xc0; 3956 reg1 = 0xc0;
3703 } else { 3957 } else {
3704 crt1isoff = FALSE; 3958 crt1isoff = FALSE;
3705 reg = 0x00; 3959 reg = 0x00;
3706 reg1 = 0x00; 3960 reg1 = 0x00;
3707 3961 }
3708 } 3962 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3709 setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg); 3963 setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
3710 setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
3711 } 3964 }
3712#endif 3965#endif
3713 3966
3714 if(crt1isoff) { 3967 if(crt1isoff) {
3715 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1; 3968 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3716 ivideo->currentvbflags |= VB_SINGLE_MODE; 3969 ivideo->currentvbflags |= VB_SINGLE_MODE;
3717 } else { 3970 } else {
3718 ivideo->currentvbflags |= VB_DISPTYPE_CRT1; 3971 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3719 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) { 3972 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3720 ivideo->currentvbflags |= VB_MIRROR_MODE; 3973 ivideo->currentvbflags |= VB_MIRROR_MODE;
3721 } else { 3974 } else {
3722 ivideo->currentvbflags |= VB_SINGLE_MODE; 3975 ivideo->currentvbflags |= VB_SINGLE_MODE;
3723 } 3976 }
3724 } 3977 }
3725 3978
3726 andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04); 3979 andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3727 3980
3728 if(ivideo->currentvbflags & CRT2_TV) { 3981 if(ivideo->currentvbflags & CRT2_TV) {
3729 if(ivideo->vbflags & VB_SISBRIDGE) { 3982 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3730 inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f); 3983 inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
3731 inSISIDXREG(SISPART2,0x20,ivideo->p2_20); 3984 inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
3732 inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b); 3985 inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
3733 inSISIDXREG(SISPART2,0x42,ivideo->p2_42); 3986 inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
3734 inSISIDXREG(SISPART2,0x43,ivideo->p2_43); 3987 inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
3735 inSISIDXREG(SISPART2,0x01,ivideo->p2_01); 3988 inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
3736 inSISIDXREG(SISPART2,0x02,ivideo->p2_02); 3989 inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
3737 } else if(ivideo->vbflags & VB_CHRONTEL) { 3990 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3738 if(ivideo->chronteltype == 1) { 3991 if(ivideo->chronteltype == 1) {
3739 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a); 3992 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3740 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8); 3993 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3741 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b); 3994 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3742 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8); 3995 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3743 } 3996 }
3744 } 3997 }
3745 } 3998 }
3746 3999
3747 if(ivideo->tvxpos) { 4000 if(ivideo->tvxpos) {
3748 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos); 4001 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3749 } 4002 }
3750 if(ivideo->tvypos) { 4003 if(ivideo->tvypos) {
3751 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos); 4004 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3752 } 4005 }
3753 4006
3754 if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) { /* Set filter for SiS301 */ 4007 /* Eventually sync engines */
4008 sisfb_check_engine_and_sync(ivideo);
3755 4009
3756 unsigned char filter_tb = 0; 4010 /* (Re-)Initialize chip engines */
4011 if(ivideo->accel) {
4012 sisfb_engine_init(ivideo);
4013 } else {
4014 ivideo->engineok = 0;
4015 }
4016}
3757 4017
3758 switch (ivideo->video_width) { 4018static int
3759 case 320: 4019sisfb_reset_mode(struct sis_video_info *ivideo)
3760 filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12; 4020{
3761 break; 4021 if(sisfb_set_mode(ivideo, 0))
3762 case 640: 4022 return 1;
3763 filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13;
3764 break;
3765 case 720:
3766 filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14;
3767 break;
3768 case 400:
3769 case 800:
3770 filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15;
3771 break;
3772 default:
3773 ivideo->sisfb_filter = -1;
3774 break;
3775 }
3776 4023
3777 orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01); 4024 sisfb_set_pitch(ivideo);
4025 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
4026 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3778 4027
3779 if(ivideo->vbflags & TV_NTSC) { 4028 return 0;
3780 4029}
3781 andSISIDXREG(SISPART2, 0x3a, 0x1f); 4030
3782 4031static void
3783 if (ivideo->vbflags & TV_SVIDEO) { 4032sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3784 4033{
3785 andSISIDXREG(SISPART2, 0x30, 0xdf); 4034 int mycrt1off;
3786
3787 } else if (ivideo->vbflags & TV_AVIDEO) {
3788
3789 orSISIDXREG(SISPART2, 0x30, 0x20);
3790
3791 switch (ivideo->video_width) {
3792 case 640:
3793 outSISIDXREG(SISPART2, 0x35, 0xEB);
3794 outSISIDXREG(SISPART2, 0x36, 0x04);
3795 outSISIDXREG(SISPART2, 0x37, 0x25);
3796 outSISIDXREG(SISPART2, 0x38, 0x18);
3797 break;
3798 case 720:
3799 outSISIDXREG(SISPART2, 0x35, 0xEE);
3800 outSISIDXREG(SISPART2, 0x36, 0x0C);
3801 outSISIDXREG(SISPART2, 0x37, 0x22);
3802 outSISIDXREG(SISPART2, 0x38, 0x08);
3803 break;
3804 case 400:
3805 case 800:
3806 outSISIDXREG(SISPART2, 0x35, 0xEB);
3807 outSISIDXREG(SISPART2, 0x36, 0x15);
3808 outSISIDXREG(SISPART2, 0x37, 0x25);
3809 outSISIDXREG(SISPART2, 0x38, 0xF6);
3810 break;
3811 }
3812 }
3813 4035
3814 } else if(ivideo->vbflags & TV_PAL) { 4036 switch(sisfb_command->sisfb_cmd) {
3815 4037 case SISFB_CMD_GETVBFLAGS:
3816 andSISIDXREG(SISPART2, 0x3A, 0x1F); 4038 if(!ivideo->modechanged) {
3817 4039 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3818 if (ivideo->vbflags & TV_SVIDEO) { 4040 } else {
3819 4041 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3820 andSISIDXREG(SISPART2, 0x30, 0xDF); 4042 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3821 4043 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3822 } else if (ivideo->vbflags & TV_AVIDEO) { 4044 }
3823 4045 break;
3824 orSISIDXREG(SISPART2, 0x30, 0x20); 4046 case SISFB_CMD_SWITCHCRT1:
3825 4047 /* arg[0]: 0 = off, 1 = on, 99 = query */
3826 switch (ivideo->video_width) { 4048 if(!ivideo->modechanged) {
3827 case 640: 4049 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3828 outSISIDXREG(SISPART2, 0x35, 0xF1); 4050 } else if(sisfb_command->sisfb_arg[0] == 99) {
3829 outSISIDXREG(SISPART2, 0x36, 0xF7); 4051 /* Query */
3830 outSISIDXREG(SISPART2, 0x37, 0x1F); 4052 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3831 outSISIDXREG(SISPART2, 0x38, 0x32); 4053 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3832 break; 4054 } else if(ivideo->sisfblocked) {
3833 case 720: 4055 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3834 outSISIDXREG(SISPART2, 0x35, 0xF3); 4056 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3835 outSISIDXREG(SISPART2, 0x36, 0x00); 4057 (sisfb_command->sisfb_arg[0] == 0)) {
3836 outSISIDXREG(SISPART2, 0x37, 0x1D); 4058 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3837 outSISIDXREG(SISPART2, 0x38, 0x20); 4059 } else {
3838 break; 4060 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3839 case 400: 4061 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3840 case 800: 4062 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3841 outSISIDXREG(SISPART2, 0x35, 0xFC); 4063 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3842 outSISIDXREG(SISPART2, 0x36, 0xFB); 4064 ivideo->sisfb_crt1off = mycrt1off;
3843 outSISIDXREG(SISPART2, 0x37, 0x14); 4065 if(sisfb_reset_mode(ivideo)) {
3844 outSISIDXREG(SISPART2, 0x38, 0x2A); 4066 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3845 break;
3846 } 4067 }
3847 } 4068 }
4069 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3848 } 4070 }
3849 4071 break;
3850 if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) { 4072 /* more to come */
3851 outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0])); 4073 default:
3852 outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1])); 4074 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3853 outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2])); 4075 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3854 outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3])); 4076 sisfb_command->sisfb_cmd);
3855 }
3856
3857 } 4077 }
3858} 4078}
3859 4079
3860#ifndef MODULE 4080#ifndef MODULE
3861SISINITSTATIC int __init sisfb_setup(char *options) 4081SISINITSTATIC int __init
4082sisfb_setup(char *options)
3862{ 4083{
3863 char *this_opt; 4084 char *this_opt;
3864
3865 sisfb_setdefaultparms();
3866 4085
3867 printk(KERN_DEBUG "sisfb: Options %s\n", options); 4086 sisfb_setdefaultparms();
3868 4087
3869 if(!options || !(*options)) { 4088 if(!options || !(*options))
3870 return 0; 4089 return 0;
3871 }
3872 4090
3873 while((this_opt = strsep(&options, ",")) != NULL) { 4091 while((this_opt = strsep(&options, ",")) != NULL) {
3874 4092
@@ -3880,9 +4098,9 @@ SISINITSTATIC int __init sisfb_setup(char *options)
3880 /* Need to check crt2 type first for fstn/dstn */ 4098 /* Need to check crt2 type first for fstn/dstn */
3881 sisfb_search_crt2type(this_opt + 14); 4099 sisfb_search_crt2type(this_opt + 14);
3882 } else if(!strnicmp(this_opt, "tvmode:",7)) { 4100 } else if(!strnicmp(this_opt, "tvmode:",7)) {
3883 sisfb_search_tvstd(this_opt + 7);
3884 } else if(!strnicmp(this_opt, "tvstandard:",11)) {
3885 sisfb_search_tvstd(this_opt + 7); 4101 sisfb_search_tvstd(this_opt + 7);
4102 } else if(!strnicmp(this_opt, "tvstandard:",11)) {
4103 sisfb_search_tvstd(this_opt + 11);
3886 } else if(!strnicmp(this_opt, "mode:", 5)) { 4104 } else if(!strnicmp(this_opt, "mode:", 5)) {
3887 sisfb_search_mode(this_opt + 5, FALSE); 4105 sisfb_search_mode(this_opt + 5, FALSE);
3888 } else if(!strnicmp(this_opt, "vesa:", 5)) { 4106 } else if(!strnicmp(this_opt, "vesa:", 5)) {
@@ -3892,74 +4110,72 @@ SISINITSTATIC int __init sisfb_setup(char *options)
3892 sisfb_inverse = 1; 4110 sisfb_inverse = 1;
3893 /* fb_invert_cmaps(); */ 4111 /* fb_invert_cmaps(); */
3894 } else if(!strnicmp(this_opt, "font:", 5)) { 4112 } else if(!strnicmp(this_opt, "font:", 5)) {
3895 if(strlen(this_opt + 5) < 40) { 4113 if(strlen(this_opt + 5) < 40) {
3896 strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1); 4114 strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
3897 sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0'; 4115 sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
3898 } 4116 }
3899#endif 4117#endif
3900 } else if(!strnicmp(this_opt, "rate:", 5)) { 4118 } else if(!strnicmp(this_opt, "rate:", 5)) {
3901 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0); 4119 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
3902 } else if(!strnicmp(this_opt, "filter:", 7)) {
3903 sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
3904 } else if(!strnicmp(this_opt, "forcecrt1:", 10)) { 4120 } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
3905 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0); 4121 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
3906 } else if(!strnicmp(this_opt, "mem:",4)) { 4122 } else if(!strnicmp(this_opt, "mem:",4)) {
3907 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0); 4123 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
3908 } else if(!strnicmp(this_opt, "pdc:", 4)) { 4124 } else if(!strnicmp(this_opt, "pdc:", 4)) {
3909 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0); 4125 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
3910 } else if(!strnicmp(this_opt, "pdc1:", 5)) { 4126 } else if(!strnicmp(this_opt, "pdc1:", 5)) {
3911 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0); 4127 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
3912 } else if(!strnicmp(this_opt, "noaccel", 7)) { 4128 } else if(!strnicmp(this_opt, "noaccel", 7)) {
3913 sisfb_accel = 0; 4129 sisfb_accel = 0;
3914 } else if(!strnicmp(this_opt, "accel", 5)) { 4130 } else if(!strnicmp(this_opt, "accel", 5)) {
3915 sisfb_accel = -1; 4131 sisfb_accel = -1;
3916 } else if(!strnicmp(this_opt, "noypan", 6)) { 4132 } else if(!strnicmp(this_opt, "noypan", 6)) {
3917 sisfb_ypan = 0; 4133 sisfb_ypan = 0;
3918 } else if(!strnicmp(this_opt, "ypan", 4)) { 4134 } else if(!strnicmp(this_opt, "ypan", 4)) {
3919 sisfb_ypan = -1; 4135 sisfb_ypan = -1;
3920 } else if(!strnicmp(this_opt, "nomax", 5)) { 4136 } else if(!strnicmp(this_opt, "nomax", 5)) {
3921 sisfb_max = 0; 4137 sisfb_max = 0;
3922 } else if(!strnicmp(this_opt, "max", 3)) { 4138 } else if(!strnicmp(this_opt, "max", 3)) {
3923 sisfb_max = -1; 4139 sisfb_max = -1;
3924 } else if(!strnicmp(this_opt, "userom:", 7)) { 4140 } else if(!strnicmp(this_opt, "userom:", 7)) {
3925 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0); 4141 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
3926 } else if(!strnicmp(this_opt, "useoem:", 7)) { 4142 } else if(!strnicmp(this_opt, "useoem:", 7)) {
3927 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); 4143 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
3928 } else if(!strnicmp(this_opt, "nocrt2rate", 10)) { 4144 } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
3929 sisfb_nocrt2rate = 1; 4145 sisfb_nocrt2rate = 1;
3930 } else if(!strnicmp(this_opt, "scalelcd:", 9)) { 4146 } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
3931 unsigned long temp = 2; 4147 unsigned long temp = 2;
3932 temp = simple_strtoul(this_opt + 9, NULL, 0); 4148 temp = simple_strtoul(this_opt + 9, NULL, 0);
3933 if((temp == 0) || (temp == 1)) { 4149 if((temp == 0) || (temp == 1)) {
3934 sisfb_scalelcd = temp ^ 1; 4150 sisfb_scalelcd = temp ^ 1;
3935 } 4151 }
3936 } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) { 4152 } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
3937 int temp = 0; 4153 int temp = 0;
3938 temp = (int)simple_strtol(this_opt + 13, NULL, 0); 4154 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
3939 if((temp >= -32) && (temp <= 32)) { 4155 if((temp >= -32) && (temp <= 32)) {
3940 sisfb_tvxposoffset = temp; 4156 sisfb_tvxposoffset = temp;
3941 } 4157 }
3942 } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) { 4158 } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
3943 int temp = 0; 4159 int temp = 0;
3944 temp = (int)simple_strtol(this_opt + 13, NULL, 0); 4160 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
3945 if((temp >= -32) && (temp <= 32)) { 4161 if((temp >= -32) && (temp <= 32)) {
3946 sisfb_tvyposoffset = temp; 4162 sisfb_tvyposoffset = temp;
3947 } 4163 }
3948 } else if(!strnicmp(this_opt, "specialtiming:", 14)) { 4164 } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
3949 sisfb_search_specialtiming(this_opt + 14); 4165 sisfb_search_specialtiming(this_opt + 14);
3950 } else if(!strnicmp(this_opt, "lvdshl:", 7)) { 4166 } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
3951 int temp = 4; 4167 int temp = 4;
3952 temp = simple_strtoul(this_opt + 7, NULL, 0); 4168 temp = simple_strtoul(this_opt + 7, NULL, 0);
3953 if((temp >= 0) && (temp <= 3)) { 4169 if((temp >= 0) && (temp <= 3)) {
3954 sisfb_lvdshl = temp; 4170 sisfb_lvdshl = temp;
3955 } 4171 }
3956 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') { 4172 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
3957 sisfb_search_mode(this_opt, TRUE); 4173 sisfb_search_mode(this_opt, TRUE);
3958#if !defined(__i386__) && !defined(__x86_64__) 4174#if !defined(__i386__) && !defined(__x86_64__)
3959 } else if(!strnicmp(this_opt, "resetcard", 9)) { 4175 } else if(!strnicmp(this_opt, "resetcard", 9)) {
3960 sisfb_resetcard = 1; 4176 sisfb_resetcard = 1;
3961 } else if(!strnicmp(this_opt, "videoram:", 9)) { 4177 } else if(!strnicmp(this_opt, "videoram:", 9)) {
3962 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0); 4178 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
3963#endif 4179#endif
3964 } else { 4180 } else {
3965 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt); 4181 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
@@ -3967,63 +4183,99 @@ SISINITSTATIC int __init sisfb_setup(char *options)
3967 4183
3968 } 4184 }
3969 4185
3970
3971
3972 return 0; 4186 return 0;
3973} 4187}
3974#endif 4188#endif
3975 4189
3976static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev) 4190static int __devinit
4191sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
4192{
4193 SIS_IOTYPE1 *rom;
4194 int romptr;
4195
4196 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4197 return 0;
4198
4199 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4200 if(romptr > (0x10000 - 8))
4201 return 0;
4202
4203 rom = rom_base + romptr;
4204
4205 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4206 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4207 return 0;
4208
4209 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4210 return 0;
4211
4212 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4213 return 0;
4214
4215 return 1;
4216}
4217
4218static unsigned char * __devinit
4219sisfb_find_rom(struct pci_dev *pdev)
3977{ 4220{
3978 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4221 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3979 USHORT pciid; 4222 SIS_IOTYPE1 *rom_base;
3980 int romptr; 4223 unsigned char *myrombase = NULL;
3981 UCHAR *myrombase; 4224 u32 temp;
3982 u32 temp; 4225#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
3983 SIS_IOTYPE1 *rom_base, *rom; 4226 size_t romsize;
4227
4228 /* First, try the official pci ROM functions (except
4229 * on integrated chipsets which have no ROM).
4230 */
3984 4231
3985 if(!(myrombase = vmalloc(65536))) return NULL; 4232 if(!ivideo->nbridge) {
3986 4233
3987#if defined(__i386__) || defined(__x86_64__) 4234 if((rom_base = pci_map_rom(pdev, &romsize))) {
3988 4235
3989 for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) { 4236 if(sisfb_check_rom(rom_base, ivideo)) {
3990 4237
3991 rom_base = ioremap(temp, 0x10000); 4238 if((myrombase = vmalloc(65536))) {
3992 if(!rom_base) continue;
3993 4239
3994 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) { 4240 /* Work around bug in pci/rom.c: Folks forgot to check
3995 iounmap(rom_base); 4241 * whether the size retrieved from the BIOS image eventually
3996 continue; 4242 * is larger than the mapped size
3997 } 4243 */
4244 if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
4245 romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
3998 4246
3999 romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8)); 4247 memcpy_fromio(myrombase, rom_base,
4000 if(romptr > (0x10000 - 8)) { 4248 (romsize > 65536) ? 65536 : romsize);
4001 iounmap(rom_base); 4249 }
4002 continue; 4250 }
4003 } 4251 pci_unmap_rom(pdev, rom_base);
4252 }
4253 }
4004 4254
4005 rom = rom_base + romptr; 4255 if(myrombase) return myrombase;
4256#endif
4006 4257
4007 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') || 4258 /* Otherwise do it the conventional way. */
4008 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
4009 iounmap(rom_base);
4010 continue;
4011 }
4012 4259
4013 pciid = readb(rom + 4) | (readb(rom + 5) << 8); 4260#if defined(__i386__) || defined(__x86_64__)
4014 if(pciid != 0x1039) {
4015 iounmap(rom_base);
4016 continue;
4017 }
4018 4261
4019 pciid = readb(rom + 6) | (readb(rom + 7) << 8); 4262 for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4020 if(pciid == ivideo->chip_id) { 4263
4021 memcpy_fromio(myrombase, rom_base, 65536); 4264 rom_base = ioremap(temp, 65536);
4022 iounmap(rom_base); 4265 if(!rom_base)
4023 return myrombase; 4266 continue;
4024 } 4267
4268 if(!sisfb_check_rom(rom_base, ivideo)) {
4269 iounmap(rom_base);
4270 continue;
4271 }
4272
4273 if((myrombase = vmalloc(65536)))
4274 memcpy_fromio(myrombase, rom_base, 65536);
4275
4276 iounmap(rom_base);
4277 break;
4025 4278
4026 iounmap(rom_base);
4027 } 4279 }
4028 4280
4029#else 4281#else
@@ -4034,752 +4286,1603 @@ static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev)
4034 4286
4035 rom_base = ioremap(ivideo->video_base, 65536); 4287 rom_base = ioremap(ivideo->video_base, 65536);
4036 if(rom_base) { 4288 if(rom_base) {
4037 if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) { 4289 if(sisfb_check_rom(rom_base, ivideo)) {
4038 romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8)); 4290 if((myrombase = vmalloc(65536)))
4039 if(romptr <= (0x10000 - 8)) { 4291 memcpy_fromio(myrombase, rom_base, 65536);
4040 rom = rom_base + romptr; 4292 }
4041 if((readb(rom) == 'P') && (readb(rom + 1) == 'C') && 4293 iounmap(rom_base);
4042 (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) {
4043 pciid = readb(rom + 4) | (readb(rom + 5) << 8);
4044 if(pciid == 0x1039) {
4045 pciid = readb(rom + 6) | (readb(rom + 7) << 8);
4046 if(pciid == ivideo->chip_id) {
4047 memcpy_fromio(myrombase, rom_base, 65536);
4048 iounmap(rom_base);
4049 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
4050 return myrombase;
4051 }
4052 }
4053 }
4054 }
4055 }
4056 iounmap(rom_base);
4057 } 4294 }
4058 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp); 4295
4296 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
4059 4297
4060#endif 4298#endif
4061 4299
4062 vfree(myrombase); 4300 return myrombase;
4063 return NULL; 4301}
4302
4303static void __devinit
4304sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
4305 unsigned int min)
4306{
4307 ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
4308
4309 if(!ivideo->video_vbase) {
4310 printk(KERN_ERR
4311 "sisfb: Unable to map maximum video RAM for size detection\n");
4312 (*mapsize) >>= 1;
4313 while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
4314 (*mapsize) >>= 1;
4315 if((*mapsize) < (min << 20))
4316 break;
4317 }
4318 if(ivideo->video_vbase) {
4319 printk(KERN_ERR
4320 "sisfb: Video RAM size detection limited to %dMB\n",
4321 (int)((*mapsize) >> 20));
4322 }
4323 }
4064} 4324}
4065 4325
4066#ifdef CONFIG_FB_SIS_300 4326#ifdef CONFIG_FB_SIS_300
4067static int __devinit 4327static int __devinit
4068sisfb_chkbuswidth300(struct pci_dev *pdev, SIS_IOTYPE1 *FBAddress) 4328sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4069{ 4329{
4070 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4330 SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
4331 unsigned short temp;
4332 unsigned char reg;
4071 int i, j; 4333 int i, j;
4072 USHORT temp; 4334
4073 UCHAR reg; 4335 andSISIDXREG(SISSR, 0x15, 0xFB);
4074 4336 orSISIDXREG(SISSR, 0x15, 0x04);
4075 andSISIDXREG(SISSR,0x15,0xFB); 4337 outSISIDXREG(SISSR, 0x13, 0x00);
4076 orSISIDXREG(SISSR,0x15,0x04); 4338 outSISIDXREG(SISSR, 0x14, 0xBF);
4077 outSISIDXREG(SISSR,0x13,0x00); 4339
4078 outSISIDXREG(SISSR,0x14,0xBF); 4340 for(i = 0; i < 2; i++) {
4079 4341 temp = 0x1234;
4080 for(i=0; i<2; i++) { 4342 for(j = 0; j < 4; j++) {
4081 temp = 0x1234; 4343 writew(temp, FBAddress);
4082 for(j=0; j<4; j++) { 4344 if(readw(FBAddress) == temp)
4083 writew(temp, FBAddress); 4345 break;
4084 if(readw(FBAddress) == temp) break; 4346 orSISIDXREG(SISSR, 0x3c, 0x01);
4085 orSISIDXREG(SISSR,0x3c,0x01); 4347 inSISIDXREG(SISSR, 0x05, reg);
4086 inSISIDXREG(SISSR,0x05,reg); 4348 inSISIDXREG(SISSR, 0x05, reg);
4087 inSISIDXREG(SISSR,0x05,reg); 4349 andSISIDXREG(SISSR, 0x3c, 0xfe);
4088 andSISIDXREG(SISSR,0x3c,0xfe); 4350 inSISIDXREG(SISSR, 0x05, reg);
4089 inSISIDXREG(SISSR,0x05,reg); 4351 inSISIDXREG(SISSR, 0x05, reg);
4090 inSISIDXREG(SISSR,0x05,reg); 4352 temp++;
4091 temp++; 4353 }
4092 }
4093 } 4354 }
4094 4355
4095 writel(0x01234567L, FBAddress); 4356 writel(0x01234567L, FBAddress);
4096 writel(0x456789ABL, (FBAddress+4)); 4357 writel(0x456789ABL, (FBAddress + 4));
4097 writel(0x89ABCDEFL, (FBAddress+8)); 4358 writel(0x89ABCDEFL, (FBAddress + 8));
4098 writel(0xCDEF0123L, (FBAddress+12)); 4359 writel(0xCDEF0123L, (FBAddress + 12));
4099 inSISIDXREG(SISSR,0x3b,reg); 4360
4361 inSISIDXREG(SISSR, 0x3b, reg);
4100 if(reg & 0x01) { 4362 if(reg & 0x01) {
4101 if(readl((FBAddress+12)) == 0xCDEF0123L) return(4); /* Channel A 128bit */ 4363 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4364 return 4; /* Channel A 128bit */
4102 } 4365 }
4103 if(readl((FBAddress+4)) == 0x456789ABL) return(2); /* Channel B 64bit */ 4366
4104 return(1); /* 32bit */ 4367 if(readl((FBAddress + 4)) == 0x456789ABL)
4368 return 2; /* Channel B 64bit */
4369
4370 return 1; /* 32bit */
4371}
4372
4373static int __devinit
4374sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
4375 int PseudoRankCapacity, int PseudoAdrPinCount,
4376 unsigned int mapsize)
4377{
4378 SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
4379 unsigned short sr14;
4380 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4381 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4382 static const unsigned short SiS_DRAMType[17][5] = {
4383 {0x0C,0x0A,0x02,0x40,0x39},
4384 {0x0D,0x0A,0x01,0x40,0x48},
4385 {0x0C,0x09,0x02,0x20,0x35},
4386 {0x0D,0x09,0x01,0x20,0x44},
4387 {0x0C,0x08,0x02,0x10,0x31},
4388 {0x0D,0x08,0x01,0x10,0x40},
4389 {0x0C,0x0A,0x01,0x20,0x34},
4390 {0x0C,0x09,0x01,0x08,0x32},
4391 {0x0B,0x08,0x02,0x08,0x21},
4392 {0x0C,0x08,0x01,0x08,0x30},
4393 {0x0A,0x08,0x02,0x04,0x11},
4394 {0x0B,0x0A,0x01,0x10,0x28},
4395 {0x09,0x08,0x02,0x02,0x01},
4396 {0x0B,0x09,0x01,0x08,0x24},
4397 {0x0B,0x08,0x01,0x04,0x20},
4398 {0x0A,0x08,0x01,0x02,0x10},
4399 {0x09,0x08,0x01,0x01,0x00}
4400 };
4401
4402 for(k = 0; k <= 16; k++) {
4403
4404 RankCapacity = buswidth * SiS_DRAMType[k][3];
4405
4406 if(RankCapacity != PseudoRankCapacity)
4407 continue;
4408
4409 if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4410 continue;
4411
4412 BankNumHigh = RankCapacity * 16 * iteration - 1;
4413 if(iteration == 3) { /* Rank No */
4414 BankNumMid = RankCapacity * 16 - 1;
4415 } else {
4416 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4417 }
4418
4419 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4420 PhysicalAdrHigh = BankNumHigh;
4421 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4422 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4423
4424 andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
4425 orSISIDXREG(SISSR, 0x15, 0x04); /* Test */
4426 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4427 if(buswidth == 4) sr14 |= 0x80;
4428 else if(buswidth == 2) sr14 |= 0x40;
4429 outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
4430 outSISIDXREG(SISSR, 0x14, sr14);
4431
4432 BankNumHigh <<= 16;
4433 BankNumMid <<= 16;
4434
4435 if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4436 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4437 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4438 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4439 continue;
4440
4441 /* Write data */
4442 writew(((unsigned short)PhysicalAdrHigh),
4443 (FBAddr + BankNumHigh + PhysicalAdrHigh));
4444 writew(((unsigned short)BankNumMid),
4445 (FBAddr + BankNumMid + PhysicalAdrHigh));
4446 writew(((unsigned short)PhysicalAdrHalfPage),
4447 (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4448 writew(((unsigned short)PhysicalAdrOtherPage),
4449 (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4450
4451 /* Read data */
4452 if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4453 return 1;
4454 }
4455
4456 return 0;
4105} 4457}
4106 4458
4107static void __devinit 4459static void __devinit
4108sisfb_setramsize300(struct pci_dev *pdev) 4460sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4109{ 4461{
4110 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4462 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4111 SIS_IOTYPE1 *FBAddr = ivideo->video_vbase; 4463 int i, j, buswidth;
4112 SIS_IOTYPE1 *Addr; 4464 int PseudoRankCapacity, PseudoAdrPinCount;
4113 USHORT sr13, sr14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0; 4465
4114 int PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount; 4466 buswidth = sisfb_post_300_buswidth(ivideo);
4115 int RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank; 4467
4116 int PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k; 4468 for(i = 6; i >= 0; i--) {
4117 const USHORT SiS_DRAMType[17][5] = { 4469 PseudoRankCapacity = 1 << i;
4118 {0x0C,0x0A,0x02,0x40,0x39}, 4470 for(j = 4; j >= 1; j--) {
4119 {0x0D,0x0A,0x01,0x40,0x48}, 4471 PseudoAdrPinCount = 15 - j;
4120 {0x0C,0x09,0x02,0x20,0x35}, 4472 if((PseudoRankCapacity * j) <= 64) {
4121 {0x0D,0x09,0x01,0x20,0x44}, 4473 if(sisfb_post_300_rwtest(ivideo,
4122 {0x0C,0x08,0x02,0x10,0x31}, 4474 j,
4123 {0x0D,0x08,0x01,0x10,0x40}, 4475 buswidth,
4124 {0x0C,0x0A,0x01,0x20,0x34}, 4476 PseudoRankCapacity,
4125 {0x0C,0x09,0x01,0x08,0x32}, 4477 PseudoAdrPinCount,
4126 {0x0B,0x08,0x02,0x08,0x21}, 4478 mapsize))
4127 {0x0C,0x08,0x01,0x08,0x30}, 4479 return;
4128 {0x0A,0x08,0x02,0x04,0x11}, 4480 }
4129 {0x0B,0x0A,0x01,0x10,0x28}, 4481 }
4130 {0x09,0x08,0x02,0x02,0x01}, 4482 }
4131 {0x0B,0x09,0x01,0x08,0x24},
4132 {0x0B,0x08,0x01,0x04,0x20},
4133 {0x0A,0x08,0x01,0x02,0x10},
4134 {0x09,0x08,0x01,0x01,0x00}
4135 };
4136
4137 buswidth = sisfb_chkbuswidth300(pdev, FBAddr);
4138
4139 MB2Bank = 16;
4140 Done = 0;
4141 for(i = 6; i >= 0; i--) {
4142 if(Done) break;
4143 PseudoRankCapacity = 1 << i;
4144 for(j = 4; j >= 1; j--) {
4145 if(Done) break;
4146 PseudoTotalCapacity = PseudoRankCapacity * j;
4147 PseudoAdrPinCount = 15 - j;
4148 if(PseudoTotalCapacity <= 64) {
4149 for(k = 0; k <= 16; k++) {
4150 if(Done) break;
4151 RankCapacity = buswidth * SiS_DRAMType[k][3];
4152 AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0];
4153 if(RankCapacity == PseudoRankCapacity)
4154 if(AdrPinCount <= PseudoAdrPinCount) {
4155 if(j == 3) { /* Rank No */
4156 BankNumHigh = RankCapacity * MB2Bank * 3 - 1;
4157 BankNumMid = RankCapacity * MB2Bank * 1 - 1;
4158 } else {
4159 BankNumHigh = RankCapacity * MB2Bank * j - 1;
4160 BankNumMid = RankCapacity * MB2Bank * j / 2 - 1;
4161 }
4162 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4163 PhysicalAdrHigh = BankNumHigh;
4164 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4165 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4166 /* Write data */
4167 andSISIDXREG(SISSR,0x15,0xFB); /* Test */
4168 orSISIDXREG(SISSR,0x15,0x04); /* Test */
4169 TotalCapacity = SiS_DRAMType[k][3] * buswidth;
4170 sr13 = SiS_DRAMType[k][4];
4171 if(buswidth == 4) sr14 = (TotalCapacity - 1) | 0x80;
4172 if(buswidth == 2) sr14 = (TotalCapacity - 1) | 0x40;
4173 if(buswidth == 1) sr14 = (TotalCapacity - 1) | 0x00;
4174 outSISIDXREG(SISSR,0x13,sr13);
4175 outSISIDXREG(SISSR,0x14,sr14);
4176 Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
4177 /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */
4178 writew(((USHORT)PhysicalAdrHigh), Addr);
4179 Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh;
4180 /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */
4181 writew(((USHORT)BankNumMid), Addr);
4182 Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage;
4183 /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */
4184 writew(((USHORT)PhysicalAdrHalfPage), Addr);
4185 Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage;
4186 /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */
4187 writew(((USHORT)PhysicalAdrOtherPage), Addr);
4188 /* Read data */
4189 Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
4190 data = readw(Addr); /* *((USHORT *)(Addr)); */
4191 if(data == PhysicalAdrHigh) Done = 1;
4192 } /* if */
4193 } /* for k */
4194 } /* if */
4195 } /* for j */
4196 } /* for i */
4197} 4483}
4198 4484
4199static void __devinit sisfb_post_sis300(struct pci_dev *pdev) 4485static void __devinit
4486sisfb_post_sis300(struct pci_dev *pdev)
4200{ 4487{
4201 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4488 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4489 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4202 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8; 4490 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4203 u16 index, rindex, memtype = 0; 4491 u16 index, rindex, memtype = 0;
4492 unsigned int mapsize;
4204 4493
4205 outSISIDXREG(SISSR,0x05,0x86); 4494 if(!ivideo->SiS_Pr.UseROM)
4495 bios = NULL;
4206 4496
4207 if(ivideo->sishw_ext.UseROM) { 4497 outSISIDXREG(SISSR, 0x05, 0x86);
4208 if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) { 4498
4209 memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52]; 4499 if(bios) {
4210 } else { 4500 if(bios[0x52] & 0x80) {
4211 inSISIDXREG(SISSR,0x3a,memtype); 4501 memtype = bios[0x52];
4212 } 4502 } else {
4213 memtype &= 0x07; 4503 inSISIDXREG(SISSR, 0x3a, memtype);
4504 }
4505 memtype &= 0x07;
4214 } 4506 }
4215 4507
4508 v3 = 0x80; v6 = 0x80;
4216 if(ivideo->revision_id <= 0x13) { 4509 if(ivideo->revision_id <= 0x13) {
4217 v1 = 0x44; v2 = 0x42; v3 = 0x80; 4510 v1 = 0x44; v2 = 0x42;
4218 v4 = 0x44; v5 = 0x42; v6 = 0x80; 4511 v4 = 0x44; v5 = 0x42;
4219 } else { 4512 } else {
4220 v1 = 0x68; v2 = 0x43; v3 = 0x80; /* Assume 125Mhz MCLK */ 4513 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4221 v4 = 0x68; v5 = 0x43; v6 = 0x80; /* Assume 125Mhz ECLK */ 4514 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4222 if(ivideo->sishw_ext.UseROM) { 4515 if(bios) {
4223 index = memtype * 5; 4516 index = memtype * 5;
4224 rindex = index + 0x54; 4517 rindex = index + 0x54;
4225 v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 4518 v1 = bios[rindex++];
4226 v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 4519 v2 = bios[rindex++];
4227 v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 4520 v3 = bios[rindex++];
4228 rindex = index + 0x7c; 4521 rindex = index + 0x7c;
4229 v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 4522 v4 = bios[rindex++];
4230 v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 4523 v5 = bios[rindex++];
4231 v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 4524 v6 = bios[rindex++];
4232 } 4525 }
4233 } 4526 }
4234 outSISIDXREG(SISSR,0x28,v1); 4527 outSISIDXREG(SISSR, 0x28, v1);
4235 outSISIDXREG(SISSR,0x29,v2); 4528 outSISIDXREG(SISSR, 0x29, v2);
4236 outSISIDXREG(SISSR,0x2a,v3); 4529 outSISIDXREG(SISSR, 0x2a, v3);
4237 outSISIDXREG(SISSR,0x2e,v4); 4530 outSISIDXREG(SISSR, 0x2e, v4);
4238 outSISIDXREG(SISSR,0x2f,v5); 4531 outSISIDXREG(SISSR, 0x2f, v5);
4239 outSISIDXREG(SISSR,0x30,v6); 4532 outSISIDXREG(SISSR, 0x30, v6);
4533
4240 v1 = 0x10; 4534 v1 = 0x10;
4241 if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4]; 4535 if(bios)
4242 outSISIDXREG(SISSR,0x07,v1); /* DAC speed */ 4536 v1 = bios[0xa4];
4243 outSISIDXREG(SISSR,0x11,0x0f); /* DDC, power save */ 4537 outSISIDXREG(SISSR, 0x07, v1); /* DAC speed */
4538
4539 outSISIDXREG(SISSR, 0x11, 0x0f); /* DDC, power save */
4540
4244 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a; 4541 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4245 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00; 4542 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4246 if(ivideo->sishw_ext.UseROM) { 4543 if(bios) {
4247 memtype += 0xa5; 4544 memtype += 0xa5;
4248 v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype]; 4545 v1 = bios[memtype];
4249 v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8]; 4546 v2 = bios[memtype + 8];
4250 v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16]; 4547 v3 = bios[memtype + 16];
4251 v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24]; 4548 v4 = bios[memtype + 24];
4252 v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32]; 4549 v5 = bios[memtype + 32];
4253 v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40]; 4550 v6 = bios[memtype + 40];
4254 v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48]; 4551 v7 = bios[memtype + 48];
4255 v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56]; 4552 v8 = bios[memtype + 56];
4256 } 4553 }
4257 if(ivideo->revision_id >= 0x80) v3 &= 0xfd; 4554 if(ivideo->revision_id >= 0x80)
4258 outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */ 4555 v3 &= 0xfd;
4259 outSISIDXREG(SISSR,0x16,v2); 4556 outSISIDXREG(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4260 outSISIDXREG(SISSR,0x17,v3); 4557 outSISIDXREG(SISSR, 0x16, v2);
4261 outSISIDXREG(SISSR,0x18,v4); 4558 outSISIDXREG(SISSR, 0x17, v3);
4262 outSISIDXREG(SISSR,0x19,v5); 4559 outSISIDXREG(SISSR, 0x18, v4);
4263 outSISIDXREG(SISSR,0x1a,v6); 4560 outSISIDXREG(SISSR, 0x19, v5);
4264 outSISIDXREG(SISSR,0x1b,v7); 4561 outSISIDXREG(SISSR, 0x1a, v6);
4265 outSISIDXREG(SISSR,0x1c,v8); /* ---- */ 4562 outSISIDXREG(SISSR, 0x1b, v7);
4266 andSISIDXREG(SISSR,0x15,0xfb); 4563 outSISIDXREG(SISSR, 0x1c, v8); /* ---- */
4267 orSISIDXREG(SISSR,0x15,0x04); 4564 andSISIDXREG(SISSR, 0x15 ,0xfb);
4268 if(ivideo->sishw_ext.UseROM) { 4565 orSISIDXREG(SISSR, 0x15, 0x04);
4269 if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) { 4566 if(bios) {
4270 orSISIDXREG(SISSR,0x19,0x20); 4567 if(bios[0x53] & 0x02) {
4271 } 4568 orSISIDXREG(SISSR, 0x19, 0x20);
4569 }
4272 } 4570 }
4273 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */ 4571 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4274 if(ivideo->revision_id >= 0x80) v1 |= 0x01; 4572 if(ivideo->revision_id >= 0x80)
4275 outSISIDXREG(SISSR,0x1f,v1); 4573 v1 |= 0x01;
4276 outSISIDXREG(SISSR,0x20,0xa0); /* linear & relocated io */ 4574 outSISIDXREG(SISSR, 0x1f, v1);
4575 outSISIDXREG(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4277 v1 = 0xf6; v2 = 0x0d; v3 = 0x00; 4576 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4278 if(ivideo->sishw_ext.UseROM) { 4577 if(bios) {
4279 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8]; 4578 v1 = bios[0xe8];
4280 v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9]; 4579 v2 = bios[0xe9];
4281 v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea]; 4580 v3 = bios[0xea];
4282 } 4581 }
4283 outSISIDXREG(SISSR,0x23,v1); 4582 outSISIDXREG(SISSR, 0x23, v1);
4284 outSISIDXREG(SISSR,0x24,v2); 4583 outSISIDXREG(SISSR, 0x24, v2);
4285 outSISIDXREG(SISSR,0x25,v3); 4584 outSISIDXREG(SISSR, 0x25, v3);
4286 outSISIDXREG(SISSR,0x21,0x84); 4585 outSISIDXREG(SISSR, 0x21, 0x84);
4287 outSISIDXREG(SISSR,0x22,0x00); 4586 outSISIDXREG(SISSR, 0x22, 0x00);
4288 outSISIDXREG(SISCR,0x37,0x00); 4587 outSISIDXREG(SISCR, 0x37, 0x00);
4289 orSISIDXREG(SISPART1,0x24,0x01); /* unlock crt2 */ 4588 orSISIDXREG(SISPART1, 0x24, 0x01); /* unlock crt2 */
4290 outSISIDXREG(SISPART1,0x00,0x00); 4589 outSISIDXREG(SISPART1, 0x00, 0x00);
4291 v1 = 0x40; v2 = 0x11; 4590 v1 = 0x40; v2 = 0x11;
4292 if(ivideo->sishw_ext.UseROM) { 4591 if(bios) {
4293 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec]; 4592 v1 = bios[0xec];
4294 v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb]; 4593 v2 = bios[0xeb];
4295 } 4594 }
4296 outSISIDXREG(SISPART1,0x02,v1); 4595 outSISIDXREG(SISPART1, 0x02, v1);
4297 if(ivideo->revision_id >= 0x80) v2 &= ~0x01; 4596
4298 inSISIDXREG(SISPART4,0x00,reg); 4597 if(ivideo->revision_id >= 0x80)
4598 v2 &= ~0x01;
4599
4600 inSISIDXREG(SISPART4, 0x00, reg);
4299 if((reg == 1) || (reg == 2)) { 4601 if((reg == 1) || (reg == 2)) {
4300 outSISIDXREG(SISCR,0x37,0x02); 4602 outSISIDXREG(SISCR, 0x37, 0x02);
4301 outSISIDXREG(SISPART2,0x00,0x1c); 4603 outSISIDXREG(SISPART2, 0x00, 0x1c);
4302 v4 = 0x00; v5 = 0x00; v6 = 0x10; 4604 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4303 if(ivideo->sishw_ext.UseROM) { 4605 if(ivideo->SiS_Pr.UseROM) {
4304 v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5]; 4606 v4 = bios[0xf5];
4305 v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6]; 4607 v5 = bios[0xf6];
4306 v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7]; 4608 v6 = bios[0xf7];
4307 } 4609 }
4308 outSISIDXREG(SISPART4,0x0d,v4); 4610 outSISIDXREG(SISPART4, 0x0d, v4);
4309 outSISIDXREG(SISPART4,0x0e,v5); 4611 outSISIDXREG(SISPART4, 0x0e, v5);
4310 outSISIDXREG(SISPART4,0x10,v6); 4612 outSISIDXREG(SISPART4, 0x10, v6);
4311 outSISIDXREG(SISPART4,0x0f,0x3f); 4613 outSISIDXREG(SISPART4, 0x0f, 0x3f);
4312 inSISIDXREG(SISPART4,0x01,reg); 4614 inSISIDXREG(SISPART4, 0x01, reg);
4313 if(reg >= 0xb0) { 4615 if(reg >= 0xb0) {
4314 inSISIDXREG(SISPART4,0x23,reg); 4616 inSISIDXREG(SISPART4, 0x23, reg);
4315 reg &= 0x20; 4617 reg &= 0x20;
4316 reg <<= 1; 4618 reg <<= 1;
4317 outSISIDXREG(SISPART4,0x23,reg); 4619 outSISIDXREG(SISPART4, 0x23, reg);
4318 } 4620 }
4319 } else { 4621 } else {
4320 v2 &= ~0x10; 4622 v2 &= ~0x10;
4321 } 4623 }
4322 outSISIDXREG(SISSR,0x32,v2); 4624 outSISIDXREG(SISSR, 0x32, v2);
4323 andSISIDXREG(SISPART1,0x24,0xfe); /* Lock CRT2 */ 4625
4324 inSISIDXREG(SISSR,0x16,reg); 4626 andSISIDXREG(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4627
4628 inSISIDXREG(SISSR, 0x16, reg);
4325 reg &= 0xc3; 4629 reg &= 0xc3;
4326 outSISIDXREG(SISCR,0x35,reg); 4630 outSISIDXREG(SISCR, 0x35, reg);
4327 outSISIDXREG(SISCR,0x83,0x00); 4631 outSISIDXREG(SISCR, 0x83, 0x00);
4328#if !defined(__i386__) && !defined(__x86_64__) 4632#if !defined(__i386__) && !defined(__x86_64__)
4329 if(sisfb_videoram) { 4633 if(sisfb_videoram) {
4330 outSISIDXREG(SISSR,0x13,0x28); /* ? */ 4634 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
4331 reg = ((sisfb_videoram >> 10) - 1) | 0x40; 4635 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4332 outSISIDXREG(SISSR,0x14,reg); 4636 outSISIDXREG(SISSR, 0x14, reg);
4333 } else { 4637 } else {
4334#endif 4638#endif
4335 /* Need to map max FB size for finding out about RAM size */ 4639 /* Need to map max FB size for finding out about RAM size */
4336 ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000); 4640 mapsize = 64 << 20;
4337 if(ivideo->video_vbase) { 4641 sisfb_post_map_vram(ivideo, &mapsize, 4);
4338 sisfb_setramsize300(pdev); 4642
4339 iounmap(ivideo->video_vbase); 4643 if(ivideo->video_vbase) {
4340 } else { 4644 sisfb_post_300_ramsize(pdev, mapsize);
4341 printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n"); 4645 iounmap(ivideo->video_vbase);
4342 outSISIDXREG(SISSR,0x13,0x28); /* ? */ 4646 } else {
4343 outSISIDXREG(SISSR,0x14,0x47); /* 8MB, 64bit default */ 4647 printk(KERN_DEBUG
4344 } 4648 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4649 outSISIDXREG(SISSR, 0x13, 0x28); /* ? */
4650 outSISIDXREG(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4651 }
4345#if !defined(__i386__) && !defined(__x86_64__) 4652#if !defined(__i386__) && !defined(__x86_64__)
4346 } 4653 }
4347#endif 4654#endif
4348 if(ivideo->sishw_ext.UseROM) { 4655 if(bios) {
4349 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6]; 4656 v1 = bios[0xe6];
4350 v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7]; 4657 v2 = bios[0xe7];
4351 } else { 4658 } else {
4352 inSISIDXREG(SISSR,0x3a,reg); 4659 inSISIDXREG(SISSR, 0x3a, reg);
4353 if((reg & 0x30) == 0x30) { 4660 if((reg & 0x30) == 0x30) {
4354 v1 = 0x04; /* PCI */ 4661 v1 = 0x04; /* PCI */
4355 v2 = 0x92; 4662 v2 = 0x92;
4356 } else { 4663 } else {
4357 v1 = 0x14; /* AGP */ 4664 v1 = 0x14; /* AGP */
4358 v2 = 0xb2; 4665 v2 = 0xb2;
4359 } 4666 }
4360 } 4667 }
4361 outSISIDXREG(SISSR,0x21,v1); 4668 outSISIDXREG(SISSR, 0x21, v1);
4362 outSISIDXREG(SISSR,0x22,v2); 4669 outSISIDXREG(SISSR, 0x22, v2);
4670
4671 /* Sense CRT1 */
4672 sisfb_sense_crt1(ivideo);
4673
4674 /* Set default mode, don't clear screen */
4675 ivideo->SiS_Pr.SiS_UseOEM = FALSE;
4676 SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
4677 SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
4678 ivideo->curFSTN = ivideo->curDSTN = 0;
4679 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4680 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4681
4682 outSISIDXREG(SISSR, 0x05, 0x86);
4683
4684 /* Display off */
4685 orSISIDXREG(SISSR, 0x01, 0x20);
4686
4687 /* Save mode number in CR34 */
4688 outSISIDXREG(SISCR, 0x34, 0x2e);
4689
4690 /* Let everyone know what the current mode is */
4691 ivideo->modeprechange = 0x2e;
4363} 4692}
4364#endif 4693#endif
4365 4694
4366#ifdef CONFIG_FB_SIS_315 4695#ifdef CONFIG_FB_SIS_315
4367static void __devinit sisfb_post_sis315330(struct pci_dev *pdev) 4696#if 0
4697static void __devinit
4698sisfb_post_sis315330(struct pci_dev *pdev)
4368{ 4699{
4369#ifdef YET_TO_BE_DONE 4700 /* TODO */
4370 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4701}
4371 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8; 4702#endif
4372 u16 index, rindex, memtype = 0; 4703
4373 u32 reg1_32, reg2_32, reg3_32; 4704static void __devinit
4705sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4706{
4707 unsigned int i;
4708 u8 reg;
4709
4710 for(i = 0; i <= (delay * 10 * 36); i++) {
4711 inSISIDXREG(SISSR, 0x05, reg);
4712 reg++;
4713 }
4714}
4715
4716static int __devinit
4717sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
4718 unsigned short pcivendor)
4719{
4720 struct pci_dev *pdev = NULL;
4721 unsigned short temp;
4722 int ret = 0;
4723
4724 while((pdev = SIS_PCI_GET_CLASS(PCI_CLASS_BRIDGE_HOST, pdev))) {
4725 temp = pdev->vendor;
4726 SIS_PCI_PUT_DEVICE(pdev);
4727 if(temp == pcivendor) {
4728 ret = 1;
4729 break;
4730 }
4731 }
4732
4733 return ret;
4734}
4735
4736static int __devinit
4737sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4738 unsigned int enda, unsigned int mapsize)
4739{
4740 unsigned int pos;
4374 int i; 4741 int i;
4375 4742
4376 /* Unlock */ 4743 writel(0, ivideo->video_vbase);
4377 /* outSISIDXREG(0x3c4,0x05,0x86); */
4378 outSISIDXREG(SISSR,0x05,0x86);
4379 4744
4380 /* Enable relocated i/o ports */ 4745 for(i = starta; i <= enda; i++) {
4381 /* setSISIDXREG(0x3c4,0x20,~0x10,0x20); */ 4746 pos = 1 << i;
4382 setSISIDXREG(SISSR,0x20,~0x10,0x20); 4747 if(pos < mapsize)
4748 writel(pos, ivideo->video_vbase + pos);
4749 }
4750
4751 sisfb_post_xgi_delay(ivideo, 150);
4752
4753 if(readl(ivideo->video_vbase) != 0)
4754 return 0;
4383 4755
4384 /* Clear regs */ 4756 for(i = starta; i <= enda; i++) {
4757 pos = 1 << i;
4758 if(pos < mapsize) {
4759 if(readl(ivideo->video_vbase + pos) != pos)
4760 return 0;
4761 } else
4762 return 0;
4763 }
4764
4765 return 1;
4766}
4767
4768static void __devinit
4769sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4770{
4771 unsigned int buswidth, ranksize, channelab, mapsize;
4772 int i, j, k, l;
4773 u8 reg, sr14;
4774 static const u8 dramsr13[12 * 5] = {
4775 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4776 0x02, 0x0e, 0x0a, 0x40, 0x59,
4777 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4778 0x02, 0x0e, 0x09, 0x20, 0x55,
4779 0x02, 0x0d, 0x0a, 0x20, 0x49,
4780 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4781 0x02, 0x0e, 0x08, 0x10, 0x51,
4782 0x02, 0x0d, 0x09, 0x10, 0x45,
4783 0x02, 0x0c, 0x0a, 0x10, 0x39,
4784 0x02, 0x0d, 0x08, 0x08, 0x41,
4785 0x02, 0x0c, 0x09, 0x08, 0x35,
4786 0x02, 0x0c, 0x08, 0x04, 0x31
4787 };
4788 static const u8 dramsr13_4[4 * 5] = {
4789 0x02, 0x0d, 0x09, 0x40, 0x45,
4790 0x02, 0x0c, 0x09, 0x20, 0x35,
4791 0x02, 0x0c, 0x08, 0x10, 0x31,
4792 0x02, 0x0b, 0x08, 0x08, 0x21
4793 };
4794
4795 /* Enable linear mode, disable 0xa0000 address decoding */
4796 /* We disable a0000 address decoding, because
4797 * - if running on x86, if the card is disabled, it means
4798 * that another card is in the system. We don't want
4799 * to interphere with that primary card's textmode.
4800 * - if running on non-x86, there usually is no VGA window
4801 * at a0000.
4802 */
4803 orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
4804
4805 /* Need to map max FB size for finding out about RAM size */
4806 mapsize = 256 << 20;
4807 sisfb_post_map_vram(ivideo, &mapsize, 32);
4808
4809 if(!ivideo->video_vbase) {
4810 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4811 outSISIDXREG(SISSR, 0x13, 0x35);
4812 outSISIDXREG(SISSR, 0x14, 0x41);
4813 /* TODO */
4814 return;
4815 }
4816
4817 /* Non-interleaving */
4818 outSISIDXREG(SISSR, 0x15, 0x00);
4819 /* No tiling */
4820 outSISIDXREG(SISSR, 0x1c, 0x00);
4821
4822 if(ivideo->chip == XGI_20) {
4823
4824 channelab = 1;
4825 inSISIDXREG(SISCR, 0x97, reg);
4826 if(!(reg & 0x01)) { /* Single 32/16 */
4827 buswidth = 32;
4828 outSISIDXREG(SISSR, 0x13, 0xb1);
4829 outSISIDXREG(SISSR, 0x14, 0x52);
4830 sisfb_post_xgi_delay(ivideo, 1);
4831 sr14 = 0x02;
4832 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4833 goto bail_out;
4834
4835 outSISIDXREG(SISSR, 0x13, 0x31);
4836 outSISIDXREG(SISSR, 0x14, 0x42);
4837 sisfb_post_xgi_delay(ivideo, 1);
4838 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4839 goto bail_out;
4840
4841 buswidth = 16;
4842 outSISIDXREG(SISSR, 0x13, 0xb1);
4843 outSISIDXREG(SISSR, 0x14, 0x41);
4844 sisfb_post_xgi_delay(ivideo, 1);
4845 sr14 = 0x01;
4846 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4847 goto bail_out;
4848 else
4849 outSISIDXREG(SISSR, 0x13, 0x31);
4850 } else { /* Dual 16/8 */
4851 buswidth = 16;
4852 outSISIDXREG(SISSR, 0x13, 0xb1);
4853 outSISIDXREG(SISSR, 0x14, 0x41);
4854 sisfb_post_xgi_delay(ivideo, 1);
4855 sr14 = 0x01;
4856 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4857 goto bail_out;
4858
4859 outSISIDXREG(SISSR, 0x13, 0x31);
4860 outSISIDXREG(SISSR, 0x14, 0x31);
4861 sisfb_post_xgi_delay(ivideo, 1);
4862 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4863 goto bail_out;
4864
4865 buswidth = 8;
4866 outSISIDXREG(SISSR, 0x13, 0xb1);
4867 outSISIDXREG(SISSR, 0x14, 0x30);
4868 sisfb_post_xgi_delay(ivideo, 1);
4869 sr14 = 0x00;
4870 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4871 goto bail_out;
4872 else
4873 outSISIDXREG(SISSR, 0x13, 0x31);
4874 }
4875
4876 } else { /* XGI_40 */
4877
4878 inSISIDXREG(SISCR, 0x97, reg);
4879 if(!(reg & 0x10)) {
4880 inSISIDXREG(SISSR, 0x39, reg);
4881 reg >>= 1;
4882 }
4883
4884 if(reg & 0x01) { /* DDRII */
4885 buswidth = 32;
4886 if(ivideo->revision_id == 2) {
4887 channelab = 2;
4888 outSISIDXREG(SISSR, 0x13, 0xa1);
4889 outSISIDXREG(SISSR, 0x14, 0x44);
4890 sr14 = 0x04;
4891 sisfb_post_xgi_delay(ivideo, 1);
4892 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4893 goto bail_out;
4894
4895 outSISIDXREG(SISSR, 0x13, 0x21);
4896 outSISIDXREG(SISSR, 0x14, 0x34);
4897 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4898 goto bail_out;
4899
4900 channelab = 1;
4901 outSISIDXREG(SISSR, 0x13, 0xa1);
4902 outSISIDXREG(SISSR, 0x14, 0x40);
4903 sr14 = 0x00;
4904 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4905 goto bail_out;
4906
4907 outSISIDXREG(SISSR, 0x13, 0x21);
4908 outSISIDXREG(SISSR, 0x14, 0x30);
4909 } else {
4910 channelab = 3;
4911 outSISIDXREG(SISSR, 0x13, 0xa1);
4912 outSISIDXREG(SISSR, 0x14, 0x4c);
4913 sr14 = 0x0c;
4914 sisfb_post_xgi_delay(ivideo, 1);
4915 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4916 goto bail_out;
4917
4918 channelab = 2;
4919 outSISIDXREG(SISSR, 0x14, 0x48);
4920 sisfb_post_xgi_delay(ivideo, 1);
4921 sr14 = 0x08;
4922 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4923 goto bail_out;
4924
4925 outSISIDXREG(SISSR, 0x13, 0x21);
4926 outSISIDXREG(SISSR, 0x14, 0x3c);
4927 sr14 = 0x0c;
4928
4929 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4930 channelab = 3;
4931 } else {
4932 channelab = 2;
4933 outSISIDXREG(SISSR, 0x14, 0x38);
4934 sr14 = 0x08;
4935 }
4936 }
4937 sisfb_post_xgi_delay(ivideo, 1);
4938
4939 } else { /* DDR */
4940
4941 buswidth = 64;
4942 if(ivideo->revision_id == 2) {
4943 channelab = 1;
4944 outSISIDXREG(SISSR, 0x13, 0xa1);
4945 outSISIDXREG(SISSR, 0x14, 0x52);
4946 sisfb_post_xgi_delay(ivideo, 1);
4947 sr14 = 0x02;
4948 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4949 goto bail_out;
4950
4951 outSISIDXREG(SISSR, 0x13, 0x21);
4952 outSISIDXREG(SISSR, 0x14, 0x42);
4953 } else {
4954 channelab = 2;
4955 outSISIDXREG(SISSR, 0x13, 0xa1);
4956 outSISIDXREG(SISSR, 0x14, 0x5a);
4957 sisfb_post_xgi_delay(ivideo, 1);
4958 sr14 = 0x0a;
4959 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4960 goto bail_out;
4961
4962 outSISIDXREG(SISSR, 0x13, 0x21);
4963 outSISIDXREG(SISSR, 0x14, 0x4a);
4964 }
4965 sisfb_post_xgi_delay(ivideo, 1);
4966
4967 }
4968 }
4969
4970bail_out:
4971 setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
4972 sisfb_post_xgi_delay(ivideo, 1);
4973
4974 j = (ivideo->chip == XGI_20) ? 5 : 9;
4975 k = (ivideo->chip == XGI_20) ? 12 : 4;
4976
4977 for(i = 0; i < k; i++) {
4978
4979 reg = (ivideo->chip == XGI_20) ?
4980 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4981 setSISIDXREG(SISSR, 0x13, 0x80, reg);
4982 sisfb_post_xgi_delay(ivideo, 50);
4983
4984 ranksize = (ivideo->chip == XGI_20) ?
4985 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4986
4987 inSISIDXREG(SISSR, 0x13, reg);
4988 if(reg & 0x80) ranksize <<= 1;
4989
4990 if(ivideo->chip == XGI_20) {
4991 if(buswidth == 16) ranksize <<= 1;
4992 else if(buswidth == 32) ranksize <<= 2;
4993 } else {
4994 if(buswidth == 64) ranksize <<= 1;
4995 }
4996
4997 reg = 0;
4998 l = channelab;
4999 if(l == 3) l = 4;
5000 if((ranksize * l) <= 256) {
5001 while((ranksize >>= 1)) reg += 0x10;
5002 }
5003
5004 if(!reg) continue;
5005
5006 setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
5007 sisfb_post_xgi_delay(ivideo, 1);
5008
5009 if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
5010 break;
5011 }
5012
5013 iounmap(ivideo->video_vbase);
5014}
5015
5016static void __devinit
5017sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
5018{
5019 u8 v1, v2, v3;
5020 int index;
5021 static const u8 cs90[8 * 3] = {
5022 0x16, 0x01, 0x01,
5023 0x3e, 0x03, 0x01,
5024 0x7c, 0x08, 0x01,
5025 0x79, 0x06, 0x01,
5026 0x29, 0x01, 0x81,
5027 0x5c, 0x23, 0x01,
5028 0x5c, 0x23, 0x01,
5029 0x5c, 0x23, 0x01
5030 };
5031 static const u8 csb8[8 * 3] = {
5032 0x5c, 0x23, 0x01,
5033 0x29, 0x01, 0x01,
5034 0x7c, 0x08, 0x01,
5035 0x79, 0x06, 0x01,
5036 0x29, 0x01, 0x81,
5037 0x5c, 0x23, 0x01,
5038 0x5c, 0x23, 0x01,
5039 0x5c, 0x23, 0x01
5040 };
5041
5042 regb = 0; /* ! */
5043
5044 index = regb * 3;
5045 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
5046 if(ivideo->haveXGIROM) {
5047 v1 = ivideo->bios_abase[0x90 + index];
5048 v2 = ivideo->bios_abase[0x90 + index + 1];
5049 v3 = ivideo->bios_abase[0x90 + index + 2];
5050 }
5051 outSISIDXREG(SISSR, 0x28, v1);
5052 outSISIDXREG(SISSR, 0x29, v2);
5053 outSISIDXREG(SISSR, 0x2a, v3);
5054 sisfb_post_xgi_delay(ivideo, 0x43);
5055 sisfb_post_xgi_delay(ivideo, 0x43);
5056 sisfb_post_xgi_delay(ivideo, 0x43);
5057 index = regb * 3;
5058 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
5059 if(ivideo->haveXGIROM) {
5060 v1 = ivideo->bios_abase[0xb8 + index];
5061 v2 = ivideo->bios_abase[0xb8 + index + 1];
5062 v3 = ivideo->bios_abase[0xb8 + index + 2];
5063 }
5064 outSISIDXREG(SISSR, 0x2e, v1);
5065 outSISIDXREG(SISSR, 0x2f, v2);
5066 outSISIDXREG(SISSR, 0x30, v3);
5067 sisfb_post_xgi_delay(ivideo, 0x43);
5068 sisfb_post_xgi_delay(ivideo, 0x43);
5069 sisfb_post_xgi_delay(ivideo, 0x43);
5070}
5071
5072static int __devinit
5073sisfb_post_xgi(struct pci_dev *pdev)
5074{
5075 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5076 unsigned char *bios = ivideo->bios_abase;
5077 struct pci_dev *mypdev = NULL;
5078 const u8 *ptr, *ptr2;
5079 u8 v1, v2, v3, v4, v5, reg, ramtype;
5080 u32 rega, regb, regd;
5081 int i, j, k, index;
5082 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5083 static const u8 cs76[2] = { 0xa3, 0xfb };
5084 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5085 static const u8 cs158[8] = {
5086 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5087 };
5088 static const u8 cs160[8] = {
5089 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5090 };
5091 static const u8 cs168[8] = {
5092 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5093 };
5094 static const u8 cs128[3 * 8] = {
5095 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5096 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5097 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5098 };
5099 static const u8 cs148[2 * 8] = {
5100 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5102 };
5103 static const u8 cs31a[8 * 4] = {
5104 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5105 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5108 };
5109 static const u8 cs33a[8 * 4] = {
5110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5114 };
5115 static const u8 cs45a[8 * 2] = {
5116 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5118 };
5119 static const u8 cs170[7 * 8] = {
5120 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5121 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5122 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5123 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5124 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5125 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5126 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5127 };
5128 static const u8 cs1a8[3 * 8] = {
5129 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5130 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5132 };
5133 static const u8 cs100[2 * 8] = {
5134 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5135 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5136 };
5137
5138 /* VGA enable */
5139 reg = inSISREG(SISVGAENABLE) | 0x01;
5140 outSISREG(SISVGAENABLE, reg);
5141
5142 /* Misc */
5143 reg = inSISREG(SISMISCR) | 0x01;
5144 outSISREG(SISMISCW, reg);
5145
5146 /* Unlock SR */
5147 outSISIDXREG(SISSR, 0x05, 0x86);
5148 inSISIDXREG(SISSR, 0x05, reg);
5149 if(reg != 0xa1)
5150 return 0;
5151
5152 /* Clear some regs */
4385 for(i = 0; i < 0x22; i++) { 5153 for(i = 0; i < 0x22; i++) {
4386 outSISIDXREG(SISSR,(0x06 + i),0x00); 5154 if(0x06 + i == 0x20) continue;
5155 outSISIDXREG(SISSR, 0x06 + i, 0x00);
4387 } 5156 }
4388 v1 = 0x0d; 5157 for(i = 0; i < 0x0b; i++) {
4389 if( is 330) v1 = 0x0b; 5158 outSISIDXREG(SISSR, 0x31 + i, 0x00);
4390 for(i = 0; i < v1; i++) {
4391 outSISIDXREG(SISSR,(0x31 + i),0x00);
4392 } 5159 }
4393 for(i = 0; i < 0x10; i++) { 5160 for(i = 0; i < 0x10; i++) {
4394 outSISIDXREG(SISCR,(0x30 + i),0x00); 5161 outSISIDXREG(SISCR, 0x30 + i, 0x00);
4395 }
4396
4397 /* Reset clocks */
4398 reg = inSISREG(SISMISCR);
4399 outSISIDXREG(SISSR,0x28,0x81);
4400 outSISIDXREG(SISSR,0x2A,0x00);
4401 outSISIDXREG(SISSR,0x29,0xE1);
4402 outSISREG(SISMISCW,(reg | 0x0c));
4403 outSISIDXREG(SISSR,0x2B,0x81);
4404 outSISIDXREG(SISSR,0x2D,0x00);
4405 outSISIDXREG(SISSR,0x2C,0xE1);
4406 outSISIDXREG(SISSR,0x2E,0x81);
4407 outSISIDXREG(SISSR,0x30,0x00);
4408 outSISIDXREG(SISSR,0x2F,0xE1);
4409 SiS_DDC2Delay(....);
4410 outSISREG(SISMISCW,reg);
4411
4412 /* Get memory type */
4413 if(ivideo->sishw_ext.UseROM) {
4414 if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80)) {
4415 memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
4416 } else {
4417 inSISIDXREG(SISSR,0x3a,memtype);
4418 }
4419 memtype &= 0x03;
4420 if( is 330 ) {
4421 if(memtype <= 1) memtype = 0;
4422 else {
4423 inSISIDXREG(SISCR,0x5F,reg);
4424 reg &= 0x30;
4425 switch(reg) {
4426 case 0x00: memtype = 1; break;
4427 case 0x10: memtype = 3; break;
4428 case 0x20: memtype = 3; break;
4429 default: memtype = 2;
4430 }
4431 }
4432 }
4433 } 5162 }
4434 5163
4435 /* Set clocks */ 5164 ptr = cs78;
4436 v1 = 0x3b; v2 = 0x22; v3 = 0x01; /* Assume 143Mhz MCLK */ 5165 if(ivideo->haveXGIROM) {
4437 v4 = 0x5c; v5 = 0x23; v6 = 0x01; /* Assume 166Mhz ECLK */ 5166 ptr = (const u8 *)&bios[0x78];
4438 if(ivideo->sishw_ext.UseROM) { 5167 }
4439 index = memtype * 5; 5168 for(i = 0; i < 3; i++) {
4440 rindex = index + 0x54; 5169 outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
4441 v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 5170 }
4442 v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 5171
4443 v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 5172 ptr = cs76;
4444 rindex = index + 0x68; 5173 if(ivideo->haveXGIROM) {
4445 v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 5174 ptr = (const u8 *)&bios[0x76];
4446 v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 5175 }
4447 v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++]; 5176 for(i = 0; i < 2; i++) {
4448 } 5177 outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
4449 outSISIDXREG(SISSR,0x28,v1); 5178 }
4450 outSISIDXREG(SISSR,0x29,v2); 5179
4451 outSISIDXREG(SISSR,0x2a,v3); 5180 v1 = 0x18; v2 = 0x00;
4452 if( is 330 ) { 5181 if(ivideo->haveXGIROM) {
4453 inSISIDXREG(SISSR,0x3a,reg); 5182 v1 = bios[0x74];
4454 reg &= 0x03; 5183 v2 = bios[0x75];
4455 if(reg >= 2) { 5184 }
4456 ... 5185 outSISIDXREG(SISSR, 0x07, v1);
4457 } 5186 outSISIDXREG(SISSR, 0x11, 0x0f);
5187 outSISIDXREG(SISSR, 0x1f, v2);
5188 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5189 outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5190 outSISIDXREG(SISSR, 0x27, 0x74);
5191
5192 ptr = cs7b;
5193 if(ivideo->haveXGIROM) {
5194 ptr = (const u8 *)&bios[0x7b];
5195 }
5196 for(i = 0; i < 3; i++) {
5197 outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
4458 } 5198 }
4459 outSISIDXREG(SISSR,0x2e,v4);
4460 outSISIDXREG(SISSR,0x2f,v5);
4461 outSISIDXREG(SISSR,0x30,v6);
4462
4463 /* End of comp with 330 */
4464
4465 v1 = 0x18;
4466 if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0x7c];
4467 outSISIDXREG(SISSR,0x07,v1);
4468 outSISIDXREG(SISSR,0x11,0x0f);
4469
4470 v1 = 0x00; v2 = 0x0f; v3 = 0xba; v4 = 0xa9;
4471 v5 = 0xa0; v6 = 0x00; v7 = 0x30;
4472 if(ivideo->sishw_ext.UseROM) {
4473 index = memtype + 0x7d;
4474 v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
4475 v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
4476 v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
4477 v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
4478 v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
4479 v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
4480 v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
4481 }
4482 outSISIDXREG(SISSR,0x15,v1); /* Ram type (assuming 0, BIOS 0x7d step 4) */
4483 outSISIDXREG(SISSR,0x16,v2);
4484 outSISIDXREG(SISSR,0x17,v3);
4485 outSISIDXREG(SISSR,0x18,v4);
4486 outSISIDXREG(SISSR,0x19,v5);
4487 outSISIDXREG(SISSR,0x1a,v6);
4488 outSISIDXREG(SISSR,0x1b,v7);
4489 outSISIDXREG(SISSR,0x1c,v8); /* ---- */
4490
4491 v1 = 0x77; v2 = 0x77; v3 = 0x00; v4 = 0x5b; v5 = 0x00;
4492 if(ivideo->sishw_ext.UseROM) {
4493 index = memtype + 0xa2;
4494 v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
4495 v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
4496 v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
4497 v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
4498 v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
4499 }
4500 outSISIDXREG(SISCR,0x40,v1);
4501 outSISIDXREG(SISCR,0x41,v2);
4502 outSISIDXREG(SISCR,0x42,v3);
4503 outSISIDXREG(SISCR,0x43,v4);
4504 outSISIDXREG(SISCR,0x44,v5);
4505
4506 if( is 330 ) {
4507
4508 v1 = 0x;
4509 if(ivideo->sishw_ext.UseROM) {
4510 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
4511 }
4512 outSISIDXREG(SISCR,0x59,v1);
4513
4514 v1 = 0x; v2 = 0x; v3 = 0x; v4 = 0x;
4515 v5 = 0x; v6 = 0x; v7 = 0x; v8 = 0x;
4516 if(ivideo->sishw_ext.UseROM) {
4517 index = memtype + 0xbe;
4518 v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
4519 v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
4520 v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
4521 v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
4522 v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
4523 v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
4524 v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
4525 v8 = ivideo->sishw_ext.pjVirtualRomBase[index + 28];
4526 }
4527 outSISIDXREG(SISCR,0x68,v1);
4528 outSISIDXREG(SISCR,0x69,v2);
4529 outSISIDXREG(SISCR,0x6a,v3);
4530 outSISIDXREG(SISCR,0x6b,v4);
4531 outSISIDXREG(SISCR,0x6c,v5);
4532 outSISIDXREG(SISCR,0x6d,v6);
4533 outSISIDXREG(SISCR,0x6e,v7);
4534 outSISIDXREG(SISCR,0x6f,v8);
4535
4536 v1 = 0x20;
4537 inSISIDXREG(SISSR,0x3b,reg);
4538
4539 if(!(reg & 0x04)) {
4540 inSISIDXREG(SISCR,0x5F,reg);
4541 reg &= 0x30;
4542 if(reg) v1 = 0x23;
4543 }
4544 outSISIDXREG(SISCR,0x48,v1);
4545 outSISIDXREG(SISCR,0x4c,0x20);
4546
4547 xx= xxx();
4548 if(xx >= 1) {
4549 v1 = 0x;
4550 if(ivideo->sishw_ext.UseROM) {
4551 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
4552 }
4553 outSISIDXREG(SISCR,0x59,v1);
4554 }
4555 5199
5200 if(ivideo->chip == XGI_40) {
5201 if(ivideo->revision_id == 2) {
5202 setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
5203 }
5204 outSISIDXREG(SISCR, 0x7d, 0xfe);
5205 outSISIDXREG(SISCR, 0x7e, 0x0f);
5206 }
5207 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5208 andSISIDXREG(SISCR, 0x58, 0xd7);
5209 inSISIDXREG(SISCR, 0xcb, reg);
5210 if(reg & 0x20) {
5211 setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5212 }
5213 }
4556 5214
5215 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5216 setSISIDXREG(SISCR, 0x38, 0x1f, reg);
4557 5217
5218 if(ivideo->chip == XGI_20) {
5219 outSISIDXREG(SISSR, 0x36, 0x70);
4558 } else { 5220 } else {
5221 outSISIDXREG(SISVID, 0x00, 0x86);
5222 outSISIDXREG(SISVID, 0x32, 0x00);
5223 outSISIDXREG(SISVID, 0x30, 0x00);
5224 outSISIDXREG(SISVID, 0x32, 0x01);
5225 outSISIDXREG(SISVID, 0x30, 0x00);
5226 andSISIDXREG(SISVID, 0x2f, 0xdf);
5227 andSISIDXREG(SISCAP, 0x00, 0x3f);
5228
5229 outSISIDXREG(SISPART1, 0x2f, 0x01);
5230 outSISIDXREG(SISPART1, 0x00, 0x00);
5231 outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
5232 outSISIDXREG(SISPART1, 0x2e, 0x08);
5233 andSISIDXREG(SISPART1, 0x35, 0x7f);
5234 andSISIDXREG(SISPART1, 0x50, 0xfe);
5235
5236 inSISIDXREG(SISPART4, 0x00, reg);
5237 if(reg == 1 || reg == 2) {
5238 outSISIDXREG(SISPART2, 0x00, 0x1c);
5239 outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
5240 outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
5241 outSISIDXREG(SISPART4, 0x10, bios[0x81]);
5242 andSISIDXREG(SISPART4, 0x0f, 0x3f);
5243
5244 inSISIDXREG(SISPART4, 0x01, reg);
5245 if((reg & 0xf0) >= 0xb0) {
5246 inSISIDXREG(SISPART4, 0x23, reg);
5247 if(reg & 0x20) reg |= 0x40;
5248 outSISIDXREG(SISPART4, 0x23, reg);
5249 reg = (reg & 0x20) ? 0x02 : 0x00;
5250 setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
5251 }
5252 }
4559 5253
4560 outSISIDXREG(SISCR,0x48,0x23); 5254 v1 = bios[0x77];
5255
5256 inSISIDXREG(SISSR, 0x3b, reg);
5257 if(reg & 0x02) {
5258 inSISIDXREG(SISSR, 0x3a, reg);
5259 v2 = (reg & 0x30) >> 3;
5260 if(!(v2 & 0x04)) v2 ^= 0x02;
5261 inSISIDXREG(SISSR, 0x39, reg);
5262 if(reg & 0x80) v2 |= 0x80;
5263 v2 |= 0x01;
5264
5265 if((mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5266 SIS_PCI_PUT_DEVICE(mypdev);
5267 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5268 v2 &= 0xf9;
5269 v2 |= 0x08;
5270 v1 &= 0xfe;
5271 } else {
5272 mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0735, NULL);
5273 if(!mypdev)
5274 mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0645, NULL);
5275 if(!mypdev)
5276 mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0650, NULL);
5277 if(mypdev) {
5278 pci_read_config_dword(mypdev, 0x94, &regd);
5279 regd &= 0xfffffeff;
5280 pci_write_config_dword(mypdev, 0x94, regd);
5281 v1 &= 0xfe;
5282 SIS_PCI_PUT_DEVICE(mypdev);
5283 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5284 v1 &= 0xfe;
5285 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5286 sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5287 sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5288 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5289 if((v2 & 0x06) == 4)
5290 v2 ^= 0x06;
5291 v2 |= 0x08;
5292 }
5293 }
5294 setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
5295 }
5296 outSISIDXREG(SISSR, 0x22, v1);
5297
5298 if(ivideo->revision_id == 2) {
5299 inSISIDXREG(SISSR, 0x3b, v1);
5300 inSISIDXREG(SISSR, 0x3a, v2);
5301 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5302 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5303 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
5304
5305 if((mypdev = SIS_PCI_GET_DEVICE(0x10de, 0x01e0, NULL))) {
5306 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5307 * of nforce 2 ROM
5308 */
5309 if(0)
5310 setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
5311 SIS_PCI_PUT_DEVICE(mypdev);
5312 }
5313 }
4561 5314
4562 andSISIDXREG(SISSR,0x16,0x0f); 5315 v1 = 0x30;
4563 if(memtype <= 1) { 5316 inSISIDXREG(SISSR, 0x3b, reg);
4564 orSISIDXREG(SISSR,0x16,0x80); 5317 inSISIDXREG(SISCR, 0x5f, v2);
4565 } else { 5318 if((!(reg & 0x02)) && (v2 & 0x0e))
4566 v1 = 0x0f; 5319 v1 |= 0x08;
4567 if(ivideo->sishw_ext.UseROM) { 5320 outSISIDXREG(SISSR, 0x27, v1);
4568 v1 = ivideo->sishw_ext.pjVirtualRomBase[0x81 + memtype]; 5321
4569 } 5322 if(bios[0x64] & 0x01) {
4570 if(!(v1 & 0x10)) v2 = 0xc0; 5323 setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
4571 else v2 = 0xd0; 5324 }
4572 orSISIDXREG(SISSR,0x16,v2);
4573 andSISIDXREG(SISSR,0x16,0x0f);
4574 if(!(v1 & 0x10)) v2 = 0x80;
4575 else v2 = 0xA0;
4576 orSISIDXREG(SISSR,0x16,v2);
4577 }
4578
4579 if(memtype >= 2) {
4580 const u8 sr3cseq1[] = { 0xc0,0xe0,0xf0,0xe0,0xf0,0xa0,0xb0,0xa0,0xb0,0x90,0xd0 };
4581 const u8 sr3cseq2[] = { 0xc0,0xa0,0xb0,0xa0,0xb0,0xe0,0xf0,0xa0,0xb0,0x90,0xd0 };
4582 for(i = 0; i < 11; i++) {
4583 outSISIDXREG(SISSR,0x3c,sr3cseq1[i]);
4584 }
4585 outSISIDXREG(SISSR,0x3d,0x00);
4586 outSISIDXREG(SISSR,0x3d,0x04);
4587 SiS_DDC2Delay(0x200);
4588 v1 = inSISIDXREG(SISCR,0xEC);
4589 v2 = inSISIDXREG(SISCR,0xED);
4590 reg1_32 = (v2 << 8) | v1;
4591 outSISIDXREG(SISSR,0x3D,0x00);
4592 for(i = 0; i < 11; i++) {
4593 outSISIDXREG(SISSR,0x3c,sr3cseq2[i]);
4594 }
4595 outSISIDXREG(SISSR,0x3d,0x00);
4596 outSISIDXREG(SISSR,0x3d,0x04);
4597 SiS_DDC2Delay(0x200);
4598 v1 = inSISIDXREG(SISCR,0xEC);
4599 v2 = inSISIDXREG(SISCR,0xED);
4600 reg2_32 = (v2 << 8) | v1;
4601 outSISIDXREG(SISSR,0x3D,0x00);
4602 reg3_32 = reg2_32 << 1;
4603 reg2_32 >>= 1;
4604 reg3_32 += reg2_32;
4605 v1 = 0x40;
4606 if(reg3_32 > reg1_32) v1 = 0x10;
4607 outSISIDXREG(SISCR,0x59,v1);
4608 }
4609 5325
5326 v1 = bios[0x4f7];
5327 pci_read_config_dword(pdev, 0x50, &regd);
5328 regd = (regd >> 20) & 0x0f;
5329 if(regd == 1) {
5330 v1 &= 0xfc;
5331 orSISIDXREG(SISCR, 0x5f, 0x08);
5332 }
5333 outSISIDXREG(SISCR, 0x48, v1);
5334
5335 setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5336 setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5337 setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5338 setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5339 setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5340 outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
5341 setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5342 outSISIDXREG(SISCR, 0x74, 0xd0);
5343 setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5344 setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5345 setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5346 v1 = bios[0x501];
5347 if((mypdev = SIS_PCI_GET_DEVICE(0x8086, 0x2530, NULL))) {
5348 v1 = 0xf0;
5349 SIS_PCI_PUT_DEVICE(mypdev);
5350 }
5351 outSISIDXREG(SISCR, 0x77, v1);
4610 } 5352 }
4611 5353
4612 v1 = 0x00; 5354 /* RAM type */
4613 if(ivideo->sishw_ext.UseROM) { 5355
4614 v1 = ivideo->sishw_ext.pjVirtualRomBase[0x99]; 5356 regb = 0; /* ! */
5357
5358 v1 = 0xff;
5359 if(ivideo->haveXGIROM) {
5360 v1 = bios[0x140 + regb];
4615 } 5361 }
4616 outSISIDXREG(SISSR,0x1f,v1); 5362 outSISIDXREG(SISCR, 0x6d, v1);
4617 5363
4618 outSISIDXREG(SISSR,0x20,0x20); 5364 ptr = cs128;
5365 if(ivideo->haveXGIROM) {
5366 ptr = (const u8 *)&bios[0x128];
5367 }
5368 for(i = 0, j = 0; i < 3; i++, j += 8) {
5369 outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
5370 }
4619 5371
4620 v1 = 0xf6; v2 = 0x0d; v3 = 0x33; 5372 ptr = cs31a;
4621 if(ivideo->sishw_ext.UseROM) { 5373 ptr2 = cs33a;
4622 v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9c]; 5374 if(ivideo->haveXGIROM) {
4623 v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9d]; 5375 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
4624 v3 = ivideo->sishw_ext.pjVirtualRomBase[0x9e]; 5376 ptr = (const u8 *)&bios[index];
5377 ptr2 = (const u8 *)&bios[index + 0x20];
5378 }
5379 for(i = 0; i < 2; i++) {
5380 if(i == 0) {
5381 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5382 rega = 0x6b;
5383 } else {
5384 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5385 rega = 0x6e;
5386 }
5387 reg = 0x00;
5388 for(j = 0; j < 16; j++) {
5389 reg &= 0xf3;
5390 if(regd & 0x01) reg |= 0x04;
5391 if(regd & 0x02) reg |= 0x08;
5392 regd >>= 2;
5393 outSISIDXREG(SISCR, rega, reg);
5394 inSISIDXREG(SISCR, rega, reg);
5395 inSISIDXREG(SISCR, rega, reg);
5396 reg += 0x10;
5397 }
4625 } 5398 }
4626 outSISIDXREG(SISSR,0x23,v1);
4627 outSISIDXREG(SISSR,0x24,v2);
4628 outSISIDXREG(SISSR,0x25,v3);
4629 5399
4630 outSISIDXREG(SISSR,0x21,0x84); 5400 andSISIDXREG(SISCR, 0x6e, 0xfc);
4631 outSISIDXREG(SISSR,0x22,0x00);
4632 outSISIDXREG(SISSR,0x27,0x1f);
4633 5401
4634 v1 = 0x00; v2 = 0x00; 5402 ptr = NULL;
4635 if(ivideo->sishw_ext.UseROM) { 5403 if(ivideo->haveXGIROM) {
4636 v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9F]; 5404 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
4637 v2 = ivideo->sishw_ext.pjVirtualRomBase[0xA1]; 5405 ptr = (const u8 *)&bios[index];
4638 } 5406 }
4639 outSISIDXREG(SISSR,0x31,v1); 5407 for(i = 0; i < 4; i++) {
4640 outSISIDXREG(SISSR,0x33,v2); 5408 setSISIDXREG(SISCR, 0x6e, 0xfc, i);
4641 5409 reg = 0x00;
4642 v1 = 0x11; 5410 for(j = 0; j < 2; j++) {
4643 if(ivideo->sishw_ext.UseROM) { 5411 regd = 0;
4644 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xA0]; 5412 if(ptr) {
4645 } 5413 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
4646 v2 = inSISIDXREG(SISPART4,0x00); 5414 ptr += 4;
4647 if((v2 != 1) && (v2 != 2)) v1 &= 0xef; 5415 }
4648 outSISIDXREG(SISSR,0x32,v1); 5416 /* reg = 0x00; */
4649 5417 for(k = 0; k < 16; k++) {
4650 /* AGP */ 5418 reg &= 0xfc;
4651 pci_read_config_long(pdev, 0x50, &reg1_32); 5419 if(regd & 0x01) reg |= 0x01;
4652 reg1_32 >>= 20; 5420 if(regd & 0x02) reg |= 0x02;
4653 reg1_32 &= 0x0f; 5421 regd >>= 2;
4654 if(reg1_32 == 1) { 5422 outSISIDXREG(SISCR, 0x6f, reg);
4655 v1 = 0xAA; v2 = 0x33; 5423 inSISIDXREG(SISCR, 0x6f, reg);
4656 if(ivideo->sishw_ext.UseROM) { 5424 inSISIDXREG(SISCR, 0x6f, reg);
4657 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF7]; 5425 reg += 0x08;
4658 v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9E]; 5426 }
4659 } 5427 }
4660 } else {
4661 v1 = 0x88; v2 = 0x03;
4662 if(ivideo->sishw_ext.UseROM) {
4663 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF8];
4664 v2 = ivideo->sishw_ext.pjVirtualRomBase[0xF6];
4665 }
4666 } 5428 }
4667 outSISIDXREG(SISCR,0x49,v1);
4668 outSISIDXREG(SISSR,0x25,v2);
4669 5429
4670 v1 = inSISIDXREG(SISPART4,0x00); 5430 ptr = cs148;
4671 if((v1 == 1) || (v1 == 2)) { 5431 if(ivideo->haveXGIROM) {
4672 orSISIDXREG(SISPART1,0x2F,0x01); /* Unlock CRT2 */ 5432 ptr = (const u8 *)&bios[0x148];
4673 outSISIDXREG(SISPART1,0x00,0x00); 5433 }
4674 v1 = 0x00; 5434 for(i = 0, j = 0; i < 2; i++, j += 8) {
4675 if(ivideo->sishw_ext.UseROM) { 5435 outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
4676 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb6];
4677 }
4678 outSISIDXREG(SISPART1,0x02,v1);
4679 outSISIDXREG(SISPART1,0x2E,0x08);
4680 outSISIDXREG(SISPART2,0x00,0x1c);
4681 v1 = 0x40; v2 = 0x00; v3 = 0x80;
4682 if(ivideo->sishw_ext.UseROM) {
4683 v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb7];
4684 v2 = ivideo->sishw_ext.pjVirtualRomBase[0xb8];
4685 v3 = ivideo->sishw_ext.pjVirtualRomBase[0xbb];
4686 }
4687 outSISIDXREG(SISPART4,0x0d,v1);
4688 outSISIDXREG(SISPART4,0x0e,v2);
4689 outSISIDXREG(SISPART4,0x10,v3);
4690 outSISIDXREG(SISPART4,0x0F,0x3F);
4691
4692 inSISIDXREG(SISPART4,0x01,reg);
4693 if(reg >= 0xb0) {
4694 inSISIDXREG(SISPART4,0x23,reg);
4695 reg &= 0x20;
4696 reg <<= 1;
4697 outSISIDXREG(SISPART4,0x23,reg);
4698 }
4699 } 5436 }
4700 outSISIDXREG(SISCR,0x37,0x02); /* Why? */
4701
4702 outSISIDXREG(SISCR,0x83,0x00);
4703 outSISIDXREG(SISCR,0x90,0x00);
4704 andSISIDXREG(SISSR,0x5B,0xDF);
4705 outSISIDXREG(SISVID,0x00,0x86);
4706 outSISIDXREG(SISVID,0x32,0x00);
4707 outSISIDXREG(SISVID,0x30,0x00);
4708 outSISIDXREG(SISVID,0x32,0x01);
4709 outSISIDXREG(SISVID,0x30,0x00);
4710 orSISIDXREG(SISCR,0x63,0x80);
4711 /* End of Init1 */
4712
4713 /* Set Mode 0x2e */
4714
4715 /* Ramsize */
4716 orSISIDXREG(SISSR,0x16,0x0f);
4717 orSISIDXREG(SISSR,0x18,0xA9);
4718 orSISIDXREG(SISSR,0x19,0xA0);
4719 orSISIDXREG(SISSR,0x1B,0x30);
4720 andSISIDXREG(SISSR,0x17,0xF8);
4721 orSISIDXREG(SISSR,0x19,0x03);
4722 andSIDIDXREG(SISSR,0x13,0x00);
4723 5437
4724 /* Need to map max FB size for finding out about RAM size */ 5438 andSISIDXREG(SISCR, 0x89, 0x8f);
4725 ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000);
4726 if(ivideo->video_vbase) {
4727 /* Find out about bus width */
4728 if(memtype <= 1) {
4729 outSISIDXREG(SISSR,0x14,0x02);
4730 andSISIDXREG(SISSR,0x16,0x0F);
4731 orSISIDXREG(SISSR,0x16,0x80);
4732 5439
4733 ... 5440 ptr = cs45a;
5441 if(ivideo->haveXGIROM) {
5442 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5443 ptr = (const u8 *)&bios[index];
5444 }
5445 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5446 reg = 0x80;
5447 for(i = 0; i < 5; i++) {
5448 reg &= 0xfc;
5449 if(regd & 0x01) reg |= 0x01;
5450 if(regd & 0x02) reg |= 0x02;
5451 regd >>= 2;
5452 outSISIDXREG(SISCR, 0x89, reg);
5453 inSISIDXREG(SISCR, 0x89, reg);
5454 inSISIDXREG(SISCR, 0x89, reg);
5455 reg += 0x10;
5456 }
4734 5457
4735 } else { 5458 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5459 if(ivideo->haveXGIROM) {
5460 v1 = bios[0x118 + regb];
5461 v2 = bios[0xf8 + regb];
5462 v3 = bios[0x120 + regb];
5463 v4 = bios[0x1ca];
5464 }
5465 outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
5466 outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
5467 orSISIDXREG(SISCR, 0x40, v1 & 0x80);
5468 outSISIDXREG(SISCR, 0x41, v2);
4736 5469
4737 ... 5470 ptr = cs170;
5471 if(ivideo->haveXGIROM) {
5472 ptr = (const u8 *)&bios[0x170];
5473 }
5474 for(i = 0, j = 0; i < 7; i++, j += 8) {
5475 outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
5476 }
4738 5477
4739 } 5478 outSISIDXREG(SISCR, 0x59, v3);
4740 5479
4741 /* Find out about size */ 5480 ptr = cs1a8;
5481 if(ivideo->haveXGIROM) {
5482 ptr = (const u8 *)&bios[0x1a8];
5483 }
5484 for(i = 0, j = 0; i < 3; i++, j += 8) {
5485 outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
5486 }
4742 5487
5488 ptr = cs100;
5489 if(ivideo->haveXGIROM) {
5490 ptr = (const u8 *)&bios[0x100];
5491 }
5492 for(i = 0, j = 0; i < 2; i++, j += 8) {
5493 outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
5494 }
4743 5495
4744 iounmap(ivideo->video_vbase); 5496 outSISIDXREG(SISCR, 0xcf, v4);
4745 } else { 5497
4746 printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n"); 5498 outSISIDXREG(SISCR, 0x83, 0x09);
4747 outSISIDXREG(SISSR,0x14,0x??); /* 8MB, 64bit default */ 5499 outSISIDXREG(SISCR, 0x87, 0x00);
5500
5501 if(ivideo->chip == XGI_40) {
5502 if( (ivideo->revision_id == 1) ||
5503 (ivideo->revision_id == 2) ) {
5504 outSISIDXREG(SISCR, 0x8c, 0x87);
5505 }
5506 }
5507
5508 outSISIDXREG(SISSR, 0x17, 0x00);
5509 outSISIDXREG(SISSR, 0x1a, 0x87);
5510
5511 if(ivideo->chip == XGI_20) {
5512 outSISIDXREG(SISSR, 0x15, 0x00);
5513 outSISIDXREG(SISSR, 0x1c, 0x00);
5514 }
5515
5516 ramtype = 0x00; v1 = 0x10;
5517 if(ivideo->haveXGIROM) {
5518 ramtype = bios[0x62];
5519 v1 = bios[0x1d2];
5520 }
5521 if(!(ramtype & 0x80)) {
5522 if(ivideo->chip == XGI_20) {
5523 outSISIDXREG(SISCR, 0x97, v1);
5524 inSISIDXREG(SISCR, 0x97, reg);
5525 if(reg & 0x10) {
5526 ramtype = (reg & 0x01) << 1;
5527 }
5528 } else {
5529 inSISIDXREG(SISSR, 0x39, reg);
5530 ramtype = reg & 0x02;
5531 if(!(ramtype)) {
5532 inSISIDXREG(SISSR, 0x3a, reg);
5533 ramtype = (reg >> 1) & 0x01;
5534 }
5535 }
5536 }
5537 ramtype &= 0x07;
5538
5539 regb = 0; /* ! */
5540
5541 switch(ramtype) {
5542 case 0:
5543 sisfb_post_xgi_setclocks(ivideo, regb);
5544 if((ivideo->chip == XGI_20) ||
5545 (ivideo->revision_id == 1) ||
5546 (ivideo->revision_id == 2)) {
5547 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5548 if(ivideo->haveXGIROM) {
5549 v1 = bios[regb + 0x158];
5550 v2 = bios[regb + 0x160];
5551 v3 = bios[regb + 0x168];
5552 }
5553 outSISIDXREG(SISCR, 0x82, v1);
5554 outSISIDXREG(SISCR, 0x85, v2);
5555 outSISIDXREG(SISCR, 0x86, v3);
5556 } else {
5557 outSISIDXREG(SISCR, 0x82, 0x88);
5558 outSISIDXREG(SISCR, 0x86, 0x00);
5559 inSISIDXREG(SISCR, 0x86, reg);
5560 outSISIDXREG(SISCR, 0x86, 0x88);
5561 inSISIDXREG(SISCR, 0x86, reg);
5562 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
5563 outSISIDXREG(SISCR, 0x82, 0x77);
5564 outSISIDXREG(SISCR, 0x85, 0x00);
5565 inSISIDXREG(SISCR, 0x85, reg);
5566 outSISIDXREG(SISCR, 0x85, 0x88);
5567 inSISIDXREG(SISCR, 0x85, reg);
5568 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
5569 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
5570 }
5571 if(ivideo->chip == XGI_40) {
5572 outSISIDXREG(SISCR, 0x97, 0x00);
5573 }
5574 outSISIDXREG(SISCR, 0x98, 0x01);
5575 outSISIDXREG(SISCR, 0x9a, 0x02);
5576
5577 outSISIDXREG(SISSR, 0x18, 0x01);
5578 if((ivideo->chip == XGI_20) ||
5579 (ivideo->revision_id == 2)) {
5580 outSISIDXREG(SISSR, 0x19, 0x40);
5581 } else {
5582 outSISIDXREG(SISSR, 0x19, 0x20);
5583 }
5584 outSISIDXREG(SISSR, 0x16, 0x00);
5585 outSISIDXREG(SISSR, 0x16, 0x80);
5586 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5587 sisfb_post_xgi_delay(ivideo, 0x43);
5588 sisfb_post_xgi_delay(ivideo, 0x43);
5589 sisfb_post_xgi_delay(ivideo, 0x43);
5590 outSISIDXREG(SISSR, 0x18, 0x00);
5591 if((ivideo->chip == XGI_20) ||
5592 (ivideo->revision_id == 2)) {
5593 outSISIDXREG(SISSR, 0x19, 0x40);
5594 } else {
5595 outSISIDXREG(SISSR, 0x19, 0x20);
5596 }
5597 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5598 /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
5599 }
5600 outSISIDXREG(SISSR, 0x16, 0x00);
5601 outSISIDXREG(SISSR, 0x16, 0x80);
5602 sisfb_post_xgi_delay(ivideo, 4);
5603 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5604 if(ivideo->haveXGIROM) {
5605 v1 = bios[0xf0];
5606 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5607 v2 = bios[index];
5608 v3 = bios[index + 1];
5609 v4 = bios[index + 2];
5610 v5 = bios[index + 3];
5611 }
5612 outSISIDXREG(SISSR, 0x18, v1);
5613 outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5614 outSISIDXREG(SISSR, 0x16, v2);
5615 outSISIDXREG(SISSR, 0x16, v3);
5616 sisfb_post_xgi_delay(ivideo, 0x43);
5617 outSISIDXREG(SISSR, 0x1b, 0x03);
5618 sisfb_post_xgi_delay(ivideo, 0x22);
5619 outSISIDXREG(SISSR, 0x18, v1);
5620 outSISIDXREG(SISSR, 0x19, 0x00);
5621 outSISIDXREG(SISSR, 0x16, v4);
5622 outSISIDXREG(SISSR, 0x16, v5);
5623 outSISIDXREG(SISSR, 0x1b, 0x00);
5624 break;
5625 case 1:
5626 outSISIDXREG(SISCR, 0x82, 0x77);
5627 outSISIDXREG(SISCR, 0x86, 0x00);
5628 inSISIDXREG(SISCR, 0x86, reg);
5629 outSISIDXREG(SISCR, 0x86, 0x88);
5630 inSISIDXREG(SISCR, 0x86, reg);
5631 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5632 if(ivideo->haveXGIROM) {
5633 v1 = bios[regb + 0x168];
5634 v2 = bios[regb + 0x160];
5635 v3 = bios[regb + 0x158];
5636 }
5637 outSISIDXREG(SISCR, 0x86, v1);
5638 outSISIDXREG(SISCR, 0x82, 0x77);
5639 outSISIDXREG(SISCR, 0x85, 0x00);
5640 inSISIDXREG(SISCR, 0x85, reg);
5641 outSISIDXREG(SISCR, 0x85, 0x88);
5642 inSISIDXREG(SISCR, 0x85, reg);
5643 outSISIDXREG(SISCR, 0x85, v2);
5644 outSISIDXREG(SISCR, 0x82, v3);
5645 outSISIDXREG(SISCR, 0x98, 0x01);
5646 outSISIDXREG(SISCR, 0x9a, 0x02);
5647
5648 outSISIDXREG(SISSR, 0x28, 0x64);
5649 outSISIDXREG(SISSR, 0x29, 0x63);
5650 sisfb_post_xgi_delay(ivideo, 15);
5651 outSISIDXREG(SISSR, 0x18, 0x00);
5652 outSISIDXREG(SISSR, 0x19, 0x20);
5653 outSISIDXREG(SISSR, 0x16, 0x00);
5654 outSISIDXREG(SISSR, 0x16, 0x80);
5655 outSISIDXREG(SISSR, 0x18, 0xc5);
5656 outSISIDXREG(SISSR, 0x19, 0x23);
5657 outSISIDXREG(SISSR, 0x16, 0x00);
5658 outSISIDXREG(SISSR, 0x16, 0x80);
5659 sisfb_post_xgi_delay(ivideo, 1);
5660 outSISIDXREG(SISCR, 0x97,0x11);
5661 sisfb_post_xgi_setclocks(ivideo, regb);
5662 sisfb_post_xgi_delay(ivideo, 0x46);
5663 outSISIDXREG(SISSR, 0x18, 0xc5);
5664 outSISIDXREG(SISSR, 0x19, 0x23);
5665 outSISIDXREG(SISSR, 0x16, 0x00);
5666 outSISIDXREG(SISSR, 0x16, 0x80);
5667 sisfb_post_xgi_delay(ivideo, 1);
5668 outSISIDXREG(SISSR, 0x1b, 0x04);
5669 sisfb_post_xgi_delay(ivideo, 1);
5670 outSISIDXREG(SISSR, 0x1b, 0x00);
5671 sisfb_post_xgi_delay(ivideo, 1);
5672 v1 = 0x31;
5673 if(ivideo->haveXGIROM) {
5674 v1 = bios[0xf0];
5675 }
5676 outSISIDXREG(SISSR, 0x18, v1);
5677 outSISIDXREG(SISSR, 0x19, 0x06);
5678 outSISIDXREG(SISSR, 0x16, 0x04);
5679 outSISIDXREG(SISSR, 0x16, 0x84);
5680 sisfb_post_xgi_delay(ivideo, 1);
5681 break;
5682 default:
5683 sisfb_post_xgi_setclocks(ivideo, regb);
5684 if((ivideo->chip == XGI_40) &&
5685 ((ivideo->revision_id == 1) ||
5686 (ivideo->revision_id == 2))) {
5687 outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
5688 outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
5689 outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
5690 } else {
5691 outSISIDXREG(SISCR, 0x82, 0x88);
5692 outSISIDXREG(SISCR, 0x86, 0x00);
5693 inSISIDXREG(SISCR, 0x86, reg);
5694 outSISIDXREG(SISCR, 0x86, 0x88);
5695 outSISIDXREG(SISCR, 0x82, 0x77);
5696 outSISIDXREG(SISCR, 0x85, 0x00);
5697 inSISIDXREG(SISCR, 0x85, reg);
5698 outSISIDXREG(SISCR, 0x85, 0x88);
5699 inSISIDXREG(SISCR, 0x85, reg);
5700 v1 = cs160[regb]; v2 = cs158[regb];
5701 if(ivideo->haveXGIROM) {
5702 v1 = bios[regb + 0x160];
5703 v2 = bios[regb + 0x158];
5704 }
5705 outSISIDXREG(SISCR, 0x85, v1);
5706 outSISIDXREG(SISCR, 0x82, v2);
5707 }
5708 if(ivideo->chip == XGI_40) {
5709 outSISIDXREG(SISCR, 0x97, 0x11);
5710 }
5711 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5712 outSISIDXREG(SISCR, 0x98, 0x01);
5713 } else {
5714 outSISIDXREG(SISCR, 0x98, 0x03);
5715 }
5716 outSISIDXREG(SISCR, 0x9a, 0x02);
5717
5718 if(ivideo->chip == XGI_40) {
5719 outSISIDXREG(SISSR, 0x18, 0x01);
5720 } else {
5721 outSISIDXREG(SISSR, 0x18, 0x00);
5722 }
5723 outSISIDXREG(SISSR, 0x19, 0x40);
5724 outSISIDXREG(SISSR, 0x16, 0x00);
5725 outSISIDXREG(SISSR, 0x16, 0x80);
5726 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5727 sisfb_post_xgi_delay(ivideo, 0x43);
5728 sisfb_post_xgi_delay(ivideo, 0x43);
5729 sisfb_post_xgi_delay(ivideo, 0x43);
5730 outSISIDXREG(SISSR, 0x18, 0x00);
5731 outSISIDXREG(SISSR, 0x19, 0x40);
5732 outSISIDXREG(SISSR, 0x16, 0x00);
5733 outSISIDXREG(SISSR, 0x16, 0x80);
5734 }
5735 sisfb_post_xgi_delay(ivideo, 4);
5736 v1 = 0x31;
5737 if(ivideo->haveXGIROM) {
5738 v1 = bios[0xf0];
5739 }
5740 outSISIDXREG(SISSR, 0x18, v1);
5741 outSISIDXREG(SISSR, 0x19, 0x01);
5742 if(ivideo->chip == XGI_40) {
5743 outSISIDXREG(SISSR, 0x16, bios[0x53e]);
5744 outSISIDXREG(SISSR, 0x16, bios[0x53f]);
5745 } else {
5746 outSISIDXREG(SISSR, 0x16, 0x05);
5747 outSISIDXREG(SISSR, 0x16, 0x85);
5748 }
5749 sisfb_post_xgi_delay(ivideo, 0x43);
5750 if(ivideo->chip == XGI_40) {
5751 outSISIDXREG(SISSR, 0x1b, 0x01);
5752 } else {
5753 outSISIDXREG(SISSR, 0x1b, 0x03);
5754 }
5755 sisfb_post_xgi_delay(ivideo, 0x22);
5756 outSISIDXREG(SISSR, 0x18, v1);
5757 outSISIDXREG(SISSR, 0x19, 0x00);
5758 if(ivideo->chip == XGI_40) {
5759 outSISIDXREG(SISSR, 0x16, bios[0x540]);
5760 outSISIDXREG(SISSR, 0x16, bios[0x541]);
5761 } else {
5762 outSISIDXREG(SISSR, 0x16, 0x05);
5763 outSISIDXREG(SISSR, 0x16, 0x85);
5764 }
5765 outSISIDXREG(SISSR, 0x1b, 0x00);
5766 }
5767
5768 regb = 0; /* ! */
5769 v1 = 0x03;
5770 if(ivideo->haveXGIROM) {
5771 v1 = bios[0x110 + regb];
5772 }
5773 outSISIDXREG(SISSR, 0x1b, v1);
5774
5775 /* RAM size */
5776 v1 = 0x00; v2 = 0x00;
5777 if(ivideo->haveXGIROM) {
5778 v1 = bios[0x62];
5779 v2 = bios[0x63];
4748 } 5780 }
5781 regb = 0; /* ! */
5782 regd = 1 << regb;
5783 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5784
5785 outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
5786 outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5787
5788 } else {
5789
5790 /* Set default mode, don't clear screen */
5791 ivideo->SiS_Pr.SiS_UseOEM = FALSE;
5792 SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
5793 SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
5794 ivideo->curFSTN = ivideo->curDSTN = 0;
5795 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5796 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5797
5798 outSISIDXREG(SISSR, 0x05, 0x86);
5799
5800 /* Disable read-cache */
5801 andSISIDXREG(SISSR, 0x21, 0xdf);
5802 sisfb_post_xgi_ramsize(ivideo);
5803 /* Enable read-cache */
5804 orSISIDXREG(SISSR, 0x21, 0x20);
4749 5805
4750 /* AGP (Missing: Checks for VIA and AMD hosts) */
4751 v1 = 0xA5; v2 = 0xFB;
4752 if(ivideo->sishw_ext.UseROM) {
4753 v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9A];
4754 v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9B];
4755 } 5806 }
4756 outSISIDXREG(SISSR,0x21,v1);
4757 outSISIDXREG(SISSR,0x22,v2);
4758 5807
5808#if 0
5809 printk(KERN_DEBUG "-----------------\n");
5810 for(i = 0; i < 0xff; i++) {
5811 inSISIDXREG(SISCR, i, reg);
5812 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5813 }
5814 for(i = 0; i < 0x40; i++) {
5815 inSISIDXREG(SISSR, i, reg);
5816 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5817 }
5818 printk(KERN_DEBUG "-----------------\n");
4759#endif 5819#endif
4760 return; 5820
5821 /* Sense CRT1 */
5822 if(ivideo->chip == XGI_20) {
5823 orSISIDXREG(SISCR, 0x32, 0x20);
5824 } else {
5825 inSISIDXREG(SISPART4, 0x00, reg);
5826 if((reg == 1) || (reg == 2)) {
5827 sisfb_sense_crt1(ivideo);
5828 } else {
5829 orSISIDXREG(SISCR, 0x32, 0x20);
5830 }
5831 }
5832
5833 /* Set default mode, don't clear screen */
5834 ivideo->SiS_Pr.SiS_UseOEM = FALSE;
5835 SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
5836 SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
5837 ivideo->curFSTN = ivideo->curDSTN = 0;
5838 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5839
5840 outSISIDXREG(SISSR, 0x05, 0x86);
5841
5842 /* Display off */
5843 orSISIDXREG(SISSR, 0x01, 0x20);
5844
5845 /* Save mode number in CR34 */
5846 outSISIDXREG(SISCR, 0x34, 0x2e);
5847
5848 /* Let everyone know what the current mode is */
5849 ivideo->modeprechange = 0x2e;
5850
5851 if(ivideo->chip == XGI_40) {
5852 inSISIDXREG(SISCR, 0xca, reg);
5853 inSISIDXREG(SISCR, 0xcc, v1);
5854 if((reg & 0x10) && (!(v1 & 0x04))) {
5855 printk(KERN_ERR
5856 "sisfb: Please connect power to the card.\n");
5857 return 0;
5858 }
5859 }
5860
5861 return 1;
4761} 5862}
4762#endif 5863#endif
4763 5864
4764 5865static int __devinit
4765static int __devinit sisfb_probe(struct pci_dev *pdev, 5866sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
4766 const struct pci_device_id *ent)
4767{ 5867{
4768 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data]; 5868 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
4769 struct sis_video_info *ivideo = NULL; 5869 struct sis_video_info *ivideo = NULL;
4770 struct fb_info *sis_fb_info = NULL; 5870 struct fb_info *sis_fb_info = NULL;
4771 u16 reg16; 5871 u16 reg16;
4772 u8 reg; 5872 u8 reg;
4773 int sisvga_enabled = 0, i; 5873 int i, ret;
4774 5874
4775 if(sisfb_off) return -ENXIO; 5875 if(sisfb_off)
5876 return -ENXIO;
4776 5877
4777#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)) 5878#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
4778 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev); 5879 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
4779 if(!sis_fb_info) return -ENOMEM; 5880 if(!sis_fb_info)
5881 return -ENOMEM;
4780#else 5882#else
4781 sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL); 5883 sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL);
4782 if(!sis_fb_info) return -ENOMEM; 5884 if(!sis_fb_info)
5885 return -ENOMEM;
4783 memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo)); 5886 memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo));
4784 sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info)); 5887 sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info));
4785#endif 5888#endif
@@ -4787,27 +5890,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4787 ivideo = (struct sis_video_info *)sis_fb_info->par; 5890 ivideo = (struct sis_video_info *)sis_fb_info->par;
4788 ivideo->memyselfandi = sis_fb_info; 5891 ivideo->memyselfandi = sis_fb_info;
4789 5892
5893 ivideo->sisfb_id = SISFB_ID;
5894
4790 if(card_list == NULL) { 5895 if(card_list == NULL) {
4791 ivideo->cardnumber = 0; 5896 ivideo->cardnumber = 0;
4792 } else { 5897 } else {
4793 struct sis_video_info *countvideo = card_list; 5898 struct sis_video_info *countvideo = card_list;
4794 ivideo->cardnumber = 1; 5899 ivideo->cardnumber = 1;
4795 while((countvideo = countvideo->next) != NULL) ivideo->cardnumber++; 5900 while((countvideo = countvideo->next) != 0)
5901 ivideo->cardnumber++;
4796 } 5902 }
4797 5903
4798 strncpy(ivideo->myid, chipinfo->chip_name, 30); 5904 strncpy(ivideo->myid, chipinfo->chip_name, 30);
4799 5905
4800 ivideo->warncount = 0; 5906 ivideo->warncount = 0;
4801 ivideo->chip_id = pdev->device; 5907 ivideo->chip_id = pdev->device;
5908 ivideo->chip_vendor = pdev->vendor;
4802 pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id); 5909 pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
4803 ivideo->sishw_ext.jChipRevision = ivideo->revision_id; 5910 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
4804 pci_read_config_word(pdev, PCI_COMMAND, &reg16); 5911 pci_read_config_word(pdev, PCI_COMMAND, &reg16);
4805 sisvga_enabled = reg16 & 0x01; 5912 ivideo->sisvga_enabled = reg16 & 0x01;
4806 ivideo->pcibus = pdev->bus->number; 5913 ivideo->pcibus = pdev->bus->number;
4807 ivideo->pcislot = PCI_SLOT(pdev->devfn); 5914 ivideo->pcislot = PCI_SLOT(pdev->devfn);
4808 ivideo->pcifunc = PCI_FUNC(pdev->devfn); 5915 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
4809 ivideo->subsysvendor = pdev->subsystem_vendor; 5916 ivideo->subsysvendor = pdev->subsystem_vendor;
4810 ivideo->subsysdevice = pdev->subsystem_device; 5917 ivideo->subsysdevice = pdev->subsystem_device;
5918#ifdef SIS_OLD_CONFIG_COMPAT
5919 ivideo->ioctl32registered = 0;
5920#endif
4811 5921
4812#ifndef MODULE 5922#ifndef MODULE
4813 if(sisfb_mode_idx == -1) { 5923 if(sisfb_mode_idx == -1) {
@@ -4827,6 +5937,24 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4827 5937
4828 ivideo->sisfb_thismonitor.datavalid = FALSE; 5938 ivideo->sisfb_thismonitor.datavalid = FALSE;
4829 5939
5940 ivideo->current_base = 0;
5941
5942 ivideo->engineok = 0;
5943
5944 ivideo->sisfb_was_boot_device = 0;
5945#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
5946 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5947 if(ivideo->sisvga_enabled)
5948 ivideo->sisfb_was_boot_device = 1;
5949 else {
5950 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5951 "but marked as boot video device ???\n");
5952 printk(KERN_DEBUG "sisfb: I will not accept this "
5953 "as the primary VGA device\n");
5954 }
5955 }
5956#endif
5957
4830 ivideo->sisfb_parm_mem = sisfb_parm_mem; 5958 ivideo->sisfb_parm_mem = sisfb_parm_mem;
4831 ivideo->sisfb_accel = sisfb_accel; 5959 ivideo->sisfb_accel = sisfb_accel;
4832 ivideo->sisfb_ypan = sisfb_ypan; 5960 ivideo->sisfb_ypan = sisfb_ypan;
@@ -4846,7 +5974,6 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4846 ivideo->sisfb_tvstd = sisfb_tvstd; 5974 ivideo->sisfb_tvstd = sisfb_tvstd;
4847 ivideo->tvxpos = sisfb_tvxposoffset; 5975 ivideo->tvxpos = sisfb_tvxposoffset;
4848 ivideo->tvypos = sisfb_tvyposoffset; 5976 ivideo->tvypos = sisfb_tvyposoffset;
4849 ivideo->sisfb_filter = sisfb_filter;
4850 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate; 5977 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
4851#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) 5978#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
4852 ivideo->sisfb_inverse = sisfb_inverse; 5979 ivideo->sisfb_inverse = sisfb_inverse;
@@ -4854,7 +5981,7 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4854 5981
4855 ivideo->refresh_rate = 0; 5982 ivideo->refresh_rate = 0;
4856 if(ivideo->sisfb_parm_rate != -1) { 5983 if(ivideo->sisfb_parm_rate != -1) {
4857 ivideo->refresh_rate = ivideo->sisfb_parm_rate; 5984 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
4858 } 5985 }
4859 5986
4860 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd; 5987 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
@@ -4863,8 +5990,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4863 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl; 5990 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
4864 5991
4865 ivideo->SiS_Pr.SiS_Backup70xx = 0xff; 5992 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
4866 ivideo->SiS_Pr.SiS_CHOverScan = -1; 5993 ivideo->SiS_Pr.SiS_CHOverScan = -1;
4867 ivideo->SiS_Pr.SiS_ChSW = FALSE; 5994 ivideo->SiS_Pr.SiS_ChSW = FALSE;
4868 ivideo->SiS_Pr.SiS_UseLCDA = FALSE; 5995 ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
4869 ivideo->SiS_Pr.HaveEMI = FALSE; 5996 ivideo->SiS_Pr.HaveEMI = FALSE;
4870 ivideo->SiS_Pr.HaveEMILCD = FALSE; 5997 ivideo->SiS_Pr.HaveEMILCD = FALSE;
@@ -4873,12 +6000,13 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4873 ivideo->SiS_Pr.SiS_MyCR63 = 0x63; 6000 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
4874 ivideo->SiS_Pr.PDC = -1; 6001 ivideo->SiS_Pr.PDC = -1;
4875 ivideo->SiS_Pr.PDCA = -1; 6002 ivideo->SiS_Pr.PDCA = -1;
6003 ivideo->SiS_Pr.DDCPortMixup = FALSE;
4876#ifdef CONFIG_FB_SIS_315 6004#ifdef CONFIG_FB_SIS_315
4877 if(ivideo->chip >= SIS_330) { 6005 if(ivideo->chip >= SIS_330) {
4878 ivideo->SiS_Pr.SiS_MyCR63 = 0x53; 6006 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
4879 if(ivideo->chip >= SIS_661) { 6007 if(ivideo->chip >= SIS_661) {
4880 ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE; 6008 ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
4881 } 6009 }
4882 } 6010 }
4883#endif 6011#endif
4884 6012
@@ -4891,9 +6019,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4891 switch(ivideo->nbridge->device) { 6019 switch(ivideo->nbridge->device) {
4892#ifdef CONFIG_FB_SIS_300 6020#ifdef CONFIG_FB_SIS_300
4893 case PCI_DEVICE_ID_SI_730: 6021 case PCI_DEVICE_ID_SI_730:
4894 ivideo->chip = SIS_730; 6022 ivideo->chip = SIS_730;
4895 strcpy(ivideo->myid, "SiS 730"); 6023 strcpy(ivideo->myid, "SiS 730");
4896 break; 6024 break;
4897#endif 6025#endif
4898#ifdef CONFIG_FB_SIS_315 6026#ifdef CONFIG_FB_SIS_315
4899 case PCI_DEVICE_ID_SI_651: 6027 case PCI_DEVICE_ID_SI_651:
@@ -4901,22 +6029,28 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4901 strcpy(ivideo->myid, "SiS 651"); 6029 strcpy(ivideo->myid, "SiS 651");
4902 break; 6030 break;
4903 case PCI_DEVICE_ID_SI_740: 6031 case PCI_DEVICE_ID_SI_740:
4904 ivideo->chip = SIS_740; 6032 ivideo->chip = SIS_740;
4905 strcpy(ivideo->myid, "SiS 740"); 6033 strcpy(ivideo->myid, "SiS 740");
4906 break; 6034 break;
4907 case PCI_DEVICE_ID_SI_661: 6035 case PCI_DEVICE_ID_SI_661:
4908 ivideo->chip = SIS_661; 6036 ivideo->chip = SIS_661;
4909 strcpy(ivideo->myid, "SiS 661"); 6037 strcpy(ivideo->myid, "SiS 661");
4910 break; 6038 break;
4911 case PCI_DEVICE_ID_SI_741: 6039 case PCI_DEVICE_ID_SI_741:
4912 ivideo->chip = SIS_741; 6040 ivideo->chip = SIS_741;
4913 strcpy(ivideo->myid, "SiS 741"); 6041 strcpy(ivideo->myid, "SiS 741");
4914 break; 6042 break;
4915 case PCI_DEVICE_ID_SI_760: 6043 case PCI_DEVICE_ID_SI_760:
4916 ivideo->chip = SIS_760; 6044 ivideo->chip = SIS_760;
4917 strcpy(ivideo->myid, "SiS 760"); 6045 strcpy(ivideo->myid, "SiS 760");
4918 break; 6046 break;
6047 case PCI_DEVICE_ID_SI_761:
6048 ivideo->chip = SIS_761;
6049 strcpy(ivideo->myid, "SiS 761");
6050 break;
4919#endif 6051#endif
6052 default:
6053 break;
4920 } 6054 }
4921 } 6055 }
4922 6056
@@ -4924,71 +6058,83 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4924 strcpy(sis_fb_info->modename, ivideo->myid); 6058 strcpy(sis_fb_info->modename, ivideo->myid);
4925#endif 6059#endif
4926 6060
4927 ivideo->sishw_ext.jChipType = ivideo->chip; 6061 ivideo->SiS_Pr.ChipType = ivideo->chip;
6062
6063 ivideo->SiS_Pr.ivideo = (void *)ivideo;
4928 6064
4929#ifdef CONFIG_FB_SIS_315 6065#ifdef CONFIG_FB_SIS_315
4930 if((ivideo->sishw_ext.jChipType == SIS_315PRO) || 6066 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
4931 (ivideo->sishw_ext.jChipType == SIS_315)) { 6067 (ivideo->SiS_Pr.ChipType == SIS_315)) {
4932 ivideo->sishw_ext.jChipType = SIS_315H; 6068 ivideo->SiS_Pr.ChipType = SIS_315H;
4933 } 6069 }
4934#endif 6070#endif
4935 6071
6072 if(!ivideo->sisvga_enabled) {
6073 if(pci_enable_device(pdev)) {
6074 if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge);
6075 pci_set_drvdata(pdev, NULL);
6076 kfree(sis_fb_info);
6077 return -EIO;
6078 }
6079 }
6080
4936 ivideo->video_base = pci_resource_start(pdev, 0); 6081 ivideo->video_base = pci_resource_start(pdev, 0);
4937 ivideo->mmio_base = pci_resource_start(pdev, 1); 6082 ivideo->mmio_base = pci_resource_start(pdev, 1);
4938 ivideo->mmio_size = pci_resource_len(pdev, 1); 6083 ivideo->mmio_size = pci_resource_len(pdev, 1);
4939 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30; 6084 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
4940 ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO; 6085 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
4941 6086
4942 if(!sisvga_enabled) { 6087 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
4943 if(pci_enable_device(pdev)) {
4944 pci_set_drvdata(pdev, NULL);
4945 kfree(sis_fb_info);
4946 return -EIO;
4947 }
4948 }
4949
4950 SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress);
4951 6088
4952#ifdef CONFIG_FB_SIS_300 6089#ifdef CONFIG_FB_SIS_300
4953 /* Find PCI systems for Chrontel/GPIO communication setup */ 6090 /* Find PCI systems for Chrontel/GPIO communication setup */
4954 if(ivideo->chip == SIS_630) { 6091 if(ivideo->chip == SIS_630) {
4955 i=0; 6092 i = 0;
4956 do { 6093 do {
4957 if(mychswtable[i].subsysVendor == ivideo->subsysvendor && 6094 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
4958 mychswtable[i].subsysCard == ivideo->subsysdevice) { 6095 mychswtable[i].subsysCard == ivideo->subsysdevice) {
4959 ivideo->SiS_Pr.SiS_ChSW = TRUE; 6096 ivideo->SiS_Pr.SiS_ChSW = TRUE;
4960 printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n", 6097 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
4961 mychswtable[i].vendorName, mychswtable[i].cardName); 6098 "requiring Chrontel/GPIO setup\n",
4962 break; 6099 mychswtable[i].vendorName,
4963 } 6100 mychswtable[i].cardName);
4964 i++; 6101 ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL);
4965 } while(mychswtable[i].subsysVendor != 0); 6102 break;
6103 }
6104 i++;
6105 } while(mychswtable[i].subsysVendor != 0);
6106 }
6107#endif
6108
6109#ifdef CONFIG_FB_SIS_315
6110 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6111 ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3));
4966 } 6112 }
4967#endif 6113#endif
4968 6114
4969 outSISIDXREG(SISSR, 0x05, 0x86); 6115 outSISIDXREG(SISSR, 0x05, 0x86);
4970 6116
4971 if( (!sisvga_enabled) 6117 if( (!ivideo->sisvga_enabled)
4972#if !defined(__i386__) && !defined(__x86_64__) 6118#if !defined(__i386__) && !defined(__x86_64__)
4973 || (sisfb_resetcard) 6119 || (sisfb_resetcard)
4974#endif 6120#endif
4975 ) { 6121 ) {
4976 for(i = 0x30; i <= 0x3f; i++) { 6122 for(i = 0x30; i <= 0x3f; i++) {
4977 outSISIDXREG(SISCR,i,0x00); 6123 outSISIDXREG(SISCR, i, 0x00);
4978 } 6124 }
4979 } 6125 }
4980 6126
4981 /* Find out about current video mode */ 6127 /* Find out about current video mode */
4982 ivideo->modeprechange = 0x03; 6128 ivideo->modeprechange = 0x03;
4983 inSISIDXREG(SISCR,0x34,reg); 6129 inSISIDXREG(SISCR, 0x34, reg);
4984 if(reg & 0x7f) { 6130 if(reg & 0x7f) {
4985 ivideo->modeprechange = reg & 0x7f; 6131 ivideo->modeprechange = reg & 0x7f;
4986 } else if(sisvga_enabled) { 6132 } else if(ivideo->sisvga_enabled) {
4987#if defined(__i386__) || defined(__x86_64__) 6133#if defined(__i386__) || defined(__x86_64__)
4988 unsigned char SIS_IOTYPE2 *tt = ioremap(0, 0x1000); 6134 unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
4989 if(tt) { 6135 if(tt) {
4990 ivideo->modeprechange = readb(tt + 0x449); 6136 ivideo->modeprechange = readb(tt + 0x49);
4991 iounmap(tt); 6137 iounmap(tt);
4992 } 6138 }
4993#endif 6139#endif
4994 } 6140 }
@@ -4996,219 +6142,221 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
4996#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 6142#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
4997#ifdef MODULE 6143#ifdef MODULE
4998 if((reg & 0x80) && (reg != 0xff)) { 6144 if((reg & 0x80) && (reg != 0xff)) {
4999 if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) { 6145 if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni])
5000 printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n"); 6146 != 0xFF) {
5001 pci_set_drvdata(pdev, NULL); 6147 printk(KERN_INFO "sisfb: Cannot initialize display mode, "
5002 kfree(sis_fb_info); 6148 "X server is active\n");
5003 return -EBUSY; 6149 ret = -EBUSY;
5004 } 6150 goto error_4;
6151 }
5005 } 6152 }
5006#endif
5007#endif 6153#endif
5008
5009 ivideo->sishw_ext.bIntegratedMMEnabled = TRUE;
5010#ifdef CONFIG_FB_SIS_300
5011 if(ivideo->sisvga_engine == SIS_300_VGA) {
5012 if(ivideo->chip != SIS_300) {
5013 inSISIDXREG(SISSR, 0x1a, reg);
5014 if(!(reg & 0x10)) {
5015 ivideo->sishw_ext.bIntegratedMMEnabled = FALSE;
5016 }
5017 }
5018 }
5019#endif 6154#endif
5020 6155
6156 /* Search and copy ROM image */
5021 ivideo->bios_abase = NULL; 6157 ivideo->bios_abase = NULL;
6158 ivideo->SiS_Pr.VirtualRomBase = NULL;
6159 ivideo->SiS_Pr.UseROM = FALSE;
6160 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE;
5022 if(ivideo->sisfb_userom) { 6161 if(ivideo->sisfb_userom) {
5023 ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev); 6162 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
5024 ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase; 6163 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
5025 if(ivideo->sishw_ext.pjVirtualRomBase) { 6164 ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE;
5026 printk(KERN_INFO "sisfb: Video ROM found and copied\n"); 6165 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
5027 ivideo->sishw_ext.UseROM = TRUE; 6166 ivideo->SiS_Pr.UseROM ? "" : "not ");
5028 } else { 6167 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
5029 ivideo->sishw_ext.UseROM = FALSE; 6168 ivideo->SiS_Pr.UseROM = FALSE;
5030 printk(KERN_INFO "sisfb: Video ROM not found\n"); 6169 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE;
5031 } 6170 if( (ivideo->revision_id == 2) &&
6171 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6172 ivideo->SiS_Pr.DDCPortMixup = TRUE;
6173 }
6174 }
5032 } else { 6175 } else {
5033 ivideo->sishw_ext.pjVirtualRomBase = NULL; 6176 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
5034 ivideo->sishw_ext.UseROM = FALSE;
5035 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
5036 } 6177 }
5037 6178
5038 /* Find systems for special custom timing */ 6179 /* Find systems for special custom timing */
5039 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) { 6180 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
5040 int j; 6181 sisfb_detect_custom_timing(ivideo);
5041 unsigned char *biosver = NULL;
5042 unsigned char *biosdate = NULL;
5043 BOOLEAN footprint;
5044 u32 chksum = 0;
5045
5046 if(ivideo->sishw_ext.UseROM) {
5047 biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06;
5048 biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c;
5049 for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i];
5050 }
5051
5052 i=0;
5053 do {
5054 if( (mycustomttable[i].chipID == ivideo->chip) &&
5055 ((!strlen(mycustomttable[i].biosversion)) ||
5056 (ivideo->sishw_ext.UseROM &&
5057 (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) &&
5058 ((!strlen(mycustomttable[i].biosdate)) ||
5059 (ivideo->sishw_ext.UseROM &&
5060 (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) &&
5061 ((!mycustomttable[i].bioschksum) ||
5062 (ivideo->sishw_ext.UseROM &&
5063 (mycustomttable[i].bioschksum == chksum))) &&
5064 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
5065 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
5066 footprint = TRUE;
5067 for(j = 0; j < 5; j++) {
5068 if(mycustomttable[i].biosFootprintAddr[j]) {
5069 if(ivideo->sishw_ext.UseROM) {
5070 if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
5071 mycustomttable[i].biosFootprintData[j]) {
5072 footprint = FALSE;
5073 }
5074 } else footprint = FALSE;
5075 }
5076 }
5077 if(footprint) {
5078 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
5079 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
5080 mycustomttable[i].vendorName,
5081 mycustomttable[i].cardName);
5082 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
5083 mycustomttable[i].optionName);
5084 break;
5085 }
5086 }
5087 i++;
5088 } while(mycustomttable[i].chipID);
5089 } 6182 }
5090 6183
5091#ifdef CONFIG_FB_SIS_300 6184 /* POST card in case this has not been done by the BIOS */
5092 if(ivideo->sisvga_engine == SIS_300_VGA) { 6185 if( (!ivideo->sisvga_enabled)
5093 if( (!sisvga_enabled)
5094#if !defined(__i386__) && !defined(__x86_64__) 6186#if !defined(__i386__) && !defined(__x86_64__)
5095 || (sisfb_resetcard) 6187 || (sisfb_resetcard)
5096#endif 6188#endif
5097 ) { 6189 ) {
6190#ifdef CONFIG_FB_SIS_300
6191 if(ivideo->sisvga_engine == SIS_300_VGA) {
5098 if(ivideo->chip == SIS_300) { 6192 if(ivideo->chip == SIS_300) {
5099 sisfb_post_sis300(pdev); 6193 sisfb_post_sis300(pdev);
6194 ivideo->sisfb_can_post = 1;
5100 } 6195 }
5101 } 6196 }
5102 }
5103#endif 6197#endif
5104 6198
5105#ifdef CONFIG_FB_SIS_315 6199#ifdef CONFIG_FB_SIS_315
5106 if(ivideo->sisvga_engine == SIS_315_VGA) { 6200 if(ivideo->sisvga_engine == SIS_315_VGA) {
5107 if( (!sisvga_enabled) 6201 int result = 1;
5108#if !defined(__i386__) && !defined(__x86_64__) 6202 /* if((ivideo->chip == SIS_315H) ||
5109 || (sisfb_resetcard)
5110#endif
5111 ) {
5112 if((ivideo->chip == SIS_315H) ||
5113 (ivideo->chip == SIS_315) || 6203 (ivideo->chip == SIS_315) ||
5114 (ivideo->chip == SIS_315PRO) || 6204 (ivideo->chip == SIS_315PRO) ||
5115 (ivideo->chip == SIS_330)) { 6205 (ivideo->chip == SIS_330)) {
5116 sisfb_post_sis315330(pdev); 6206 sisfb_post_sis315330(pdev);
6207 } else */ if(ivideo->chip == XGI_20) {
6208 result = sisfb_post_xgi(pdev);
6209 ivideo->sisfb_can_post = 1;
6210 } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6211 result = sisfb_post_xgi(pdev);
6212 ivideo->sisfb_can_post = 1;
6213 } else {
6214 printk(KERN_INFO "sisfb: Card is not "
6215 "POSTed and sisfb can't do this either.\n");
6216 }
6217 if(!result) {
6218 printk(KERN_ERR "sisfb: Failed to POST card\n");
6219 ret = -ENODEV;
6220 goto error_3;
5117 } 6221 }
5118 } 6222 }
5119 }
5120#endif 6223#endif
6224 }
5121 6225
6226 ivideo->sisfb_card_posted = 1;
6227
6228 /* Find out about RAM size */
5122 if(sisfb_get_dram_size(ivideo)) { 6229 if(sisfb_get_dram_size(ivideo)) {
5123 printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n"); 6230 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
5124 if(ivideo->bios_abase) vfree(ivideo->bios_abase); 6231 ret = -ENODEV;
5125 pci_set_drvdata(pdev, NULL); 6232 goto error_3;
5126 kfree(sis_fb_info);
5127 return -ENODEV;
5128 } 6233 }
5129 6234
6235
6236 /* Enable PCI addressing and MMIO */
5130 if((ivideo->sisfb_mode_idx < 0) || 6237 if((ivideo->sisfb_mode_idx < 0) ||
5131 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { 6238 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
5132 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ 6239 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
5133 orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE)); 6240 orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
5134 /* Enable 2D accelerator engine */ 6241 /* Enable 2D accelerator engine */
5135 orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D); 6242 orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
5136 } 6243 }
5137 6244
5138 if(sisfb_pdc != 0xff) { 6245 if(sisfb_pdc != 0xff) {
5139 if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c; 6246 if(ivideo->sisvga_engine == SIS_300_VGA)
5140 else sisfb_pdc &= 0x1f; 6247 sisfb_pdc &= 0x3c;
5141 ivideo->SiS_Pr.PDC = sisfb_pdc; 6248 else
6249 sisfb_pdc &= 0x1f;
6250 ivideo->SiS_Pr.PDC = sisfb_pdc;
5142 } 6251 }
5143#ifdef CONFIG_FB_SIS_315 6252#ifdef CONFIG_FB_SIS_315
5144 if(ivideo->sisvga_engine == SIS_315_VGA) { 6253 if(ivideo->sisvga_engine == SIS_315_VGA) {
5145 if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f; 6254 if(sisfb_pdca != 0xff)
6255 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
5146 } 6256 }
5147#endif 6257#endif
5148 6258
5149 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) { 6259 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
5150 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n"); 6260 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6261 (int)(ivideo->video_size >> 20));
5151 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n"); 6262 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
5152 if(ivideo->bios_abase) vfree(ivideo->bios_abase); 6263 ret = -ENODEV;
5153 pci_set_drvdata(pdev, NULL); 6264 goto error_3;
5154 kfree(sis_fb_info);
5155 return -ENODEV;
5156 } 6265 }
5157 6266
5158 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) { 6267 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
5159 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n"); 6268 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
5160 release_mem_region(ivideo->video_base, ivideo->video_size); 6269 ret = -ENODEV;
5161 if(ivideo->bios_abase) vfree(ivideo->bios_abase); 6270 goto error_2;
5162 pci_set_drvdata(pdev, NULL);
5163 kfree(sis_fb_info);
5164 return -ENODEV;
5165 } 6271 }
5166 6272
5167 ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size); 6273 ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
5168 ivideo->sishw_ext.pjVideoMemoryAddress = ivideo->video_vbase; 6274 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
5169 if(!ivideo->video_vbase) { 6275 if(!ivideo->video_vbase) {
5170 printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n"); 6276 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
5171 release_mem_region(ivideo->video_base, ivideo->video_size); 6277 ret = -ENODEV;
5172 release_mem_region(ivideo->mmio_base, ivideo->mmio_size); 6278 goto error_1;
5173 if(ivideo->bios_abase) vfree(ivideo->bios_abase);
5174 pci_set_drvdata(pdev, NULL);
5175 kfree(sis_fb_info);
5176 return -ENODEV;
5177 } 6279 }
5178 6280
5179 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size); 6281 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
5180 if(!ivideo->mmio_vbase) { 6282 if(!ivideo->mmio_vbase) {
5181 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n"); 6283 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
5182 iounmap(ivideo->video_vbase); 6284 ret = -ENODEV;
5183 release_mem_region(ivideo->video_base, ivideo->video_size); 6285error_0: iounmap(ivideo->video_vbase);
5184 release_mem_region(ivideo->mmio_base, ivideo->mmio_size); 6286error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
5185 if(ivideo->bios_abase) vfree(ivideo->bios_abase); 6287error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6288error_3: vfree(ivideo->bios_abase);
6289#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
6290error_4:
6291#endif
6292 if(ivideo->lpcdev)
6293 SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
6294 if(ivideo->nbridge)
6295 SIS_PCI_PUT_DEVICE(ivideo->nbridge);
5186 pci_set_drvdata(pdev, NULL); 6296 pci_set_drvdata(pdev, NULL);
5187 kfree(sis_fb_info); 6297 if(!ivideo->sisvga_enabled)
5188 return -ENODEV; 6298 pci_disable_device(pdev);
6299 kfree(sis_fb_info);
6300 return ret;
5189 } 6301 }
5190 6302
5191 printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n", 6303 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
5192 ivideo->video_base, (ULONG)ivideo->video_vbase, ivideo->video_size / 1024); 6304 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6305
6306 if(ivideo->video_offset) {
6307 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6308 ivideo->video_offset / 1024);
6309 }
5193 6310
5194 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n", 6311 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
5195 ivideo->mmio_base, (ULONG)ivideo->mmio_vbase, ivideo->mmio_size / 1024); 6312 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6313
5196 6314
6315 /* Determine the size of the command queue */
6316 if(ivideo->sisvga_engine == SIS_300_VGA) {
6317 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6318 } else {
6319 if(ivideo->chip == XGI_20) {
6320 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6321 } else {
6322 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6323 }
6324 }
6325
6326 /* Engines are no longer initialized here; this is
6327 * now done after the first mode-switch (if the
6328 * submitted var has its acceleration flags set).
6329 */
6330
6331 /* Calculate the base of the (unused) hw cursor */
6332 ivideo->hwcursor_vbase = ivideo->video_vbase
6333 + ivideo->video_size
6334 - ivideo->cmdQueueSize
6335 - ivideo->hwcursor_size;
6336 ivideo->caps |= HW_CURSOR_CAP;
6337
6338 /* Initialize offscreen memory manager */
5197 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) { 6339 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
5198 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n"); 6340 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
5199 } 6341 }
5200 6342
5201 /* Used for clearing the screen only, therefore respect our mem limit */ 6343 /* Used for clearing the screen only, therefore respect our mem limit */
5202 ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem; 6344 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6345 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
5203 6346
5204 ivideo->mtrr = 0; 6347 ivideo->mtrr = -1;
5205 6348
5206 ivideo->vbflags = 0; 6349 ivideo->vbflags = 0;
5207 ivideo->lcddefmodeidx = DEFAULT_LCDMODE; 6350 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
5208 ivideo->tvdefmodeidx = DEFAULT_TVMODE; 6351 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
5209 ivideo->defmodeidx = DEFAULT_MODE; 6352 ivideo->defmodeidx = DEFAULT_MODE;
5210 6353
5211 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext); 6354 ivideo->newrom = 0;
6355 if(ivideo->chip < XGI_20) {
6356 if(ivideo->bios_abase) {
6357 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6358 }
6359 }
5212 6360
5213 if((ivideo->sisfb_mode_idx < 0) || 6361 if((ivideo->sisfb_mode_idx < 0) ||
5214 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { 6362 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
@@ -5217,192 +6365,57 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5217 6365
5218 sisfb_get_VB_type(ivideo); 6366 sisfb_get_VB_type(ivideo);
5219 6367
5220 if(ivideo->vbflags & VB_VIDEOBRIDGE) { 6368 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
5221 sisfb_detect_VB_connect(ivideo); 6369 sisfb_detect_VB_connect(ivideo);
5222 } 6370 }
5223 6371
5224 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD); 6372 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
5225 6373
5226 if(ivideo->vbflags & VB_VIDEOBRIDGE) { 6374 /* Decide on which CRT2 device to use */
5227 if(ivideo->sisfb_crt2type != -1) { 6375 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
5228 if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) { 6376 if(ivideo->sisfb_crt2type != -1) {
5229 ivideo->currentvbflags |= CRT2_LCD; 6377 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
5230 } else if(ivideo->sisfb_crt2type != CRT2_LCD) { 6378 (ivideo->vbflags & CRT2_LCD)) {
5231 ivideo->currentvbflags |= ivideo->sisfb_crt2type; 6379 ivideo->currentvbflags |= CRT2_LCD;
5232 } 6380 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
5233 } else { 6381 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
5234 /* Chrontel 700x TV detection often unreliable, therefore use a 6382 }
5235 * different default order on such machines 6383 } else {
5236 */ 6384 /* Chrontel 700x TV detection often unreliable, therefore
5237 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags & VB_CHRONTEL)) { 6385 * use a different default order on such machines
5238 if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD; 6386 */
5239 else if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV; 6387 if((ivideo->sisvga_engine == SIS_300_VGA) &&
5240 else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA; 6388 (ivideo->vbflags2 & VB2_CHRONTEL)) {
5241 } else { 6389 if(ivideo->vbflags & CRT2_LCD)
5242 if(ivideo->vbflags & CRT2_TV) ivideo->currentvbflags |= CRT2_TV; 6390 ivideo->currentvbflags |= CRT2_LCD;
5243 else if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD; 6391 else if(ivideo->vbflags & CRT2_TV)
5244 else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA; 6392 ivideo->currentvbflags |= CRT2_TV;
5245 } 6393 else if(ivideo->vbflags & CRT2_VGA)
5246 } 6394 ivideo->currentvbflags |= CRT2_VGA;
6395 } else {
6396 if(ivideo->vbflags & CRT2_TV)
6397 ivideo->currentvbflags |= CRT2_TV;
6398 else if(ivideo->vbflags & CRT2_LCD)
6399 ivideo->currentvbflags |= CRT2_LCD;
6400 else if(ivideo->vbflags & CRT2_VGA)
6401 ivideo->currentvbflags |= CRT2_VGA;
6402 }
6403 }
5247 } 6404 }
5248 6405
5249 if(ivideo->vbflags & CRT2_LCD) { 6406 if(ivideo->vbflags & CRT2_LCD) {
5250 inSISIDXREG(SISCR, 0x36, reg); 6407 sisfb_detect_lcd_type(ivideo);
5251 reg &= 0x0f;
5252 if(ivideo->sisvga_engine == SIS_300_VGA) {
5253 ivideo->CRT2LCDType = sis300paneltype[reg];
5254 } else if(ivideo->chip >= SIS_661) {
5255 ivideo->CRT2LCDType = sis661paneltype[reg];
5256 } else {
5257 ivideo->CRT2LCDType = sis310paneltype[reg];
5258 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
5259 if((ivideo->CRT2LCDType != LCD_640x480_2) &&
5260 (ivideo->CRT2LCDType != LCD_640x480_3)) {
5261 ivideo->CRT2LCDType = LCD_320x480;
5262 }
5263 }
5264 }
5265 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
5266 /* For broken BIOSes: Assume 1024x768, RGB18 */
5267 ivideo->CRT2LCDType = LCD_1024x768;
5268 setSISIDXREG(SISCR,0x36,0xf0,0x02);
5269 setSISIDXREG(SISCR,0x37,0xee,0x01);
5270 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
5271 }
5272 for(i = 0; i < SIS_LCD_NUMBER; i++) {
5273 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
5274 ivideo->lcdxres = sis_lcd_data[i].xres;
5275 ivideo->lcdyres = sis_lcd_data[i].yres;
5276 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
5277 break;
5278 }
5279 }
5280 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
5281 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99;
5282 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
5283 ivideo->lcdxres = 848; ivideo->lcdyres = 480; ivideo->lcddefmodeidx = 47;
5284 }
5285 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
5286 ivideo->lcdxres, ivideo->lcdyres);
5287 }
5288
5289#ifdef CONFIG_FB_SIS_300
5290 /* Save the current PanelDelayCompensation if the LCD is currently used */
5291 if(ivideo->sisvga_engine == SIS_300_VGA) {
5292 if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) {
5293 int tmp;
5294 inSISIDXREG(SISCR,0x30,tmp);
5295 if(tmp & 0x20) {
5296 /* Currently on LCD? If yes, read current pdc */
5297 inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
5298 ivideo->detectedpdc &= 0x3c;
5299 if(ivideo->SiS_Pr.PDC == -1) {
5300 /* Let option override detection */
5301 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
5302 }
5303 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
5304 ivideo->detectedpdc);
5305 }
5306 if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
5307 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
5308 ivideo->SiS_Pr.PDC);
5309 }
5310 }
5311 } 6408 }
5312#endif
5313
5314#ifdef CONFIG_FB_SIS_315
5315 if(ivideo->sisvga_engine == SIS_315_VGA) {
5316
5317 /* Try to find about LCDA */
5318 if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
5319 int tmp;
5320 inSISIDXREG(SISPART1,0x13,tmp);
5321 if(tmp & 0x04) {
5322 ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
5323 ivideo->detectedlcda = 0x03;
5324 }
5325 }
5326
5327 /* Save PDC */
5328 if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
5329 int tmp;
5330 inSISIDXREG(SISCR,0x30,tmp);
5331 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
5332 /* Currently on LCD? If yes, read current pdc */
5333 u8 pdc;
5334 inSISIDXREG(SISPART1,0x2D,pdc);
5335 ivideo->detectedpdc = (pdc & 0x0f) << 1;
5336 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
5337 inSISIDXREG(SISPART1,0x35,pdc);
5338 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
5339 inSISIDXREG(SISPART1,0x20,pdc);
5340 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
5341 if(ivideo->newrom) {
5342 /* New ROM invalidates other PDC resp. */
5343 if(ivideo->detectedlcda != 0xff) {
5344 ivideo->detectedpdc = 0xff;
5345 } else {
5346 ivideo->detectedpdca = 0xff;
5347 }
5348 }
5349 if(ivideo->SiS_Pr.PDC == -1) {
5350 if(ivideo->detectedpdc != 0xff) {
5351 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
5352 }
5353 }
5354 if(ivideo->SiS_Pr.PDCA == -1) {
5355 if(ivideo->detectedpdca != 0xff) {
5356 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
5357 }
5358 }
5359 if(ivideo->detectedpdc != 0xff) {
5360 printk(KERN_INFO
5361 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
5362 ivideo->detectedpdc);
5363 }
5364 if(ivideo->detectedpdca != 0xff) {
5365 printk(KERN_INFO
5366 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
5367 ivideo->detectedpdca);
5368 }
5369 }
5370
5371 /* Save EMI */
5372 if(ivideo->vbflags & (VB_302LV | VB_302ELV)) {
5373 inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
5374 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
5375 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
5376 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
5377 ivideo->SiS_Pr.HaveEMI = TRUE;
5378 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
5379 ivideo->SiS_Pr.HaveEMILCD = TRUE;
5380 }
5381 }
5382 }
5383
5384 /* Let user override detected PDCs (all bridges) */
5385 if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
5386 if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
5387 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
5388 ivideo->SiS_Pr.PDC);
5389 }
5390 if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
5391 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
5392 ivideo->SiS_Pr.PDCA);
5393 }
5394 }
5395 6409
5396 } 6410 sisfb_save_pdc_emi(ivideo);
5397#endif
5398 6411
5399 if(!ivideo->sisfb_crt1off) { 6412 if(!ivideo->sisfb_crt1off) {
5400 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0); 6413 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
5401 } else { 6414 } else {
5402 if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) && 6415 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
5403 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) { 6416 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
5404 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1); 6417 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
5405 } 6418 }
5406 } 6419 }
5407 6420
5408 if(ivideo->sisfb_mode_idx >= 0) { 6421 if(ivideo->sisfb_mode_idx >= 0) {
@@ -5434,7 +6447,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5434 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; 6447 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
5435 6448
5436 if(ivideo->refresh_rate != 0) { 6449 if(ivideo->refresh_rate != 0) {
5437 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx); 6450 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6451 ivideo->sisfb_mode_idx);
5438 } 6452 }
5439 6453
5440 if(ivideo->rate_idx == 0) { 6454 if(ivideo->rate_idx == 0) {
@@ -5443,9 +6457,12 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5443 } 6457 }
5444 6458
5445 if(ivideo->sisfb_thismonitor.datavalid) { 6459 if(ivideo->sisfb_thismonitor.datavalid) {
5446 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx, 6460 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
5447 ivideo->rate_idx, ivideo->refresh_rate)) { 6461 ivideo->sisfb_mode_idx,
5448 printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); 6462 ivideo->rate_idx,
6463 ivideo->refresh_rate)) {
6464 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6465 "exceeds monitor specs!\n");
5449 } 6466 }
5450 } 6467 }
5451 6468
@@ -5454,28 +6471,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5454 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; 6471 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
5455 6472
5456 sisfb_set_vparms(ivideo); 6473 sisfb_set_vparms(ivideo);
5457
5458#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5459 6474
5460 /* ---------------- For 2.4: Now switch the mode ------------------ */ 6475#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5461 6476
5462 printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n", 6477 /* ---------------- For 2.4: Now switch the mode ------------------ */
5463 ivideo->video_width, ivideo->video_height, ivideo->video_bpp, 6478
6479 printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n",
6480 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
5464 ivideo->refresh_rate); 6481 ivideo->refresh_rate);
5465 6482
6483 /* Determine whether or not acceleration is to be
6484 * used. Need to know before pre/post_set_mode()
6485 */
6486 ivideo->accel = 0;
6487 ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT;
6488 if(ivideo->sisfb_accel) {
6489 ivideo->accel = -1;
6490 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6491 }
6492
6493 /* Now switch the mode */
5466 sisfb_pre_setmode(ivideo); 6494 sisfb_pre_setmode(ivideo);
5467 6495
5468 if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) { 6496 if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) {
5469 printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n", 6497 printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
5470 ivideo->mode_no); 6498 ivideo->mode_no);
5471 iounmap(ivideo->video_vbase); 6499 ret = -EINVAL;
5472 iounmap(ivideo->mmio_vbase); 6500 iounmap(ivideo->mmio_vbase);
5473 release_mem_region(ivideo->video_base, ivideo->video_size); 6501 goto error_0;
5474 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
5475 if(ivideo->bios_abase) vfree(ivideo->bios_abase);
5476 pci_set_drvdata(pdev, NULL);
5477 kfree(sis_fb_info);
5478 return -EINVAL;
5479 } 6502 }
5480 6503
5481 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); 6504 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
@@ -5488,18 +6511,17 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5488 /* Force reset of x virtual in crtc_to_var */ 6511 /* Force reset of x virtual in crtc_to_var */
5489 ivideo->default_var.xres_virtual = 0; 6512 ivideo->default_var.xres_virtual = 0;
5490 6513
6514 /* Copy mode timing to var */
5491 sisfb_crtc_to_var(ivideo, &ivideo->default_var); 6515 sisfb_crtc_to_var(ivideo, &ivideo->default_var);
5492 6516
6517 /* Find out about screen pitch */
5493 sisfb_calc_pitch(ivideo, &ivideo->default_var); 6518 sisfb_calc_pitch(ivideo, &ivideo->default_var);
5494 sisfb_set_pitch(ivideo); 6519 sisfb_set_pitch(ivideo);
5495 6520
5496 ivideo->accel = 0; 6521 /* Init the accelerator (does nothing currently) */
5497 if(ivideo->sisfb_accel) {
5498 ivideo->accel = -1;
5499 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
5500 }
5501 sisfb_initaccel(ivideo); 6522 sisfb_initaccel(ivideo);
5502 6523
6524 /* Init some fbinfo entries */
5503 sis_fb_info->node = -1; 6525 sis_fb_info->node = -1;
5504 sis_fb_info->flags = FBINFO_FLAG_DEFAULT; 6526 sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
5505 sis_fb_info->fbops = &sisfb_ops; 6527 sis_fb_info->fbops = &sisfb_ops;
@@ -5515,41 +6537,42 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5515#else /* --------- For 2.6: Setup a somewhat sane default var ------------ */ 6537#else /* --------- For 2.6: Setup a somewhat sane default var ------------ */
5516 6538
5517 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n", 6539 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
5518 ivideo->video_width, ivideo->video_height, ivideo->video_bpp, 6540 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
5519 ivideo->refresh_rate); 6541 ivideo->refresh_rate);
5520 6542
6543 /* Set up the default var according to chosen default display mode */
5521 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width; 6544 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
5522 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height; 6545 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
5523 ivideo->default_var.bits_per_pixel = ivideo->video_bpp; 6546 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
5524 6547
5525 sisfb_bpp_to_var(ivideo, &ivideo->default_var); 6548 sisfb_bpp_to_var(ivideo, &ivideo->default_var);
5526 6549
5527 ivideo->default_var.pixclock = (u32) (1000000000 / 6550 ivideo->default_var.pixclock = (u32) (1000000000 /
5528 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext, 6551 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
5529 ivideo->mode_no, ivideo->rate_idx)); 6552
5530 6553 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
5531 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext, 6554 ivideo->rate_idx, &ivideo->default_var)) {
5532 ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) { 6555 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
5533 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { 6556 ivideo->default_var.pixclock <<= 1;
5534 ivideo->default_var.pixclock <<= 1; 6557 }
5535 } 6558 }
5536 }
5537 6559
5538 if(ivideo->sisfb_ypan) { 6560 if(ivideo->sisfb_ypan) {
5539 /* Maximize regardless of sisfb_max at startup */ 6561 /* Maximize regardless of sisfb_max at startup */
5540 ivideo->default_var.yres_virtual = sisfb_calc_maxyres(ivideo, &ivideo->default_var); 6562 ivideo->default_var.yres_virtual =
5541 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) { 6563 sisfb_calc_maxyres(ivideo, &ivideo->default_var);
5542 ivideo->default_var.yres_virtual = ivideo->default_var.yres; 6564 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
5543 } 6565 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6566 }
5544 } 6567 }
5545 6568
5546 sisfb_calc_pitch(ivideo, &ivideo->default_var); 6569 sisfb_calc_pitch(ivideo, &ivideo->default_var);
5547 6570
5548 ivideo->accel = 0; 6571 ivideo->accel = 0;
5549 if(ivideo->sisfb_accel) { 6572 if(ivideo->sisfb_accel) {
5550 ivideo->accel = -1; 6573 ivideo->accel = -1;
5551#ifdef STUPID_ACCELF_TEXT_SHIT 6574#ifdef STUPID_ACCELF_TEXT_SHIT
5552 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT; 6575 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
5553#endif 6576#endif
5554 } 6577 }
5555 sisfb_initaccel(ivideo); 6578 sisfb_initaccel(ivideo);
@@ -5566,21 +6589,21 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5566#endif 6589#endif
5567 sis_fb_info->var = ivideo->default_var; 6590 sis_fb_info->var = ivideo->default_var;
5568 sis_fb_info->fix = ivideo->sisfb_fix; 6591 sis_fb_info->fix = ivideo->sisfb_fix;
5569 sis_fb_info->screen_base = ivideo->video_vbase; 6592 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
5570 sis_fb_info->fbops = &sisfb_ops; 6593 sis_fb_info->fbops = &sisfb_ops;
5571 6594
5572 sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info); 6595 sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
5573 sis_fb_info->pseudo_palette = ivideo->pseudo_palette; 6596 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
5574 6597
5575 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); 6598 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
5576#endif /* 2.6 */ 6599#endif /* 2.6 */
5577 6600
5578 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags); 6601 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
5579 6602
5580#ifdef CONFIG_MTRR 6603#ifdef CONFIG_MTRR
5581 ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size, 6604 ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
5582 MTRR_TYPE_WRCOMB, 1); 6605 MTRR_TYPE_WRCOMB, 1);
5583 if(!ivideo->mtrr) { 6606 if(ivideo->mtrr < 0) {
5584 printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n"); 6607 printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
5585 } 6608 }
5586#endif 6609#endif
@@ -5591,14 +6614,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5591 6614
5592 if(register_framebuffer(sis_fb_info) < 0) { 6615 if(register_framebuffer(sis_fb_info) < 0) {
5593 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n"); 6616 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
5594 iounmap(ivideo->video_vbase); 6617 ret = -EINVAL;
5595 iounmap(ivideo->mmio_vbase); 6618 iounmap(ivideo->mmio_vbase);
5596 release_mem_region(ivideo->video_base, ivideo->video_size); 6619 goto error_0;
5597 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
5598 if(ivideo->bios_abase) vfree(ivideo->bios_abase);
5599 pci_set_drvdata(pdev, NULL);
5600 kfree(sis_fb_info);
5601 return -EINVAL;
5602 } 6620 }
5603 6621
5604 ivideo->registered = 1; 6622 ivideo->registered = 1;
@@ -5607,21 +6625,47 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5607 ivideo->next = card_list; 6625 ivideo->next = card_list;
5608 card_list = ivideo; 6626 card_list = ivideo;
5609 6627
6628#ifdef SIS_OLD_CONFIG_COMPAT
6629 {
6630 int ret;
6631 /* Our ioctls are all "32/64bit compatible" */
6632 ret = register_ioctl32_conversion(FBIO_ALLOC, NULL);
6633 ret |= register_ioctl32_conversion(FBIO_FREE, NULL);
6634 ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL);
6635 ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL);
6636 ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL);
6637 ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL);
6638 ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL);
6639 ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL);
6640 ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL);
6641 ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
6642 ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
6643 ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL);
6644 if(ret)
6645 printk(KERN_ERR
6646 "sisfb: Error registering ioctl32 translations\n");
6647 else
6648 ivideo->ioctl32registered = 1;
6649 }
6650#endif
6651
5610 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n", 6652 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
5611 ivideo->sisfb_accel ? "enabled" : "disabled", 6653 ivideo->sisfb_accel ? "enabled" : "disabled",
5612 ivideo->sisfb_ypan ? 6654 ivideo->sisfb_ypan ?
5613 (ivideo->sisfb_max ? "enabled (auto-max)" : "enabled (no auto-max)") : "disabled"); 6655 (ivideo->sisfb_max ? "enabled (auto-max)" :
6656 "enabled (no auto-max)") :
6657 "disabled");
5614 6658
5615 6659
5616 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%d\n", 6660 printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
5617#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 6661#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5618 GET_FB_IDX(sis_fb_info->node), 6662 GET_FB_IDX(sis_fb_info->node),
5619#else 6663#else
5620 sis_fb_info->node, 6664 sis_fb_info->node,
5621#endif 6665#endif
5622 ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL); 6666 ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
5623 6667
5624 printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n"); 6668 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
5625 6669
5626 } /* if mode = "none" */ 6670 } /* if mode = "none" */
5627 6671
@@ -5634,26 +6678,62 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
5634 6678
5635static void __devexit sisfb_remove(struct pci_dev *pdev) 6679static void __devexit sisfb_remove(struct pci_dev *pdev)
5636{ 6680{
5637 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 6681 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5638 struct fb_info *sis_fb_info = ivideo->memyselfandi; 6682 struct fb_info *sis_fb_info = ivideo->memyselfandi;
5639 int registered = ivideo->registered; 6683 int registered = ivideo->registered;
6684 int modechanged = ivideo->modechanged;
6685
6686#ifdef SIS_OLD_CONFIG_COMPAT
6687 if(ivideo->ioctl32registered) {
6688 int ret;
6689 ret = unregister_ioctl32_conversion(FBIO_ALLOC);
6690 ret |= unregister_ioctl32_conversion(FBIO_FREE);
6691 ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK);
6692 ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
6693 ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
6694 ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
6695 ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
6696 ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
6697 ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
6698 ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
6699 ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
6700 ret |= unregister_ioctl32_conversion(SISFB_COMMAND);
6701 if(ret)
6702 printk(KERN_ERR
6703 "sisfb: Error unregistering ioctl32 translations\n");
6704 }
6705#endif
5640 6706
5641 /* Unmap */ 6707 /* Unmap */
5642 iounmap(ivideo->video_vbase);
5643 iounmap(ivideo->mmio_vbase); 6708 iounmap(ivideo->mmio_vbase);
5644 vfree(ivideo->bios_abase); 6709 iounmap(ivideo->video_vbase);
5645 6710
5646 /* Release mem regions */ 6711 /* Release mem regions */
5647 release_mem_region(ivideo->video_base, ivideo->video_size); 6712 release_mem_region(ivideo->video_base, ivideo->video_size);
5648 release_mem_region(ivideo->mmio_base, ivideo->mmio_size); 6713 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
5649 6714
6715 vfree(ivideo->bios_abase);
6716
6717 if(ivideo->lpcdev)
6718 SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
6719
6720 if(ivideo->nbridge)
6721 SIS_PCI_PUT_DEVICE(ivideo->nbridge);
6722
5650#ifdef CONFIG_MTRR 6723#ifdef CONFIG_MTRR
5651 /* Release MTRR region */ 6724 /* Release MTRR region */
5652 if(ivideo->mtrr) { 6725 if(ivideo->mtrr >= 0)
5653 mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size); 6726 mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
5654 }
5655#endif 6727#endif
5656 6728
6729 pci_set_drvdata(pdev, NULL);
6730
6731 /* If device was disabled when starting, disable
6732 * it when quitting.
6733 */
6734 if(!ivideo->sisvga_enabled)
6735 pci_disable_device(pdev);
6736
5657 /* Unregister the framebuffer */ 6737 /* Unregister the framebuffer */
5658 if(ivideo->registered) { 6738 if(ivideo->registered) {
5659 unregister_framebuffer(sis_fb_info); 6739 unregister_framebuffer(sis_fb_info);
@@ -5664,7 +6744,7 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
5664#endif 6744#endif
5665 } 6745 }
5666 6746
5667 pci_set_drvdata(pdev, NULL); 6747 /* OK, our ivideo is gone for good from here. */
5668 6748
5669 /* TODO: Restore the initial mode 6749 /* TODO: Restore the initial mode
5670 * This sounds easy but is as good as impossible 6750 * This sounds easy but is as good as impossible
@@ -5673,15 +6753,15 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
5673 * from machine to machine. Depends on the type 6753 * from machine to machine. Depends on the type
5674 * of integration between chipset and bridge. 6754 * of integration between chipset and bridge.
5675 */ 6755 */
5676 if(registered) { 6756 if(registered && modechanged)
5677 printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n"); 6757 printk(KERN_INFO
5678 } 6758 "sisfb: Restoring of text mode not supported yet\n");
5679}; 6759};
5680 6760
5681static struct pci_driver sisfb_driver = { 6761static struct pci_driver sisfb_driver = {
5682 .name = "sisfb", 6762 .name = "sisfb",
5683 .id_table = sisfb_pci_table, 6763 .id_table = sisfb_pci_table,
5684 .probe = sisfb_probe, 6764 .probe = sisfb_probe,
5685 .remove = __devexit_p(sisfb_remove) 6765 .remove = __devexit_p(sisfb_remove)
5686}; 6766};
5687 6767
@@ -5693,10 +6773,11 @@ SISINITSTATIC int __init sisfb_init(void)
5693 6773
5694 if(fb_get_options("sisfb", &options)) 6774 if(fb_get_options("sisfb", &options))
5695 return -ENODEV; 6775 return -ENODEV;
6776
5696 sisfb_setup(options); 6777 sisfb_setup(options);
5697#endif 6778#endif
5698#endif 6779#endif
5699 return(pci_register_driver(&sisfb_driver)); 6780 return pci_register_driver(&sisfb_driver);
5700} 6781}
5701 6782
5702#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) 6783#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
@@ -5711,36 +6792,129 @@ module_init(sisfb_init);
5711 6792
5712#ifdef MODULE 6793#ifdef MODULE
5713 6794
5714static char *mode = NULL; 6795static char *mode = NULL;
5715static int vesa = -1; 6796static int vesa = -1;
5716static unsigned int rate = 0; 6797static unsigned int rate = 0;
5717static unsigned int crt1off = 1; 6798static unsigned int crt1off = 1;
5718static unsigned int mem = 0; 6799static unsigned int mem = 0;
5719static char *forcecrt2type = NULL; 6800static char *forcecrt2type = NULL;
5720static int forcecrt1 = -1; 6801static int forcecrt1 = -1;
5721static int pdc = -1; 6802static int pdc = -1;
5722static int pdc1 = -1; 6803static int pdc1 = -1;
5723static int noaccel = -1; 6804static int noaccel = -1;
5724static int noypan = -1; 6805static int noypan = -1;
5725static int nomax = -1; 6806static int nomax = -1;
6807#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
6808static int inverse = 0;
6809#endif
6810static int userom = -1;
6811static int useoem = -1;
6812static char *tvstandard = NULL;
6813static int nocrt2rate = 0;
6814static int scalelcd = -1;
6815static char *specialtiming = NULL;
6816static int lvdshl = -1;
6817static int tvxposoffset = 0, tvyposoffset = 0;
6818#if !defined(__i386__) && !defined(__x86_64__)
6819static int resetcard = 0;
6820static int videoram = 0;
6821#endif
6822
6823static int __init sisfb_init_module(void)
6824{
6825 sisfb_setdefaultparms();
6826
6827 if(rate)
6828 sisfb_parm_rate = rate;
6829
6830 if((scalelcd == 0) || (scalelcd == 1))
6831 sisfb_scalelcd = scalelcd ^ 1;
6832
6833 /* Need to check crt2 type first for fstn/dstn */
6834
6835 if(forcecrt2type)
6836 sisfb_search_crt2type(forcecrt2type);
6837
6838 if(tvstandard)
6839 sisfb_search_tvstd(tvstandard);
6840
6841 if(mode)
6842 sisfb_search_mode(mode, FALSE);
6843 else if(vesa != -1)
6844 sisfb_search_vesamode(vesa, FALSE);
6845
6846 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6847
6848 sisfb_forcecrt1 = forcecrt1;
6849 if(forcecrt1 == 1)
6850 sisfb_crt1off = 0;
6851 else if(forcecrt1 == 0)
6852 sisfb_crt1off = 1;
6853
6854 if(noaccel == 1)
6855 sisfb_accel = 0;
6856 else if(noaccel == 0)
6857 sisfb_accel = 1;
6858
6859 if(noypan == 1)
6860 sisfb_ypan = 0;
6861 else if(noypan == 0)
6862 sisfb_ypan = 1;
6863
6864 if(nomax == 1)
6865 sisfb_max = 0;
6866 else if(nomax == 0)
6867 sisfb_max = 1;
6868
5726#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 6869#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5727static int inverse = 0; 6870 if(inverse) sisfb_inverse = 1;
5728#endif 6871#endif
5729static int userom = -1; 6872
5730static int useoem = -1; 6873 if(mem)
5731static char *tvstandard = NULL; 6874 sisfb_parm_mem = mem;
5732static int nocrt2rate = 0; 6875
5733static int scalelcd = -1; 6876 if(userom != -1)
5734static char *specialtiming = NULL; 6877 sisfb_userom = userom;
5735static int lvdshl = -1; 6878
5736static int tvxposoffset = 0, tvyposoffset = 0; 6879 if(useoem != -1)
5737static int filter = -1; 6880 sisfb_useoem = useoem;
6881
6882 if(pdc != -1)
6883 sisfb_pdc = (pdc & 0x7f);
6884
6885 if(pdc1 != -1)
6886 sisfb_pdca = (pdc1 & 0x1f);
6887
6888 sisfb_nocrt2rate = nocrt2rate;
6889
6890 if(specialtiming)
6891 sisfb_search_specialtiming(specialtiming);
6892
6893 if((lvdshl >= 0) && (lvdshl <= 3))
6894 sisfb_lvdshl = lvdshl;
6895
6896 sisfb_tvxposoffset = tvxposoffset;
6897 sisfb_tvyposoffset = tvyposoffset;
6898
5738#if !defined(__i386__) && !defined(__x86_64__) 6899#if !defined(__i386__) && !defined(__x86_64__)
5739static int resetcard = 0; 6900 sisfb_resetcard = (resetcard) ? 1 : 0;
5740static int videoram = 0; 6901 if(videoram)
6902 sisfb_videoram = videoram;
5741#endif 6903#endif
5742 6904
5743MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver"); 6905 return sisfb_init();
6906}
6907
6908static void __exit sisfb_remove_module(void)
6909{
6910 pci_unregister_driver(&sisfb_driver);
6911 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6912}
6913
6914module_init(sisfb_init_module);
6915module_exit(sisfb_remove_module);
6916
6917MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
5744MODULE_LICENSE("GPL"); 6918MODULE_LICENSE("GPL");
5745MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others"); 6919MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
5746 6920
@@ -5764,7 +6938,6 @@ MODULE_PARM(lvdshl, "i");
5764MODULE_PARM(tvstandard, "s"); 6938MODULE_PARM(tvstandard, "s");
5765MODULE_PARM(tvxposoffset, "i"); 6939MODULE_PARM(tvxposoffset, "i");
5766MODULE_PARM(tvyposoffset, "i"); 6940MODULE_PARM(tvyposoffset, "i");
5767MODULE_PARM(filter, "i");
5768MODULE_PARM(nocrt2rate, "i"); 6941MODULE_PARM(nocrt2rate, "i");
5769MODULE_PARM(inverse, "i"); 6942MODULE_PARM(inverse, "i");
5770#if !defined(__i386__) && !defined(__x86_64__) 6943#if !defined(__i386__) && !defined(__x86_64__)
@@ -5793,7 +6966,6 @@ module_param(lvdshl, int, 0);
5793module_param(tvstandard, charp, 0); 6966module_param(tvstandard, charp, 0);
5794module_param(tvxposoffset, int, 0); 6967module_param(tvxposoffset, int, 0);
5795module_param(tvyposoffset, int, 0); 6968module_param(tvyposoffset, int, 0);
5796module_param(filter, int, 0);
5797module_param(nocrt2rate, int, 0); 6969module_param(nocrt2rate, int, 0);
5798#if !defined(__i386__) && !defined(__x86_64__) 6970#if !defined(__i386__) && !defined(__x86_64__)
5799module_param(resetcard, int, 0); 6971module_param(resetcard, int, 0);
@@ -5801,25 +6973,35 @@ module_param(videoram, int, 0);
5801#endif 6973#endif
5802#endif 6974#endif
5803 6975
6976#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5804MODULE_PARM_DESC(mem, 6977MODULE_PARM_DESC(mem,
5805 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" 6978 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
5806 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" 6979 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
5807 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n" 6980 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
5808 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" 6981 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
5809 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n" 6982 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
5810 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n" 6983 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
5811 "for XFree86 4.x/X.org 6.7 and later.\n"); 6984 "for XFree86 4.x/X.org 6.7 and later.\n");
6985#else
6986MODULE_PARM_DESC(mem,
6987 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6988 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6989 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6990 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6991 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6992 "The value is to be specified without 'KB'.\n");
6993#endif
5812 6994
5813MODULE_PARM_DESC(noaccel, 6995MODULE_PARM_DESC(noaccel,
5814 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n" 6996 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
5815 "(default: 0)\n"); 6997 "(default: 0)\n");
5816 6998
5817MODULE_PARM_DESC(noypan, 6999MODULE_PARM_DESC(noypan,
5818 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n" 7000 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
5819 "will be performed by redrawing the screen. (default: 0)\n"); 7001 "will be performed by redrawing the screen. (default: 0)\n");
5820 7002
5821MODULE_PARM_DESC(nomax, 7003MODULE_PARM_DESC(nomax,
5822 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n" 7004 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
5823 "memory for the virtual screen in order to optimize scrolling performance. If\n" 7005 "memory for the virtual screen in order to optimize scrolling performance. If\n"
5824 "this is set to anything other than 0, sisfb will not do this and thereby \n" 7006 "this is set to anything other than 0, sisfb will not do this and thereby \n"
5825 "enable the user to positively specify a virtual Y size of the screen using\n" 7007 "enable the user to positively specify a virtual Y size of the screen using\n"
@@ -5827,30 +7009,30 @@ MODULE_PARM_DESC(nomax,
5827 7009
5828#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 7010#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5829MODULE_PARM_DESC(mode, 7011MODULE_PARM_DESC(mode,
5830 "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n" 7012 "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
5831 "1024x768x16. Other formats supported include XxY-Depth and\n" 7013 "1024x768x16. Other formats supported include XxY-Depth and\n"
5832 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" 7014 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
5833 "number, it will be interpreted as a VESA mode number. (default: none if\n" 7015 "number, it will be interpreted as a VESA mode number. (default: none if\n"
5834 "sisfb is a module; this leaves the console untouched and the driver will\n" 7016 "sisfb is a module; this leaves the console untouched and the driver will\n"
5835 "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n" 7017 "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
5836 "is in the kernel)\n"); 7018 "is in the kernel)\n");
5837MODULE_PARM_DESC(vesa, 7019MODULE_PARM_DESC(vesa,
5838 "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n" 7020 "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
5839 "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n" 7021 "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
5840 "and the driver will only do the video memory management for eg. DRM/DRI;\n" 7022 "and the driver will only do the video memory management for eg. DRM/DRI;\n"
5841 "0x0103 if sisfb is in the kernel)\n"); 7023 "0x0103 if sisfb is in the kernel)\n");
5842#endif 7024#endif
5843 7025
5844#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 7026#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
5845MODULE_PARM_DESC(mode, 7027MODULE_PARM_DESC(mode,
5846 "\nSelects the desired default display mode in the format XxYxDepth,\n" 7028 "\nSelects the desired default display mode in the format XxYxDepth,\n"
5847 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n" 7029 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
5848 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" 7030 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
5849 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n"); 7031 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
5850 7032
5851MODULE_PARM_DESC(vesa, 7033MODULE_PARM_DESC(vesa,
5852 "\nSelects the desired default display mode by VESA defined mode number, eg.\n" 7034 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
5853 "0x117 (default: 0x0103)\n"); 7035 "0x117 (default: 0x0103)\n");
5854#endif 7036#endif
5855 7037
5856MODULE_PARM_DESC(rate, 7038MODULE_PARM_DESC(rate,
@@ -5880,16 +7062,16 @@ MODULE_PARM_DESC(scalelcd,
5880 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n"); 7062 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
5881 7063
5882MODULE_PARM_DESC(pdc, 7064MODULE_PARM_DESC(pdc,
5883 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n" 7065 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
5884 "should detect this correctly in most cases; however, sometimes this is not\n" 7066 "should detect this correctly in most cases; however, sometimes this is not\n"
5885 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n" 7067 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
5886 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n" 7068 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
5887 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n" 7069 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
5888 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n"); 7070 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
5889 7071
5890#ifdef CONFIG_FB_SIS_315 7072#ifdef CONFIG_FB_SIS_315
5891MODULE_PARM_DESC(pdc1, 7073MODULE_PARM_DESC(pdc1,
5892 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n" 7074 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
5893 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n" 7075 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
5894 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n" 7076 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
5895 "implemented yet.\n"); 7077 "implemented yet.\n");
@@ -5913,17 +7095,13 @@ MODULE_PARM_DESC(tvyposoffset,
5913 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n" 7095 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
5914 "Default: 0\n"); 7096 "Default: 0\n");
5915 7097
5916MODULE_PARM_DESC(filter,
5917 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
5918 "(Possible values 0-7, default: [no filter])\n");
5919
5920MODULE_PARM_DESC(nocrt2rate, 7098MODULE_PARM_DESC(nocrt2rate,
5921 "\nSetting this to 1 will force the driver to use the default refresh rate for\n" 7099 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
5922 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n"); 7100 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
5923 7101
5924#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 7102#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5925MODULE_PARM_DESC(inverse, 7103MODULE_PARM_DESC(inverse,
5926 "\nSetting this to anything but 0 should invert the display colors, but this\n" 7104 "\nSetting this to anything but 0 should invert the display colors, but this\n"
5927 "does not seem to work. (default: 0)\n"); 7105 "does not seem to work. (default: 0)\n");
5928#endif 7106#endif
5929 7107
@@ -5931,98 +7109,23 @@ MODULE_PARM_DESC(inverse,
5931#ifdef CONFIG_FB_SIS_300 7109#ifdef CONFIG_FB_SIS_300
5932MODULE_PARM_DESC(resetcard, 7110MODULE_PARM_DESC(resetcard,
5933 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n" 7111 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
5934 "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n" 7112 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
5935 "Default: 0\n"); 7113 "currently). Default: 0\n");
5936 7114
5937MODULE_PARM_DESC(videoram, 7115MODULE_PARM_DESC(videoram,
5938 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n" 7116 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
5939 "some non-x86 architectures where the memory auto detection fails. Only\n" 7117 "some non-x86 architectures where the memory auto detection fails. Only\n"
5940 "relevant if resetcard is set, too. Default: [auto-detect]\n"); 7118 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
5941#endif
5942#endif 7119#endif
5943
5944static int __devinit sisfb_init_module(void)
5945{
5946 sisfb_setdefaultparms();
5947
5948 if(rate) sisfb_parm_rate = rate;
5949
5950 if((scalelcd == 0) || (scalelcd == 1)) {
5951 sisfb_scalelcd = scalelcd ^ 1;
5952 }
5953
5954 /* Need to check crt2 type first for fstn/dstn */
5955
5956 if(forcecrt2type)
5957 sisfb_search_crt2type(forcecrt2type);
5958
5959 if(tvstandard)
5960 sisfb_search_tvstd(tvstandard);
5961
5962 if(mode)
5963 sisfb_search_mode(mode, FALSE);
5964 else if(vesa != -1)
5965 sisfb_search_vesamode(vesa, FALSE);
5966
5967 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
5968
5969 sisfb_forcecrt1 = forcecrt1;
5970 if(forcecrt1 == 1) sisfb_crt1off = 0;
5971 else if(forcecrt1 == 0) sisfb_crt1off = 1;
5972
5973 if(noaccel == 1) sisfb_accel = 0;
5974 else if(noaccel == 0) sisfb_accel = 1;
5975
5976 if(noypan == 1) sisfb_ypan = 0;
5977 else if(noypan == 0) sisfb_ypan = 1;
5978
5979 if(nomax == 1) sisfb_max = 0;
5980 else if(nomax == 0) sisfb_max = 1;
5981
5982#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5983 if(inverse) sisfb_inverse = 1;
5984#endif 7120#endif
5985 7121
5986 if(mem) sisfb_parm_mem = mem;
5987
5988 if(userom != -1) sisfb_userom = userom;
5989 if(useoem != -1) sisfb_useoem = useoem;
5990
5991 if(pdc != -1) sisfb_pdc = (pdc & 0x7f);
5992 if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
5993
5994 sisfb_nocrt2rate = nocrt2rate;
5995
5996 if(specialtiming)
5997 sisfb_search_specialtiming(specialtiming);
5998
5999 if((lvdshl >= 0) && (lvdshl <= 3)) sisfb_lvdshl = lvdshl;
6000
6001 if(filter != -1) sisfb_filter = filter;
6002
6003 sisfb_tvxposoffset = tvxposoffset;
6004 sisfb_tvyposoffset = tvyposoffset;
6005
6006#if !defined(__i386__) && !defined(__x86_64__)
6007 sisfb_resetcard = (resetcard) ? 1 : 0;
6008 if(videoram) sisfb_videoram = videoram;
6009#endif
6010
6011 return(sisfb_init());
6012}
6013
6014static void __exit sisfb_remove_module(void)
6015{
6016 pci_unregister_driver(&sisfb_driver);
6017 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6018}
6019
6020module_init(sisfb_init_module);
6021module_exit(sisfb_remove_module);
6022
6023#endif /* /MODULE */ 7122#endif /* /MODULE */
6024 7123
7124/* _GPL only for new symbols. */
6025EXPORT_SYMBOL(sis_malloc); 7125EXPORT_SYMBOL(sis_malloc);
6026EXPORT_SYMBOL(sis_free); 7126EXPORT_SYMBOL(sis_free);
7127EXPORT_SYMBOL_GPL(sis_malloc_new);
7128EXPORT_SYMBOL_GPL(sis_free_new);
7129
6027 7130
6028 7131