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