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