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