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