cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sis_main.c (189040B)


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