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