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