xref: /linux/drivers/video/fbdev/sis/sis_main.c (revision 4949009eb8d40a441dcddcd96e101e77d31cf1b2)
1 /*
2  * SiS 300/540/630[S]/730[S],
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
5  * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
6  *
7  * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the named License,
12  * or any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
22  *
23  * Author:	Thomas Winischhofer <thomas@winischhofer.net>
24  *
25  * Author of (practically wiped) code base:
26  *		SiS (www.sis.com)
27  *		Copyright (C) 1999 Silicon Integrated Systems, Inc.
28  *
29  * See http://www.winischhofer.net/ for more information and updates
30  *
31  * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
32  * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
33  *
34  */
35 
36 #include <linux/module.h>
37 #include <linux/moduleparam.h>
38 #include <linux/kernel.h>
39 #include <linux/spinlock.h>
40 #include <linux/errno.h>
41 #include <linux/string.h>
42 #include <linux/mm.h>
43 #include <linux/screen_info.h>
44 #include <linux/slab.h>
45 #include <linux/fb.h>
46 #include <linux/selection.h>
47 #include <linux/ioport.h>
48 #include <linux/init.h>
49 #include <linux/pci.h>
50 #include <linux/vmalloc.h>
51 #include <linux/capability.h>
52 #include <linux/fs.h>
53 #include <linux/types.h>
54 #include <linux/uaccess.h>
55 #include <asm/io.h>
56 #ifdef CONFIG_MTRR
57 #include <asm/mtrr.h>
58 #endif
59 
60 #include "sis.h"
61 #include "sis_main.h"
62 
63 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
64 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
65 #warning sisfb will not work!
66 #endif
67 
68 static void sisfb_handle_command(struct sis_video_info *ivideo,
69 				 struct sisfb_cmd *sisfb_command);
70 
71 /* ------------------ Internal helper routines ----------------- */
72 
73 static void __init
74 sisfb_setdefaultparms(void)
75 {
76 	sisfb_off		= 0;
77 	sisfb_parm_mem		= 0;
78 	sisfb_accel		= -1;
79 	sisfb_ypan		= -1;
80 	sisfb_max		= -1;
81 	sisfb_userom		= -1;
82 	sisfb_useoem		= -1;
83 	sisfb_mode_idx		= -1;
84 	sisfb_parm_rate		= -1;
85 	sisfb_crt1off		= 0;
86 	sisfb_forcecrt1		= -1;
87 	sisfb_crt2type		= -1;
88 	sisfb_crt2flags		= 0;
89 	sisfb_pdc		= 0xff;
90 	sisfb_pdca		= 0xff;
91 	sisfb_scalelcd		= -1;
92 	sisfb_specialtiming 	= CUT_NONE;
93 	sisfb_lvdshl		= -1;
94 	sisfb_dstn		= 0;
95 	sisfb_fstn		= 0;
96 	sisfb_tvplug		= -1;
97 	sisfb_tvstd		= -1;
98 	sisfb_tvxposoffset	= 0;
99 	sisfb_tvyposoffset	= 0;
100 	sisfb_nocrt2rate	= 0;
101 #if !defined(__i386__) && !defined(__x86_64__)
102 	sisfb_resetcard		= 0;
103 	sisfb_videoram		= 0;
104 #endif
105 }
106 
107 /* ------------- Parameter parsing -------------- */
108 
109 static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
110 {
111 	int i = 0, j = 0;
112 
113 	/* We don't know the hardware specs yet and there is no ivideo */
114 
115 	if(vesamode == 0) {
116 		if(!quiet)
117 			printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
118 
119 		sisfb_mode_idx = DEFAULT_MODE;
120 
121 		return;
122 	}
123 
124 	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
125 
126 	while(sisbios_mode[i++].mode_no[0] != 0) {
127 		if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
128 		    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
129 			if(sisfb_fstn) {
130 				if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
131 				   sisbios_mode[i-1].mode_no[1] == 0x56 ||
132 				   sisbios_mode[i-1].mode_no[1] == 0x53)
133 					continue;
134 			} else {
135 				if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
136 				   sisbios_mode[i-1].mode_no[1] == 0x5b)
137 					continue;
138 			}
139 			sisfb_mode_idx = i - 1;
140 			j = 1;
141 			break;
142 		}
143 	}
144 	if((!j) && !quiet)
145 		printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
146 }
147 
148 static void sisfb_search_mode(char *name, bool quiet)
149 {
150 	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
151 	int i = 0;
152 	char strbuf[16], strbuf1[20];
153 	char *nameptr = name;
154 
155 	/* We don't know the hardware specs yet and there is no ivideo */
156 
157 	if(name == NULL) {
158 		if(!quiet)
159 			printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
160 
161 		sisfb_mode_idx = DEFAULT_MODE;
162 		return;
163 	}
164 
165 	if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
166 		if(!quiet)
167 			printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
168 
169 		sisfb_mode_idx = DEFAULT_MODE;
170 		return;
171 	}
172 
173 	if(strlen(name) <= 19) {
174 		strcpy(strbuf1, name);
175 		for(i = 0; i < strlen(strbuf1); i++) {
176 			if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
177 		}
178 
179 		/* This does some fuzzy mode naming detection */
180 		if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
181 			if((rate <= 32) || (depth > 32)) {
182 				j = rate; rate = depth; depth = j;
183 			}
184 			sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
185 			nameptr = strbuf;
186 			sisfb_parm_rate = rate;
187 		} else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
188 			sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
189 			nameptr = strbuf;
190 		} else {
191 			xres = 0;
192 			if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
193 				sprintf(strbuf, "%ux%ux8", xres, yres);
194 				nameptr = strbuf;
195 			} else {
196 				sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
197 				return;
198 			}
199 		}
200 	}
201 
202 	i = 0; j = 0;
203 	while(sisbios_mode[i].mode_no[0] != 0) {
204 		if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
205 			if(sisfb_fstn) {
206 				if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
207 				   sisbios_mode[i-1].mode_no[1] == 0x56 ||
208 				   sisbios_mode[i-1].mode_no[1] == 0x53)
209 					continue;
210 			} else {
211 				if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
212 				   sisbios_mode[i-1].mode_no[1] == 0x5b)
213 					continue;
214 			}
215 			sisfb_mode_idx = i - 1;
216 			j = 1;
217 			break;
218 		}
219 	}
220 
221 	if((!j) && !quiet)
222 		printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
223 }
224 
225 #ifndef MODULE
226 static void sisfb_get_vga_mode_from_kernel(void)
227 {
228 #ifdef CONFIG_X86
229 	char mymode[32];
230 	int  mydepth = screen_info.lfb_depth;
231 
232 	if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
233 
234 	if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
235 	    (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
236 	    (mydepth >= 8) && (mydepth <= 32) ) {
237 
238 		if(mydepth == 24) mydepth = 32;
239 
240 		sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
241 					screen_info.lfb_height,
242 					mydepth);
243 
244 		printk(KERN_DEBUG
245 			"sisfb: Using vga mode %s pre-set by kernel as default\n",
246 			mymode);
247 
248 		sisfb_search_mode(mymode, true);
249 	}
250 #endif
251 	return;
252 }
253 #endif
254 
255 static void __init
256 sisfb_search_crt2type(const char *name)
257 {
258 	int i = 0;
259 
260 	/* We don't know the hardware specs yet and there is no ivideo */
261 
262 	if(name == NULL) return;
263 
264 	while(sis_crt2type[i].type_no != -1) {
265 		if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
266 			sisfb_crt2type = sis_crt2type[i].type_no;
267 			sisfb_tvplug = sis_crt2type[i].tvplug_no;
268 			sisfb_crt2flags = sis_crt2type[i].flags;
269 			break;
270 		}
271 		i++;
272 	}
273 
274 	sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
275 	sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
276 
277 	if(sisfb_crt2type < 0)
278 		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
279 }
280 
281 static void __init
282 sisfb_search_tvstd(const char *name)
283 {
284 	int i = 0;
285 
286 	/* We don't know the hardware specs yet and there is no ivideo */
287 
288 	if(name == NULL)
289 		return;
290 
291 	while(sis_tvtype[i].type_no != -1) {
292 		if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
293 			sisfb_tvstd = sis_tvtype[i].type_no;
294 			break;
295 		}
296 		i++;
297 	}
298 }
299 
300 static void __init
301 sisfb_search_specialtiming(const char *name)
302 {
303 	int i = 0;
304 	bool found = false;
305 
306 	/* We don't know the hardware specs yet and there is no ivideo */
307 
308 	if(name == NULL)
309 		return;
310 
311 	if(!strncasecmp(name, "none", 4)) {
312 		sisfb_specialtiming = CUT_FORCENONE;
313 		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
314 	} else {
315 		while(mycustomttable[i].chipID != 0) {
316 			if(!strncasecmp(name,mycustomttable[i].optionName,
317 			   strlen(mycustomttable[i].optionName))) {
318 				sisfb_specialtiming = mycustomttable[i].SpecialID;
319 				found = true;
320 				printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
321 					mycustomttable[i].vendorName,
322 					mycustomttable[i].cardName,
323 					mycustomttable[i].optionName);
324 				break;
325 			}
326 			i++;
327 		}
328 		if(!found) {
329 			printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
330 			printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
331 			i = 0;
332 			while(mycustomttable[i].chipID != 0) {
333 				printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
334 					mycustomttable[i].optionName,
335 					mycustomttable[i].vendorName,
336 					mycustomttable[i].cardName);
337 				i++;
338 			}
339 		}
340 	}
341 }
342 
343 /* ----------- Various detection routines ----------- */
344 
345 static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
346 {
347 	unsigned char *biosver = NULL;
348 	unsigned char *biosdate = NULL;
349 	bool footprint;
350 	u32 chksum = 0;
351 	int i, j;
352 
353 	if(ivideo->SiS_Pr.UseROM) {
354 		biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
355 		biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
356 		for(i = 0; i < 32768; i++)
357 			chksum += ivideo->SiS_Pr.VirtualRomBase[i];
358 	}
359 
360 	i = 0;
361 	do {
362 		if( (mycustomttable[i].chipID == ivideo->chip)			&&
363 		    ((!strlen(mycustomttable[i].biosversion)) ||
364 		     (ivideo->SiS_Pr.UseROM &&
365 		      (!strncmp(mycustomttable[i].biosversion, biosver,
366 				strlen(mycustomttable[i].biosversion)))))	&&
367 		    ((!strlen(mycustomttable[i].biosdate)) ||
368 		     (ivideo->SiS_Pr.UseROM &&
369 		      (!strncmp(mycustomttable[i].biosdate, biosdate,
370 				strlen(mycustomttable[i].biosdate)))))		&&
371 		    ((!mycustomttable[i].bioschksum) ||
372 		     (ivideo->SiS_Pr.UseROM &&
373 		      (mycustomttable[i].bioschksum == chksum)))		&&
374 		    (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
375 		    (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
376 			footprint = true;
377 			for(j = 0; j < 5; j++) {
378 				if(mycustomttable[i].biosFootprintAddr[j]) {
379 					if(ivideo->SiS_Pr.UseROM) {
380 						if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
381 							mycustomttable[i].biosFootprintData[j]) {
382 							footprint = false;
383 						}
384 					} else
385 						footprint = false;
386 				}
387 			}
388 			if(footprint) {
389 				ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
390 				printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
391 					mycustomttable[i].vendorName,
392 				mycustomttable[i].cardName);
393 				printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
394 					mycustomttable[i].optionName);
395 				break;
396 			}
397 		}
398 		i++;
399 	} while(mycustomttable[i].chipID);
400 }
401 
402 static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
403 {
404 	int i, j, xres, yres, refresh, index;
405 	u32 emodes;
406 
407 	if(buffer[0] != 0x00 || buffer[1] != 0xff ||
408 	   buffer[2] != 0xff || buffer[3] != 0xff ||
409 	   buffer[4] != 0xff || buffer[5] != 0xff ||
410 	   buffer[6] != 0xff || buffer[7] != 0x00) {
411 		printk(KERN_DEBUG "sisfb: Bad EDID header\n");
412 		return false;
413 	}
414 
415 	if(buffer[0x12] != 0x01) {
416 		printk(KERN_INFO "sisfb: EDID version %d not supported\n",
417 			buffer[0x12]);
418 		return false;
419 	}
420 
421 	monitor->feature = buffer[0x18];
422 
423 	if(!(buffer[0x14] & 0x80)) {
424 		if(!(buffer[0x14] & 0x08)) {
425 			printk(KERN_INFO
426 				"sisfb: WARNING: Monitor does not support separate syncs\n");
427 		}
428 	}
429 
430 	if(buffer[0x13] >= 0x01) {
431 	   /* EDID V1 rev 1 and 2: Search for monitor descriptor
432 	    * to extract ranges
433 	    */
434 	    j = 0x36;
435 	    for(i=0; i<4; i++) {
436 	       if(buffer[j]     == 0x00 && buffer[j + 1] == 0x00 &&
437 		  buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
438 		  buffer[j + 4] == 0x00) {
439 		  monitor->hmin = buffer[j + 7];
440 		  monitor->hmax = buffer[j + 8];
441 		  monitor->vmin = buffer[j + 5];
442 		  monitor->vmax = buffer[j + 6];
443 		  monitor->dclockmax = buffer[j + 9] * 10 * 1000;
444 		  monitor->datavalid = true;
445 		  break;
446 	       }
447 	       j += 18;
448 	    }
449 	}
450 
451 	if(!monitor->datavalid) {
452 	   /* Otherwise: Get a range from the list of supported
453 	    * Estabished Timings. This is not entirely accurate,
454 	    * because fixed frequency monitors are not supported
455 	    * that way.
456 	    */
457 	   monitor->hmin = 65535; monitor->hmax = 0;
458 	   monitor->vmin = 65535; monitor->vmax = 0;
459 	   monitor->dclockmax = 0;
460 	   emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
461 	   for(i = 0; i < 13; i++) {
462 	      if(emodes & sisfb_ddcsmodes[i].mask) {
463 		 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
464 		 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
465 		 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
466 		 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
467 		 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
468 	      }
469 	   }
470 	   index = 0x26;
471 	   for(i = 0; i < 8; i++) {
472 	      xres = (buffer[index] + 31) * 8;
473 	      switch(buffer[index + 1] & 0xc0) {
474 		 case 0xc0: yres = (xres * 9) / 16; break;
475 		 case 0x80: yres = (xres * 4) /  5; break;
476 		 case 0x40: yres = (xres * 3) /  4; break;
477 		 default:   yres = xres;	    break;
478 	      }
479 	      refresh = (buffer[index + 1] & 0x3f) + 60;
480 	      if((xres >= 640) && (yres >= 480)) {
481 		 for(j = 0; j < 8; j++) {
482 		    if((xres == sisfb_ddcfmodes[j].x) &&
483 		       (yres == sisfb_ddcfmodes[j].y) &&
484 		       (refresh == sisfb_ddcfmodes[j].v)) {
485 		      if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
486 		      if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
487 		      if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
488 		      if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
489 		      if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
490 		    }
491 		 }
492 	      }
493 	      index += 2;
494 	   }
495 	   if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
496 	      monitor->datavalid = true;
497 	   }
498 	}
499 
500 	return monitor->datavalid;
501 }
502 
503 static void sisfb_handle_ddc(struct sis_video_info *ivideo,
504 			     struct sisfb_monitor *monitor, int crtno)
505 {
506 	unsigned short temp, i, realcrtno = crtno;
507 	unsigned char  buffer[256];
508 
509 	monitor->datavalid = false;
510 
511 	if(crtno) {
512 	   if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
513 	   else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
514 	   else return;
515 	}
516 
517 	if((ivideo->sisfb_crt1off) && (!crtno))
518 		return;
519 
520 	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
521 				realcrtno, 0, &buffer[0], ivideo->vbflags2);
522 	if((!temp) || (temp == 0xffff)) {
523 	   printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
524 	   return;
525 	} else {
526 	   printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
527 	   printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
528 		crtno + 1,
529 		(temp & 0x1a) ? "" : "[none of the supported]",
530 		(temp & 0x02) ? "2 " : "",
531 		(temp & 0x08) ? "D&P" : "",
532 		(temp & 0x10) ? "FPDI-2" : "");
533 	   if(temp & 0x02) {
534 	      i = 3;  /* Number of retrys */
535 	      do {
536 		 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
537 				     realcrtno, 1, &buffer[0], ivideo->vbflags2);
538 	      } while((temp) && i--);
539 	      if(!temp) {
540 		 if(sisfb_interpret_edid(monitor, &buffer[0])) {
541 		    printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
542 			monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
543 			monitor->dclockmax / 1000);
544 		 } else {
545 		    printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
546 		 }
547 	      } else {
548 		 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
549 	      }
550 	   } else {
551 	      printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
552 	   }
553 	}
554 }
555 
556 /* -------------- Mode validation --------------- */
557 
558 static bool
559 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
560 		int mode_idx, int rate_idx, int rate)
561 {
562 	int htotal, vtotal;
563 	unsigned int dclock, hsync;
564 
565 	if(!monitor->datavalid)
566 		return true;
567 
568 	if(mode_idx < 0)
569 		return false;
570 
571 	/* Skip for 320x200, 320x240, 640x400 */
572 	switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
573 	case 0x59:
574 	case 0x41:
575 	case 0x4f:
576 	case 0x50:
577 	case 0x56:
578 	case 0x53:
579 	case 0x2f:
580 	case 0x5d:
581 	case 0x5e:
582 		return true;
583 #ifdef CONFIG_FB_SIS_315
584 	case 0x5a:
585 	case 0x5b:
586 		if(ivideo->sisvga_engine == SIS_315_VGA) return true;
587 #endif
588 	}
589 
590 	if(rate < (monitor->vmin - 1))
591 		return false;
592 	if(rate > (monitor->vmax + 1))
593 		return false;
594 
595 	if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
596 				  sisbios_mode[mode_idx].mode_no[ivideo->mni],
597 				  &htotal, &vtotal, rate_idx)) {
598 		dclock = (htotal * vtotal * rate) / 1000;
599 		if(dclock > (monitor->dclockmax + 1000))
600 			return false;
601 		hsync = dclock / htotal;
602 		if(hsync < (monitor->hmin - 1))
603 			return false;
604 		if(hsync > (monitor->hmax + 1))
605 			return false;
606         } else {
607 		return false;
608 	}
609 	return true;
610 }
611 
612 static int
613 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
614 {
615 	u16 xres=0, yres, myres;
616 
617 #ifdef CONFIG_FB_SIS_300
618 	if(ivideo->sisvga_engine == SIS_300_VGA) {
619 		if(!(sisbios_mode[myindex].chipset & MD_SIS300))
620 			return -1 ;
621 	}
622 #endif
623 #ifdef CONFIG_FB_SIS_315
624 	if(ivideo->sisvga_engine == SIS_315_VGA) {
625 		if(!(sisbios_mode[myindex].chipset & MD_SIS315))
626 			return -1;
627 	}
628 #endif
629 
630 	myres = sisbios_mode[myindex].yres;
631 
632 	switch(vbflags & VB_DISPTYPE_DISP2) {
633 
634 	case CRT2_LCD:
635 		xres = ivideo->lcdxres; yres = ivideo->lcdyres;
636 
637 		if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
638 		   (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
639 			if(sisbios_mode[myindex].xres > xres)
640 				return -1;
641 			if(myres > yres)
642 				return -1;
643 		}
644 
645 		if(ivideo->sisfb_fstn) {
646 			if(sisbios_mode[myindex].xres == 320) {
647 				if(myres == 240) {
648 					switch(sisbios_mode[myindex].mode_no[1]) {
649 						case 0x50: myindex = MODE_FSTN_8;  break;
650 						case 0x56: myindex = MODE_FSTN_16; break;
651 						case 0x53: return -1;
652 					}
653 				}
654 			}
655 		}
656 
657 		if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
658 			 	sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
659 			 	ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
660 			return -1;
661 		}
662 		break;
663 
664 	case CRT2_TV:
665 		if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
666 				sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
667 			return -1;
668 		}
669 		break;
670 
671 	case CRT2_VGA:
672 		if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
673 				sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
674 			return -1;
675 		}
676 		break;
677 	}
678 
679 	return myindex;
680 }
681 
682 static u8
683 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
684 {
685 	int i = 0;
686 	u16 xres = sisbios_mode[mode_idx].xres;
687 	u16 yres = sisbios_mode[mode_idx].yres;
688 
689 	ivideo->rate_idx = 0;
690 	while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
691 		if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
692 			if(sisfb_vrate[i].refresh == rate) {
693 				ivideo->rate_idx = sisfb_vrate[i].idx;
694 				break;
695 			} else if(sisfb_vrate[i].refresh > rate) {
696 				if((sisfb_vrate[i].refresh - rate) <= 3) {
697 					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
698 						rate, sisfb_vrate[i].refresh);
699 					ivideo->rate_idx = sisfb_vrate[i].idx;
700 					ivideo->refresh_rate = sisfb_vrate[i].refresh;
701 				} else if((sisfb_vrate[i].idx != 1) &&
702 						((rate - sisfb_vrate[i-1].refresh) <= 2)) {
703 					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
704 						rate, sisfb_vrate[i-1].refresh);
705 					ivideo->rate_idx = sisfb_vrate[i-1].idx;
706 					ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
707 				}
708 				break;
709 			} else if((rate - sisfb_vrate[i].refresh) <= 2) {
710 				DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
711 						rate, sisfb_vrate[i].refresh);
712 				ivideo->rate_idx = sisfb_vrate[i].idx;
713 				break;
714 			}
715 		}
716 		i++;
717 	}
718 	if(ivideo->rate_idx > 0) {
719 		return ivideo->rate_idx;
720 	} else {
721 		printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
722 				rate, xres, yres);
723 		return 0;
724 	}
725 }
726 
727 static bool
728 sisfb_bridgeisslave(struct sis_video_info *ivideo)
729 {
730 	unsigned char P1_00;
731 
732 	if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
733 		return false;
734 
735 	P1_00 = SiS_GetReg(SISPART1, 0x00);
736 	if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
737 	    ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
738 		return true;
739 	} else {
740 		return false;
741 	}
742 }
743 
744 static bool
745 sisfballowretracecrt1(struct sis_video_info *ivideo)
746 {
747 	u8 temp;
748 
749 	temp = SiS_GetReg(SISCR, 0x17);
750 	if(!(temp & 0x80))
751 		return false;
752 
753 	temp = SiS_GetReg(SISSR, 0x1f);
754 	if(temp & 0xc0)
755 		return false;
756 
757 	return true;
758 }
759 
760 static bool
761 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
762 {
763 	if(!sisfballowretracecrt1(ivideo))
764 		return false;
765 
766 	if (SiS_GetRegByte(SISINPSTAT) & 0x08)
767 		return true;
768 	else
769 		return false;
770 }
771 
772 static void
773 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
774 {
775 	int watchdog;
776 
777 	if(!sisfballowretracecrt1(ivideo))
778 		return;
779 
780 	watchdog = 65536;
781 	while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
782 	watchdog = 65536;
783 	while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
784 }
785 
786 static bool
787 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
788 {
789 	unsigned char temp, reg;
790 
791 	switch(ivideo->sisvga_engine) {
792 	case SIS_300_VGA: reg = 0x25; break;
793 	case SIS_315_VGA: reg = 0x30; break;
794 	default:	  return false;
795 	}
796 
797 	temp = SiS_GetReg(SISPART1, reg);
798 	if(temp & 0x02)
799 		return true;
800 	else
801 		return false;
802 }
803 
804 static bool
805 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
806 {
807 	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
808 		if(!sisfb_bridgeisslave(ivideo)) {
809 			return sisfbcheckvretracecrt2(ivideo);
810 		}
811 	}
812 	return sisfbcheckvretracecrt1(ivideo);
813 }
814 
815 static u32
816 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
817 {
818 	u8 idx, reg1, reg2, reg3, reg4;
819 	u32 ret = 0;
820 
821 	(*vcount) = (*hcount) = 0;
822 
823 	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
824 
825 		ret |= (FB_VBLANK_HAVE_VSYNC  |
826 			FB_VBLANK_HAVE_HBLANK |
827 			FB_VBLANK_HAVE_VBLANK |
828 			FB_VBLANK_HAVE_VCOUNT |
829 			FB_VBLANK_HAVE_HCOUNT);
830 		switch(ivideo->sisvga_engine) {
831 			case SIS_300_VGA: idx = 0x25; break;
832 			default:
833 			case SIS_315_VGA: idx = 0x30; break;
834 		}
835 		reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
836 		reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
837 		reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
838 		reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
839 		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
840 		if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
841 		if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
842 		(*vcount) = reg3 | ((reg4 & 0x70) << 4);
843 		(*hcount) = reg2 | ((reg4 & 0x0f) << 8);
844 
845 	} else if(sisfballowretracecrt1(ivideo)) {
846 
847 		ret |= (FB_VBLANK_HAVE_VSYNC  |
848 			FB_VBLANK_HAVE_VBLANK |
849 			FB_VBLANK_HAVE_VCOUNT |
850 			FB_VBLANK_HAVE_HCOUNT);
851 		reg1 = SiS_GetRegByte(SISINPSTAT);
852 		if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
853 		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
854 		reg1 = SiS_GetReg(SISCR, 0x20);
855 		reg1 = SiS_GetReg(SISCR, 0x1b);
856 		reg2 = SiS_GetReg(SISCR, 0x1c);
857 		reg3 = SiS_GetReg(SISCR, 0x1d);
858 		(*vcount) = reg2 | ((reg3 & 0x07) << 8);
859 		(*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
860 	}
861 
862 	return ret;
863 }
864 
865 static int
866 sisfb_myblank(struct sis_video_info *ivideo, int blank)
867 {
868 	u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
869 	bool backlight = true;
870 
871 	switch(blank) {
872 		case FB_BLANK_UNBLANK:	/* on */
873 			sr01  = 0x00;
874 			sr11  = 0x00;
875 			sr1f  = 0x00;
876 			cr63  = 0x00;
877 			p2_0  = 0x20;
878 			p1_13 = 0x00;
879 			backlight = true;
880 			break;
881 		case FB_BLANK_NORMAL:	/* blank */
882 			sr01  = 0x20;
883 			sr11  = 0x00;
884 			sr1f  = 0x00;
885 			cr63  = 0x00;
886 			p2_0  = 0x20;
887 			p1_13 = 0x00;
888 			backlight = true;
889 			break;
890 		case FB_BLANK_VSYNC_SUSPEND:	/* no vsync */
891 			sr01  = 0x20;
892 			sr11  = 0x08;
893 			sr1f  = 0x80;
894 			cr63  = 0x40;
895 			p2_0  = 0x40;
896 			p1_13 = 0x80;
897 			backlight = false;
898 			break;
899 		case FB_BLANK_HSYNC_SUSPEND:	/* no hsync */
900 			sr01  = 0x20;
901 			sr11  = 0x08;
902 			sr1f  = 0x40;
903 			cr63  = 0x40;
904 			p2_0  = 0x80;
905 			p1_13 = 0x40;
906 			backlight = false;
907 			break;
908 		case FB_BLANK_POWERDOWN:	/* off */
909 			sr01  = 0x20;
910 			sr11  = 0x08;
911 			sr1f  = 0xc0;
912 			cr63  = 0x40;
913 			p2_0  = 0xc0;
914 			p1_13 = 0xc0;
915 			backlight = false;
916 			break;
917 		default:
918 			return 1;
919 	}
920 
921 	if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
922 
923 		if( (!ivideo->sisfb_thismonitor.datavalid) ||
924 		    ((ivideo->sisfb_thismonitor.datavalid) &&
925 		     (ivideo->sisfb_thismonitor.feature & 0xe0))) {
926 
927 			if(ivideo->sisvga_engine == SIS_315_VGA) {
928 				SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
929 			}
930 
931 			if(!(sisfb_bridgeisslave(ivideo))) {
932 				SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
933 				SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
934 			}
935 		}
936 
937 	}
938 
939 	if(ivideo->currentvbflags & CRT2_LCD) {
940 
941 		if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
942 			if(backlight) {
943 				SiS_SiS30xBLOn(&ivideo->SiS_Pr);
944 			} else {
945 				SiS_SiS30xBLOff(&ivideo->SiS_Pr);
946 			}
947 		} else if(ivideo->sisvga_engine == SIS_315_VGA) {
948 #ifdef CONFIG_FB_SIS_315
949 			if(ivideo->vbflags2 & VB2_CHRONTEL) {
950 				if(backlight) {
951 					SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
952 				} else {
953 					SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
954 				}
955 			}
956 #endif
957 		}
958 
959 		if(((ivideo->sisvga_engine == SIS_300_VGA) &&
960 		    (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
961 		   ((ivideo->sisvga_engine == SIS_315_VGA) &&
962 		    ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
963 			SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
964 		}
965 
966 		if(ivideo->sisvga_engine == SIS_300_VGA) {
967 			if((ivideo->vbflags2 & VB2_30xB) &&
968 			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
969 				SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
970 			}
971 		} else if(ivideo->sisvga_engine == SIS_315_VGA) {
972 			if((ivideo->vbflags2 & VB2_30xB) &&
973 			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
974 				SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
975 			}
976 		}
977 
978 	} else if(ivideo->currentvbflags & CRT2_VGA) {
979 
980 		if(ivideo->vbflags2 & VB2_30xB) {
981 			SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
982 		}
983 
984 	}
985 
986 	return 0;
987 }
988 
989 /* ------------- Callbacks from init.c/init301.c  -------------- */
990 
991 #ifdef CONFIG_FB_SIS_300
992 unsigned int
993 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
994 {
995    struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
996    u32 val = 0;
997 
998    pci_read_config_dword(ivideo->nbridge, reg, &val);
999    return (unsigned int)val;
1000 }
1001 
1002 void
1003 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1004 {
1005    struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1006 
1007    pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1008 }
1009 
1010 unsigned int
1011 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1012 {
1013    struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1014    u32 val = 0;
1015 
1016    if(!ivideo->lpcdev) return 0;
1017 
1018    pci_read_config_dword(ivideo->lpcdev, reg, &val);
1019    return (unsigned int)val;
1020 }
1021 #endif
1022 
1023 #ifdef CONFIG_FB_SIS_315
1024 void
1025 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1026 {
1027    struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1028 
1029    pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1030 }
1031 
1032 unsigned int
1033 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1034 {
1035    struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1036    u16 val = 0;
1037 
1038    if(!ivideo->lpcdev) return 0;
1039 
1040    pci_read_config_word(ivideo->lpcdev, reg, &val);
1041    return (unsigned int)val;
1042 }
1043 #endif
1044 
1045 /* ----------- FBDev related routines for all series ----------- */
1046 
1047 static int
1048 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1049 {
1050 	return (var->bits_per_pixel == 8) ? 256 : 16;
1051 }
1052 
1053 static void
1054 sisfb_set_vparms(struct sis_video_info *ivideo)
1055 {
1056 	switch(ivideo->video_bpp) {
1057 	case 8:
1058 		ivideo->DstColor = 0x0000;
1059 		ivideo->SiS310_AccelDepth = 0x00000000;
1060 		ivideo->video_cmap_len = 256;
1061 		break;
1062 	case 16:
1063 		ivideo->DstColor = 0x8000;
1064 		ivideo->SiS310_AccelDepth = 0x00010000;
1065 		ivideo->video_cmap_len = 16;
1066 		break;
1067 	case 32:
1068 		ivideo->DstColor = 0xC000;
1069 		ivideo->SiS310_AccelDepth = 0x00020000;
1070 		ivideo->video_cmap_len = 16;
1071 		break;
1072 	default:
1073 		ivideo->video_cmap_len = 16;
1074 		printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1075 		ivideo->accel = 0;
1076 	}
1077 }
1078 
1079 static int
1080 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1081 {
1082 	int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1083 
1084 	if(maxyres > 32767) maxyres = 32767;
1085 
1086 	return maxyres;
1087 }
1088 
1089 static void
1090 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1091 {
1092 	ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1093 	ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1094 	if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1095 		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1096 			ivideo->scrnpitchCRT1 <<= 1;
1097 		}
1098 	}
1099 }
1100 
1101 static void
1102 sisfb_set_pitch(struct sis_video_info *ivideo)
1103 {
1104 	bool isslavemode = false;
1105 	unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1106 	unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1107 
1108 	if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1109 
1110 	/* We need to set pitch for CRT1 if bridge is in slave mode, too */
1111 	if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1112 		SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1113 		SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1114 	}
1115 
1116 	/* We must not set the pitch for CRT2 if bridge is in slave mode */
1117 	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1118 		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1119 		SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1120 		SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1121 	}
1122 }
1123 
1124 static void
1125 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1126 {
1127 	ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1128 
1129 	switch(var->bits_per_pixel) {
1130 	case 8:
1131 		var->red.offset = var->green.offset = var->blue.offset = 0;
1132 		var->red.length = var->green.length = var->blue.length = 8;
1133 		break;
1134 	case 16:
1135 		var->red.offset = 11;
1136 		var->red.length = 5;
1137 		var->green.offset = 5;
1138 		var->green.length = 6;
1139 		var->blue.offset = 0;
1140 		var->blue.length = 5;
1141 		var->transp.offset = 0;
1142 		var->transp.length = 0;
1143 		break;
1144 	case 32:
1145 		var->red.offset = 16;
1146 		var->red.length = 8;
1147 		var->green.offset = 8;
1148 		var->green.length = 8;
1149 		var->blue.offset = 0;
1150 		var->blue.length = 8;
1151 		var->transp.offset = 24;
1152 		var->transp.length = 8;
1153 		break;
1154 	}
1155 }
1156 
1157 static int
1158 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1159 {
1160 	unsigned short modeno = ivideo->mode_no;
1161 
1162 	/* >=2.6.12's fbcon clears the screen anyway */
1163 	modeno |= 0x80;
1164 
1165 	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1166 
1167 	sisfb_pre_setmode(ivideo);
1168 
1169 	if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1170 		printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1171 		return -EINVAL;
1172 	}
1173 
1174 	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1175 
1176 	sisfb_post_setmode(ivideo);
1177 
1178 	return 0;
1179 }
1180 
1181 
1182 static int
1183 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1184 {
1185 	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1186 	unsigned int htotal = 0, vtotal = 0;
1187 	unsigned int drate = 0, hrate = 0;
1188 	int found_mode = 0, ret;
1189 	int old_mode;
1190 	u32 pixclock;
1191 
1192 	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1193 
1194 	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1195 
1196 	pixclock = var->pixclock;
1197 
1198 	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1199 		vtotal += var->yres;
1200 		vtotal <<= 1;
1201 	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1202 		vtotal += var->yres;
1203 		vtotal <<= 2;
1204 	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1205 		vtotal += var->yres;
1206 		vtotal <<= 1;
1207 	} else 	vtotal += var->yres;
1208 
1209 	if(!(htotal) || !(vtotal)) {
1210 		DPRINTK("sisfb: Invalid 'var' information\n");
1211 		return -EINVAL;
1212 	}
1213 
1214 	if(pixclock && htotal && vtotal) {
1215 		drate = 1000000000 / pixclock;
1216 		hrate = (drate * 1000) / htotal;
1217 		ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1218 	} else {
1219 		ivideo->refresh_rate = 60;
1220 	}
1221 
1222 	old_mode = ivideo->sisfb_mode_idx;
1223 	ivideo->sisfb_mode_idx = 0;
1224 
1225 	while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1226 	       (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1227 		if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1228 		    (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1229 		    (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1230 			ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1231 			found_mode = 1;
1232 			break;
1233 		}
1234 		ivideo->sisfb_mode_idx++;
1235 	}
1236 
1237 	if(found_mode) {
1238 		ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1239 				ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1240 	} else {
1241 		ivideo->sisfb_mode_idx = -1;
1242 	}
1243 
1244        	if(ivideo->sisfb_mode_idx < 0) {
1245 		printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1246 		       var->yres, var->bits_per_pixel);
1247 		ivideo->sisfb_mode_idx = old_mode;
1248 		return -EINVAL;
1249 	}
1250 
1251 	ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1252 
1253 	if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1254 		ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1255 		ivideo->refresh_rate = 60;
1256 	}
1257 
1258 	if(isactive) {
1259 		/* If acceleration to be used? Need to know
1260 		 * before pre/post_set_mode()
1261 		 */
1262 		ivideo->accel = 0;
1263 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1264 #ifdef STUPID_ACCELF_TEXT_SHIT
1265 		if(var->accel_flags & FB_ACCELF_TEXT) {
1266 			info->flags &= ~FBINFO_HWACCEL_DISABLED;
1267 		} else {
1268 			info->flags |= FBINFO_HWACCEL_DISABLED;
1269 		}
1270 #endif
1271 		if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1272 #else
1273 		if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1274 #endif
1275 
1276 		if((ret = sisfb_set_mode(ivideo, 1))) {
1277 			return ret;
1278 		}
1279 
1280 		ivideo->video_bpp    = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1281 		ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1282 		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1283 
1284 		sisfb_calc_pitch(ivideo, var);
1285 		sisfb_set_pitch(ivideo);
1286 
1287 		sisfb_set_vparms(ivideo);
1288 
1289 		ivideo->current_width = ivideo->video_width;
1290 		ivideo->current_height = ivideo->video_height;
1291 		ivideo->current_bpp = ivideo->video_bpp;
1292 		ivideo->current_htotal = htotal;
1293 		ivideo->current_vtotal = vtotal;
1294 		ivideo->current_linelength = ivideo->video_linelength;
1295 		ivideo->current_pixclock = var->pixclock;
1296 		ivideo->current_refresh_rate = ivideo->refresh_rate;
1297 		ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1298 	}
1299 
1300 	return 0;
1301 }
1302 
1303 static void
1304 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1305 {
1306 	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1307 
1308 	SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1309 	SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1310 	SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1311 	if(ivideo->sisvga_engine == SIS_315_VGA) {
1312 		SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1313 	}
1314 }
1315 
1316 static void
1317 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1318 {
1319 	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1320 		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1321 		SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1322 		SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1323 		SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1324 		if(ivideo->sisvga_engine == SIS_315_VGA) {
1325 			SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1326 		}
1327 	}
1328 }
1329 
1330 static int
1331 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1332 	      struct fb_var_screeninfo *var)
1333 {
1334 	ivideo->current_base = var->yoffset * info->var.xres_virtual
1335 			     + var->xoffset;
1336 
1337 	/* calculate base bpp dep. */
1338 	switch (info->var.bits_per_pixel) {
1339 	case 32:
1340 		break;
1341 	case 16:
1342 		ivideo->current_base >>= 1;
1343 		break;
1344 	case 8:
1345 	default:
1346 		ivideo->current_base >>= 2;
1347 		break;
1348 	}
1349 
1350 	ivideo->current_base += (ivideo->video_offset >> 2);
1351 
1352 	sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1353 	sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1354 
1355 	return 0;
1356 }
1357 
1358 static int
1359 sisfb_open(struct fb_info *info, int user)
1360 {
1361 	return 0;
1362 }
1363 
1364 static int
1365 sisfb_release(struct fb_info *info, int user)
1366 {
1367 	return 0;
1368 }
1369 
1370 static int
1371 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1372 		unsigned transp, struct fb_info *info)
1373 {
1374 	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1375 
1376 	if(regno >= sisfb_get_cmap_len(&info->var))
1377 		return 1;
1378 
1379 	switch(info->var.bits_per_pixel) {
1380 	case 8:
1381 		SiS_SetRegByte(SISDACA, regno);
1382 		SiS_SetRegByte(SISDACD, (red >> 10));
1383 		SiS_SetRegByte(SISDACD, (green >> 10));
1384 		SiS_SetRegByte(SISDACD, (blue >> 10));
1385 		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1386 			SiS_SetRegByte(SISDAC2A, regno);
1387 			SiS_SetRegByte(SISDAC2D, (red >> 8));
1388 			SiS_SetRegByte(SISDAC2D, (green >> 8));
1389 			SiS_SetRegByte(SISDAC2D, (blue >> 8));
1390 		}
1391 		break;
1392 	case 16:
1393 		if (regno >= 16)
1394 			break;
1395 
1396 		((u32 *)(info->pseudo_palette))[regno] =
1397 				(red & 0xf800)          |
1398 				((green & 0xfc00) >> 5) |
1399 				((blue & 0xf800) >> 11);
1400 		break;
1401 	case 32:
1402 		if (regno >= 16)
1403 			break;
1404 
1405 		red >>= 8;
1406 		green >>= 8;
1407 		blue >>= 8;
1408 		((u32 *)(info->pseudo_palette))[regno] =
1409 				(red << 16) | (green << 8) | (blue);
1410 		break;
1411 	}
1412 	return 0;
1413 }
1414 
1415 static int
1416 sisfb_set_par(struct fb_info *info)
1417 {
1418 	int err;
1419 
1420 	if((err = sisfb_do_set_var(&info->var, 1, info)))
1421 		return err;
1422 
1423 	sisfb_get_fix(&info->fix, -1, info);
1424 
1425 	return 0;
1426 }
1427 
1428 static int
1429 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1430 {
1431 	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1432 	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1433 	unsigned int drate = 0, hrate = 0, maxyres;
1434 	int found_mode = 0;
1435 	int refresh_rate, search_idx, tidx;
1436 	bool recalc_clock = false;
1437 	u32 pixclock;
1438 
1439 	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1440 
1441 	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1442 
1443 	pixclock = var->pixclock;
1444 
1445 	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1446 		vtotal += var->yres;
1447 		vtotal <<= 1;
1448 	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1449 		vtotal += var->yres;
1450 		vtotal <<= 2;
1451 	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1452 		vtotal += var->yres;
1453 		vtotal <<= 1;
1454 	} else
1455 		vtotal += var->yres;
1456 
1457 	if(!(htotal) || !(vtotal)) {
1458 		SISFAIL("sisfb: no valid timing data");
1459 	}
1460 
1461 	search_idx = 0;
1462 	while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1463 	       (sisbios_mode[search_idx].xres <= var->xres) ) {
1464 		if( (sisbios_mode[search_idx].xres == var->xres) &&
1465 		    (sisbios_mode[search_idx].yres == var->yres) &&
1466 		    (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1467 			if((tidx = sisfb_validate_mode(ivideo, search_idx,
1468 						ivideo->currentvbflags)) > 0) {
1469 				found_mode = 1;
1470 				search_idx = tidx;
1471 				break;
1472 			}
1473 		}
1474 		search_idx++;
1475 	}
1476 
1477 	if(!found_mode) {
1478 		search_idx = 0;
1479 		while(sisbios_mode[search_idx].mode_no[0] != 0) {
1480 		   if( (var->xres <= sisbios_mode[search_idx].xres) &&
1481 		       (var->yres <= sisbios_mode[search_idx].yres) &&
1482 		       (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1483 			if((tidx = sisfb_validate_mode(ivideo,search_idx,
1484 						ivideo->currentvbflags)) > 0) {
1485 				found_mode = 1;
1486 				search_idx = tidx;
1487 				break;
1488 			}
1489 		   }
1490 		   search_idx++;
1491 		}
1492 		if(found_mode) {
1493 			printk(KERN_DEBUG
1494 				"sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1495 				var->xres, var->yres, var->bits_per_pixel,
1496 				sisbios_mode[search_idx].xres,
1497 				sisbios_mode[search_idx].yres,
1498 				var->bits_per_pixel);
1499 			var->xres = sisbios_mode[search_idx].xres;
1500 			var->yres = sisbios_mode[search_idx].yres;
1501 		} else {
1502 			printk(KERN_ERR
1503 				"sisfb: Failed to find supported mode near %dx%dx%d\n",
1504 				var->xres, var->yres, var->bits_per_pixel);
1505 			return -EINVAL;
1506 		}
1507 	}
1508 
1509 	if( ((ivideo->vbflags2 & VB2_LVDS) ||
1510 	     ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1511 	    (var->bits_per_pixel == 8) ) {
1512 		/* Slave modes on LVDS and 301B-DH */
1513 		refresh_rate = 60;
1514 		recalc_clock = true;
1515 	} else if( (ivideo->current_htotal == htotal) &&
1516 		   (ivideo->current_vtotal == vtotal) &&
1517 		   (ivideo->current_pixclock == pixclock) ) {
1518 		/* x=x & y=y & c=c -> assume depth change */
1519 		drate = 1000000000 / pixclock;
1520 		hrate = (drate * 1000) / htotal;
1521 		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1522 	} else if( ( (ivideo->current_htotal != htotal) ||
1523 		     (ivideo->current_vtotal != vtotal) ) &&
1524 		   (ivideo->current_pixclock == var->pixclock) ) {
1525 		/* x!=x | y!=y & c=c -> invalid pixclock */
1526 		if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1527 			refresh_rate =
1528 				ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1529 		} else if(ivideo->sisfb_parm_rate != -1) {
1530 			/* Sic, sisfb_parm_rate - want to know originally desired rate here */
1531 			refresh_rate = ivideo->sisfb_parm_rate;
1532 		} else {
1533 			refresh_rate = 60;
1534 		}
1535 		recalc_clock = true;
1536 	} else if((pixclock) && (htotal) && (vtotal)) {
1537 		drate = 1000000000 / pixclock;
1538 		hrate = (drate * 1000) / htotal;
1539 		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1540 	} else if(ivideo->current_refresh_rate) {
1541 		refresh_rate = ivideo->current_refresh_rate;
1542 		recalc_clock = true;
1543 	} else {
1544 		refresh_rate = 60;
1545 		recalc_clock = true;
1546 	}
1547 
1548 	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1549 
1550 	/* Eventually recalculate timing and clock */
1551 	if(recalc_clock) {
1552 		if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1553 		var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1554 						sisbios_mode[search_idx].mode_no[ivideo->mni],
1555 						myrateindex));
1556 		sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1557 					sisbios_mode[search_idx].mode_no[ivideo->mni],
1558 					myrateindex, var);
1559 		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1560 			var->pixclock <<= 1;
1561 		}
1562 	}
1563 
1564 	if(ivideo->sisfb_thismonitor.datavalid) {
1565 		if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1566 				myrateindex, refresh_rate)) {
1567 			printk(KERN_INFO
1568 				"sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1569 		}
1570 	}
1571 
1572 	/* Adapt RGB settings */
1573 	sisfb_bpp_to_var(ivideo, var);
1574 
1575 	if(var->xres > var->xres_virtual)
1576 		var->xres_virtual = var->xres;
1577 
1578 	if(ivideo->sisfb_ypan) {
1579 		maxyres = sisfb_calc_maxyres(ivideo, var);
1580 		if(ivideo->sisfb_max) {
1581 			var->yres_virtual = maxyres;
1582 		} else {
1583 			if(var->yres_virtual > maxyres) {
1584 				var->yres_virtual = maxyres;
1585 			}
1586 		}
1587 		if(var->yres_virtual <= var->yres) {
1588 			var->yres_virtual = var->yres;
1589 		}
1590 	} else {
1591 		if(var->yres != var->yres_virtual) {
1592 			var->yres_virtual = var->yres;
1593 		}
1594 		var->xoffset = 0;
1595 		var->yoffset = 0;
1596 	}
1597 
1598 	/* Truncate offsets to maximum if too high */
1599 	if(var->xoffset > var->xres_virtual - var->xres) {
1600 		var->xoffset = var->xres_virtual - var->xres - 1;
1601 	}
1602 
1603 	if(var->yoffset > var->yres_virtual - var->yres) {
1604 		var->yoffset = var->yres_virtual - var->yres - 1;
1605 	}
1606 
1607 	/* Set everything else to 0 */
1608 	var->red.msb_right =
1609 		var->green.msb_right =
1610 		var->blue.msb_right =
1611 		var->transp.offset =
1612 		var->transp.length =
1613 		var->transp.msb_right = 0;
1614 
1615 	return 0;
1616 }
1617 
1618 static int
1619 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1620 {
1621 	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1622 	int err;
1623 
1624 	if (var->vmode & FB_VMODE_YWRAP)
1625 		return -EINVAL;
1626 
1627 	if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1628 	    var->yoffset + info->var.yres > info->var.yres_virtual)
1629 		return -EINVAL;
1630 
1631 	err = sisfb_pan_var(ivideo, info, var);
1632 	if (err < 0)
1633 		return err;
1634 
1635 	info->var.xoffset = var->xoffset;
1636 	info->var.yoffset = var->yoffset;
1637 
1638 	return 0;
1639 }
1640 
1641 static int
1642 sisfb_blank(int blank, struct fb_info *info)
1643 {
1644 	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1645 
1646 	return sisfb_myblank(ivideo, blank);
1647 }
1648 
1649 /* ----------- FBDev related routines for all series ---------- */
1650 
1651 static int	sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1652 			    unsigned long arg)
1653 {
1654 	struct sis_video_info	*ivideo = (struct sis_video_info *)info->par;
1655 	struct sis_memreq	sismemreq;
1656 	struct fb_vblank	sisvbblank;
1657 	u32			gpu32 = 0;
1658 #ifndef __user
1659 #define __user
1660 #endif
1661 	u32 __user 		*argp = (u32 __user *)arg;
1662 
1663 	switch(cmd) {
1664 	   case FBIO_ALLOC:
1665 		if(!capable(CAP_SYS_RAWIO))
1666 			return -EPERM;
1667 
1668 		if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1669 			return -EFAULT;
1670 
1671 		sis_malloc(&sismemreq);
1672 
1673 		if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1674 			sis_free((u32)sismemreq.offset);
1675 			return -EFAULT;
1676 		}
1677 		break;
1678 
1679 	   case FBIO_FREE:
1680 		if(!capable(CAP_SYS_RAWIO))
1681 			return -EPERM;
1682 
1683 		if(get_user(gpu32, argp))
1684 			return -EFAULT;
1685 
1686 		sis_free(gpu32);
1687 		break;
1688 
1689 	   case FBIOGET_VBLANK:
1690 
1691 		memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1692 
1693 		sisvbblank.count = 0;
1694 		sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1695 
1696 		if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1697 			return -EFAULT;
1698 
1699 		break;
1700 
1701 	   case SISFB_GET_INFO_SIZE:
1702 		return put_user(sizeof(struct sisfb_info), argp);
1703 
1704 	   case SISFB_GET_INFO_OLD:
1705 		if(ivideo->warncount++ < 10)
1706 			printk(KERN_INFO
1707 				"sisfb: Deprecated ioctl call received - update your application!\n");
1708 	   case SISFB_GET_INFO:  /* For communication with X driver */
1709 		ivideo->sisfb_infoblock.sisfb_id         = SISFB_ID;
1710 		ivideo->sisfb_infoblock.sisfb_version    = VER_MAJOR;
1711 		ivideo->sisfb_infoblock.sisfb_revision   = VER_MINOR;
1712 		ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1713 		ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1714 		ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1715 		ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1716 		ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1717 		if(ivideo->modechanged) {
1718 			ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1719 		} else {
1720 			ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1721 		}
1722 		ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1723 		ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1724 		ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1725 		ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1726 		ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1727 		ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1728 		ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1729 		ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1730 		ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1731 		ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1732 		ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1733 		ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1734 		ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1735 		ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1736 		ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1737 		ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1738 		ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1739 		ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1740 		ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1741 		ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1742 		ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1743 		ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1744 		ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1745 		ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1746 		ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1747 		ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1748 		ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1749 		ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1750 
1751 		if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1752 						sizeof(ivideo->sisfb_infoblock)))
1753 			return -EFAULT;
1754 
1755 	        break;
1756 
1757 	   case SISFB_GET_VBRSTATUS_OLD:
1758 		if(ivideo->warncount++ < 10)
1759 			printk(KERN_INFO
1760 				"sisfb: Deprecated ioctl call received - update your application!\n");
1761 	   case SISFB_GET_VBRSTATUS:
1762 		if(sisfb_CheckVBRetrace(ivideo))
1763 			return put_user((u32)1, argp);
1764 		else
1765 			return put_user((u32)0, argp);
1766 
1767 	   case SISFB_GET_AUTOMAXIMIZE_OLD:
1768 		if(ivideo->warncount++ < 10)
1769 			printk(KERN_INFO
1770 				"sisfb: Deprecated ioctl call received - update your application!\n");
1771 	   case SISFB_GET_AUTOMAXIMIZE:
1772 		if(ivideo->sisfb_max)
1773 			return put_user((u32)1, argp);
1774 		else
1775 			return put_user((u32)0, argp);
1776 
1777 	   case SISFB_SET_AUTOMAXIMIZE_OLD:
1778 		if(ivideo->warncount++ < 10)
1779 			printk(KERN_INFO
1780 				"sisfb: Deprecated ioctl call received - update your application!\n");
1781 	   case SISFB_SET_AUTOMAXIMIZE:
1782 		if(get_user(gpu32, argp))
1783 			return -EFAULT;
1784 
1785 		ivideo->sisfb_max = (gpu32) ? 1 : 0;
1786 		break;
1787 
1788 	   case SISFB_SET_TVPOSOFFSET:
1789 		if(get_user(gpu32, argp))
1790 			return -EFAULT;
1791 
1792 		sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1793 		sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1794 		break;
1795 
1796 	   case SISFB_GET_TVPOSOFFSET:
1797 		return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1798 							argp);
1799 
1800 	   case SISFB_COMMAND:
1801 		if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1802 							sizeof(struct sisfb_cmd)))
1803 			return -EFAULT;
1804 
1805 		sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1806 
1807 		if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1808 							sizeof(struct sisfb_cmd)))
1809 			return -EFAULT;
1810 
1811 		break;
1812 
1813 	   case SISFB_SET_LOCK:
1814 		if(get_user(gpu32, argp))
1815 			return -EFAULT;
1816 
1817 		ivideo->sisfblocked = (gpu32) ? 1 : 0;
1818 		break;
1819 
1820 	   default:
1821 #ifdef SIS_NEW_CONFIG_COMPAT
1822 		return -ENOIOCTLCMD;
1823 #else
1824 		return -EINVAL;
1825 #endif
1826 	}
1827 	return 0;
1828 }
1829 
1830 static int
1831 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1832 {
1833 	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1834 
1835 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1836 
1837 	strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
1838 
1839 	mutex_lock(&info->mm_lock);
1840 	fix->smem_start  = ivideo->video_base + ivideo->video_offset;
1841 	fix->smem_len    = ivideo->sisfb_mem;
1842 	mutex_unlock(&info->mm_lock);
1843 	fix->type        = FB_TYPE_PACKED_PIXELS;
1844 	fix->type_aux    = 0;
1845 	fix->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1846 	fix->xpanstep    = 1;
1847 	fix->ypanstep 	 = (ivideo->sisfb_ypan) ? 1 : 0;
1848 	fix->ywrapstep   = 0;
1849 	fix->line_length = ivideo->video_linelength;
1850 	fix->mmio_start  = ivideo->mmio_base;
1851 	fix->mmio_len    = ivideo->mmio_size;
1852 	if(ivideo->sisvga_engine == SIS_300_VGA) {
1853 		fix->accel = FB_ACCEL_SIS_GLAMOUR;
1854 	} else if((ivideo->chip == SIS_330) ||
1855 		  (ivideo->chip == SIS_760) ||
1856 		  (ivideo->chip == SIS_761)) {
1857 		fix->accel = FB_ACCEL_SIS_XABRE;
1858 	} else if(ivideo->chip == XGI_20) {
1859 		fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1860 	} else if(ivideo->chip >= XGI_40) {
1861 		fix->accel = FB_ACCEL_XGI_VOLARI_V;
1862 	} else {
1863 		fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1864 	}
1865 
1866 	return 0;
1867 }
1868 
1869 /* ----------------  fb_ops structures ----------------- */
1870 
1871 static struct fb_ops sisfb_ops = {
1872 	.owner		= THIS_MODULE,
1873 	.fb_open	= sisfb_open,
1874 	.fb_release	= sisfb_release,
1875 	.fb_check_var	= sisfb_check_var,
1876 	.fb_set_par	= sisfb_set_par,
1877 	.fb_setcolreg	= sisfb_setcolreg,
1878 	.fb_pan_display	= sisfb_pan_display,
1879 	.fb_blank	= sisfb_blank,
1880 	.fb_fillrect	= fbcon_sis_fillrect,
1881 	.fb_copyarea	= fbcon_sis_copyarea,
1882 	.fb_imageblit	= cfb_imageblit,
1883 	.fb_sync	= fbcon_sis_sync,
1884 #ifdef SIS_NEW_CONFIG_COMPAT
1885 	.fb_compat_ioctl= sisfb_ioctl,
1886 #endif
1887 	.fb_ioctl	= sisfb_ioctl
1888 };
1889 
1890 /* ---------------- Chip generation dependent routines ---------------- */
1891 
1892 static struct pci_dev *sisfb_get_northbridge(int basechipid)
1893 {
1894 	struct pci_dev *pdev = NULL;
1895 	int nbridgenum, nbridgeidx, i;
1896 	static const unsigned short nbridgeids[] = {
1897 		PCI_DEVICE_ID_SI_540,	/* for SiS 540 VGA */
1898 		PCI_DEVICE_ID_SI_630,	/* for SiS 630/730 VGA */
1899 		PCI_DEVICE_ID_SI_730,
1900 		PCI_DEVICE_ID_SI_550,   /* for SiS 550 VGA */
1901 		PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */
1902 		PCI_DEVICE_ID_SI_651,
1903 		PCI_DEVICE_ID_SI_740,
1904 		PCI_DEVICE_ID_SI_661,	/* for SiS 661/741/660/760/761 VGA */
1905 		PCI_DEVICE_ID_SI_741,
1906 		PCI_DEVICE_ID_SI_660,
1907 		PCI_DEVICE_ID_SI_760,
1908 		PCI_DEVICE_ID_SI_761
1909 	};
1910 
1911 	switch(basechipid) {
1912 #ifdef CONFIG_FB_SIS_300
1913 	case SIS_540:	nbridgeidx = 0; nbridgenum = 1; break;
1914 	case SIS_630:	nbridgeidx = 1; nbridgenum = 2; break;
1915 #endif
1916 #ifdef CONFIG_FB_SIS_315
1917 	case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;
1918 	case SIS_650:	nbridgeidx = 4; nbridgenum = 3; break;
1919 	case SIS_660:	nbridgeidx = 7; nbridgenum = 5; break;
1920 #endif
1921 	default:	return NULL;
1922 	}
1923 	for(i = 0; i < nbridgenum; i++) {
1924 		if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1925 				nbridgeids[nbridgeidx+i], NULL)))
1926 			break;
1927 	}
1928 	return pdev;
1929 }
1930 
1931 static int sisfb_get_dram_size(struct sis_video_info *ivideo)
1932 {
1933 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1934 	u8 reg;
1935 #endif
1936 
1937 	ivideo->video_size = 0;
1938 	ivideo->UMAsize = ivideo->LFBsize = 0;
1939 
1940 	switch(ivideo->chip) {
1941 #ifdef CONFIG_FB_SIS_300
1942 	case SIS_300:
1943 		reg = SiS_GetReg(SISSR, 0x14);
1944 		ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1945 		break;
1946 	case SIS_540:
1947 	case SIS_630:
1948 	case SIS_730:
1949 		if(!ivideo->nbridge)
1950 			return -1;
1951 		pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
1952 		ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
1953 		break;
1954 #endif
1955 #ifdef CONFIG_FB_SIS_315
1956 	case SIS_315H:
1957 	case SIS_315PRO:
1958 	case SIS_315:
1959 		reg = SiS_GetReg(SISSR, 0x14);
1960 		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1961 		switch((reg >> 2) & 0x03) {
1962 		case 0x01:
1963 		case 0x03:
1964 			ivideo->video_size <<= 1;
1965 			break;
1966 		case 0x02:
1967 			ivideo->video_size += (ivideo->video_size/2);
1968 		}
1969 		break;
1970 	case SIS_330:
1971 		reg = SiS_GetReg(SISSR, 0x14);
1972 		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1973 		if(reg & 0x0c) ivideo->video_size <<= 1;
1974 		break;
1975 	case SIS_550:
1976 	case SIS_650:
1977 	case SIS_740:
1978 		reg = SiS_GetReg(SISSR, 0x14);
1979 		ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
1980 		break;
1981 	case SIS_661:
1982 	case SIS_741:
1983 		reg = SiS_GetReg(SISCR, 0x79);
1984 		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
1985 		break;
1986 	case SIS_660:
1987 	case SIS_760:
1988 	case SIS_761:
1989 		reg = SiS_GetReg(SISCR, 0x79);
1990 		reg = (reg & 0xf0) >> 4;
1991 		if(reg)	{
1992 			ivideo->video_size = (1 << reg) << 20;
1993 			ivideo->UMAsize = ivideo->video_size;
1994 		}
1995 		reg = SiS_GetReg(SISCR, 0x78);
1996 		reg &= 0x30;
1997 		if(reg) {
1998 			if(reg == 0x10) {
1999 				ivideo->LFBsize = (32 << 20);
2000 			} else {
2001 				ivideo->LFBsize = (64 << 20);
2002 			}
2003 			ivideo->video_size += ivideo->LFBsize;
2004 		}
2005 		break;
2006 	case SIS_340:
2007 	case XGI_20:
2008 	case XGI_40:
2009 		reg = SiS_GetReg(SISSR, 0x14);
2010 		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2011 		if(ivideo->chip != XGI_20) {
2012 			reg = (reg & 0x0c) >> 2;
2013 			if(ivideo->revision_id == 2) {
2014 				if(reg & 0x01) reg = 0x02;
2015 				else	       reg = 0x00;
2016 			}
2017 			if(reg == 0x02)		ivideo->video_size <<= 1;
2018 			else if(reg == 0x03)	ivideo->video_size <<= 2;
2019 		}
2020 		break;
2021 #endif
2022 	default:
2023 		return -1;
2024 	}
2025 	return 0;
2026 }
2027 
2028 /* -------------- video bridge device detection --------------- */
2029 
2030 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2031 {
2032 	u8 cr32, temp;
2033 
2034 	/* No CRT2 on XGI Z7 */
2035 	if(ivideo->chip == XGI_20) {
2036 		ivideo->sisfb_crt1off = 0;
2037 		return;
2038 	}
2039 
2040 #ifdef CONFIG_FB_SIS_300
2041 	if(ivideo->sisvga_engine == SIS_300_VGA) {
2042 		temp = SiS_GetReg(SISSR, 0x17);
2043 		if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2044 			/* PAL/NTSC is stored on SR16 on such machines */
2045 			if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2046 				temp = SiS_GetReg(SISSR, 0x16);
2047 				if(temp & 0x20)
2048 					ivideo->vbflags |= TV_PAL;
2049 				else
2050 					ivideo->vbflags |= TV_NTSC;
2051 			}
2052 		}
2053 	}
2054 #endif
2055 
2056 	cr32 = SiS_GetReg(SISCR, 0x32);
2057 
2058 	if(cr32 & SIS_CRT1) {
2059 		ivideo->sisfb_crt1off = 0;
2060 	} else {
2061 		ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2062 	}
2063 
2064 	ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2065 
2066 	if(cr32 & SIS_VB_TV)   ivideo->vbflags |= CRT2_TV;
2067 	if(cr32 & SIS_VB_LCD)  ivideo->vbflags |= CRT2_LCD;
2068 	if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2069 
2070 	/* Check given parms for hardware compatibility.
2071 	 * (Cannot do this in the search_xx routines since we don't
2072 	 * know what hardware we are running on then)
2073 	 */
2074 
2075 	if(ivideo->chip != SIS_550) {
2076 	   ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2077 	}
2078 
2079 	if(ivideo->sisfb_tvplug != -1) {
2080 	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2081 	       (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2082 	      if(ivideo->sisfb_tvplug & TV_YPBPR) {
2083 		 ivideo->sisfb_tvplug = -1;
2084 		 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2085 	      }
2086 	   }
2087 	}
2088 	if(ivideo->sisfb_tvplug != -1) {
2089 	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2090 	       (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2091 	      if(ivideo->sisfb_tvplug & TV_HIVISION) {
2092 		 ivideo->sisfb_tvplug = -1;
2093 		 printk(KERN_ERR "sisfb: HiVision not supported\n");
2094 	      }
2095 	   }
2096 	}
2097 	if(ivideo->sisfb_tvstd != -1) {
2098 	   if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2099 	       (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2100 			(ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2101 	      if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2102 		 ivideo->sisfb_tvstd = -1;
2103 		 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2104 	      }
2105 	   }
2106 	}
2107 
2108 	/* Detect/set TV plug & type */
2109 	if(ivideo->sisfb_tvplug != -1) {
2110 		ivideo->vbflags |= ivideo->sisfb_tvplug;
2111 	} else {
2112 		if(cr32 & SIS_VB_YPBPR)     	 ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2113 		else if(cr32 & SIS_VB_HIVISION)  ivideo->vbflags |= TV_HIVISION;
2114 		else if(cr32 & SIS_VB_SCART)     ivideo->vbflags |= TV_SCART;
2115 		else {
2116 			if(cr32 & SIS_VB_SVIDEO)    ivideo->vbflags |= TV_SVIDEO;
2117 			if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2118 		}
2119 	}
2120 
2121 	if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2122 	    if(ivideo->sisfb_tvstd != -1) {
2123 	       ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2124 	       ivideo->vbflags |= ivideo->sisfb_tvstd;
2125 	    }
2126 	    if(ivideo->vbflags & TV_SCART) {
2127 	       ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2128 	       ivideo->vbflags |= TV_PAL;
2129 	    }
2130 	    if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2131 		if(ivideo->sisvga_engine == SIS_300_VGA) {
2132 			temp = SiS_GetReg(SISSR, 0x38);
2133 			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2134 			else		ivideo->vbflags |= TV_NTSC;
2135 		} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2136 			temp = SiS_GetReg(SISSR, 0x38);
2137 			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2138 			else		ivideo->vbflags |= TV_NTSC;
2139 		} else {
2140 			temp = SiS_GetReg(SISCR, 0x79);
2141 			if(temp & 0x20)	ivideo->vbflags |= TV_PAL;
2142 			else		ivideo->vbflags |= TV_NTSC;
2143 		}
2144 	    }
2145 	}
2146 
2147 	/* Copy forceCRT1 option to CRT1off if option is given */
2148 	if(ivideo->sisfb_forcecrt1 != -1) {
2149 	   ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2150 	}
2151 }
2152 
2153 /* ------------------ Sensing routines ------------------ */
2154 
2155 static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
2156 {
2157     unsigned short old;
2158     int count = 48;
2159 
2160     old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2161     do {
2162 	if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2163     } while(count--);
2164     return (count != -1);
2165 }
2166 
2167 static void sisfb_sense_crt1(struct sis_video_info *ivideo)
2168 {
2169     bool mustwait = false;
2170     u8  sr1F, cr17;
2171 #ifdef CONFIG_FB_SIS_315
2172     u8  cr63=0;
2173 #endif
2174     u16 temp = 0xffff;
2175     int i;
2176 
2177     sr1F = SiS_GetReg(SISSR, 0x1F);
2178     SiS_SetRegOR(SISSR, 0x1F, 0x04);
2179     SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2180     if(sr1F & 0xc0) mustwait = true;
2181 
2182 #ifdef CONFIG_FB_SIS_315
2183     if(ivideo->sisvga_engine == SIS_315_VGA) {
2184        cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2185        cr63 &= 0x40;
2186        SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2187     }
2188 #endif
2189 
2190     cr17 = SiS_GetReg(SISCR, 0x17);
2191     cr17 &= 0x80;
2192     if(!cr17) {
2193        SiS_SetRegOR(SISCR, 0x17, 0x80);
2194        mustwait = true;
2195        SiS_SetReg(SISSR, 0x00, 0x01);
2196        SiS_SetReg(SISSR, 0x00, 0x03);
2197     }
2198 
2199     if(mustwait) {
2200        for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2201     }
2202 
2203 #ifdef CONFIG_FB_SIS_315
2204     if(ivideo->chip >= SIS_330) {
2205        SiS_SetRegAND(SISCR, 0x32, ~0x20);
2206        if(ivideo->chip >= SIS_340) {
2207 	   SiS_SetReg(SISCR, 0x57, 0x4a);
2208        } else {
2209 	   SiS_SetReg(SISCR, 0x57, 0x5f);
2210        }
2211 	SiS_SetRegOR(SISCR, 0x53, 0x02);
2212 	while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)    break;
2213 	while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
2214 	if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
2215 	SiS_SetRegAND(SISCR, 0x53, 0xfd);
2216 	SiS_SetRegAND(SISCR, 0x57, 0x00);
2217     }
2218 #endif
2219 
2220     if(temp == 0xffff) {
2221        i = 3;
2222        do {
2223 	  temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2224 		ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2225        } while(((temp == 0) || (temp == 0xffff)) && i--);
2226 
2227        if((temp == 0) || (temp == 0xffff)) {
2228           if(sisfb_test_DDC1(ivideo)) temp = 1;
2229        }
2230     }
2231 
2232     if((temp) && (temp != 0xffff)) {
2233        SiS_SetRegOR(SISCR, 0x32, 0x20);
2234     }
2235 
2236 #ifdef CONFIG_FB_SIS_315
2237     if(ivideo->sisvga_engine == SIS_315_VGA) {
2238 	SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2239     }
2240 #endif
2241 
2242     SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2243 
2244     SiS_SetReg(SISSR, 0x1F, sr1F);
2245 }
2246 
2247 /* Determine and detect attached devices on SiS30x */
2248 static void SiS_SenseLCD(struct sis_video_info *ivideo)
2249 {
2250 	unsigned char buffer[256];
2251 	unsigned short temp, realcrtno, i;
2252 	u8 reg, cr37 = 0, paneltype = 0;
2253 	u16 xres, yres;
2254 
2255 	ivideo->SiS_Pr.PanelSelfDetected = false;
2256 
2257 	/* LCD detection only for TMDS bridges */
2258 	if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2259 		return;
2260 	if(ivideo->vbflags2 & VB2_30xBDH)
2261 		return;
2262 
2263 	/* If LCD already set up by BIOS, skip it */
2264 	reg = SiS_GetReg(SISCR, 0x32);
2265 	if(reg & 0x08)
2266 		return;
2267 
2268 	realcrtno = 1;
2269 	if(ivideo->SiS_Pr.DDCPortMixup)
2270 		realcrtno = 0;
2271 
2272 	/* Check DDC capabilities */
2273 	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2274 				realcrtno, 0, &buffer[0], ivideo->vbflags2);
2275 
2276 	if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2277 		return;
2278 
2279 	/* Read DDC data */
2280 	i = 3;  /* Number of retrys */
2281 	do {
2282 		temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2283 				ivideo->sisvga_engine, realcrtno, 1,
2284 				&buffer[0], ivideo->vbflags2);
2285 	} while((temp) && i--);
2286 
2287 	if(temp)
2288 		return;
2289 
2290 	/* No digital device */
2291 	if(!(buffer[0x14] & 0x80))
2292 		return;
2293 
2294 	/* First detailed timing preferred timing? */
2295 	if(!(buffer[0x18] & 0x02))
2296 		return;
2297 
2298 	xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2299 	yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2300 
2301 	switch(xres) {
2302 		case 1024:
2303 			if(yres == 768)
2304 				paneltype = 0x02;
2305 			break;
2306 		case 1280:
2307 			if(yres == 1024)
2308 				paneltype = 0x03;
2309 			break;
2310 		case 1600:
2311 			if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2312 				paneltype = 0x0b;
2313 			break;
2314 	}
2315 
2316 	if(!paneltype)
2317 		return;
2318 
2319 	if(buffer[0x23])
2320 		cr37 |= 0x10;
2321 
2322 	if((buffer[0x47] & 0x18) == 0x18)
2323 		cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2324 	else
2325 		cr37 |= 0xc0;
2326 
2327 	SiS_SetReg(SISCR, 0x36, paneltype);
2328 	cr37 &= 0xf1;
2329 	SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2330 	SiS_SetRegOR(SISCR, 0x32, 0x08);
2331 
2332 	ivideo->SiS_Pr.PanelSelfDetected = true;
2333 }
2334 
2335 static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2336 {
2337     int temp, mytest, result, i, j;
2338 
2339     for(j = 0; j < 10; j++) {
2340        result = 0;
2341        for(i = 0; i < 3; i++) {
2342           mytest = test;
2343 	   SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2344           temp = (type >> 8) | (mytest & 0x00ff);
2345 	  SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2346           SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2347           mytest >>= 8;
2348           mytest &= 0x7f;
2349 	   temp = SiS_GetReg(SISPART4, 0x03);
2350           temp ^= 0x0e;
2351           temp &= mytest;
2352           if(temp == mytest) result++;
2353 #if 1
2354 	  SiS_SetReg(SISPART4, 0x11, 0x00);
2355 	  SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2356 	  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2357 #endif
2358        }
2359        if((result == 0) || (result >= 2)) break;
2360     }
2361     return result;
2362 }
2363 
2364 static void SiS_Sense30x(struct sis_video_info *ivideo)
2365 {
2366     u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2367     u16 svhs=0, svhs_c=0;
2368     u16 cvbs=0, cvbs_c=0;
2369     u16 vga2=0, vga2_c=0;
2370     int myflag, result;
2371     char stdstr[] = "sisfb: Detected";
2372     char tvstr[]  = "TV connected to";
2373 
2374     if(ivideo->vbflags2 & VB2_301) {
2375        svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2376        myflag = SiS_GetReg(SISPART4, 0x01);
2377        if(myflag & 0x04) {
2378 	  svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2379        }
2380     } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2381        svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2382     } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2383        svhs = 0x0200; cvbs = 0x0100;
2384     } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2385        svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2386     } else
2387        return;
2388 
2389     vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2390     if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2391        svhs_c = 0x0408; cvbs_c = 0x0808;
2392     }
2393 
2394     biosflag = 2;
2395     if(ivideo->haveXGIROM) {
2396        biosflag = ivideo->bios_abase[0x58] & 0x03;
2397     } else if(ivideo->newrom) {
2398        if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2399     } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2400        if(ivideo->bios_abase) {
2401           biosflag = ivideo->bios_abase[0xfe] & 0x03;
2402        }
2403     }
2404 
2405     if(ivideo->chip == SIS_300) {
2406        myflag = SiS_GetReg(SISSR, 0x3b);
2407        if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2408     }
2409 
2410     if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2411        vga2 = vga2_c = 0;
2412     }
2413 
2414     backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2415     SiS_SetRegOR(SISSR, 0x1e, 0x20);
2416 
2417     backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2418     if(ivideo->vbflags2 & VB2_30xC) {
2419 	SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2420     } else {
2421        SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2422     }
2423     SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2424 
2425     backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2426     SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2427 
2428     backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2429     if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2430 	SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2431     }
2432 
2433     if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2434        SISDoSense(ivideo, 0, 0);
2435     }
2436 
2437     SiS_SetRegAND(SISCR, 0x32, ~0x14);
2438 
2439     if(vga2_c || vga2) {
2440        if(SISDoSense(ivideo, vga2, vga2_c)) {
2441           if(biosflag & 0x01) {
2442 	     printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2443 	     SiS_SetRegOR(SISCR, 0x32, 0x04);
2444 	  } else {
2445 	     printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2446 	     SiS_SetRegOR(SISCR, 0x32, 0x10);
2447 	  }
2448        }
2449     }
2450 
2451     SiS_SetRegAND(SISCR, 0x32, 0x3f);
2452 
2453     if(ivideo->vbflags2 & VB2_30xCLV) {
2454        SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2455     }
2456 
2457     if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2458        SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2459        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2460        if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2461           if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2462 	     printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2463 	     SiS_SetRegOR(SISCR, 0x32, 0x80);
2464 	  }
2465        }
2466        SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2467     }
2468 
2469     SiS_SetRegAND(SISCR, 0x32, ~0x03);
2470 
2471     if(!(ivideo->vbflags & TV_YPBPR)) {
2472        if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2473           printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2474 	   SiS_SetRegOR(SISCR, 0x32, 0x02);
2475        }
2476        if((biosflag & 0x02) || (!result)) {
2477           if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2478 	     printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2479 	     SiS_SetRegOR(SISCR, 0x32, 0x01);
2480           }
2481        }
2482     }
2483 
2484     SISDoSense(ivideo, 0, 0);
2485 
2486     SiS_SetReg(SISPART2, 0x00, backupP2_00);
2487     SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2488     SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2489 
2490     if(ivideo->vbflags2 & VB2_30xCLV) {
2491 	biosflag = SiS_GetReg(SISPART2, 0x00);
2492        if(biosflag & 0x20) {
2493           for(myflag = 2; myflag > 0; myflag--) {
2494 	     biosflag ^= 0x20;
2495 	     SiS_SetReg(SISPART2, 0x00, biosflag);
2496 	  }
2497        }
2498     }
2499 
2500     SiS_SetReg(SISPART2, 0x00, backupP2_00);
2501 }
2502 
2503 /* Determine and detect attached TV's on Chrontel */
2504 static void SiS_SenseCh(struct sis_video_info *ivideo)
2505 {
2506 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2507     u8 temp1, temp2;
2508     char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2509 #endif
2510 #ifdef CONFIG_FB_SIS_300
2511     unsigned char test[3];
2512     int i;
2513 #endif
2514 
2515     if(ivideo->chip < SIS_315H) {
2516 
2517 #ifdef CONFIG_FB_SIS_300
2518        ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* Chrontel 700x */
2519        SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c);	/* Set general purpose IO for Chrontel communication */
2520        SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2521        temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2522        /* See Chrontel TB31 for explanation */
2523        temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2524        if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2525 	  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2526 	  SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2527        }
2528        temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2529        if(temp2 != temp1) temp1 = temp2;
2530 
2531        if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2532 	   /* Read power status */
2533 	   temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2534 	   if((temp1 & 0x03) != 0x03) {
2535 		/* Power all outputs */
2536 		SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2537 		SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2538 	   }
2539 	   /* Sense connected TV devices */
2540 	   for(i = 0; i < 3; i++) {
2541 	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2542 	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2543 	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2544 	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2545 	       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2546 	       if(!(temp1 & 0x08))       test[i] = 0x02;
2547 	       else if(!(temp1 & 0x02))  test[i] = 0x01;
2548 	       else                      test[i] = 0;
2549 	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2550 	   }
2551 
2552 	   if(test[0] == test[1])      temp1 = test[0];
2553 	   else if(test[0] == test[2]) temp1 = test[0];
2554 	   else if(test[1] == test[2]) temp1 = test[1];
2555 	   else {
2556 		printk(KERN_INFO
2557 			"sisfb: TV detection unreliable - test results varied\n");
2558 		temp1 = test[2];
2559 	   }
2560 	   if(temp1 == 0x02) {
2561 		printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2562 		ivideo->vbflags |= TV_SVIDEO;
2563 		SiS_SetRegOR(SISCR, 0x32, 0x02);
2564 		SiS_SetRegAND(SISCR, 0x32, ~0x05);
2565 	   } else if (temp1 == 0x01) {
2566 		printk(KERN_INFO "%s CVBS output\n", stdstr);
2567 		ivideo->vbflags |= TV_AVIDEO;
2568 		SiS_SetRegOR(SISCR, 0x32, 0x01);
2569 		SiS_SetRegAND(SISCR, 0x32, ~0x06);
2570 	   } else {
2571 		SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2572 		SiS_SetRegAND(SISCR, 0x32, ~0x07);
2573 	   }
2574        } else if(temp1 == 0) {
2575 	  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2576 	  SiS_SetRegAND(SISCR, 0x32, ~0x07);
2577        }
2578        /* Set general purpose IO for Chrontel communication */
2579        SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2580 #endif
2581 
2582     } else {
2583 
2584 #ifdef CONFIG_FB_SIS_315
2585 	ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* Chrontel 7019 */
2586 	temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2587 	SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2588 	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2589 	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2590 	temp2 |= 0x01;
2591 	SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2592 	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2593 	temp2 ^= 0x01;
2594 	SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2595 	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2596 	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2597 	SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2598 	temp1 = 0;
2599 	if(temp2 & 0x02) temp1 |= 0x01;
2600 	if(temp2 & 0x10) temp1 |= 0x01;
2601 	if(temp2 & 0x04) temp1 |= 0x02;
2602 	if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2603 	switch(temp1) {
2604 	case 0x01:
2605 	     printk(KERN_INFO "%s CVBS output\n", stdstr);
2606 	     ivideo->vbflags |= TV_AVIDEO;
2607 	     SiS_SetRegOR(SISCR, 0x32, 0x01);
2608 	     SiS_SetRegAND(SISCR, 0x32, ~0x06);
2609 	     break;
2610 	case 0x02:
2611 	     printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2612 	     ivideo->vbflags |= TV_SVIDEO;
2613 	     SiS_SetRegOR(SISCR, 0x32, 0x02);
2614 	     SiS_SetRegAND(SISCR, 0x32, ~0x05);
2615 	     break;
2616 	case 0x04:
2617 	     printk(KERN_INFO "%s SCART output\n", stdstr);
2618 	     SiS_SetRegOR(SISCR, 0x32, 0x04);
2619 	     SiS_SetRegAND(SISCR, 0x32, ~0x03);
2620 	     break;
2621 	default:
2622 	     SiS_SetRegAND(SISCR, 0x32, ~0x07);
2623 	}
2624 #endif
2625     }
2626 }
2627 
2628 static void sisfb_get_VB_type(struct sis_video_info *ivideo)
2629 {
2630 	char stdstr[]    = "sisfb: Detected";
2631 	char bridgestr[] = "video bridge";
2632 	u8 vb_chipid;
2633 	u8 reg;
2634 
2635 	/* No CRT2 on XGI Z7 */
2636 	if(ivideo->chip == XGI_20)
2637 		return;
2638 
2639 	vb_chipid = SiS_GetReg(SISPART4, 0x00);
2640 	switch(vb_chipid) {
2641 	case 0x01:
2642 		reg = SiS_GetReg(SISPART4, 0x01);
2643 		if(reg < 0xb0) {
2644 			ivideo->vbflags |= VB_301;	/* Deprecated */
2645 			ivideo->vbflags2 |= VB2_301;
2646 			printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2647 		} else if(reg < 0xc0) {
2648 			ivideo->vbflags |= VB_301B;	/* Deprecated */
2649 			ivideo->vbflags2 |= VB2_301B;
2650 			reg = SiS_GetReg(SISPART4, 0x23);
2651 			if(!(reg & 0x02)) {
2652 			   ivideo->vbflags |= VB_30xBDH;	/* Deprecated */
2653 			   ivideo->vbflags2 |= VB2_30xBDH;
2654 			   printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2655 			} else {
2656 			   printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2657 			}
2658 		} else if(reg < 0xd0) {
2659 			ivideo->vbflags |= VB_301C;	/* Deprecated */
2660 			ivideo->vbflags2 |= VB2_301C;
2661 			printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2662 		} else if(reg < 0xe0) {
2663 			ivideo->vbflags |= VB_301LV;	/* Deprecated */
2664 			ivideo->vbflags2 |= VB2_301LV;
2665 			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2666 		} else if(reg <= 0xe1) {
2667 			reg = SiS_GetReg(SISPART4, 0x39);
2668 			if(reg == 0xff) {
2669 			   ivideo->vbflags |= VB_302LV;	/* Deprecated */
2670 			   ivideo->vbflags2 |= VB2_302LV;
2671 			   printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2672 			} else {
2673 			   ivideo->vbflags |= VB_301C;	/* Deprecated */
2674 			   ivideo->vbflags2 |= VB2_301C;
2675 			   printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2676 #if 0
2677 			   ivideo->vbflags |= VB_302ELV;	/* Deprecated */
2678 			   ivideo->vbflags2 |= VB2_302ELV;
2679 			   printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2680 #endif
2681 			}
2682 		}
2683 		break;
2684 	case 0x02:
2685 		ivideo->vbflags |= VB_302B;	/* Deprecated */
2686 		ivideo->vbflags2 |= VB2_302B;
2687 		printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2688 		break;
2689 	}
2690 
2691 	if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2692 		reg = SiS_GetReg(SISCR, 0x37);
2693 		reg &= SIS_EXTERNAL_CHIP_MASK;
2694 		reg >>= 1;
2695 		if(ivideo->sisvga_engine == SIS_300_VGA) {
2696 #ifdef CONFIG_FB_SIS_300
2697 			switch(reg) {
2698 			   case SIS_EXTERNAL_CHIP_LVDS:
2699 				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
2700 				ivideo->vbflags2 |= VB2_LVDS;
2701 				break;
2702 			   case SIS_EXTERNAL_CHIP_TRUMPION:
2703 				ivideo->vbflags |= (VB_LVDS | VB_TRUMPION);	/* Deprecated */
2704 				ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2705 				break;
2706 			   case SIS_EXTERNAL_CHIP_CHRONTEL:
2707 				ivideo->vbflags |= VB_CHRONTEL;	/* Deprecated */
2708 				ivideo->vbflags2 |= VB2_CHRONTEL;
2709 				break;
2710 			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2711 				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
2712 				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2713 				break;
2714 			}
2715 			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2716 #endif
2717 		} else if(ivideo->chip < SIS_661) {
2718 #ifdef CONFIG_FB_SIS_315
2719 			switch (reg) {
2720 			   case SIS310_EXTERNAL_CHIP_LVDS:
2721 				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
2722 				ivideo->vbflags2 |= VB2_LVDS;
2723 				break;
2724 			   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2725 				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
2726 				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2727 				break;
2728 			}
2729 			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2730 #endif
2731 		} else if(ivideo->chip >= SIS_661) {
2732 #ifdef CONFIG_FB_SIS_315
2733 			reg = SiS_GetReg(SISCR, 0x38);
2734 			reg >>= 5;
2735 			switch(reg) {
2736 			   case 0x02:
2737 				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
2738 				ivideo->vbflags2 |= VB2_LVDS;
2739 				break;
2740 			   case 0x03:
2741 				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
2742 				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2743 				break;
2744 			   case 0x04:
2745 				ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);	/* Deprecated */
2746 				ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2747 				break;
2748 			}
2749 			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2750 #endif
2751 		}
2752 		if(ivideo->vbflags2 & VB2_LVDS) {
2753 		   printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2754 		}
2755 		if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2756 		   printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2757 		}
2758 		if(ivideo->vbflags2 & VB2_CHRONTEL) {
2759 		   printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2760 		}
2761 		if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2762 		   printk(KERN_INFO "%s Conexant external device\n", stdstr);
2763 		}
2764 	}
2765 
2766 	if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2767 		SiS_SenseLCD(ivideo);
2768 		SiS_Sense30x(ivideo);
2769 	} else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2770 		SiS_SenseCh(ivideo);
2771 	}
2772 }
2773 
2774 /* ---------- Engine initialization routines ------------ */
2775 
2776 static void
2777 sisfb_engine_init(struct sis_video_info *ivideo)
2778 {
2779 
2780 	/* Initialize command queue (we use MMIO only) */
2781 
2782 	/* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2783 
2784 	ivideo->caps &= ~(TURBO_QUEUE_CAP    |
2785 			  MMIO_CMD_QUEUE_CAP |
2786 			  VM_CMD_QUEUE_CAP   |
2787 			  AGP_CMD_QUEUE_CAP);
2788 
2789 #ifdef CONFIG_FB_SIS_300
2790 	if(ivideo->sisvga_engine == SIS_300_VGA) {
2791 		u32 tqueue_pos;
2792 		u8 tq_state;
2793 
2794 		tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2795 
2796 		tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
2797 		tq_state |= 0xf0;
2798 		tq_state &= 0xfc;
2799 		tq_state |= (u8)(tqueue_pos >> 8);
2800 		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2801 
2802 		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2803 
2804 		ivideo->caps |= TURBO_QUEUE_CAP;
2805 	}
2806 #endif
2807 
2808 #ifdef CONFIG_FB_SIS_315
2809 	if(ivideo->sisvga_engine == SIS_315_VGA) {
2810 		u32 tempq = 0, templ;
2811 		u8  temp;
2812 
2813 		if(ivideo->chip == XGI_20) {
2814 			switch(ivideo->cmdQueueSize) {
2815 			case (64 * 1024):
2816 				temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2817 				break;
2818 			case (128 * 1024):
2819 			default:
2820 				temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2821 			}
2822 		} else {
2823 			switch(ivideo->cmdQueueSize) {
2824 			case (4 * 1024 * 1024):
2825 				temp = SIS_CMD_QUEUE_SIZE_4M;
2826 				break;
2827 			case (2 * 1024 * 1024):
2828 				temp = SIS_CMD_QUEUE_SIZE_2M;
2829 				break;
2830 			case (1 * 1024 * 1024):
2831 				temp = SIS_CMD_QUEUE_SIZE_1M;
2832 				break;
2833 			default:
2834 			case (512 * 1024):
2835 				temp = SIS_CMD_QUEUE_SIZE_512k;
2836 			}
2837 		}
2838 
2839 		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2840 		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2841 
2842 		if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2843 			/* Must disable dual pipe on XGI_40. Can't do
2844 			 * this in MMIO mode, because it requires
2845 			 * setting/clearing a bit in the MMIO fire trigger
2846 			 * register.
2847 			 */
2848 			if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2849 
2850 				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2851 
2852 				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2853 
2854 				tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2855 				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2856 
2857 				tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2858 				MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2859 
2860 				writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2861 				writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2862 				writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2863 				writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2864 
2865 				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2866 
2867 				sisfb_syncaccel(ivideo);
2868 
2869 				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2870 
2871 			}
2872 		}
2873 
2874 		tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2875 		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2876 
2877 		temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2878 		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2879 
2880 		tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2881 		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2882 
2883 		ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2884 	}
2885 #endif
2886 
2887 	ivideo->engineok = 1;
2888 }
2889 
2890 static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2891 {
2892 	u8 reg;
2893 	int i;
2894 
2895 	reg = SiS_GetReg(SISCR, 0x36);
2896 	reg &= 0x0f;
2897 	if(ivideo->sisvga_engine == SIS_300_VGA) {
2898 		ivideo->CRT2LCDType = sis300paneltype[reg];
2899 	} else if(ivideo->chip >= SIS_661) {
2900 		ivideo->CRT2LCDType = sis661paneltype[reg];
2901 	} else {
2902 		ivideo->CRT2LCDType = sis310paneltype[reg];
2903 		if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2904 			if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2905 			   (ivideo->CRT2LCDType != LCD_320x240_3)) {
2906 				ivideo->CRT2LCDType = LCD_320x240;
2907 			}
2908 		}
2909 	}
2910 
2911 	if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2912 		/* For broken BIOSes: Assume 1024x768, RGB18 */
2913 		ivideo->CRT2LCDType = LCD_1024x768;
2914 		SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2915 		SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2916 		printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2917 	}
2918 
2919 	for(i = 0; i < SIS_LCD_NUMBER; i++) {
2920 		if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2921 			ivideo->lcdxres = sis_lcd_data[i].xres;
2922 			ivideo->lcdyres = sis_lcd_data[i].yres;
2923 			ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2924 			break;
2925 		}
2926 	}
2927 
2928 #ifdef CONFIG_FB_SIS_300
2929 	if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2930 		ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2931 		ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2932 	} else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2933 		ivideo->lcdxres =  848; ivideo->lcdyres =  480;
2934 		ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2935 	} else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2936 		ivideo->lcdxres =  856; ivideo->lcdyres =  480;
2937 		ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2938 	}
2939 #endif
2940 
2941 	printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2942 			ivideo->lcdxres, ivideo->lcdyres);
2943 }
2944 
2945 static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2946 {
2947 #ifdef CONFIG_FB_SIS_300
2948 	/* Save the current PanelDelayCompensation if the LCD is currently used */
2949 	if(ivideo->sisvga_engine == SIS_300_VGA) {
2950 		if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
2951 			int tmp;
2952 			tmp = SiS_GetReg(SISCR, 0x30);
2953 			if(tmp & 0x20) {
2954 				/* Currently on LCD? If yes, read current pdc */
2955 				ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
2956 				ivideo->detectedpdc &= 0x3c;
2957 				if(ivideo->SiS_Pr.PDC == -1) {
2958 					/* Let option override detection */
2959 					ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
2960 				}
2961 				printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
2962 					ivideo->detectedpdc);
2963 			}
2964 			if((ivideo->SiS_Pr.PDC != -1) &&
2965 			   (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
2966 				printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
2967 					ivideo->SiS_Pr.PDC);
2968 			}
2969 		}
2970 	}
2971 #endif
2972 
2973 #ifdef CONFIG_FB_SIS_315
2974 	if(ivideo->sisvga_engine == SIS_315_VGA) {
2975 
2976 		/* Try to find about LCDA */
2977 		if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
2978 			int tmp;
2979 			tmp = SiS_GetReg(SISPART1, 0x13);
2980 			if(tmp & 0x04) {
2981 				ivideo->SiS_Pr.SiS_UseLCDA = true;
2982 				ivideo->detectedlcda = 0x03;
2983 			}
2984 		}
2985 
2986 		/* Save PDC */
2987 		if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
2988 			int tmp;
2989 			tmp = SiS_GetReg(SISCR, 0x30);
2990 			if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
2991 				/* Currently on LCD? If yes, read current pdc */
2992 				u8 pdc;
2993 				pdc = SiS_GetReg(SISPART1, 0x2D);
2994 				ivideo->detectedpdc  = (pdc & 0x0f) << 1;
2995 				ivideo->detectedpdca = (pdc & 0xf0) >> 3;
2996 				pdc = SiS_GetReg(SISPART1, 0x35);
2997 				ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
2998 				pdc = SiS_GetReg(SISPART1, 0x20);
2999 				ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3000 				if(ivideo->newrom) {
3001 					/* New ROM invalidates other PDC resp. */
3002 					if(ivideo->detectedlcda != 0xff) {
3003 						ivideo->detectedpdc = 0xff;
3004 					} else {
3005 						ivideo->detectedpdca = 0xff;
3006 					}
3007 				}
3008 				if(ivideo->SiS_Pr.PDC == -1) {
3009 					if(ivideo->detectedpdc != 0xff) {
3010 						ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3011 					}
3012 				}
3013 				if(ivideo->SiS_Pr.PDCA == -1) {
3014 					if(ivideo->detectedpdca != 0xff) {
3015 						ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3016 					}
3017 				}
3018 				if(ivideo->detectedpdc != 0xff) {
3019 					printk(KERN_INFO
3020 						"sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3021 						ivideo->detectedpdc);
3022 				}
3023 				if(ivideo->detectedpdca != 0xff) {
3024 					printk(KERN_INFO
3025 						"sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3026 						ivideo->detectedpdca);
3027 				}
3028 			}
3029 
3030 			/* Save EMI */
3031 			if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3032 				ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3033 				ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3034 				ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3035 				ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3036 				ivideo->SiS_Pr.HaveEMI = true;
3037 				if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3038 					ivideo->SiS_Pr.HaveEMILCD = true;
3039 				}
3040 			}
3041 		}
3042 
3043 		/* Let user override detected PDCs (all bridges) */
3044 		if(ivideo->vbflags2 & VB2_30xBLV) {
3045 			if((ivideo->SiS_Pr.PDC != -1) &&
3046 			   (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3047 				printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3048 					ivideo->SiS_Pr.PDC);
3049 			}
3050 			if((ivideo->SiS_Pr.PDCA != -1) &&
3051 			   (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3052 				printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3053 				 ivideo->SiS_Pr.PDCA);
3054 			}
3055 		}
3056 
3057 	}
3058 #endif
3059 }
3060 
3061 /* -------------------- Memory manager routines ---------------------- */
3062 
3063 static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
3064 {
3065 	u32 ret = ivideo->sisfb_parm_mem * 1024;
3066 	u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3067 	u32 def;
3068 
3069 	/* Calculate heap start = end of memory for console
3070 	 *
3071 	 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3072 	 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3073 	 *
3074 	 * On 76x in UMA+LFB mode, the layout is as follows:
3075 	 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3076 	 * where the heap is the entire UMA area, eventually
3077 	 * into the LFB area if the given mem parameter is
3078 	 * higher than the size of the UMA memory.
3079 	 *
3080 	 * Basically given by "mem" parameter
3081 	 *
3082 	 * maximum = videosize - cmd_queue - hwcursor
3083 	 *           (results in a heap of size 0)
3084 	 * default = SiS 300: depends on videosize
3085 	 *           SiS 315/330/340/XGI: 32k below max
3086 	 */
3087 
3088 	if(ivideo->sisvga_engine == SIS_300_VGA) {
3089 		if(ivideo->video_size > 0x1000000) {
3090 			def = 0xc00000;
3091 		} else if(ivideo->video_size > 0x800000) {
3092 			def = 0x800000;
3093 		} else {
3094 			def = 0x400000;
3095 		}
3096 	} else if(ivideo->UMAsize && ivideo->LFBsize) {
3097 		ret = def = 0;
3098 	} else {
3099 		def = maxoffs - 0x8000;
3100 	}
3101 
3102 	/* Use default for secondary card for now (FIXME) */
3103 	if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3104 		ret = def;
3105 
3106 	return ret;
3107 }
3108 
3109 static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
3110 {
3111 	u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3112 	u32 ret = 0;
3113 
3114 	if(ivideo->UMAsize && ivideo->LFBsize) {
3115 		if( (!ivideo->sisfb_parm_mem)			||
3116 		    ((ivideo->sisfb_parm_mem * 1024) > max)	||
3117 		    ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3118 			ret = ivideo->UMAsize;
3119 			max -= ivideo->UMAsize;
3120 		} else {
3121 			ret = max - (ivideo->sisfb_parm_mem * 1024);
3122 			max = ivideo->sisfb_parm_mem * 1024;
3123 		}
3124 		ivideo->video_offset = ret;
3125 		ivideo->sisfb_mem = max;
3126 	} else {
3127 		ret = max - ivideo->heapstart;
3128 		ivideo->sisfb_mem = ivideo->heapstart;
3129 	}
3130 
3131 	return ret;
3132 }
3133 
3134 static int sisfb_heap_init(struct sis_video_info *ivideo)
3135 {
3136 	struct SIS_OH *poh;
3137 
3138 	ivideo->video_offset = 0;
3139 	if(ivideo->sisfb_parm_mem) {
3140 		if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3141 		    (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3142 			ivideo->sisfb_parm_mem = 0;
3143 		}
3144 	}
3145 
3146 	ivideo->heapstart = sisfb_getheapstart(ivideo);
3147 	ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3148 
3149 	ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3150 	ivideo->sisfb_heap_end   = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3151 
3152 	printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3153 		(int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3154 
3155 	ivideo->sisfb_heap.vinfo = ivideo;
3156 
3157 	ivideo->sisfb_heap.poha_chain = NULL;
3158 	ivideo->sisfb_heap.poh_freelist = NULL;
3159 
3160 	poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3161 	if(poh == NULL)
3162 		return 1;
3163 
3164 	poh->poh_next = &ivideo->sisfb_heap.oh_free;
3165 	poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3166 	poh->size = ivideo->sisfb_heap_size;
3167 	poh->offset = ivideo->heapstart;
3168 
3169 	ivideo->sisfb_heap.oh_free.poh_next = poh;
3170 	ivideo->sisfb_heap.oh_free.poh_prev = poh;
3171 	ivideo->sisfb_heap.oh_free.size = 0;
3172 	ivideo->sisfb_heap.max_freesize = poh->size;
3173 
3174 	ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3175 	ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3176 	ivideo->sisfb_heap.oh_used.size = SENTINEL;
3177 
3178 	if(ivideo->cardnumber == 0) {
3179 		/* For the first card, make this heap the "global" one
3180 		 * for old DRM (which could handle only one card)
3181 		 */
3182 		sisfb_heap = &ivideo->sisfb_heap;
3183 	}
3184 
3185 	return 0;
3186 }
3187 
3188 static struct SIS_OH *
3189 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3190 {
3191 	struct SIS_OHALLOC	*poha;
3192 	struct SIS_OH		*poh;
3193 	unsigned long		cOhs;
3194 	int			i;
3195 
3196 	if(memheap->poh_freelist == NULL) {
3197 		poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3198 		if(!poha)
3199 			return NULL;
3200 
3201 		poha->poha_next = memheap->poha_chain;
3202 		memheap->poha_chain = poha;
3203 
3204 		cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3205 
3206 		poh = &poha->aoh[0];
3207 		for(i = cOhs - 1; i != 0; i--) {
3208 			poh->poh_next = poh + 1;
3209 			poh = poh + 1;
3210 		}
3211 
3212 		poh->poh_next = NULL;
3213 		memheap->poh_freelist = &poha->aoh[0];
3214 	}
3215 
3216 	poh = memheap->poh_freelist;
3217 	memheap->poh_freelist = poh->poh_next;
3218 
3219 	return poh;
3220 }
3221 
3222 static struct SIS_OH *
3223 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3224 {
3225 	struct SIS_OH	*pohThis;
3226 	struct SIS_OH	*pohRoot;
3227 	int		bAllocated = 0;
3228 
3229 	if(size > memheap->max_freesize) {
3230 		DPRINTK("sisfb: Can't allocate %dk video memory\n",
3231 			(unsigned int) size / 1024);
3232 		return NULL;
3233 	}
3234 
3235 	pohThis = memheap->oh_free.poh_next;
3236 
3237 	while(pohThis != &memheap->oh_free) {
3238 		if(size <= pohThis->size) {
3239 			bAllocated = 1;
3240 			break;
3241 		}
3242 		pohThis = pohThis->poh_next;
3243 	}
3244 
3245 	if(!bAllocated) {
3246 		DPRINTK("sisfb: Can't allocate %dk video memory\n",
3247 			(unsigned int) size / 1024);
3248 		return NULL;
3249 	}
3250 
3251 	if(size == pohThis->size) {
3252 		pohRoot = pohThis;
3253 		sisfb_delete_node(pohThis);
3254 	} else {
3255 		pohRoot = sisfb_poh_new_node(memheap);
3256 		if(pohRoot == NULL)
3257 			return NULL;
3258 
3259 		pohRoot->offset = pohThis->offset;
3260 		pohRoot->size = size;
3261 
3262 		pohThis->offset += size;
3263 		pohThis->size -= size;
3264 	}
3265 
3266 	memheap->max_freesize -= size;
3267 
3268 	pohThis = &memheap->oh_used;
3269 	sisfb_insert_node(pohThis, pohRoot);
3270 
3271 	return pohRoot;
3272 }
3273 
3274 static void
3275 sisfb_delete_node(struct SIS_OH *poh)
3276 {
3277 	poh->poh_prev->poh_next = poh->poh_next;
3278 	poh->poh_next->poh_prev = poh->poh_prev;
3279 }
3280 
3281 static void
3282 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3283 {
3284 	struct SIS_OH *pohTemp = pohList->poh_next;
3285 
3286 	pohList->poh_next = poh;
3287 	pohTemp->poh_prev = poh;
3288 
3289 	poh->poh_prev = pohList;
3290 	poh->poh_next = pohTemp;
3291 }
3292 
3293 static struct SIS_OH *
3294 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3295 {
3296 	struct SIS_OH *pohThis;
3297 	struct SIS_OH *poh_freed;
3298 	struct SIS_OH *poh_prev;
3299 	struct SIS_OH *poh_next;
3300 	u32    ulUpper;
3301 	u32    ulLower;
3302 	int    foundNode = 0;
3303 
3304 	poh_freed = memheap->oh_used.poh_next;
3305 
3306 	while(poh_freed != &memheap->oh_used) {
3307 		if(poh_freed->offset == base) {
3308 			foundNode = 1;
3309 			break;
3310 		}
3311 
3312 		poh_freed = poh_freed->poh_next;
3313 	}
3314 
3315 	if(!foundNode)
3316 		return NULL;
3317 
3318 	memheap->max_freesize += poh_freed->size;
3319 
3320 	poh_prev = poh_next = NULL;
3321 	ulUpper = poh_freed->offset + poh_freed->size;
3322 	ulLower = poh_freed->offset;
3323 
3324 	pohThis = memheap->oh_free.poh_next;
3325 
3326 	while(pohThis != &memheap->oh_free) {
3327 		if(pohThis->offset == ulUpper) {
3328 			poh_next = pohThis;
3329 		} else if((pohThis->offset + pohThis->size) == ulLower) {
3330 			poh_prev = pohThis;
3331 		}
3332 		pohThis = pohThis->poh_next;
3333 	}
3334 
3335 	sisfb_delete_node(poh_freed);
3336 
3337 	if(poh_prev && poh_next) {
3338 		poh_prev->size += (poh_freed->size + poh_next->size);
3339 		sisfb_delete_node(poh_next);
3340 		sisfb_free_node(memheap, poh_freed);
3341 		sisfb_free_node(memheap, poh_next);
3342 		return poh_prev;
3343 	}
3344 
3345 	if(poh_prev) {
3346 		poh_prev->size += poh_freed->size;
3347 		sisfb_free_node(memheap, poh_freed);
3348 		return poh_prev;
3349 	}
3350 
3351 	if(poh_next) {
3352 		poh_next->size += poh_freed->size;
3353 		poh_next->offset = poh_freed->offset;
3354 		sisfb_free_node(memheap, poh_freed);
3355 		return poh_next;
3356 	}
3357 
3358 	sisfb_insert_node(&memheap->oh_free, poh_freed);
3359 
3360 	return poh_freed;
3361 }
3362 
3363 static void
3364 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3365 {
3366 	if(poh == NULL)
3367 		return;
3368 
3369 	poh->poh_next = memheap->poh_freelist;
3370 	memheap->poh_freelist = poh;
3371 }
3372 
3373 static void
3374 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3375 {
3376 	struct SIS_OH *poh = NULL;
3377 
3378 	if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3379 		poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3380 
3381 	if(poh == NULL) {
3382 		req->offset = req->size = 0;
3383 		DPRINTK("sisfb: Video RAM allocation failed\n");
3384 	} else {
3385 		req->offset = poh->offset;
3386 		req->size = poh->size;
3387 		DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3388 			(poh->offset + ivideo->video_vbase));
3389 	}
3390 }
3391 
3392 void
3393 sis_malloc(struct sis_memreq *req)
3394 {
3395 	struct sis_video_info *ivideo = sisfb_heap->vinfo;
3396 
3397 	if(&ivideo->sisfb_heap == sisfb_heap)
3398 		sis_int_malloc(ivideo, req);
3399 	else
3400 		req->offset = req->size = 0;
3401 }
3402 
3403 void
3404 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3405 {
3406 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3407 
3408 	sis_int_malloc(ivideo, req);
3409 }
3410 
3411 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3412 
3413 static void
3414 sis_int_free(struct sis_video_info *ivideo, u32 base)
3415 {
3416 	struct SIS_OH *poh;
3417 
3418 	if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3419 		return;
3420 
3421 	poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3422 
3423 	if(poh == NULL) {
3424 		DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3425 			(unsigned int) base);
3426 	}
3427 }
3428 
3429 void
3430 sis_free(u32 base)
3431 {
3432 	struct sis_video_info *ivideo = sisfb_heap->vinfo;
3433 
3434 	sis_int_free(ivideo, base);
3435 }
3436 
3437 void
3438 sis_free_new(struct pci_dev *pdev, u32 base)
3439 {
3440 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3441 
3442 	sis_int_free(ivideo, base);
3443 }
3444 
3445 /* --------------------- SetMode routines ------------------------- */
3446 
3447 static void
3448 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3449 {
3450 	u8 cr30, cr31;
3451 
3452 	/* Check if MMIO and engines are enabled,
3453 	 * and sync in case they are. Can't use
3454 	 * ivideo->accel here, as this might have
3455 	 * been changed before this is called.
3456 	 */
3457 	cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
3458 	cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
3459 	/* MMIO and 2D/3D engine enabled? */
3460 	if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3461 #ifdef CONFIG_FB_SIS_300
3462 		if(ivideo->sisvga_engine == SIS_300_VGA) {
3463 			/* Don't care about TurboQueue. It's
3464 			 * enough to know that the engines
3465 			 * are enabled
3466 			 */
3467 			sisfb_syncaccel(ivideo);
3468 		}
3469 #endif
3470 #ifdef CONFIG_FB_SIS_315
3471 		if(ivideo->sisvga_engine == SIS_315_VGA) {
3472 			/* Check that any queue mode is
3473 			 * enabled, and that the queue
3474 			 * is not in the state of "reset"
3475 			 */
3476 			cr30 = SiS_GetReg(SISSR, 0x26);
3477 			if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3478 				sisfb_syncaccel(ivideo);
3479 			}
3480 		}
3481 #endif
3482 	}
3483 }
3484 
3485 static void
3486 sisfb_pre_setmode(struct sis_video_info *ivideo)
3487 {
3488 	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3489 	int tvregnum = 0;
3490 
3491 	ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3492 
3493 	SiS_SetReg(SISSR, 0x05, 0x86);
3494 
3495 	cr31 = SiS_GetReg(SISCR, 0x31);
3496 	cr31 &= ~0x60;
3497 	cr31 |= 0x04;
3498 
3499 	cr33 = ivideo->rate_idx & 0x0F;
3500 
3501 #ifdef CONFIG_FB_SIS_315
3502 	if(ivideo->sisvga_engine == SIS_315_VGA) {
3503 	   if(ivideo->chip >= SIS_661) {
3504 	      cr38 = SiS_GetReg(SISCR, 0x38);
3505 	      cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
3506 	   } else {
3507 	      tvregnum = 0x38;
3508 	      cr38 = SiS_GetReg(SISCR, tvregnum);
3509 	      cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
3510 	   }
3511 	}
3512 #endif
3513 #ifdef CONFIG_FB_SIS_300
3514 	if(ivideo->sisvga_engine == SIS_300_VGA) {
3515 	   tvregnum = 0x35;
3516 	   cr38 = SiS_GetReg(SISCR, tvregnum);
3517 	}
3518 #endif
3519 
3520 	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3521 	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3522 	ivideo->curFSTN = ivideo->curDSTN = 0;
3523 
3524 	switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3525 
3526 	   case CRT2_TV:
3527 	      cr38 &= ~0xc0;   /* Clear PAL-M / PAL-N bits */
3528 	      if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3529 #ifdef CONFIG_FB_SIS_315
3530 		 if(ivideo->chip >= SIS_661) {
3531 		    cr38 |= 0x04;
3532 		    if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
3533 		    else if(ivideo->vbflags & TV_YPBPR750P)  cr35 |= 0x40;
3534 		    else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3535 		    cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3536 		    cr35 &= ~0x01;
3537 		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3538 		 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3539 		    cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3540 		    cr38 |= 0x08;
3541 		    if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
3542 		    else if(ivideo->vbflags & TV_YPBPR750P)  cr38 |= 0x20;
3543 		    else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3544 		    cr31 &= ~0x01;
3545 		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3546 		 }
3547 #endif
3548 	      } else if((ivideo->vbflags & TV_HIVISION) &&
3549 				(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3550 		 if(ivideo->chip >= SIS_661) {
3551 		    cr38 |= 0x04;
3552 		    cr35 |= 0x60;
3553 		 } else {
3554 		    cr30 |= 0x80;
3555 		 }
3556 		 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3557 		 cr31 |= 0x01;
3558 		 cr35 |= 0x01;
3559 		 ivideo->currentvbflags |= TV_HIVISION;
3560 	      } else if(ivideo->vbflags & TV_SCART) {
3561 		 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3562 		 cr31 |= 0x01;
3563 		 cr35 |= 0x01;
3564 		 ivideo->currentvbflags |= TV_SCART;
3565 	      } else {
3566 		 if(ivideo->vbflags & TV_SVIDEO) {
3567 		    cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3568 		    ivideo->currentvbflags |= TV_SVIDEO;
3569 		 }
3570 		 if(ivideo->vbflags & TV_AVIDEO) {
3571 		    cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3572 		    ivideo->currentvbflags |= TV_AVIDEO;
3573 		 }
3574 	      }
3575 	      cr31 |= SIS_DRIVER_MODE;
3576 
3577 	      if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3578 		 if(ivideo->vbflags & TV_PAL) {
3579 		    cr31 |= 0x01; cr35 |= 0x01;
3580 		    ivideo->currentvbflags |= TV_PAL;
3581 		    if(ivideo->vbflags & TV_PALM) {
3582 		       cr38 |= 0x40; cr35 |= 0x04;
3583 		       ivideo->currentvbflags |= TV_PALM;
3584 		    } else if(ivideo->vbflags & TV_PALN) {
3585 		       cr38 |= 0x80; cr35 |= 0x08;
3586 		       ivideo->currentvbflags |= TV_PALN;
3587 		    }
3588 		 } else {
3589 		    cr31 &= ~0x01; cr35 &= ~0x01;
3590 		    ivideo->currentvbflags |= TV_NTSC;
3591 		    if(ivideo->vbflags & TV_NTSCJ) {
3592 		       cr38 |= 0x40; cr35 |= 0x02;
3593 		       ivideo->currentvbflags |= TV_NTSCJ;
3594 		    }
3595 		 }
3596 	      }
3597 	      break;
3598 
3599 	   case CRT2_LCD:
3600 	      cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3601 	      cr31 |= SIS_DRIVER_MODE;
3602 	      SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3603 	      SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3604 	      ivideo->curFSTN = ivideo->sisfb_fstn;
3605 	      ivideo->curDSTN = ivideo->sisfb_dstn;
3606 	      break;
3607 
3608 	   case CRT2_VGA:
3609 	      cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3610 	      cr31 |= SIS_DRIVER_MODE;
3611 	      if(ivideo->sisfb_nocrt2rate) {
3612 		 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3613 	      } else {
3614 		 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3615 	      }
3616 	      break;
3617 
3618 	   default:	/* disable CRT2 */
3619 	      cr30 = 0x00;
3620 	      cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3621 	}
3622 
3623 	SiS_SetReg(SISCR, 0x30, cr30);
3624 	SiS_SetReg(SISCR, 0x33, cr33);
3625 
3626 	if(ivideo->chip >= SIS_661) {
3627 #ifdef CONFIG_FB_SIS_315
3628 	   cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
3629 	   SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3630 	   cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
3631 	   SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3632 #endif
3633 	} else if(ivideo->chip != SIS_300) {
3634 	   SiS_SetReg(SISCR, tvregnum, cr38);
3635 	}
3636 	SiS_SetReg(SISCR, 0x31, cr31);
3637 
3638 	ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3639 
3640 	sisfb_check_engine_and_sync(ivideo);
3641 }
3642 
3643 /* Fix SR11 for 661 and later */
3644 #ifdef CONFIG_FB_SIS_315
3645 static void
3646 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3647 {
3648 	u8  tmpreg;
3649 
3650 	if(ivideo->chip >= SIS_661) {
3651 		tmpreg = SiS_GetReg(SISSR, 0x11);
3652 		if(tmpreg & 0x20) {
3653 			tmpreg = SiS_GetReg(SISSR, 0x3e);
3654 			tmpreg = (tmpreg + 1) & 0xff;
3655 			SiS_SetReg(SISSR, 0x3e, tmpreg);
3656 			tmpreg = SiS_GetReg(SISSR, 0x11);
3657 		}
3658 		if(tmpreg & 0xf0) {
3659 			SiS_SetRegAND(SISSR, 0x11, 0x0f);
3660 		}
3661 	}
3662 }
3663 #endif
3664 
3665 static void
3666 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3667 {
3668 	if(val > 32) val = 32;
3669 	if(val < -32) val = -32;
3670 	ivideo->tvxpos = val;
3671 
3672 	if(ivideo->sisfblocked) return;
3673 	if(!ivideo->modechanged) return;
3674 
3675 	if(ivideo->currentvbflags & CRT2_TV) {
3676 
3677 		if(ivideo->vbflags2 & VB2_CHRONTEL) {
3678 
3679 			int x = ivideo->tvx;
3680 
3681 			switch(ivideo->chronteltype) {
3682 			case 1:
3683 				x += val;
3684 				if(x < 0) x = 0;
3685 				SiS_SetReg(SISSR, 0x05, 0x86);
3686 				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3687 				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3688 				break;
3689 			case 2:
3690 				/* Not supported by hardware */
3691 				break;
3692 			}
3693 
3694 		} else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3695 
3696 			u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3697 			unsigned short temp;
3698 
3699 			p2_1f = ivideo->p2_1f;
3700 			p2_20 = ivideo->p2_20;
3701 			p2_2b = ivideo->p2_2b;
3702 			p2_42 = ivideo->p2_42;
3703 			p2_43 = ivideo->p2_43;
3704 
3705 			temp = p2_1f | ((p2_20 & 0xf0) << 4);
3706 			temp += (val * 2);
3707 			p2_1f = temp & 0xff;
3708 			p2_20 = (temp & 0xf00) >> 4;
3709 			p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3710 			temp = p2_43 | ((p2_42 & 0xf0) << 4);
3711 			temp += (val * 2);
3712 			p2_43 = temp & 0xff;
3713 			p2_42 = (temp & 0xf00) >> 4;
3714 			SiS_SetReg(SISPART2, 0x1f, p2_1f);
3715 			SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3716 			SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3717 			SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3718 			SiS_SetReg(SISPART2, 0x43, p2_43);
3719 		}
3720 	}
3721 }
3722 
3723 static void
3724 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3725 {
3726 	if(val > 32) val = 32;
3727 	if(val < -32) val = -32;
3728 	ivideo->tvypos = val;
3729 
3730 	if(ivideo->sisfblocked) return;
3731 	if(!ivideo->modechanged) return;
3732 
3733 	if(ivideo->currentvbflags & CRT2_TV) {
3734 
3735 		if(ivideo->vbflags2 & VB2_CHRONTEL) {
3736 
3737 			int y = ivideo->tvy;
3738 
3739 			switch(ivideo->chronteltype) {
3740 			case 1:
3741 				y -= val;
3742 				if(y < 0) y = 0;
3743 				SiS_SetReg(SISSR, 0x05, 0x86);
3744 				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3745 				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3746 				break;
3747 			case 2:
3748 				/* Not supported by hardware */
3749 				break;
3750 			}
3751 
3752 		} else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3753 
3754 			char p2_01, p2_02;
3755 			val /= 2;
3756 			p2_01 = ivideo->p2_01;
3757 			p2_02 = ivideo->p2_02;
3758 
3759 			p2_01 += val;
3760 			p2_02 += val;
3761 			if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3762 				while((p2_01 <= 0) || (p2_02 <= 0)) {
3763 					p2_01 += 2;
3764 					p2_02 += 2;
3765 				}
3766 			}
3767 			SiS_SetReg(SISPART2, 0x01, p2_01);
3768 			SiS_SetReg(SISPART2, 0x02, p2_02);
3769 		}
3770 	}
3771 }
3772 
3773 static void
3774 sisfb_post_setmode(struct sis_video_info *ivideo)
3775 {
3776 	bool crt1isoff = false;
3777 	bool doit = true;
3778 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3779 	u8 reg;
3780 #endif
3781 #ifdef CONFIG_FB_SIS_315
3782 	u8 reg1;
3783 #endif
3784 
3785 	SiS_SetReg(SISSR, 0x05, 0x86);
3786 
3787 #ifdef CONFIG_FB_SIS_315
3788 	sisfb_fixup_SR11(ivideo);
3789 #endif
3790 
3791 	/* Now we actually HAVE changed the display mode */
3792 	ivideo->modechanged = 1;
3793 
3794 	/* We can't switch off CRT1 if bridge is in slave mode */
3795 	if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3796 		if(sisfb_bridgeisslave(ivideo)) doit = false;
3797 	} else
3798 		ivideo->sisfb_crt1off = 0;
3799 
3800 #ifdef CONFIG_FB_SIS_300
3801 	if(ivideo->sisvga_engine == SIS_300_VGA) {
3802 		if((ivideo->sisfb_crt1off) && (doit)) {
3803 			crt1isoff = true;
3804 			reg = 0x00;
3805 		} else {
3806 			crt1isoff = false;
3807 			reg = 0x80;
3808 		}
3809 		SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3810 	}
3811 #endif
3812 #ifdef CONFIG_FB_SIS_315
3813 	if(ivideo->sisvga_engine == SIS_315_VGA) {
3814 		if((ivideo->sisfb_crt1off) && (doit)) {
3815 			crt1isoff = true;
3816 			reg  = 0x40;
3817 			reg1 = 0xc0;
3818 		} else {
3819 			crt1isoff = false;
3820 			reg  = 0x00;
3821 			reg1 = 0x00;
3822 		}
3823 		SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3824 		SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3825 	}
3826 #endif
3827 
3828 	if(crt1isoff) {
3829 		ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3830 		ivideo->currentvbflags |= VB_SINGLE_MODE;
3831 	} else {
3832 		ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3833 		if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3834 			ivideo->currentvbflags |= VB_MIRROR_MODE;
3835 		} else {
3836 			ivideo->currentvbflags |= VB_SINGLE_MODE;
3837 		}
3838 	}
3839 
3840 	SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3841 
3842 	if(ivideo->currentvbflags & CRT2_TV) {
3843 		if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3844 			ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3845 			ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3846 			ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3847 			ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3848 			ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3849 			ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3850 			ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3851 		} else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3852 			if(ivideo->chronteltype == 1) {
3853 				ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3854 				ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3855 				ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3856 				ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3857 			}
3858 		}
3859 	}
3860 
3861 	if(ivideo->tvxpos) {
3862 		sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3863 	}
3864 	if(ivideo->tvypos) {
3865 		sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3866 	}
3867 
3868 	/* Eventually sync engines */
3869 	sisfb_check_engine_and_sync(ivideo);
3870 
3871 	/* (Re-)Initialize chip engines */
3872 	if(ivideo->accel) {
3873 		sisfb_engine_init(ivideo);
3874 	} else {
3875 		ivideo->engineok = 0;
3876 	}
3877 }
3878 
3879 static int
3880 sisfb_reset_mode(struct sis_video_info *ivideo)
3881 {
3882 	if(sisfb_set_mode(ivideo, 0))
3883 		return 1;
3884 
3885 	sisfb_set_pitch(ivideo);
3886 	sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3887 	sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3888 
3889 	return 0;
3890 }
3891 
3892 static void
3893 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3894 {
3895 	int mycrt1off;
3896 
3897 	switch(sisfb_command->sisfb_cmd) {
3898 	case SISFB_CMD_GETVBFLAGS:
3899 		if(!ivideo->modechanged) {
3900 			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3901 		} else {
3902 			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3903 			sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3904 			sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3905 		}
3906 		break;
3907 	case SISFB_CMD_SWITCHCRT1:
3908 		/* arg[0]: 0 = off, 1 = on, 99 = query */
3909 		if(!ivideo->modechanged) {
3910 			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3911 		} else if(sisfb_command->sisfb_arg[0] == 99) {
3912 			/* Query */
3913 			sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3914 			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3915 		} else if(ivideo->sisfblocked) {
3916 			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3917 		} else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3918 					(sisfb_command->sisfb_arg[0] == 0)) {
3919 			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3920 		} else {
3921 			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3922 			mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3923 			if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3924 			    ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3925 				ivideo->sisfb_crt1off = mycrt1off;
3926 				if(sisfb_reset_mode(ivideo)) {
3927 					sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3928 				}
3929 			}
3930 			sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3931 		}
3932 		break;
3933 	/* more to come */
3934 	default:
3935 		sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3936 		printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3937 			sisfb_command->sisfb_cmd);
3938 	}
3939 }
3940 
3941 #ifndef MODULE
3942 static int __init sisfb_setup(char *options)
3943 {
3944 	char *this_opt;
3945 
3946 	sisfb_setdefaultparms();
3947 
3948 	if(!options || !(*options))
3949 		return 0;
3950 
3951 	while((this_opt = strsep(&options, ",")) != NULL) {
3952 
3953 		if(!(*this_opt)) continue;
3954 
3955 		if(!strncasecmp(this_opt, "off", 3)) {
3956 			sisfb_off = 1;
3957 		} else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
3958 			/* Need to check crt2 type first for fstn/dstn */
3959 			sisfb_search_crt2type(this_opt + 14);
3960 		} else if(!strncasecmp(this_opt, "tvmode:",7)) {
3961 			sisfb_search_tvstd(this_opt + 7);
3962 		} else if(!strncasecmp(this_opt, "tvstandard:",11)) {
3963 			sisfb_search_tvstd(this_opt + 11);
3964 		} else if(!strncasecmp(this_opt, "mode:", 5)) {
3965 			sisfb_search_mode(this_opt + 5, false);
3966 		} else if(!strncasecmp(this_opt, "vesa:", 5)) {
3967 			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
3968 		} else if(!strncasecmp(this_opt, "rate:", 5)) {
3969 			sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
3970 		} else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
3971 			sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
3972 		} else if(!strncasecmp(this_opt, "mem:",4)) {
3973 			sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
3974 		} else if(!strncasecmp(this_opt, "pdc:", 4)) {
3975 			sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
3976 		} else if(!strncasecmp(this_opt, "pdc1:", 5)) {
3977 			sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
3978 		} else if(!strncasecmp(this_opt, "noaccel", 7)) {
3979 			sisfb_accel = 0;
3980 		} else if(!strncasecmp(this_opt, "accel", 5)) {
3981 			sisfb_accel = -1;
3982 		} else if(!strncasecmp(this_opt, "noypan", 6)) {
3983 			sisfb_ypan = 0;
3984 		} else if(!strncasecmp(this_opt, "ypan", 4)) {
3985 			sisfb_ypan = -1;
3986 		} else if(!strncasecmp(this_opt, "nomax", 5)) {
3987 			sisfb_max = 0;
3988 		} else if(!strncasecmp(this_opt, "max", 3)) {
3989 			sisfb_max = -1;
3990 		} else if(!strncasecmp(this_opt, "userom:", 7)) {
3991 			sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
3992 		} else if(!strncasecmp(this_opt, "useoem:", 7)) {
3993 			sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
3994 		} else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
3995 			sisfb_nocrt2rate = 1;
3996 		} else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
3997 			unsigned long temp = 2;
3998 			temp = simple_strtoul(this_opt + 9, NULL, 0);
3999 			if((temp == 0) || (temp == 1)) {
4000 			   sisfb_scalelcd = temp ^ 1;
4001 			}
4002 		} else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
4003 			int temp = 0;
4004 			temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4005 			if((temp >= -32) && (temp <= 32)) {
4006 			   sisfb_tvxposoffset = temp;
4007 			}
4008 		} else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
4009 			int temp = 0;
4010 			temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4011 			if((temp >= -32) && (temp <= 32)) {
4012 			   sisfb_tvyposoffset = temp;
4013 			}
4014 		} else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
4015 			sisfb_search_specialtiming(this_opt + 14);
4016 		} else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
4017 			int temp = 4;
4018 			temp = simple_strtoul(this_opt + 7, NULL, 0);
4019 			if((temp >= 0) && (temp <= 3)) {
4020 			   sisfb_lvdshl = temp;
4021 			}
4022 		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4023 			sisfb_search_mode(this_opt, true);
4024 #if !defined(__i386__) && !defined(__x86_64__)
4025 		} else if(!strncasecmp(this_opt, "resetcard", 9)) {
4026 			sisfb_resetcard = 1;
4027 	        } else if(!strncasecmp(this_opt, "videoram:", 9)) {
4028 			sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4029 #endif
4030 		} else {
4031 			printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4032 		}
4033 
4034 	}
4035 
4036 	return 0;
4037 }
4038 #endif
4039 
4040 static int sisfb_check_rom(void __iomem *rom_base,
4041 			   struct sis_video_info *ivideo)
4042 {
4043 	void __iomem *rom;
4044 	int romptr;
4045 
4046 	if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4047 		return 0;
4048 
4049 	romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4050 	if(romptr > (0x10000 - 8))
4051 		return 0;
4052 
4053 	rom = rom_base + romptr;
4054 
4055 	if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
4056 	   (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4057 		return 0;
4058 
4059 	if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4060 		return 0;
4061 
4062 	if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4063 		return 0;
4064 
4065 	return 1;
4066 }
4067 
4068 static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
4069 {
4070 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4071 	void __iomem *rom_base;
4072 	unsigned char *myrombase = NULL;
4073 	size_t romsize;
4074 
4075 	/* First, try the official pci ROM functions (except
4076 	 * on integrated chipsets which have no ROM).
4077 	 */
4078 
4079 	if(!ivideo->nbridge) {
4080 
4081 		if((rom_base = pci_map_rom(pdev, &romsize))) {
4082 
4083 			if(sisfb_check_rom(rom_base, ivideo)) {
4084 
4085 				if((myrombase = vmalloc(65536))) {
4086 					memcpy_fromio(myrombase, rom_base,
4087 							(romsize > 65536) ? 65536 : romsize);
4088 				}
4089 			}
4090 			pci_unmap_rom(pdev, rom_base);
4091 		}
4092 	}
4093 
4094 	if(myrombase) return myrombase;
4095 
4096 	/* Otherwise do it the conventional way. */
4097 
4098 #if defined(__i386__) || defined(__x86_64__)
4099 	{
4100 		u32 temp;
4101 
4102 		for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4103 
4104 			rom_base = ioremap(temp, 65536);
4105 			if (!rom_base)
4106 				continue;
4107 
4108 			if (!sisfb_check_rom(rom_base, ivideo)) {
4109 				iounmap(rom_base);
4110 				continue;
4111 			}
4112 
4113 			if ((myrombase = vmalloc(65536)))
4114 				memcpy_fromio(myrombase, rom_base, 65536);
4115 
4116 			iounmap(rom_base);
4117 			break;
4118 
4119 		}
4120 
4121 	}
4122 #endif
4123 
4124 	return myrombase;
4125 }
4126 
4127 static void sisfb_post_map_vram(struct sis_video_info *ivideo,
4128 				unsigned int *mapsize, unsigned int min)
4129 {
4130 	if (*mapsize < (min << 20))
4131 		return;
4132 
4133 	ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
4134 
4135 	if(!ivideo->video_vbase) {
4136 		printk(KERN_ERR
4137 			"sisfb: Unable to map maximum video RAM for size detection\n");
4138 		(*mapsize) >>= 1;
4139 		while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
4140 			(*mapsize) >>= 1;
4141 			if((*mapsize) < (min << 20))
4142 				break;
4143 		}
4144 		if(ivideo->video_vbase) {
4145 			printk(KERN_ERR
4146 				"sisfb: Video RAM size detection limited to %dMB\n",
4147 				(int)((*mapsize) >> 20));
4148 		}
4149 	}
4150 }
4151 
4152 #ifdef CONFIG_FB_SIS_300
4153 static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4154 {
4155 	void __iomem *FBAddress = ivideo->video_vbase;
4156 	unsigned short temp;
4157 	unsigned char reg;
4158 	int i, j;
4159 
4160 	SiS_SetRegAND(SISSR, 0x15, 0xFB);
4161 	SiS_SetRegOR(SISSR, 0x15, 0x04);
4162 	SiS_SetReg(SISSR, 0x13, 0x00);
4163 	SiS_SetReg(SISSR, 0x14, 0xBF);
4164 
4165 	for(i = 0; i < 2; i++) {
4166 		temp = 0x1234;
4167 		for(j = 0; j < 4; j++) {
4168 			writew(temp, FBAddress);
4169 			if(readw(FBAddress) == temp)
4170 				break;
4171 			SiS_SetRegOR(SISSR, 0x3c, 0x01);
4172 			reg = SiS_GetReg(SISSR, 0x05);
4173 			reg = SiS_GetReg(SISSR, 0x05);
4174 			SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4175 			reg = SiS_GetReg(SISSR, 0x05);
4176 			reg = SiS_GetReg(SISSR, 0x05);
4177 			temp++;
4178 		}
4179 	}
4180 
4181 	writel(0x01234567L, FBAddress);
4182 	writel(0x456789ABL, (FBAddress + 4));
4183 	writel(0x89ABCDEFL, (FBAddress + 8));
4184 	writel(0xCDEF0123L, (FBAddress + 12));
4185 
4186 	reg = SiS_GetReg(SISSR, 0x3b);
4187 	if(reg & 0x01) {
4188 		if(readl((FBAddress + 12)) == 0xCDEF0123L)
4189 			return 4;	/* Channel A 128bit */
4190 	}
4191 
4192 	if(readl((FBAddress + 4)) == 0x456789ABL)
4193 		return 2;		/* Channel B 64bit */
4194 
4195 	return 1;			/* 32bit */
4196 }
4197 
4198 static const unsigned short SiS_DRAMType[17][5] = {
4199 	{0x0C,0x0A,0x02,0x40,0x39},
4200 	{0x0D,0x0A,0x01,0x40,0x48},
4201 	{0x0C,0x09,0x02,0x20,0x35},
4202 	{0x0D,0x09,0x01,0x20,0x44},
4203 	{0x0C,0x08,0x02,0x10,0x31},
4204 	{0x0D,0x08,0x01,0x10,0x40},
4205 	{0x0C,0x0A,0x01,0x20,0x34},
4206 	{0x0C,0x09,0x01,0x08,0x32},
4207 	{0x0B,0x08,0x02,0x08,0x21},
4208 	{0x0C,0x08,0x01,0x08,0x30},
4209 	{0x0A,0x08,0x02,0x04,0x11},
4210 	{0x0B,0x0A,0x01,0x10,0x28},
4211 	{0x09,0x08,0x02,0x02,0x01},
4212 	{0x0B,0x09,0x01,0x08,0x24},
4213 	{0x0B,0x08,0x01,0x04,0x20},
4214 	{0x0A,0x08,0x01,0x02,0x10},
4215 	{0x09,0x08,0x01,0x01,0x00}
4216 };
4217 
4218 static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
4219 				 int buswidth, int PseudoRankCapacity,
4220 				 int PseudoAdrPinCount, unsigned int mapsize)
4221 {
4222 	void __iomem *FBAddr = ivideo->video_vbase;
4223 	unsigned short sr14;
4224 	unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4225 	unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4226 
4227 	 for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
4228 
4229 		RankCapacity = buswidth * SiS_DRAMType[k][3];
4230 
4231 		if(RankCapacity != PseudoRankCapacity)
4232 			continue;
4233 
4234 		if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4235 			continue;
4236 
4237 		BankNumHigh = RankCapacity * 16 * iteration - 1;
4238 		if(iteration == 3) {             /* Rank No */
4239 			BankNumMid  = RankCapacity * 16 - 1;
4240 		} else {
4241 			BankNumMid  = RankCapacity * 16 * iteration / 2 - 1;
4242 		}
4243 
4244 		PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4245 		PhysicalAdrHigh = BankNumHigh;
4246 		PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4247 		PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4248 
4249 		SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4250 		SiS_SetRegOR(SISSR, 0x15, 0x04);  /* Test */
4251 		sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4252 		if(buswidth == 4)      sr14 |= 0x80;
4253 		else if(buswidth == 2) sr14 |= 0x40;
4254 		SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4255 		SiS_SetReg(SISSR, 0x14, sr14);
4256 
4257 		BankNumHigh <<= 16;
4258 		BankNumMid <<= 16;
4259 
4260 		if((BankNumHigh + PhysicalAdrHigh      >= mapsize) ||
4261 		   (BankNumMid  + PhysicalAdrHigh      >= mapsize) ||
4262 		   (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
4263 		   (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4264 			continue;
4265 
4266 		/* Write data */
4267 		writew(((unsigned short)PhysicalAdrHigh),
4268 				(FBAddr + BankNumHigh + PhysicalAdrHigh));
4269 		writew(((unsigned short)BankNumMid),
4270 				(FBAddr + BankNumMid  + PhysicalAdrHigh));
4271 		writew(((unsigned short)PhysicalAdrHalfPage),
4272 				(FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4273 		writew(((unsigned short)PhysicalAdrOtherPage),
4274 				(FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4275 
4276 		/* Read data */
4277 		if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4278 			return 1;
4279 	}
4280 
4281 	return 0;
4282 }
4283 
4284 static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4285 {
4286 	struct	sis_video_info *ivideo = pci_get_drvdata(pdev);
4287 	int	i, j, buswidth;
4288 	int	PseudoRankCapacity, PseudoAdrPinCount;
4289 
4290 	buswidth = sisfb_post_300_buswidth(ivideo);
4291 
4292 	for(i = 6; i >= 0; i--) {
4293 		PseudoRankCapacity = 1 << i;
4294 		for(j = 4; j >= 1; j--) {
4295 			PseudoAdrPinCount = 15 - j;
4296 			if((PseudoRankCapacity * j) <= 64) {
4297 				if(sisfb_post_300_rwtest(ivideo,
4298 						j,
4299 						buswidth,
4300 						PseudoRankCapacity,
4301 						PseudoAdrPinCount,
4302 						mapsize))
4303 					return;
4304 			}
4305 		}
4306 	}
4307 }
4308 
4309 static void sisfb_post_sis300(struct pci_dev *pdev)
4310 {
4311 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4312 	unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4313 	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
4314 	u16 index, rindex, memtype = 0;
4315 	unsigned int mapsize;
4316 
4317 	if(!ivideo->SiS_Pr.UseROM)
4318 		bios = NULL;
4319 
4320 	SiS_SetReg(SISSR, 0x05, 0x86);
4321 
4322 	if(bios) {
4323 		if(bios[0x52] & 0x80) {
4324 			memtype = bios[0x52];
4325 		} else {
4326 			memtype = SiS_GetReg(SISSR, 0x3a);
4327 		}
4328 		memtype &= 0x07;
4329 	}
4330 
4331 	v3 = 0x80; v6 = 0x80;
4332 	if(ivideo->revision_id <= 0x13) {
4333 		v1 = 0x44; v2 = 0x42;
4334 		v4 = 0x44; v5 = 0x42;
4335 	} else {
4336 		v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4337 		v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4338 		if(bios) {
4339 			index = memtype * 5;
4340 			rindex = index + 0x54;
4341 			v1 = bios[rindex++];
4342 			v2 = bios[rindex++];
4343 			v3 = bios[rindex++];
4344 			rindex = index + 0x7c;
4345 			v4 = bios[rindex++];
4346 			v5 = bios[rindex++];
4347 			v6 = bios[rindex++];
4348 		}
4349 	}
4350 	SiS_SetReg(SISSR, 0x28, v1);
4351 	SiS_SetReg(SISSR, 0x29, v2);
4352 	SiS_SetReg(SISSR, 0x2a, v3);
4353 	SiS_SetReg(SISSR, 0x2e, v4);
4354 	SiS_SetReg(SISSR, 0x2f, v5);
4355 	SiS_SetReg(SISSR, 0x30, v6);
4356 
4357 	v1 = 0x10;
4358 	if(bios)
4359 		v1 = bios[0xa4];
4360 	SiS_SetReg(SISSR, 0x07, v1);       /* DAC speed */
4361 
4362 	SiS_SetReg(SISSR, 0x11, 0x0f);     /* DDC, power save */
4363 
4364 	v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4365 	v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4366 	if(bios) {
4367 		memtype += 0xa5;
4368 		v1 = bios[memtype];
4369 		v2 = bios[memtype + 8];
4370 		v3 = bios[memtype + 16];
4371 		v4 = bios[memtype + 24];
4372 		v5 = bios[memtype + 32];
4373 		v6 = bios[memtype + 40];
4374 		v7 = bios[memtype + 48];
4375 		v8 = bios[memtype + 56];
4376 	}
4377 	if(ivideo->revision_id >= 0x80)
4378 		v3 &= 0xfd;
4379 	SiS_SetReg(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4380 	SiS_SetReg(SISSR, 0x16, v2);
4381 	SiS_SetReg(SISSR, 0x17, v3);
4382 	SiS_SetReg(SISSR, 0x18, v4);
4383 	SiS_SetReg(SISSR, 0x19, v5);
4384 	SiS_SetReg(SISSR, 0x1a, v6);
4385 	SiS_SetReg(SISSR, 0x1b, v7);
4386 	SiS_SetReg(SISSR, 0x1c, v8);	   /* ---- */
4387 	SiS_SetRegAND(SISSR, 0x15, 0xfb);
4388 	SiS_SetRegOR(SISSR, 0x15, 0x04);
4389 	if(bios) {
4390 		if(bios[0x53] & 0x02) {
4391 			SiS_SetRegOR(SISSR, 0x19, 0x20);
4392 		}
4393 	}
4394 	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
4395 	if(ivideo->revision_id >= 0x80)
4396 		v1 |= 0x01;
4397 	SiS_SetReg(SISSR, 0x1f, v1);
4398 	SiS_SetReg(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
4399 	v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4400 	if(bios) {
4401 		v1 = bios[0xe8];
4402 		v2 = bios[0xe9];
4403 		v3 = bios[0xea];
4404 	}
4405 	SiS_SetReg(SISSR, 0x23, v1);
4406 	SiS_SetReg(SISSR, 0x24, v2);
4407 	SiS_SetReg(SISSR, 0x25, v3);
4408 	SiS_SetReg(SISSR, 0x21, 0x84);
4409 	SiS_SetReg(SISSR, 0x22, 0x00);
4410 	SiS_SetReg(SISCR, 0x37, 0x00);
4411 	SiS_SetRegOR(SISPART1, 0x24, 0x01);   /* unlock crt2 */
4412 	SiS_SetReg(SISPART1, 0x00, 0x00);
4413 	v1 = 0x40; v2 = 0x11;
4414 	if(bios) {
4415 		v1 = bios[0xec];
4416 		v2 = bios[0xeb];
4417 	}
4418 	SiS_SetReg(SISPART1, 0x02, v1);
4419 
4420 	if(ivideo->revision_id >= 0x80)
4421 		v2 &= ~0x01;
4422 
4423 	reg = SiS_GetReg(SISPART4, 0x00);
4424 	if((reg == 1) || (reg == 2)) {
4425 		SiS_SetReg(SISCR, 0x37, 0x02);
4426 		SiS_SetReg(SISPART2, 0x00, 0x1c);
4427 		v4 = 0x00; v5 = 0x00; v6 = 0x10;
4428 		if(ivideo->SiS_Pr.UseROM) {
4429 			v4 = bios[0xf5];
4430 			v5 = bios[0xf6];
4431 			v6 = bios[0xf7];
4432 		}
4433 		SiS_SetReg(SISPART4, 0x0d, v4);
4434 		SiS_SetReg(SISPART4, 0x0e, v5);
4435 		SiS_SetReg(SISPART4, 0x10, v6);
4436 		SiS_SetReg(SISPART4, 0x0f, 0x3f);
4437 		reg = SiS_GetReg(SISPART4, 0x01);
4438 		if(reg >= 0xb0) {
4439 			reg = SiS_GetReg(SISPART4, 0x23);
4440 			reg &= 0x20;
4441 			reg <<= 1;
4442 			SiS_SetReg(SISPART4, 0x23, reg);
4443 		}
4444 	} else {
4445 		v2 &= ~0x10;
4446 	}
4447 	SiS_SetReg(SISSR, 0x32, v2);
4448 
4449 	SiS_SetRegAND(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
4450 
4451 	reg = SiS_GetReg(SISSR, 0x16);
4452 	reg &= 0xc3;
4453 	SiS_SetReg(SISCR, 0x35, reg);
4454 	SiS_SetReg(SISCR, 0x83, 0x00);
4455 #if !defined(__i386__) && !defined(__x86_64__)
4456 	if(sisfb_videoram) {
4457 		SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
4458 		reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4459 		SiS_SetReg(SISSR, 0x14, reg);
4460 	} else {
4461 #endif
4462 		/* Need to map max FB size for finding out about RAM size */
4463 		mapsize = ivideo->video_size;
4464 		sisfb_post_map_vram(ivideo, &mapsize, 4);
4465 
4466 		if(ivideo->video_vbase) {
4467 			sisfb_post_300_ramsize(pdev, mapsize);
4468 			iounmap(ivideo->video_vbase);
4469 		} else {
4470 			printk(KERN_DEBUG
4471 				"sisfb: Failed to map memory for size detection, assuming 8MB\n");
4472 			SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
4473 			SiS_SetReg(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
4474 		}
4475 #if !defined(__i386__) && !defined(__x86_64__)
4476 	}
4477 #endif
4478 	if(bios) {
4479 		v1 = bios[0xe6];
4480 		v2 = bios[0xe7];
4481 	} else {
4482 		reg = SiS_GetReg(SISSR, 0x3a);
4483 		if((reg & 0x30) == 0x30) {
4484 			v1 = 0x04; /* PCI */
4485 			v2 = 0x92;
4486 		} else {
4487 			v1 = 0x14; /* AGP */
4488 			v2 = 0xb2;
4489 		}
4490 	}
4491 	SiS_SetReg(SISSR, 0x21, v1);
4492 	SiS_SetReg(SISSR, 0x22, v2);
4493 
4494 	/* Sense CRT1 */
4495 	sisfb_sense_crt1(ivideo);
4496 
4497 	/* Set default mode, don't clear screen */
4498 	ivideo->SiS_Pr.SiS_UseOEM = false;
4499 	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4500 	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4501 	ivideo->curFSTN = ivideo->curDSTN = 0;
4502 	ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4503 	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4504 
4505 	SiS_SetReg(SISSR, 0x05, 0x86);
4506 
4507 	/* Display off */
4508 	SiS_SetRegOR(SISSR, 0x01, 0x20);
4509 
4510 	/* Save mode number in CR34 */
4511 	SiS_SetReg(SISCR, 0x34, 0x2e);
4512 
4513 	/* Let everyone know what the current mode is */
4514 	ivideo->modeprechange = 0x2e;
4515 }
4516 #endif
4517 
4518 #ifdef CONFIG_FB_SIS_315
4519 #if 0
4520 static void sisfb_post_sis315330(struct pci_dev *pdev)
4521 {
4522 	/* TODO */
4523 }
4524 #endif
4525 
4526 static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4527 {
4528 	return ivideo->chip_real_id == XGI_21;
4529 }
4530 
4531 static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4532 {
4533 	unsigned int i;
4534 	u8 reg;
4535 
4536 	for(i = 0; i <= (delay * 10 * 36); i++) {
4537 		reg = SiS_GetReg(SISSR, 0x05);
4538 		reg++;
4539 	}
4540 }
4541 
4542 static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
4543 				  struct pci_dev *mypdev,
4544 				  unsigned short pcivendor)
4545 {
4546 	struct pci_dev *pdev = NULL;
4547 	unsigned short temp;
4548 	int ret = 0;
4549 
4550 	while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4551 		temp = pdev->vendor;
4552 		if(temp == pcivendor) {
4553 			ret = 1;
4554 			pci_dev_put(pdev);
4555 			break;
4556 		}
4557 	}
4558 
4559 	return ret;
4560 }
4561 
4562 static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4563 				 unsigned int enda, unsigned int mapsize)
4564 {
4565 	unsigned int pos;
4566 	int i;
4567 
4568 	writel(0, ivideo->video_vbase);
4569 
4570 	for(i = starta; i <= enda; i++) {
4571 		pos = 1 << i;
4572 		if(pos < mapsize)
4573 			writel(pos, ivideo->video_vbase + pos);
4574 	}
4575 
4576 	sisfb_post_xgi_delay(ivideo, 150);
4577 
4578 	if(readl(ivideo->video_vbase) != 0)
4579 		return 0;
4580 
4581 	for(i = starta; i <= enda; i++) {
4582 		pos = 1 << i;
4583 		if(pos < mapsize) {
4584 			if(readl(ivideo->video_vbase + pos) != pos)
4585 				return 0;
4586 		} else
4587 			return 0;
4588 	}
4589 
4590 	return 1;
4591 }
4592 
4593 static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4594 {
4595 	unsigned int buswidth, ranksize, channelab, mapsize;
4596 	int i, j, k, l, status;
4597 	u8 reg, sr14;
4598 	static const u8 dramsr13[12 * 5] = {
4599 		0x02, 0x0e, 0x0b, 0x80, 0x5d,
4600 		0x02, 0x0e, 0x0a, 0x40, 0x59,
4601 		0x02, 0x0d, 0x0b, 0x40, 0x4d,
4602 		0x02, 0x0e, 0x09, 0x20, 0x55,
4603 		0x02, 0x0d, 0x0a, 0x20, 0x49,
4604 		0x02, 0x0c, 0x0b, 0x20, 0x3d,
4605 		0x02, 0x0e, 0x08, 0x10, 0x51,
4606 		0x02, 0x0d, 0x09, 0x10, 0x45,
4607 		0x02, 0x0c, 0x0a, 0x10, 0x39,
4608 		0x02, 0x0d, 0x08, 0x08, 0x41,
4609 		0x02, 0x0c, 0x09, 0x08, 0x35,
4610 		0x02, 0x0c, 0x08, 0x04, 0x31
4611 	};
4612 	static const u8 dramsr13_4[4 * 5] = {
4613 		0x02, 0x0d, 0x09, 0x40, 0x45,
4614 		0x02, 0x0c, 0x09, 0x20, 0x35,
4615 		0x02, 0x0c, 0x08, 0x10, 0x31,
4616 		0x02, 0x0b, 0x08, 0x08, 0x21
4617 	};
4618 
4619 	/* Enable linear mode, disable 0xa0000 address decoding */
4620 	/* We disable a0000 address decoding, because
4621 	 * - if running on x86, if the card is disabled, it means
4622 	 *   that another card is in the system. We don't want
4623 	 *   to interphere with that primary card's textmode.
4624 	 * - if running on non-x86, there usually is no VGA window
4625 	 *   at a0000.
4626 	 */
4627 	SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4628 
4629 	/* Need to map max FB size for finding out about RAM size */
4630 	mapsize = ivideo->video_size;
4631 	sisfb_post_map_vram(ivideo, &mapsize, 32);
4632 
4633 	if(!ivideo->video_vbase) {
4634 		printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4635 		SiS_SetReg(SISSR, 0x13, 0x35);
4636 		SiS_SetReg(SISSR, 0x14, 0x41);
4637 		/* TODO */
4638 		return -ENOMEM;
4639 	}
4640 
4641 	/* Non-interleaving */
4642 	SiS_SetReg(SISSR, 0x15, 0x00);
4643 	/* No tiling */
4644 	SiS_SetReg(SISSR, 0x1c, 0x00);
4645 
4646 	if(ivideo->chip == XGI_20) {
4647 
4648 		channelab = 1;
4649 		reg = SiS_GetReg(SISCR, 0x97);
4650 		if(!(reg & 0x01)) {	/* Single 32/16 */
4651 			buswidth = 32;
4652 			SiS_SetReg(SISSR, 0x13, 0xb1);
4653 			SiS_SetReg(SISSR, 0x14, 0x52);
4654 			sisfb_post_xgi_delay(ivideo, 1);
4655 			sr14 = 0x02;
4656 			if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4657 				goto bail_out;
4658 
4659 			SiS_SetReg(SISSR, 0x13, 0x31);
4660 			SiS_SetReg(SISSR, 0x14, 0x42);
4661 			sisfb_post_xgi_delay(ivideo, 1);
4662 			if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4663 				goto bail_out;
4664 
4665 			buswidth = 16;
4666 			SiS_SetReg(SISSR, 0x13, 0xb1);
4667 			SiS_SetReg(SISSR, 0x14, 0x41);
4668 			sisfb_post_xgi_delay(ivideo, 1);
4669 			sr14 = 0x01;
4670 			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4671 				goto bail_out;
4672 			else
4673 				SiS_SetReg(SISSR, 0x13, 0x31);
4674 		} else {		/* Dual 16/8 */
4675 			buswidth = 16;
4676 			SiS_SetReg(SISSR, 0x13, 0xb1);
4677 			SiS_SetReg(SISSR, 0x14, 0x41);
4678 			sisfb_post_xgi_delay(ivideo, 1);
4679 			sr14 = 0x01;
4680 			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4681 				goto bail_out;
4682 
4683 			SiS_SetReg(SISSR, 0x13, 0x31);
4684 			SiS_SetReg(SISSR, 0x14, 0x31);
4685 			sisfb_post_xgi_delay(ivideo, 1);
4686 			if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4687 				goto bail_out;
4688 
4689 			buswidth = 8;
4690 			SiS_SetReg(SISSR, 0x13, 0xb1);
4691 			SiS_SetReg(SISSR, 0x14, 0x30);
4692 			sisfb_post_xgi_delay(ivideo, 1);
4693 			sr14 = 0x00;
4694 			if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4695 				goto bail_out;
4696 			else
4697 				SiS_SetReg(SISSR, 0x13, 0x31);
4698 		}
4699 
4700 	} else {	/* XGI_40 */
4701 
4702 		reg = SiS_GetReg(SISCR, 0x97);
4703 		if(!(reg & 0x10)) {
4704 			reg = SiS_GetReg(SISSR, 0x39);
4705 			reg >>= 1;
4706 		}
4707 
4708 		if(reg & 0x01) {	/* DDRII */
4709 			buswidth = 32;
4710 			if(ivideo->revision_id == 2) {
4711 				channelab = 2;
4712 				SiS_SetReg(SISSR, 0x13, 0xa1);
4713 				SiS_SetReg(SISSR, 0x14, 0x44);
4714 				sr14 = 0x04;
4715 				sisfb_post_xgi_delay(ivideo, 1);
4716 				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4717 					goto bail_out;
4718 
4719 				SiS_SetReg(SISSR, 0x13, 0x21);
4720 				SiS_SetReg(SISSR, 0x14, 0x34);
4721 				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4722 					goto bail_out;
4723 
4724 				channelab = 1;
4725 				SiS_SetReg(SISSR, 0x13, 0xa1);
4726 				SiS_SetReg(SISSR, 0x14, 0x40);
4727 				sr14 = 0x00;
4728 				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4729 					goto bail_out;
4730 
4731 				SiS_SetReg(SISSR, 0x13, 0x21);
4732 				SiS_SetReg(SISSR, 0x14, 0x30);
4733 			} else {
4734 				channelab = 3;
4735 				SiS_SetReg(SISSR, 0x13, 0xa1);
4736 				SiS_SetReg(SISSR, 0x14, 0x4c);
4737 				sr14 = 0x0c;
4738 				sisfb_post_xgi_delay(ivideo, 1);
4739 				if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4740 					goto bail_out;
4741 
4742 				channelab = 2;
4743 				SiS_SetReg(SISSR, 0x14, 0x48);
4744 				sisfb_post_xgi_delay(ivideo, 1);
4745 				sr14 = 0x08;
4746 				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4747 					goto bail_out;
4748 
4749 				SiS_SetReg(SISSR, 0x13, 0x21);
4750 				SiS_SetReg(SISSR, 0x14, 0x3c);
4751 				sr14 = 0x0c;
4752 
4753 				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4754 					channelab = 3;
4755 				} else {
4756 					channelab = 2;
4757 					SiS_SetReg(SISSR, 0x14, 0x38);
4758 					sr14 = 0x08;
4759 				}
4760 			}
4761 			sisfb_post_xgi_delay(ivideo, 1);
4762 
4763 		} else {	/* DDR */
4764 
4765 			buswidth = 64;
4766 			if(ivideo->revision_id == 2) {
4767 				channelab = 1;
4768 				SiS_SetReg(SISSR, 0x13, 0xa1);
4769 				SiS_SetReg(SISSR, 0x14, 0x52);
4770 				sisfb_post_xgi_delay(ivideo, 1);
4771 				sr14 = 0x02;
4772 				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4773 					goto bail_out;
4774 
4775 				SiS_SetReg(SISSR, 0x13, 0x21);
4776 				SiS_SetReg(SISSR, 0x14, 0x42);
4777 			} else {
4778 				channelab = 2;
4779 				SiS_SetReg(SISSR, 0x13, 0xa1);
4780 				SiS_SetReg(SISSR, 0x14, 0x5a);
4781 				sisfb_post_xgi_delay(ivideo, 1);
4782 				sr14 = 0x0a;
4783 				if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4784 					goto bail_out;
4785 
4786 				SiS_SetReg(SISSR, 0x13, 0x21);
4787 				SiS_SetReg(SISSR, 0x14, 0x4a);
4788 			}
4789 			sisfb_post_xgi_delay(ivideo, 1);
4790 
4791 		}
4792 	}
4793 
4794 bail_out:
4795 	SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4796 	sisfb_post_xgi_delay(ivideo, 1);
4797 
4798 	j = (ivideo->chip == XGI_20) ? 5 : 9;
4799 	k = (ivideo->chip == XGI_20) ? 12 : 4;
4800 	status = -EIO;
4801 
4802 	for(i = 0; i < k; i++) {
4803 
4804 		reg = (ivideo->chip == XGI_20) ?
4805 				dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4806 		SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4807 		sisfb_post_xgi_delay(ivideo, 50);
4808 
4809 		ranksize = (ivideo->chip == XGI_20) ?
4810 				dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4811 
4812 		reg = SiS_GetReg(SISSR, 0x13);
4813 		if(reg & 0x80) ranksize <<= 1;
4814 
4815 		if(ivideo->chip == XGI_20) {
4816 			if(buswidth == 16)      ranksize <<= 1;
4817 			else if(buswidth == 32) ranksize <<= 2;
4818 		} else {
4819 			if(buswidth == 64)      ranksize <<= 1;
4820 		}
4821 
4822 		reg = 0;
4823 		l = channelab;
4824 		if(l == 3) l = 4;
4825 		if((ranksize * l) <= 256) {
4826 			while((ranksize >>= 1)) reg += 0x10;
4827 		}
4828 
4829 		if(!reg) continue;
4830 
4831 		SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4832 		sisfb_post_xgi_delay(ivideo, 1);
4833 
4834 		if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4835 			status = 0;
4836 			break;
4837 		}
4838 	}
4839 
4840 	iounmap(ivideo->video_vbase);
4841 
4842 	return status;
4843 }
4844 
4845 static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4846 {
4847 	u8 v1, v2, v3;
4848 	int index;
4849 	static const u8 cs90[8 * 3] = {
4850 		0x16, 0x01, 0x01,
4851 		0x3e, 0x03, 0x01,
4852 		0x7c, 0x08, 0x01,
4853 		0x79, 0x06, 0x01,
4854 		0x29, 0x01, 0x81,
4855 		0x5c, 0x23, 0x01,
4856 		0x5c, 0x23, 0x01,
4857 		0x5c, 0x23, 0x01
4858 	};
4859 	static const u8 csb8[8 * 3] = {
4860 		0x5c, 0x23, 0x01,
4861 		0x29, 0x01, 0x01,
4862 		0x7c, 0x08, 0x01,
4863 		0x79, 0x06, 0x01,
4864 		0x29, 0x01, 0x81,
4865 		0x5c, 0x23, 0x01,
4866 		0x5c, 0x23, 0x01,
4867 		0x5c, 0x23, 0x01
4868 	};
4869 
4870 	regb = 0;  /* ! */
4871 
4872 	index = regb * 3;
4873 	v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4874 	if(ivideo->haveXGIROM) {
4875 		v1 = ivideo->bios_abase[0x90 + index];
4876 		v2 = ivideo->bios_abase[0x90 + index + 1];
4877 		v3 = ivideo->bios_abase[0x90 + index + 2];
4878 	}
4879 	SiS_SetReg(SISSR, 0x28, v1);
4880 	SiS_SetReg(SISSR, 0x29, v2);
4881 	SiS_SetReg(SISSR, 0x2a, v3);
4882 	sisfb_post_xgi_delay(ivideo, 0x43);
4883 	sisfb_post_xgi_delay(ivideo, 0x43);
4884 	sisfb_post_xgi_delay(ivideo, 0x43);
4885 	index = regb * 3;
4886 	v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4887 	if(ivideo->haveXGIROM) {
4888 		v1 = ivideo->bios_abase[0xb8 + index];
4889 		v2 = ivideo->bios_abase[0xb8 + index + 1];
4890 		v3 = ivideo->bios_abase[0xb8 + index + 2];
4891 	}
4892 	SiS_SetReg(SISSR, 0x2e, v1);
4893 	SiS_SetReg(SISSR, 0x2f, v2);
4894 	SiS_SetReg(SISSR, 0x30, v3);
4895 	sisfb_post_xgi_delay(ivideo, 0x43);
4896 	sisfb_post_xgi_delay(ivideo, 0x43);
4897 	sisfb_post_xgi_delay(ivideo, 0x43);
4898 }
4899 
4900 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
4901 					    u8 regb)
4902 {
4903 	unsigned char *bios = ivideo->bios_abase;
4904 	u8 v1;
4905 
4906 	SiS_SetReg(SISSR, 0x28, 0x64);
4907 	SiS_SetReg(SISSR, 0x29, 0x63);
4908 	sisfb_post_xgi_delay(ivideo, 15);
4909 	SiS_SetReg(SISSR, 0x18, 0x00);
4910 	SiS_SetReg(SISSR, 0x19, 0x20);
4911 	SiS_SetReg(SISSR, 0x16, 0x00);
4912 	SiS_SetReg(SISSR, 0x16, 0x80);
4913 	SiS_SetReg(SISSR, 0x18, 0xc5);
4914 	SiS_SetReg(SISSR, 0x19, 0x23);
4915 	SiS_SetReg(SISSR, 0x16, 0x00);
4916 	SiS_SetReg(SISSR, 0x16, 0x80);
4917 	sisfb_post_xgi_delay(ivideo, 1);
4918 	SiS_SetReg(SISCR, 0x97, 0x11);
4919 	sisfb_post_xgi_setclocks(ivideo, regb);
4920 	sisfb_post_xgi_delay(ivideo, 0x46);
4921 	SiS_SetReg(SISSR, 0x18, 0xc5);
4922 	SiS_SetReg(SISSR, 0x19, 0x23);
4923 	SiS_SetReg(SISSR, 0x16, 0x00);
4924 	SiS_SetReg(SISSR, 0x16, 0x80);
4925 	sisfb_post_xgi_delay(ivideo, 1);
4926 	SiS_SetReg(SISSR, 0x1b, 0x04);
4927 	sisfb_post_xgi_delay(ivideo, 1);
4928 	SiS_SetReg(SISSR, 0x1b, 0x00);
4929 	sisfb_post_xgi_delay(ivideo, 1);
4930 	v1 = 0x31;
4931 	if (ivideo->haveXGIROM) {
4932 		v1 = bios[0xf0];
4933 	}
4934 	SiS_SetReg(SISSR, 0x18, v1);
4935 	SiS_SetReg(SISSR, 0x19, 0x06);
4936 	SiS_SetReg(SISSR, 0x16, 0x04);
4937 	SiS_SetReg(SISSR, 0x16, 0x84);
4938 	sisfb_post_xgi_delay(ivideo, 1);
4939 }
4940 
4941 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4942 {
4943 	sisfb_post_xgi_setclocks(ivideo, 1);
4944 
4945 	SiS_SetReg(SISCR, 0x97, 0x11);
4946 	sisfb_post_xgi_delay(ivideo, 0x46);
4947 
4948 	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS2 */
4949 	SiS_SetReg(SISSR, 0x19, 0x80);
4950 	SiS_SetReg(SISSR, 0x16, 0x05);
4951 	SiS_SetReg(SISSR, 0x16, 0x85);
4952 
4953 	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS3 */
4954 	SiS_SetReg(SISSR, 0x19, 0xc0);
4955 	SiS_SetReg(SISSR, 0x16, 0x05);
4956 	SiS_SetReg(SISSR, 0x16, 0x85);
4957 
4958 	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS1 */
4959 	SiS_SetReg(SISSR, 0x19, 0x40);
4960 	SiS_SetReg(SISSR, 0x16, 0x05);
4961 	SiS_SetReg(SISSR, 0x16, 0x85);
4962 
4963 	SiS_SetReg(SISSR, 0x18, 0x42);	/* MRS1 */
4964 	SiS_SetReg(SISSR, 0x19, 0x02);
4965 	SiS_SetReg(SISSR, 0x16, 0x05);
4966 	SiS_SetReg(SISSR, 0x16, 0x85);
4967 	sisfb_post_xgi_delay(ivideo, 1);
4968 
4969 	SiS_SetReg(SISSR, 0x1b, 0x04);
4970 	sisfb_post_xgi_delay(ivideo, 1);
4971 
4972 	SiS_SetReg(SISSR, 0x1b, 0x00);
4973 	sisfb_post_xgi_delay(ivideo, 1);
4974 
4975 	SiS_SetReg(SISSR, 0x18, 0x42);	/* MRS1 */
4976 	SiS_SetReg(SISSR, 0x19, 0x00);
4977 	SiS_SetReg(SISSR, 0x16, 0x05);
4978 	SiS_SetReg(SISSR, 0x16, 0x85);
4979 	sisfb_post_xgi_delay(ivideo, 1);
4980 }
4981 
4982 static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
4983 {
4984 	unsigned char *bios = ivideo->bios_abase;
4985 	static const u8 cs158[8] = {
4986 		0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
4987 	};
4988 	static const u8 cs160[8] = {
4989 		0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
4990 	};
4991 	static const u8 cs168[8] = {
4992 		0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
4993 	};
4994 	u8 reg;
4995 	u8 v1;
4996 	u8 v2;
4997 	u8 v3;
4998 
4999 	SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5000 	SiS_SetReg(SISCR, 0x82, 0x77);
5001 	SiS_SetReg(SISCR, 0x86, 0x00);
5002 	reg = SiS_GetReg(SISCR, 0x86);
5003 	SiS_SetReg(SISCR, 0x86, 0x88);
5004 	reg = SiS_GetReg(SISCR, 0x86);
5005 	v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5006 	if (ivideo->haveXGIROM) {
5007 		v1 = bios[regb + 0x168];
5008 		v2 = bios[regb + 0x160];
5009 		v3 = bios[regb + 0x158];
5010 	}
5011 	SiS_SetReg(SISCR, 0x86, v1);
5012 	SiS_SetReg(SISCR, 0x82, 0x77);
5013 	SiS_SetReg(SISCR, 0x85, 0x00);
5014 	reg = SiS_GetReg(SISCR, 0x85);
5015 	SiS_SetReg(SISCR, 0x85, 0x88);
5016 	reg = SiS_GetReg(SISCR, 0x85);
5017 	SiS_SetReg(SISCR, 0x85, v2);
5018 	SiS_SetReg(SISCR, 0x82, v3);
5019 	SiS_SetReg(SISCR, 0x98, 0x01);
5020 	SiS_SetReg(SISCR, 0x9a, 0x02);
5021 	if (sisfb_xgi_is21(ivideo))
5022 		sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5023 	else
5024 		sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5025 }
5026 
5027 static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5028 {
5029 	unsigned char *bios = ivideo->bios_abase;
5030 	u8 ramtype;
5031 	u8 reg;
5032 	u8 v1;
5033 
5034 	ramtype = 0x00; v1 = 0x10;
5035 	if (ivideo->haveXGIROM) {
5036 		ramtype = bios[0x62];
5037 		v1 = bios[0x1d2];
5038 	}
5039 	if (!(ramtype & 0x80)) {
5040 		if (sisfb_xgi_is21(ivideo)) {
5041 			SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5042 			SiS_SetRegOR(SISCR, 0x4a, 0x80);  /* GPIOH EN */
5043 			reg = SiS_GetReg(SISCR, 0x48);
5044 			SiS_SetRegOR(SISCR, 0xb4, 0x02);
5045 			ramtype = reg & 0x01;		  /* GPIOH */
5046 		} else if (ivideo->chip == XGI_20) {
5047 			SiS_SetReg(SISCR, 0x97, v1);
5048 			reg = SiS_GetReg(SISCR, 0x97);
5049 			if (reg & 0x10) {
5050 				ramtype = (reg & 0x01) << 1;
5051 			}
5052 		} else {
5053 			reg = SiS_GetReg(SISSR, 0x39);
5054 			ramtype = reg & 0x02;
5055 			if (!(ramtype)) {
5056 				reg = SiS_GetReg(SISSR, 0x3a);
5057 				ramtype = (reg >> 1) & 0x01;
5058 			}
5059 		}
5060 	}
5061 	ramtype &= 0x07;
5062 
5063 	return ramtype;
5064 }
5065 
5066 static int sisfb_post_xgi(struct pci_dev *pdev)
5067 {
5068 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5069 	unsigned char *bios = ivideo->bios_abase;
5070 	struct pci_dev *mypdev = NULL;
5071 	const u8 *ptr, *ptr2;
5072 	u8 v1, v2, v3, v4, v5, reg, ramtype;
5073 	u32 rega, regb, regd;
5074 	int i, j, k, index;
5075 	static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5076 	static const u8 cs76[2] = { 0xa3, 0xfb };
5077 	static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5078 	static const u8 cs158[8] = {
5079 		0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5080 	};
5081 	static const u8 cs160[8] = {
5082 		0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5083 	};
5084 	static const u8 cs168[8] = {
5085 		0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5086 	};
5087 	static const u8 cs128[3 * 8] = {
5088 		0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5089 		0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5090 		0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5091 	};
5092 	static const u8 cs148[2 * 8] = {
5093 		0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5094 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5095 	};
5096 	static const u8 cs31a[8 * 4] = {
5097 		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5098 		0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5099 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5100 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5101 	};
5102 	static const u8 cs33a[8 * 4] = {
5103 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5104 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5105 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5106 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5107 	};
5108 	static const u8 cs45a[8 * 2] = {
5109 		0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5110 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5111 	};
5112 	static const u8 cs170[7 * 8] = {
5113 		0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5114 		0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5115 		0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5116 		0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5117 		0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5118 		0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5119 		0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5120 	};
5121 	static const u8 cs1a8[3 * 8] = {
5122 		0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5123 		0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5124 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5125 	};
5126 	static const u8 cs100[2 * 8] = {
5127 		0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5128 		0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5129 	};
5130 
5131 	/* VGA enable */
5132 	reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5133 	SiS_SetRegByte(SISVGAENABLE, reg);
5134 
5135 	/* Misc */
5136 	reg = SiS_GetRegByte(SISMISCR) | 0x01;
5137 	SiS_SetRegByte(SISMISCW, reg);
5138 
5139 	/* Unlock SR */
5140 	SiS_SetReg(SISSR, 0x05, 0x86);
5141 	reg = SiS_GetReg(SISSR, 0x05);
5142 	if(reg != 0xa1)
5143 		return 0;
5144 
5145 	/* Clear some regs */
5146 	for(i = 0; i < 0x22; i++) {
5147 		if(0x06 + i == 0x20) continue;
5148 		SiS_SetReg(SISSR, 0x06 + i, 0x00);
5149 	}
5150 	for(i = 0; i < 0x0b; i++) {
5151 		SiS_SetReg(SISSR, 0x31 + i, 0x00);
5152 	}
5153 	for(i = 0; i < 0x10; i++) {
5154 		SiS_SetReg(SISCR, 0x30 + i, 0x00);
5155 	}
5156 
5157 	ptr = cs78;
5158 	if(ivideo->haveXGIROM) {
5159 		ptr = (const u8 *)&bios[0x78];
5160 	}
5161 	for(i = 0; i < 3; i++) {
5162 		SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5163 	}
5164 
5165 	ptr = cs76;
5166 	if(ivideo->haveXGIROM) {
5167 		ptr = (const u8 *)&bios[0x76];
5168 	}
5169 	for(i = 0; i < 2; i++) {
5170 		SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5171 	}
5172 
5173 	v1 = 0x18; v2 = 0x00;
5174 	if(ivideo->haveXGIROM) {
5175 		v1 = bios[0x74];
5176 		v2 = bios[0x75];
5177 	}
5178 	SiS_SetReg(SISSR, 0x07, v1);
5179 	SiS_SetReg(SISSR, 0x11, 0x0f);
5180 	SiS_SetReg(SISSR, 0x1f, v2);
5181 	/* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5182 	SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5183 	SiS_SetReg(SISSR, 0x27, 0x74);
5184 
5185 	ptr = cs7b;
5186 	if(ivideo->haveXGIROM) {
5187 		ptr = (const u8 *)&bios[0x7b];
5188 	}
5189 	for(i = 0; i < 3; i++) {
5190 		SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5191 	}
5192 
5193 	if(ivideo->chip == XGI_40) {
5194 		if(ivideo->revision_id == 2) {
5195 			SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5196 		}
5197 		SiS_SetReg(SISCR, 0x7d, 0xfe);
5198 		SiS_SetReg(SISCR, 0x7e, 0x0f);
5199 	}
5200 	if(ivideo->revision_id == 0) {	/* 40 *and* 20? */
5201 		SiS_SetRegAND(SISCR, 0x58, 0xd7);
5202 		reg = SiS_GetReg(SISCR, 0xcb);
5203 		if(reg & 0x20) {
5204 			SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5205 		}
5206 	}
5207 
5208 	reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5209 	SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5210 
5211 	if(ivideo->chip == XGI_20) {
5212 		SiS_SetReg(SISSR, 0x36, 0x70);
5213 	} else {
5214 		SiS_SetReg(SISVID, 0x00, 0x86);
5215 		SiS_SetReg(SISVID, 0x32, 0x00);
5216 		SiS_SetReg(SISVID, 0x30, 0x00);
5217 		SiS_SetReg(SISVID, 0x32, 0x01);
5218 		SiS_SetReg(SISVID, 0x30, 0x00);
5219 		SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5220 		SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5221 
5222 		SiS_SetReg(SISPART1, 0x2f, 0x01);
5223 		SiS_SetReg(SISPART1, 0x00, 0x00);
5224 		SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5225 		SiS_SetReg(SISPART1, 0x2e, 0x08);
5226 		SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5227 		SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5228 
5229 		reg = SiS_GetReg(SISPART4, 0x00);
5230 		if(reg == 1 || reg == 2) {
5231 			SiS_SetReg(SISPART2, 0x00, 0x1c);
5232 			SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5233 			SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5234 			SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5235 			SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5236 
5237 			reg = SiS_GetReg(SISPART4, 0x01);
5238 			if((reg & 0xf0) >= 0xb0) {
5239 				reg = SiS_GetReg(SISPART4, 0x23);
5240 				if(reg & 0x20) reg |= 0x40;
5241 				SiS_SetReg(SISPART4, 0x23, reg);
5242 				reg = (reg & 0x20) ? 0x02 : 0x00;
5243 				SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5244 			}
5245 		}
5246 
5247 		v1 = bios[0x77];
5248 
5249 		reg = SiS_GetReg(SISSR, 0x3b);
5250 		if(reg & 0x02) {
5251 			reg = SiS_GetReg(SISSR, 0x3a);
5252 			v2 = (reg & 0x30) >> 3;
5253 			if(!(v2 & 0x04)) v2 ^= 0x02;
5254 			reg = SiS_GetReg(SISSR, 0x39);
5255 			if(reg & 0x80) v2 |= 0x80;
5256 			v2 |= 0x01;
5257 
5258 			if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5259 				pci_dev_put(mypdev);
5260 				if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5261 					v2 &= 0xf9;
5262 				v2 |= 0x08;
5263 				v1 &= 0xfe;
5264 			} else {
5265 				mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5266 				if(!mypdev)
5267 					mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5268 				if(!mypdev)
5269 					mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5270 				if(mypdev) {
5271 					pci_read_config_dword(mypdev, 0x94, &regd);
5272 					regd &= 0xfffffeff;
5273 					pci_write_config_dword(mypdev, 0x94, regd);
5274 					v1 &= 0xfe;
5275 					pci_dev_put(mypdev);
5276 				} else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5277 					v1 &= 0xfe;
5278 				} else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5279 					  sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5280 					  sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5281 					  sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5282 					if((v2 & 0x06) == 4)
5283 						v2 ^= 0x06;
5284 					v2 |= 0x08;
5285 				}
5286 			}
5287 			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5288 		}
5289 		SiS_SetReg(SISSR, 0x22, v1);
5290 
5291 		if(ivideo->revision_id == 2) {
5292 			v1 = SiS_GetReg(SISSR, 0x3b);
5293 			v2 = SiS_GetReg(SISSR, 0x3a);
5294 			regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5295 			if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5296 				SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5297 
5298 			if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5299 				/* TODO: set CR5f &0xf1 | 0x01 for version 6570
5300 				 * of nforce 2 ROM
5301 				 */
5302 				if(0)
5303 					SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5304 				pci_dev_put(mypdev);
5305 			}
5306 		}
5307 
5308 		v1 = 0x30;
5309 		reg = SiS_GetReg(SISSR, 0x3b);
5310 		v2 = SiS_GetReg(SISCR, 0x5f);
5311 		if((!(reg & 0x02)) && (v2 & 0x0e))
5312 			v1 |= 0x08;
5313 		SiS_SetReg(SISSR, 0x27, v1);
5314 
5315 		if(bios[0x64] & 0x01) {
5316 			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5317 		}
5318 
5319 		v1 = bios[0x4f7];
5320 		pci_read_config_dword(pdev, 0x50, &regd);
5321 		regd = (regd >> 20) & 0x0f;
5322 		if(regd == 1) {
5323 			v1 &= 0xfc;
5324 			SiS_SetRegOR(SISCR, 0x5f, 0x08);
5325 		}
5326 		SiS_SetReg(SISCR, 0x48, v1);
5327 
5328 		SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5329 		SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5330 		SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5331 		SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5332 		SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5333 		SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5334 		SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5335 		SiS_SetReg(SISCR, 0x74, 0xd0);
5336 		SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5337 		SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5338 		SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5339 		v1 = bios[0x501];
5340 		if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5341 			v1 = 0xf0;
5342 			pci_dev_put(mypdev);
5343 		}
5344 		SiS_SetReg(SISCR, 0x77, v1);
5345 	}
5346 
5347 	/* RAM type:
5348 	 *
5349 	 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5350 	 *
5351 	 * The code seems to written so that regb should equal ramtype,
5352 	 * however, so far it has been hardcoded to 0. Enable other values only
5353 	 * on XGI Z9, as it passes the POST, and add a warning for others.
5354 	 */
5355 	ramtype = sisfb_post_xgi_ramtype(ivideo);
5356 	if (!sisfb_xgi_is21(ivideo) && ramtype) {
5357 		dev_warn(&pdev->dev,
5358 			 "RAM type something else than expected: %d\n",
5359 			 ramtype);
5360 		regb = 0;
5361 	} else {
5362 		regb = ramtype;
5363 	}
5364 
5365 	v1 = 0xff;
5366 	if(ivideo->haveXGIROM) {
5367 		v1 = bios[0x140 + regb];
5368 	}
5369 	SiS_SetReg(SISCR, 0x6d, v1);
5370 
5371 	ptr = cs128;
5372 	if(ivideo->haveXGIROM) {
5373 		ptr = (const u8 *)&bios[0x128];
5374 	}
5375 	for(i = 0, j = 0; i < 3; i++, j += 8) {
5376 		SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5377 	}
5378 
5379 	ptr  = cs31a;
5380 	ptr2 = cs33a;
5381 	if(ivideo->haveXGIROM) {
5382 		index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5383 		ptr  = (const u8 *)&bios[index];
5384 		ptr2 = (const u8 *)&bios[index + 0x20];
5385 	}
5386 	for(i = 0; i < 2; i++) {
5387 		if(i == 0) {
5388 			regd = le32_to_cpu(((u32 *)ptr)[regb]);
5389 			rega = 0x6b;
5390 		} else {
5391 			regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5392 			rega = 0x6e;
5393 		}
5394 		reg = 0x00;
5395 		for(j = 0; j < 16; j++) {
5396 			reg &= 0xf3;
5397 			if(regd & 0x01) reg |= 0x04;
5398 			if(regd & 0x02) reg |= 0x08;
5399 			regd >>= 2;
5400 			SiS_SetReg(SISCR, rega, reg);
5401 			reg = SiS_GetReg(SISCR, rega);
5402 			reg = SiS_GetReg(SISCR, rega);
5403 			reg += 0x10;
5404 		}
5405 	}
5406 
5407 	SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5408 
5409 	ptr  = NULL;
5410 	if(ivideo->haveXGIROM) {
5411 		index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5412 		ptr  = (const u8 *)&bios[index];
5413 	}
5414 	for(i = 0; i < 4; i++) {
5415 		SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5416 		reg = 0x00;
5417 		for(j = 0; j < 2; j++) {
5418 			regd = 0;
5419 			if(ptr) {
5420 				regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5421 				ptr += 4;
5422 			}
5423 			/* reg = 0x00; */
5424 			for(k = 0; k < 16; k++) {
5425 				reg &= 0xfc;
5426 				if(regd & 0x01) reg |= 0x01;
5427 				if(regd & 0x02) reg |= 0x02;
5428 				regd >>= 2;
5429 				SiS_SetReg(SISCR, 0x6f, reg);
5430 				reg = SiS_GetReg(SISCR, 0x6f);
5431 				reg = SiS_GetReg(SISCR, 0x6f);
5432 				reg += 0x08;
5433 			}
5434 		}
5435 	}
5436 
5437 	ptr  = cs148;
5438 	if(ivideo->haveXGIROM) {
5439 		ptr  = (const u8 *)&bios[0x148];
5440 	}
5441 	for(i = 0, j = 0; i < 2; i++, j += 8) {
5442 		SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5443 	}
5444 
5445 	SiS_SetRegAND(SISCR, 0x89, 0x8f);
5446 
5447 	ptr  = cs45a;
5448 	if(ivideo->haveXGIROM) {
5449 		index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5450 		ptr  = (const u8 *)&bios[index];
5451 	}
5452 	regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5453 	reg = 0x80;
5454 	for(i = 0; i < 5; i++) {
5455 		reg &= 0xfc;
5456 		if(regd & 0x01) reg |= 0x01;
5457 		if(regd & 0x02) reg |= 0x02;
5458 		regd >>= 2;
5459 		SiS_SetReg(SISCR, 0x89, reg);
5460 		reg = SiS_GetReg(SISCR, 0x89);
5461 		reg = SiS_GetReg(SISCR, 0x89);
5462 		reg += 0x10;
5463 	}
5464 
5465 	v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5466 	if(ivideo->haveXGIROM) {
5467 		v1 = bios[0x118 + regb];
5468 		v2 = bios[0xf8 + regb];
5469 		v3 = bios[0x120 + regb];
5470 		v4 = bios[0x1ca];
5471 	}
5472 	SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5473 	SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5474 	SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5475 	SiS_SetReg(SISCR, 0x41, v2);
5476 
5477 	ptr  = cs170;
5478 	if(ivideo->haveXGIROM) {
5479 		ptr  = (const u8 *)&bios[0x170];
5480 	}
5481 	for(i = 0, j = 0; i < 7; i++, j += 8) {
5482 		SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5483 	}
5484 
5485 	SiS_SetReg(SISCR, 0x59, v3);
5486 
5487 	ptr  = cs1a8;
5488 	if(ivideo->haveXGIROM) {
5489 		ptr  = (const u8 *)&bios[0x1a8];
5490 	}
5491 	for(i = 0, j = 0; i < 3; i++, j += 8) {
5492 		SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5493 	}
5494 
5495 	ptr  = cs100;
5496 	if(ivideo->haveXGIROM) {
5497 		ptr  = (const u8 *)&bios[0x100];
5498 	}
5499 	for(i = 0, j = 0; i < 2; i++, j += 8) {
5500 		SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5501 	}
5502 
5503 	SiS_SetReg(SISCR, 0xcf, v4);
5504 
5505 	SiS_SetReg(SISCR, 0x83, 0x09);
5506 	SiS_SetReg(SISCR, 0x87, 0x00);
5507 
5508 	if(ivideo->chip == XGI_40) {
5509 		if( (ivideo->revision_id == 1) ||
5510 		    (ivideo->revision_id == 2) ) {
5511 			SiS_SetReg(SISCR, 0x8c, 0x87);
5512 		}
5513 	}
5514 
5515 	if (regb == 1)
5516 		SiS_SetReg(SISSR, 0x17, 0x80);		/* DDR2 */
5517 	else
5518 		SiS_SetReg(SISSR, 0x17, 0x00);		/* DDR1 */
5519 	SiS_SetReg(SISSR, 0x1a, 0x87);
5520 
5521 	if(ivideo->chip == XGI_20) {
5522 		SiS_SetReg(SISSR, 0x15, 0x00);
5523 		SiS_SetReg(SISSR, 0x1c, 0x00);
5524 	}
5525 
5526 	switch(ramtype) {
5527 	case 0:
5528 		sisfb_post_xgi_setclocks(ivideo, regb);
5529 		if((ivideo->chip == XGI_20) ||
5530 		   (ivideo->revision_id == 1)   ||
5531 		   (ivideo->revision_id == 2)) {
5532 			v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5533 			if(ivideo->haveXGIROM) {
5534 				v1 = bios[regb + 0x158];
5535 				v2 = bios[regb + 0x160];
5536 				v3 = bios[regb + 0x168];
5537 			}
5538 			SiS_SetReg(SISCR, 0x82, v1);
5539 			SiS_SetReg(SISCR, 0x85, v2);
5540 			SiS_SetReg(SISCR, 0x86, v3);
5541 		} else {
5542 			SiS_SetReg(SISCR, 0x82, 0x88);
5543 			SiS_SetReg(SISCR, 0x86, 0x00);
5544 			reg = SiS_GetReg(SISCR, 0x86);
5545 			SiS_SetReg(SISCR, 0x86, 0x88);
5546 			reg = SiS_GetReg(SISCR, 0x86);
5547 			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5548 			SiS_SetReg(SISCR, 0x82, 0x77);
5549 			SiS_SetReg(SISCR, 0x85, 0x00);
5550 			reg = SiS_GetReg(SISCR, 0x85);
5551 			SiS_SetReg(SISCR, 0x85, 0x88);
5552 			reg = SiS_GetReg(SISCR, 0x85);
5553 			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5554 			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5555 		}
5556 		if(ivideo->chip == XGI_40) {
5557 			SiS_SetReg(SISCR, 0x97, 0x00);
5558 		}
5559 		SiS_SetReg(SISCR, 0x98, 0x01);
5560 		SiS_SetReg(SISCR, 0x9a, 0x02);
5561 
5562 		SiS_SetReg(SISSR, 0x18, 0x01);
5563 		if((ivideo->chip == XGI_20) ||
5564 		   (ivideo->revision_id == 2)) {
5565 			SiS_SetReg(SISSR, 0x19, 0x40);
5566 		} else {
5567 			SiS_SetReg(SISSR, 0x19, 0x20);
5568 		}
5569 		SiS_SetReg(SISSR, 0x16, 0x00);
5570 		SiS_SetReg(SISSR, 0x16, 0x80);
5571 		if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5572 			sisfb_post_xgi_delay(ivideo, 0x43);
5573 			sisfb_post_xgi_delay(ivideo, 0x43);
5574 			sisfb_post_xgi_delay(ivideo, 0x43);
5575 			SiS_SetReg(SISSR, 0x18, 0x00);
5576 			if((ivideo->chip == XGI_20) ||
5577 			   (ivideo->revision_id == 2)) {
5578 				SiS_SetReg(SISSR, 0x19, 0x40);
5579 			} else {
5580 				SiS_SetReg(SISSR, 0x19, 0x20);
5581 			}
5582 		} else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5583 			/* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5584 		}
5585 		SiS_SetReg(SISSR, 0x16, 0x00);
5586 		SiS_SetReg(SISSR, 0x16, 0x80);
5587 		sisfb_post_xgi_delay(ivideo, 4);
5588 		v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5589 		if(ivideo->haveXGIROM) {
5590 			v1 = bios[0xf0];
5591 			index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5592 			v2 = bios[index];
5593 			v3 = bios[index + 1];
5594 			v4 = bios[index + 2];
5595 			v5 = bios[index + 3];
5596 		}
5597 		SiS_SetReg(SISSR, 0x18, v1);
5598 		SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5599 		SiS_SetReg(SISSR, 0x16, v2);
5600 		SiS_SetReg(SISSR, 0x16, v3);
5601 		sisfb_post_xgi_delay(ivideo, 0x43);
5602 		SiS_SetReg(SISSR, 0x1b, 0x03);
5603 		sisfb_post_xgi_delay(ivideo, 0x22);
5604 		SiS_SetReg(SISSR, 0x18, v1);
5605 		SiS_SetReg(SISSR, 0x19, 0x00);
5606 		SiS_SetReg(SISSR, 0x16, v4);
5607 		SiS_SetReg(SISSR, 0x16, v5);
5608 		SiS_SetReg(SISSR, 0x1b, 0x00);
5609 		break;
5610 	case 1:
5611 		sisfb_post_xgi_ddr2(ivideo, regb);
5612 		break;
5613 	default:
5614 		sisfb_post_xgi_setclocks(ivideo, regb);
5615 		if((ivideo->chip == XGI_40) &&
5616 		   ((ivideo->revision_id == 1) ||
5617 		    (ivideo->revision_id == 2))) {
5618 			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5619 			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5620 			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5621 		} else {
5622 			SiS_SetReg(SISCR, 0x82, 0x88);
5623 			SiS_SetReg(SISCR, 0x86, 0x00);
5624 			reg = SiS_GetReg(SISCR, 0x86);
5625 			SiS_SetReg(SISCR, 0x86, 0x88);
5626 			SiS_SetReg(SISCR, 0x82, 0x77);
5627 			SiS_SetReg(SISCR, 0x85, 0x00);
5628 			reg = SiS_GetReg(SISCR, 0x85);
5629 			SiS_SetReg(SISCR, 0x85, 0x88);
5630 			reg = SiS_GetReg(SISCR, 0x85);
5631 			v1 = cs160[regb]; v2 = cs158[regb];
5632 			if(ivideo->haveXGIROM) {
5633 				v1 = bios[regb + 0x160];
5634 				v2 = bios[regb + 0x158];
5635 			}
5636 			SiS_SetReg(SISCR, 0x85, v1);
5637 			SiS_SetReg(SISCR, 0x82, v2);
5638 		}
5639 		if(ivideo->chip == XGI_40) {
5640 			SiS_SetReg(SISCR, 0x97, 0x11);
5641 		}
5642 		if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5643 			SiS_SetReg(SISCR, 0x98, 0x01);
5644 		} else {
5645 			SiS_SetReg(SISCR, 0x98, 0x03);
5646 		}
5647 		SiS_SetReg(SISCR, 0x9a, 0x02);
5648 
5649 		if(ivideo->chip == XGI_40) {
5650 			SiS_SetReg(SISSR, 0x18, 0x01);
5651 		} else {
5652 			SiS_SetReg(SISSR, 0x18, 0x00);
5653 		}
5654 		SiS_SetReg(SISSR, 0x19, 0x40);
5655 		SiS_SetReg(SISSR, 0x16, 0x00);
5656 		SiS_SetReg(SISSR, 0x16, 0x80);
5657 		if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5658 			sisfb_post_xgi_delay(ivideo, 0x43);
5659 			sisfb_post_xgi_delay(ivideo, 0x43);
5660 			sisfb_post_xgi_delay(ivideo, 0x43);
5661 			SiS_SetReg(SISSR, 0x18, 0x00);
5662 			SiS_SetReg(SISSR, 0x19, 0x40);
5663 			SiS_SetReg(SISSR, 0x16, 0x00);
5664 			SiS_SetReg(SISSR, 0x16, 0x80);
5665 		}
5666 		sisfb_post_xgi_delay(ivideo, 4);
5667 		v1 = 0x31;
5668 		if(ivideo->haveXGIROM) {
5669 			v1 = bios[0xf0];
5670 		}
5671 		SiS_SetReg(SISSR, 0x18, v1);
5672 		SiS_SetReg(SISSR, 0x19, 0x01);
5673 		if(ivideo->chip == XGI_40) {
5674 			SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5675 			SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5676 		} else {
5677 			SiS_SetReg(SISSR, 0x16, 0x05);
5678 			SiS_SetReg(SISSR, 0x16, 0x85);
5679 		}
5680 		sisfb_post_xgi_delay(ivideo, 0x43);
5681 		if(ivideo->chip == XGI_40) {
5682 			SiS_SetReg(SISSR, 0x1b, 0x01);
5683 		} else {
5684 			SiS_SetReg(SISSR, 0x1b, 0x03);
5685 		}
5686 		sisfb_post_xgi_delay(ivideo, 0x22);
5687 		SiS_SetReg(SISSR, 0x18, v1);
5688 		SiS_SetReg(SISSR, 0x19, 0x00);
5689 		if(ivideo->chip == XGI_40) {
5690 			SiS_SetReg(SISSR, 0x16, bios[0x540]);
5691 			SiS_SetReg(SISSR, 0x16, bios[0x541]);
5692 		} else {
5693 			SiS_SetReg(SISSR, 0x16, 0x05);
5694 			SiS_SetReg(SISSR, 0x16, 0x85);
5695 		}
5696 		SiS_SetReg(SISSR, 0x1b, 0x00);
5697 	}
5698 
5699 	regb = 0;	/* ! */
5700 	v1 = 0x03;
5701 	if(ivideo->haveXGIROM) {
5702 		v1 = bios[0x110 + regb];
5703 	}
5704 	SiS_SetReg(SISSR, 0x1b, v1);
5705 
5706 	/* RAM size */
5707 	v1 = 0x00; v2 = 0x00;
5708 	if(ivideo->haveXGIROM) {
5709 		v1 = bios[0x62];
5710 		v2 = bios[0x63];
5711 	}
5712 	regb = 0;	/* ! */
5713 	regd = 1 << regb;
5714 	if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5715 
5716 		SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5717 		SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5718 
5719 	} else {
5720 		int err;
5721 
5722 		/* Set default mode, don't clear screen */
5723 		ivideo->SiS_Pr.SiS_UseOEM = false;
5724 		SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5725 		SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5726 		ivideo->curFSTN = ivideo->curDSTN = 0;
5727 		ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5728 		SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5729 
5730 		SiS_SetReg(SISSR, 0x05, 0x86);
5731 
5732 		/* Disable read-cache */
5733 		SiS_SetRegAND(SISSR, 0x21, 0xdf);
5734 		err = sisfb_post_xgi_ramsize(ivideo);
5735 		/* Enable read-cache */
5736 		SiS_SetRegOR(SISSR, 0x21, 0x20);
5737 
5738 		if (err) {
5739 			dev_err(&pdev->dev,
5740 				"%s: RAM size detection failed: %d\n",
5741 				__func__, err);
5742 			return 0;
5743 		}
5744 	}
5745 
5746 #if 0
5747 	printk(KERN_DEBUG "-----------------\n");
5748 	for(i = 0; i < 0xff; i++) {
5749 		reg = SiS_GetReg(SISCR, i);
5750 		printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5751 	}
5752 	for(i = 0; i < 0x40; i++) {
5753 		reg = SiS_GetReg(SISSR, i);
5754 		printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5755 	}
5756 	printk(KERN_DEBUG "-----------------\n");
5757 #endif
5758 
5759 	/* Sense CRT1 */
5760 	if(ivideo->chip == XGI_20) {
5761 		SiS_SetRegOR(SISCR, 0x32, 0x20);
5762 	} else {
5763 		reg = SiS_GetReg(SISPART4, 0x00);
5764 		if((reg == 1) || (reg == 2)) {
5765 			sisfb_sense_crt1(ivideo);
5766 		} else {
5767 			SiS_SetRegOR(SISCR, 0x32, 0x20);
5768 		}
5769 	}
5770 
5771 	/* Set default mode, don't clear screen */
5772 	ivideo->SiS_Pr.SiS_UseOEM = false;
5773 	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5774 	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5775 	ivideo->curFSTN = ivideo->curDSTN = 0;
5776 	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5777 
5778 	SiS_SetReg(SISSR, 0x05, 0x86);
5779 
5780 	/* Display off */
5781 	SiS_SetRegOR(SISSR, 0x01, 0x20);
5782 
5783 	/* Save mode number in CR34 */
5784 	SiS_SetReg(SISCR, 0x34, 0x2e);
5785 
5786 	/* Let everyone know what the current mode is */
5787 	ivideo->modeprechange = 0x2e;
5788 
5789 	if(ivideo->chip == XGI_40) {
5790 		reg = SiS_GetReg(SISCR, 0xca);
5791 		v1 = SiS_GetReg(SISCR, 0xcc);
5792 		if((reg & 0x10) && (!(v1 & 0x04))) {
5793 			printk(KERN_ERR
5794 				"sisfb: Please connect power to the card.\n");
5795 			return 0;
5796 		}
5797 	}
5798 
5799 	return 1;
5800 }
5801 #endif
5802 
5803 static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5804 {
5805 	struct sisfb_chip_info	*chipinfo = &sisfb_chip_info[ent->driver_data];
5806 	struct sis_video_info	*ivideo = NULL;
5807 	struct fb_info		*sis_fb_info = NULL;
5808 	u16 reg16;
5809 	u8  reg;
5810 	int i, ret;
5811 
5812 	if(sisfb_off)
5813 		return -ENXIO;
5814 
5815 	sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5816 	if(!sis_fb_info)
5817 		return -ENOMEM;
5818 
5819 	ivideo = (struct sis_video_info *)sis_fb_info->par;
5820 	ivideo->memyselfandi = sis_fb_info;
5821 
5822 	ivideo->sisfb_id = SISFB_ID;
5823 
5824 	if(card_list == NULL) {
5825 		ivideo->cardnumber = 0;
5826 	} else {
5827 		struct sis_video_info *countvideo = card_list;
5828 		ivideo->cardnumber = 1;
5829 		while((countvideo = countvideo->next) != NULL)
5830 			ivideo->cardnumber++;
5831 	}
5832 
5833 	strlcpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
5834 
5835 	ivideo->warncount = 0;
5836 	ivideo->chip_id = pdev->device;
5837 	ivideo->chip_vendor = pdev->vendor;
5838 	ivideo->revision_id = pdev->revision;
5839 	ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5840 	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
5841 	ivideo->sisvga_enabled = reg16 & 0x01;
5842 	ivideo->pcibus = pdev->bus->number;
5843 	ivideo->pcislot = PCI_SLOT(pdev->devfn);
5844 	ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5845 	ivideo->subsysvendor = pdev->subsystem_vendor;
5846 	ivideo->subsysdevice = pdev->subsystem_device;
5847 
5848 #ifndef MODULE
5849 	if(sisfb_mode_idx == -1) {
5850 		sisfb_get_vga_mode_from_kernel();
5851 	}
5852 #endif
5853 
5854 	ivideo->chip = chipinfo->chip;
5855 	ivideo->chip_real_id = chipinfo->chip;
5856 	ivideo->sisvga_engine = chipinfo->vgaengine;
5857 	ivideo->hwcursor_size = chipinfo->hwcursor_size;
5858 	ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5859 	ivideo->mni = chipinfo->mni;
5860 
5861 	ivideo->detectedpdc  = 0xff;
5862 	ivideo->detectedpdca = 0xff;
5863 	ivideo->detectedlcda = 0xff;
5864 
5865 	ivideo->sisfb_thismonitor.datavalid = false;
5866 
5867 	ivideo->current_base = 0;
5868 
5869 	ivideo->engineok = 0;
5870 
5871 	ivideo->sisfb_was_boot_device = 0;
5872 
5873 	if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5874 		if(ivideo->sisvga_enabled)
5875 			ivideo->sisfb_was_boot_device = 1;
5876 		else {
5877 			printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5878 				"but marked as boot video device ???\n");
5879 			printk(KERN_DEBUG "sisfb: I will not accept this "
5880 				"as the primary VGA device\n");
5881 		}
5882 	}
5883 
5884 	ivideo->sisfb_parm_mem = sisfb_parm_mem;
5885 	ivideo->sisfb_accel = sisfb_accel;
5886 	ivideo->sisfb_ypan = sisfb_ypan;
5887 	ivideo->sisfb_max = sisfb_max;
5888 	ivideo->sisfb_userom = sisfb_userom;
5889 	ivideo->sisfb_useoem = sisfb_useoem;
5890 	ivideo->sisfb_mode_idx = sisfb_mode_idx;
5891 	ivideo->sisfb_parm_rate = sisfb_parm_rate;
5892 	ivideo->sisfb_crt1off = sisfb_crt1off;
5893 	ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5894 	ivideo->sisfb_crt2type = sisfb_crt2type;
5895 	ivideo->sisfb_crt2flags = sisfb_crt2flags;
5896 	/* pdc(a), scalelcd, special timing, lvdshl handled below */
5897 	ivideo->sisfb_dstn = sisfb_dstn;
5898 	ivideo->sisfb_fstn = sisfb_fstn;
5899 	ivideo->sisfb_tvplug = sisfb_tvplug;
5900 	ivideo->sisfb_tvstd = sisfb_tvstd;
5901 	ivideo->tvxpos = sisfb_tvxposoffset;
5902 	ivideo->tvypos = sisfb_tvyposoffset;
5903 	ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5904 	ivideo->refresh_rate = 0;
5905 	if(ivideo->sisfb_parm_rate != -1) {
5906 		ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5907 	}
5908 
5909 	ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5910 	ivideo->SiS_Pr.CenterScreen = -1;
5911 	ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5912 	ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5913 
5914 	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5915 	ivideo->SiS_Pr.SiS_CHOverScan = -1;
5916 	ivideo->SiS_Pr.SiS_ChSW = false;
5917 	ivideo->SiS_Pr.SiS_UseLCDA = false;
5918 	ivideo->SiS_Pr.HaveEMI = false;
5919 	ivideo->SiS_Pr.HaveEMILCD = false;
5920 	ivideo->SiS_Pr.OverruleEMI = false;
5921 	ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5922 	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5923 	ivideo->SiS_Pr.PDC  = -1;
5924 	ivideo->SiS_Pr.PDCA = -1;
5925 	ivideo->SiS_Pr.DDCPortMixup = false;
5926 #ifdef CONFIG_FB_SIS_315
5927 	if(ivideo->chip >= SIS_330) {
5928 		ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5929 		if(ivideo->chip >= SIS_661) {
5930 			ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5931 		}
5932 	}
5933 #endif
5934 
5935 	memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5936 
5937 	pci_set_drvdata(pdev, ivideo);
5938 
5939 	/* Patch special cases */
5940 	if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5941 		switch(ivideo->nbridge->device) {
5942 #ifdef CONFIG_FB_SIS_300
5943 		case PCI_DEVICE_ID_SI_730:
5944 			ivideo->chip = SIS_730;
5945 			strcpy(ivideo->myid, "SiS 730");
5946 			break;
5947 #endif
5948 #ifdef CONFIG_FB_SIS_315
5949 		case PCI_DEVICE_ID_SI_651:
5950 			/* ivideo->chip is ok */
5951 			strcpy(ivideo->myid, "SiS 651");
5952 			break;
5953 		case PCI_DEVICE_ID_SI_740:
5954 			ivideo->chip = SIS_740;
5955 			strcpy(ivideo->myid, "SiS 740");
5956 			break;
5957 		case PCI_DEVICE_ID_SI_661:
5958 			ivideo->chip = SIS_661;
5959 			strcpy(ivideo->myid, "SiS 661");
5960 			break;
5961 		case PCI_DEVICE_ID_SI_741:
5962 			ivideo->chip = SIS_741;
5963 			strcpy(ivideo->myid, "SiS 741");
5964 			break;
5965 		case PCI_DEVICE_ID_SI_760:
5966 			ivideo->chip = SIS_760;
5967 			strcpy(ivideo->myid, "SiS 760");
5968 			break;
5969 		case PCI_DEVICE_ID_SI_761:
5970 			ivideo->chip = SIS_761;
5971 			strcpy(ivideo->myid, "SiS 761");
5972 			break;
5973 #endif
5974 		default:
5975 			break;
5976 		}
5977 	}
5978 
5979 	ivideo->SiS_Pr.ChipType = ivideo->chip;
5980 
5981 	ivideo->SiS_Pr.ivideo = (void *)ivideo;
5982 
5983 #ifdef CONFIG_FB_SIS_315
5984 	if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
5985 	   (ivideo->SiS_Pr.ChipType == SIS_315)) {
5986 		ivideo->SiS_Pr.ChipType = SIS_315H;
5987 	}
5988 #endif
5989 
5990 	if(!ivideo->sisvga_enabled) {
5991 		if(pci_enable_device(pdev)) {
5992 			pci_dev_put(ivideo->nbridge);
5993 			framebuffer_release(sis_fb_info);
5994 			return -EIO;
5995 		}
5996 	}
5997 
5998 	ivideo->video_base = pci_resource_start(pdev, 0);
5999 	ivideo->video_size = pci_resource_len(pdev, 0);
6000 	ivideo->mmio_base  = pci_resource_start(pdev, 1);
6001 	ivideo->mmio_size  = pci_resource_len(pdev, 1);
6002 	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
6003 	ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
6004 
6005 	SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
6006 
6007 #ifdef CONFIG_FB_SIS_300
6008 	/* Find PCI systems for Chrontel/GPIO communication setup */
6009 	if(ivideo->chip == SIS_630) {
6010 		i = 0;
6011         	do {
6012 			if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
6013 			   mychswtable[i].subsysCard   == ivideo->subsysdevice) {
6014 				ivideo->SiS_Pr.SiS_ChSW = true;
6015 				printk(KERN_DEBUG "sisfb: Identified [%s %s] "
6016 					"requiring Chrontel/GPIO setup\n",
6017 					mychswtable[i].vendorName,
6018 					mychswtable[i].cardName);
6019 				ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
6020 				break;
6021 			}
6022 			i++;
6023 		} while(mychswtable[i].subsysVendor != 0);
6024 	}
6025 #endif
6026 
6027 #ifdef CONFIG_FB_SIS_315
6028 	if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6029 		ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
6030 	}
6031 #endif
6032 
6033 	SiS_SetReg(SISSR, 0x05, 0x86);
6034 
6035 	if( (!ivideo->sisvga_enabled)
6036 #if !defined(__i386__) && !defined(__x86_64__)
6037 			      || (sisfb_resetcard)
6038 #endif
6039 						   ) {
6040 		for(i = 0x30; i <= 0x3f; i++) {
6041 			SiS_SetReg(SISCR, i, 0x00);
6042 		}
6043 	}
6044 
6045 	/* Find out about current video mode */
6046 	ivideo->modeprechange = 0x03;
6047 	reg = SiS_GetReg(SISCR, 0x34);
6048 	if(reg & 0x7f) {
6049 		ivideo->modeprechange = reg & 0x7f;
6050 	} else if(ivideo->sisvga_enabled) {
6051 #if defined(__i386__) || defined(__x86_64__)
6052 		unsigned char __iomem *tt = ioremap(0x400, 0x100);
6053 		if(tt) {
6054 			ivideo->modeprechange = readb(tt + 0x49);
6055 			iounmap(tt);
6056 		}
6057 #endif
6058 	}
6059 
6060 	/* Search and copy ROM image */
6061 	ivideo->bios_abase = NULL;
6062 	ivideo->SiS_Pr.VirtualRomBase = NULL;
6063 	ivideo->SiS_Pr.UseROM = false;
6064 	ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6065 	if(ivideo->sisfb_userom) {
6066 		ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6067 		ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6068 		ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6069 		printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6070 			ivideo->SiS_Pr.UseROM ? "" : "not ");
6071 		if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6072 		   ivideo->SiS_Pr.UseROM = false;
6073 		   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6074 		   if( (ivideo->revision_id == 2) &&
6075 		       (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6076 			ivideo->SiS_Pr.DDCPortMixup = true;
6077 		   }
6078 		}
6079 	} else {
6080 		printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6081 	}
6082 
6083 	/* Find systems for special custom timing */
6084 	if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6085 		sisfb_detect_custom_timing(ivideo);
6086 	}
6087 
6088 #ifdef CONFIG_FB_SIS_315
6089 	if (ivideo->chip == XGI_20) {
6090 		/* Check if our Z7 chip is actually Z9 */
6091 		SiS_SetRegOR(SISCR, 0x4a, 0x40);	/* GPIOG EN */
6092 		reg = SiS_GetReg(SISCR, 0x48);
6093 		if (reg & 0x02) {			/* GPIOG */
6094 			ivideo->chip_real_id = XGI_21;
6095 			dev_info(&pdev->dev, "Z9 detected\n");
6096 		}
6097 	}
6098 #endif
6099 
6100 	/* POST card in case this has not been done by the BIOS */
6101 	if( (!ivideo->sisvga_enabled)
6102 #if !defined(__i386__) && !defined(__x86_64__)
6103 			     || (sisfb_resetcard)
6104 #endif
6105 						 ) {
6106 #ifdef CONFIG_FB_SIS_300
6107 		if(ivideo->sisvga_engine == SIS_300_VGA) {
6108 			if(ivideo->chip == SIS_300) {
6109 				sisfb_post_sis300(pdev);
6110 				ivideo->sisfb_can_post = 1;
6111 			}
6112 		}
6113 #endif
6114 
6115 #ifdef CONFIG_FB_SIS_315
6116 		if(ivideo->sisvga_engine == SIS_315_VGA) {
6117 			int result = 1;
6118 		/*	if((ivideo->chip == SIS_315H)   ||
6119 			   (ivideo->chip == SIS_315)    ||
6120 			   (ivideo->chip == SIS_315PRO) ||
6121 			   (ivideo->chip == SIS_330)) {
6122 				sisfb_post_sis315330(pdev);
6123 			} else */ if(ivideo->chip == XGI_20) {
6124 				result = sisfb_post_xgi(pdev);
6125 				ivideo->sisfb_can_post = 1;
6126 			} else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6127 				result = sisfb_post_xgi(pdev);
6128 				ivideo->sisfb_can_post = 1;
6129 			} else {
6130 				printk(KERN_INFO "sisfb: Card is not "
6131 					"POSTed and sisfb can't do this either.\n");
6132 			}
6133 			if(!result) {
6134 				printk(KERN_ERR "sisfb: Failed to POST card\n");
6135 				ret = -ENODEV;
6136 				goto error_3;
6137 			}
6138 		}
6139 #endif
6140 	}
6141 
6142 	ivideo->sisfb_card_posted = 1;
6143 
6144 	/* Find out about RAM size */
6145 	if(sisfb_get_dram_size(ivideo)) {
6146 		printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6147 		ret = -ENODEV;
6148 		goto error_3;
6149 	}
6150 
6151 
6152 	/* Enable PCI addressing and MMIO */
6153 	if((ivideo->sisfb_mode_idx < 0) ||
6154 	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6155 		/* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
6156 		SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6157 		/* Enable 2D accelerator engine */
6158 		SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6159 	}
6160 
6161 	if(sisfb_pdc != 0xff) {
6162 		if(ivideo->sisvga_engine == SIS_300_VGA)
6163 			sisfb_pdc &= 0x3c;
6164 		else
6165 			sisfb_pdc &= 0x1f;
6166 		ivideo->SiS_Pr.PDC = sisfb_pdc;
6167 	}
6168 #ifdef CONFIG_FB_SIS_315
6169 	if(ivideo->sisvga_engine == SIS_315_VGA) {
6170 		if(sisfb_pdca != 0xff)
6171 			ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6172 	}
6173 #endif
6174 
6175 	if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6176 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6177 				(int)(ivideo->video_size >> 20));
6178 		printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6179 		ret = -ENODEV;
6180 		goto error_3;
6181 	}
6182 
6183 	if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6184 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6185 		ret = -ENODEV;
6186 		goto error_2;
6187 	}
6188 
6189 	ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
6190 	ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6191 	if(!ivideo->video_vbase) {
6192 		printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6193 		ret = -ENODEV;
6194 		goto error_1;
6195 	}
6196 
6197 	ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6198 	if(!ivideo->mmio_vbase) {
6199 		printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6200 		ret = -ENODEV;
6201 error_0:	iounmap(ivideo->video_vbase);
6202 error_1:	release_mem_region(ivideo->video_base, ivideo->video_size);
6203 error_2:	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6204 error_3:	vfree(ivideo->bios_abase);
6205 		pci_dev_put(ivideo->lpcdev);
6206 		pci_dev_put(ivideo->nbridge);
6207 		if(!ivideo->sisvga_enabled)
6208 			pci_disable_device(pdev);
6209 		framebuffer_release(sis_fb_info);
6210 		return ret;
6211 	}
6212 
6213 	printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6214 		ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6215 
6216 	if(ivideo->video_offset) {
6217 		printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6218 			ivideo->video_offset / 1024);
6219 	}
6220 
6221 	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6222 		ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6223 
6224 
6225 	/* Determine the size of the command queue */
6226 	if(ivideo->sisvga_engine == SIS_300_VGA) {
6227 		ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6228 	} else {
6229 		if(ivideo->chip == XGI_20) {
6230 			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6231 		} else {
6232 			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6233 		}
6234 	}
6235 
6236 	/* Engines are no longer initialized here; this is
6237 	 * now done after the first mode-switch (if the
6238 	 * submitted var has its acceleration flags set).
6239 	 */
6240 
6241 	/* Calculate the base of the (unused) hw cursor */
6242 	ivideo->hwcursor_vbase = ivideo->video_vbase
6243 				 + ivideo->video_size
6244 				 - ivideo->cmdQueueSize
6245 				 - ivideo->hwcursor_size;
6246 	ivideo->caps |= HW_CURSOR_CAP;
6247 
6248 	/* Initialize offscreen memory manager */
6249 	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6250 		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6251 	}
6252 
6253 	/* Used for clearing the screen only, therefore respect our mem limit */
6254 	ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6255 	ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6256 
6257 	ivideo->mtrr = -1;
6258 
6259 	ivideo->vbflags = 0;
6260 	ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6261 	ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
6262 	ivideo->defmodeidx    = DEFAULT_MODE;
6263 
6264 	ivideo->newrom = 0;
6265 	if(ivideo->chip < XGI_20) {
6266 		if(ivideo->bios_abase) {
6267 			ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6268 		}
6269 	}
6270 
6271 	if((ivideo->sisfb_mode_idx < 0) ||
6272 	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6273 
6274 		sisfb_sense_crt1(ivideo);
6275 
6276 		sisfb_get_VB_type(ivideo);
6277 
6278 		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6279 			sisfb_detect_VB_connect(ivideo);
6280 		}
6281 
6282 		ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6283 
6284 		/* Decide on which CRT2 device to use */
6285 		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6286 			if(ivideo->sisfb_crt2type != -1) {
6287 				if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6288 				   (ivideo->vbflags & CRT2_LCD)) {
6289 					ivideo->currentvbflags |= CRT2_LCD;
6290 				} else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6291 					ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6292 				}
6293 			} else {
6294 				/* Chrontel 700x TV detection often unreliable, therefore
6295 				 * use a different default order on such machines
6296 				 */
6297 				if((ivideo->sisvga_engine == SIS_300_VGA) &&
6298 				   (ivideo->vbflags2 & VB2_CHRONTEL)) {
6299 					if(ivideo->vbflags & CRT2_LCD)
6300 						ivideo->currentvbflags |= CRT2_LCD;
6301 					else if(ivideo->vbflags & CRT2_TV)
6302 						ivideo->currentvbflags |= CRT2_TV;
6303 					else if(ivideo->vbflags & CRT2_VGA)
6304 						ivideo->currentvbflags |= CRT2_VGA;
6305 				} else {
6306 					if(ivideo->vbflags & CRT2_TV)
6307 						ivideo->currentvbflags |= CRT2_TV;
6308 					else if(ivideo->vbflags & CRT2_LCD)
6309 						ivideo->currentvbflags |= CRT2_LCD;
6310 					else if(ivideo->vbflags & CRT2_VGA)
6311 						ivideo->currentvbflags |= CRT2_VGA;
6312 				}
6313 			}
6314 		}
6315 
6316 		if(ivideo->vbflags & CRT2_LCD) {
6317 			sisfb_detect_lcd_type(ivideo);
6318 		}
6319 
6320 		sisfb_save_pdc_emi(ivideo);
6321 
6322 		if(!ivideo->sisfb_crt1off) {
6323 			sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6324 		} else {
6325 			if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6326 			   (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6327 				sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6328 			}
6329 		}
6330 
6331 		if(ivideo->sisfb_mode_idx >= 0) {
6332 			int bu = ivideo->sisfb_mode_idx;
6333 			ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6334 					ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6335 			if(bu != ivideo->sisfb_mode_idx) {
6336 				printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6337 					sisbios_mode[bu].xres,
6338 					sisbios_mode[bu].yres,
6339 					sisbios_mode[bu].bpp);
6340 			}
6341 		}
6342 
6343 		if(ivideo->sisfb_mode_idx < 0) {
6344 			switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6345 			   case CRT2_LCD:
6346 				ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6347 				break;
6348 			   case CRT2_TV:
6349 				ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6350 				break;
6351 			   default:
6352 				ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6353 				break;
6354 			}
6355 		}
6356 
6357 		ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6358 
6359 		if(ivideo->refresh_rate != 0) {
6360 			sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6361 						ivideo->sisfb_mode_idx);
6362 		}
6363 
6364 		if(ivideo->rate_idx == 0) {
6365 			ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6366 			ivideo->refresh_rate = 60;
6367 		}
6368 
6369 		if(ivideo->sisfb_thismonitor.datavalid) {
6370 			if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6371 						ivideo->sisfb_mode_idx,
6372 						ivideo->rate_idx,
6373 						ivideo->refresh_rate)) {
6374 				printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6375 							"exceeds monitor specs!\n");
6376 			}
6377 		}
6378 
6379 		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6380 		ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6381 		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6382 
6383 		sisfb_set_vparms(ivideo);
6384 
6385 		printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6386 			ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6387 			ivideo->refresh_rate);
6388 
6389 		/* Set up the default var according to chosen default display mode */
6390 		ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6391 		ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6392 		ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6393 
6394 		sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6395 
6396 		ivideo->default_var.pixclock = (u32) (1000000000 /
6397 			sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6398 
6399 		if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6400 						ivideo->rate_idx, &ivideo->default_var)) {
6401 			if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6402 				ivideo->default_var.pixclock <<= 1;
6403 			}
6404 		}
6405 
6406 		if(ivideo->sisfb_ypan) {
6407 			/* Maximize regardless of sisfb_max at startup */
6408 			ivideo->default_var.yres_virtual =
6409 				sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6410 			if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6411 				ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6412 			}
6413 		}
6414 
6415 		sisfb_calc_pitch(ivideo, &ivideo->default_var);
6416 
6417 		ivideo->accel = 0;
6418 		if(ivideo->sisfb_accel) {
6419 			ivideo->accel = -1;
6420 #ifdef STUPID_ACCELF_TEXT_SHIT
6421 			ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6422 #endif
6423 		}
6424 		sisfb_initaccel(ivideo);
6425 
6426 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6427 		sis_fb_info->flags = FBINFO_DEFAULT 		|
6428 				     FBINFO_HWACCEL_YPAN 	|
6429 				     FBINFO_HWACCEL_XPAN 	|
6430 				     FBINFO_HWACCEL_COPYAREA 	|
6431 				     FBINFO_HWACCEL_FILLRECT 	|
6432 				     ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6433 #else
6434 		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6435 #endif
6436 		sis_fb_info->var = ivideo->default_var;
6437 		sis_fb_info->fix = ivideo->sisfb_fix;
6438 		sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6439 		sis_fb_info->fbops = &sisfb_ops;
6440 		sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6441 
6442 		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6443 
6444 		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6445 
6446 #ifdef CONFIG_MTRR
6447 		ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
6448 					MTRR_TYPE_WRCOMB, 1);
6449 		if(ivideo->mtrr < 0) {
6450 			printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
6451 		}
6452 #endif
6453 
6454 		if(register_framebuffer(sis_fb_info) < 0) {
6455 			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6456 			ret = -EINVAL;
6457 			iounmap(ivideo->mmio_vbase);
6458 			goto error_0;
6459 		}
6460 
6461 		ivideo->registered = 1;
6462 
6463 		/* Enlist us */
6464 		ivideo->next = card_list;
6465 		card_list = ivideo;
6466 
6467 		printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6468 			ivideo->sisfb_accel ? "enabled" : "disabled",
6469 			ivideo->sisfb_ypan  ?
6470 				(ivideo->sisfb_max ? "enabled (auto-max)" :
6471 						"enabled (no auto-max)") :
6472 									"disabled");
6473 
6474 
6475 		fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
6476 			ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6477 
6478 		printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6479 
6480 	}	/* if mode = "none" */
6481 
6482 	return 0;
6483 }
6484 
6485 /*****************************************************/
6486 /*                PCI DEVICE HANDLING                */
6487 /*****************************************************/
6488 
6489 static void sisfb_remove(struct pci_dev *pdev)
6490 {
6491 	struct sis_video_info	*ivideo = pci_get_drvdata(pdev);
6492 	struct fb_info		*sis_fb_info = ivideo->memyselfandi;
6493 	int			registered = ivideo->registered;
6494 	int			modechanged = ivideo->modechanged;
6495 
6496 	/* Unmap */
6497 	iounmap(ivideo->mmio_vbase);
6498 	iounmap(ivideo->video_vbase);
6499 
6500 	/* Release mem regions */
6501 	release_mem_region(ivideo->video_base, ivideo->video_size);
6502 	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6503 
6504 	vfree(ivideo->bios_abase);
6505 
6506 	pci_dev_put(ivideo->lpcdev);
6507 
6508 	pci_dev_put(ivideo->nbridge);
6509 
6510 #ifdef CONFIG_MTRR
6511 	/* Release MTRR region */
6512 	if(ivideo->mtrr >= 0)
6513 		mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
6514 #endif
6515 
6516 	/* If device was disabled when starting, disable
6517 	 * it when quitting.
6518 	 */
6519 	if(!ivideo->sisvga_enabled)
6520 		pci_disable_device(pdev);
6521 
6522 	/* Unregister the framebuffer */
6523 	if(ivideo->registered) {
6524 		unregister_framebuffer(sis_fb_info);
6525 		framebuffer_release(sis_fb_info);
6526 	}
6527 
6528 	/* OK, our ivideo is gone for good from here. */
6529 
6530 	/* TODO: Restore the initial mode
6531 	 * This sounds easy but is as good as impossible
6532 	 * on many machines with SiS chip and video bridge
6533 	 * since text modes are always set up differently
6534 	 * from machine to machine. Depends on the type
6535 	 * of integration between chipset and bridge.
6536 	 */
6537 	if(registered && modechanged)
6538 		printk(KERN_INFO
6539 			"sisfb: Restoring of text mode not supported yet\n");
6540 };
6541 
6542 static struct pci_driver sisfb_driver = {
6543 	.name		= "sisfb",
6544 	.id_table 	= sisfb_pci_table,
6545 	.probe		= sisfb_probe,
6546 	.remove 	= sisfb_remove,
6547 };
6548 
6549 static int __init sisfb_init(void)
6550 {
6551 #ifndef MODULE
6552 	char *options = NULL;
6553 
6554 	if(fb_get_options("sisfb", &options))
6555 		return -ENODEV;
6556 
6557 	sisfb_setup(options);
6558 #endif
6559 	return pci_register_driver(&sisfb_driver);
6560 }
6561 
6562 #ifndef MODULE
6563 module_init(sisfb_init);
6564 #endif
6565 
6566 /*****************************************************/
6567 /*                      MODULE                       */
6568 /*****************************************************/
6569 
6570 #ifdef MODULE
6571 
6572 static char		*mode = NULL;
6573 static int		vesa = -1;
6574 static unsigned int	rate = 0;
6575 static unsigned int	crt1off = 1;
6576 static unsigned int	mem = 0;
6577 static char		*forcecrt2type = NULL;
6578 static int		forcecrt1 = -1;
6579 static int		pdc = -1;
6580 static int		pdc1 = -1;
6581 static int		noaccel = -1;
6582 static int		noypan  = -1;
6583 static int		nomax = -1;
6584 static int		userom = -1;
6585 static int		useoem = -1;
6586 static char		*tvstandard = NULL;
6587 static int		nocrt2rate = 0;
6588 static int		scalelcd = -1;
6589 static char		*specialtiming = NULL;
6590 static int		lvdshl = -1;
6591 static int		tvxposoffset = 0, tvyposoffset = 0;
6592 #if !defined(__i386__) && !defined(__x86_64__)
6593 static int		resetcard = 0;
6594 static int		videoram = 0;
6595 #endif
6596 
6597 static int __init sisfb_init_module(void)
6598 {
6599 	sisfb_setdefaultparms();
6600 
6601 	if(rate)
6602 		sisfb_parm_rate = rate;
6603 
6604 	if((scalelcd == 0) || (scalelcd == 1))
6605 		sisfb_scalelcd = scalelcd ^ 1;
6606 
6607 	/* Need to check crt2 type first for fstn/dstn */
6608 
6609 	if(forcecrt2type)
6610 		sisfb_search_crt2type(forcecrt2type);
6611 
6612 	if(tvstandard)
6613 		sisfb_search_tvstd(tvstandard);
6614 
6615 	if(mode)
6616 		sisfb_search_mode(mode, false);
6617 	else if(vesa != -1)
6618 		sisfb_search_vesamode(vesa, false);
6619 
6620 	sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6621 
6622 	sisfb_forcecrt1 = forcecrt1;
6623 	if(forcecrt1 == 1)
6624 		sisfb_crt1off = 0;
6625 	else if(forcecrt1 == 0)
6626 		sisfb_crt1off = 1;
6627 
6628 	if(noaccel == 1)
6629 		sisfb_accel = 0;
6630 	else if(noaccel == 0)
6631 		sisfb_accel = 1;
6632 
6633 	if(noypan == 1)
6634 		sisfb_ypan = 0;
6635 	else if(noypan == 0)
6636 		sisfb_ypan = 1;
6637 
6638 	if(nomax == 1)
6639 		sisfb_max = 0;
6640 	else if(nomax == 0)
6641 		sisfb_max = 1;
6642 
6643 	if(mem)
6644 		sisfb_parm_mem = mem;
6645 
6646 	if(userom != -1)
6647 		sisfb_userom = userom;
6648 
6649 	if(useoem != -1)
6650 		sisfb_useoem = useoem;
6651 
6652         if(pdc != -1)
6653 		sisfb_pdc  = (pdc  & 0x7f);
6654 
6655 	if(pdc1 != -1)
6656 		sisfb_pdca = (pdc1 & 0x1f);
6657 
6658 	sisfb_nocrt2rate = nocrt2rate;
6659 
6660 	if(specialtiming)
6661 		sisfb_search_specialtiming(specialtiming);
6662 
6663 	if((lvdshl >= 0) && (lvdshl <= 3))
6664 		sisfb_lvdshl = lvdshl;
6665 
6666 	sisfb_tvxposoffset = tvxposoffset;
6667 	sisfb_tvyposoffset = tvyposoffset;
6668 
6669 #if !defined(__i386__) && !defined(__x86_64__)
6670 	sisfb_resetcard = (resetcard) ? 1 : 0;
6671 	if(videoram)
6672 		sisfb_videoram = videoram;
6673 #endif
6674 
6675 	return sisfb_init();
6676 }
6677 
6678 static void __exit sisfb_remove_module(void)
6679 {
6680 	pci_unregister_driver(&sisfb_driver);
6681 	printk(KERN_DEBUG "sisfb: Module unloaded\n");
6682 }
6683 
6684 module_init(sisfb_init_module);
6685 module_exit(sisfb_remove_module);
6686 
6687 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6688 MODULE_LICENSE("GPL");
6689 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6690 
6691 module_param(mem, int, 0);
6692 module_param(noaccel, int, 0);
6693 module_param(noypan, int, 0);
6694 module_param(nomax, int, 0);
6695 module_param(userom, int, 0);
6696 module_param(useoem, int, 0);
6697 module_param(mode, charp, 0);
6698 module_param(vesa, int, 0);
6699 module_param(rate, int, 0);
6700 module_param(forcecrt1, int, 0);
6701 module_param(forcecrt2type, charp, 0);
6702 module_param(scalelcd, int, 0);
6703 module_param(pdc, int, 0);
6704 module_param(pdc1, int, 0);
6705 module_param(specialtiming, charp, 0);
6706 module_param(lvdshl, int, 0);
6707 module_param(tvstandard, charp, 0);
6708 module_param(tvxposoffset, int, 0);
6709 module_param(tvyposoffset, int, 0);
6710 module_param(nocrt2rate, int, 0);
6711 #if !defined(__i386__) && !defined(__x86_64__)
6712 module_param(resetcard, int, 0);
6713 module_param(videoram, int, 0);
6714 #endif
6715 
6716 MODULE_PARM_DESC(mem,
6717 	"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6718 	  "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6719 	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6720 	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6721 	  "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6722 	  "The value is to be specified without 'KB'.\n");
6723 
6724 MODULE_PARM_DESC(noaccel,
6725 	"\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6726 	  "(default: 0)\n");
6727 
6728 MODULE_PARM_DESC(noypan,
6729 	"\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6730 	  "will be performed by redrawing the screen. (default: 0)\n");
6731 
6732 MODULE_PARM_DESC(nomax,
6733 	"\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6734 	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
6735 	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
6736 	  "enable the user to positively specify a virtual Y size of the screen using\n"
6737 	  "fbset. (default: 0)\n");
6738 
6739 MODULE_PARM_DESC(mode,
6740 	"\nSelects the desired default display mode in the format XxYxDepth,\n"
6741 	 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6742 	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6743 	 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6744 
6745 MODULE_PARM_DESC(vesa,
6746 	"\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6747 	 "0x117 (default: 0x0103)\n");
6748 
6749 MODULE_PARM_DESC(rate,
6750 	"\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6751 	  "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6752 	  "will be ignored (default: 60)\n");
6753 
6754 MODULE_PARM_DESC(forcecrt1,
6755 	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6756 	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6757 	  "0=CRT1 OFF) (default: [autodetected])\n");
6758 
6759 MODULE_PARM_DESC(forcecrt2type,
6760 	"\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6761 	  "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6762 	  "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6763 	  "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6764 	  "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6765 	  "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6766 	  "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6767 	  "depends on the very hardware in use. (default: [autodetected])\n");
6768 
6769 MODULE_PARM_DESC(scalelcd,
6770 	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6771 	  "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6772 	  "show black bars around the image, TMDS panels will probably do the scaling\n"
6773 	  "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6774 
6775 MODULE_PARM_DESC(pdc,
6776 	"\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6777 	  "should detect this correctly in most cases; however, sometimes this is not\n"
6778 	  "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6779 	  "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6780 	  "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6781 	  "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6782 
6783 #ifdef CONFIG_FB_SIS_315
6784 MODULE_PARM_DESC(pdc1,
6785 	"\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6786 	  "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6787 	  "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6788 	  "implemented yet.\n");
6789 #endif
6790 
6791 MODULE_PARM_DESC(specialtiming,
6792 	"\nPlease refer to documentation for more information on this option.\n");
6793 
6794 MODULE_PARM_DESC(lvdshl,
6795 	"\nPlease refer to documentation for more information on this option.\n");
6796 
6797 MODULE_PARM_DESC(tvstandard,
6798 	"\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6799 	  "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6800 
6801 MODULE_PARM_DESC(tvxposoffset,
6802 	"\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6803 	  "Default: 0\n");
6804 
6805 MODULE_PARM_DESC(tvyposoffset,
6806 	"\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6807 	  "Default: 0\n");
6808 
6809 MODULE_PARM_DESC(nocrt2rate,
6810 	"\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6811 	  "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6812 
6813 #if !defined(__i386__) && !defined(__x86_64__)
6814 #ifdef CONFIG_FB_SIS_300
6815 MODULE_PARM_DESC(resetcard,
6816 	"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6817 	  "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6818 	  "currently). Default: 0\n");
6819 
6820 MODULE_PARM_DESC(videoram,
6821 	"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6822 	  "some non-x86 architectures where the memory auto detection fails. Only\n"
6823 	  "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6824 #endif
6825 #endif
6826 
6827 #endif 	   /*  /MODULE  */
6828 
6829 /* _GPL only for new symbols. */
6830 EXPORT_SYMBOL(sis_malloc);
6831 EXPORT_SYMBOL(sis_free);
6832 EXPORT_SYMBOL_GPL(sis_malloc_new);
6833 EXPORT_SYMBOL_GPL(sis_free_new);
6834 
6835 
6836 
6837