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