Linux Audio

Check our new training course

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