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