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