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