File Index
Files and directories
Sign in
FILE

sis_main.c

File preview with syntax highlighting.

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