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