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