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