brintos

brintos / linux-shallow public Read only

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