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