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