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