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