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