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