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