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