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