18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * SiS 300/540/630[S]/730[S],
48c2ecf20Sopenharmony_ci * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
58c2ecf20Sopenharmony_ci * XGI V3XT/V5/V8, Z7
68c2ecf20Sopenharmony_ci * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Author:	Thomas Winischhofer <thomas@winischhofer.net>
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * Author of (practically wiped) code base:
138c2ecf20Sopenharmony_ci *		SiS (www.sis.com)
148c2ecf20Sopenharmony_ci *		Copyright (C) 1999 Silicon Integrated Systems, Inc.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * See http://www.winischhofer.net/ for more information and updates
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
198c2ecf20Sopenharmony_ci * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <linux/module.h>
238c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
248c2ecf20Sopenharmony_ci#include <linux/kernel.h>
258c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
268c2ecf20Sopenharmony_ci#include <linux/errno.h>
278c2ecf20Sopenharmony_ci#include <linux/string.h>
288c2ecf20Sopenharmony_ci#include <linux/mm.h>
298c2ecf20Sopenharmony_ci#include <linux/screen_info.h>
308c2ecf20Sopenharmony_ci#include <linux/slab.h>
318c2ecf20Sopenharmony_ci#include <linux/fb.h>
328c2ecf20Sopenharmony_ci#include <linux/selection.h>
338c2ecf20Sopenharmony_ci#include <linux/ioport.h>
348c2ecf20Sopenharmony_ci#include <linux/init.h>
358c2ecf20Sopenharmony_ci#include <linux/pci.h>
368c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
378c2ecf20Sopenharmony_ci#include <linux/capability.h>
388c2ecf20Sopenharmony_ci#include <linux/fs.h>
398c2ecf20Sopenharmony_ci#include <linux/types.h>
408c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
418c2ecf20Sopenharmony_ci#include <asm/io.h>
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#include "sis.h"
448c2ecf20Sopenharmony_ci#include "sis_main.h"
458c2ecf20Sopenharmony_ci#include "init301.h"
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
488c2ecf20Sopenharmony_ci#warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
498c2ecf20Sopenharmony_ci#warning sisfb will not work!
508c2ecf20Sopenharmony_ci#endif
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* ---------------------- Prototypes ------------------------- */
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* Interface used by the world */
558c2ecf20Sopenharmony_ci#ifndef MODULE
568c2ecf20Sopenharmony_cistatic int sisfb_setup(char *options);
578c2ecf20Sopenharmony_ci#endif
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci/* Interface to the low level console driver */
608c2ecf20Sopenharmony_cistatic int sisfb_init(void);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/* fbdev routines */
638c2ecf20Sopenharmony_cistatic int	sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
648c2ecf20Sopenharmony_ci				struct fb_info *info);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic int	sisfb_ioctl(struct fb_info *info, unsigned int cmd,
678c2ecf20Sopenharmony_ci			    unsigned long arg);
688c2ecf20Sopenharmony_cistatic int	sisfb_set_par(struct fb_info *info);
698c2ecf20Sopenharmony_cistatic int	sisfb_blank(int blank,
708c2ecf20Sopenharmony_ci				struct fb_info *info);
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic void sisfb_handle_command(struct sis_video_info *ivideo,
738c2ecf20Sopenharmony_ci				 struct sisfb_cmd *sisfb_command);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic void	sisfb_search_mode(char *name, bool quiet);
768c2ecf20Sopenharmony_cistatic int	sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
778c2ecf20Sopenharmony_cistatic u8	sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
788c2ecf20Sopenharmony_ci				int index);
798c2ecf20Sopenharmony_cistatic int	sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
808c2ecf20Sopenharmony_ci				unsigned blue, unsigned transp,
818c2ecf20Sopenharmony_ci				struct fb_info *fb_info);
828c2ecf20Sopenharmony_cistatic int	sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
838c2ecf20Sopenharmony_ci				struct fb_info *info);
848c2ecf20Sopenharmony_cistatic void	sisfb_pre_setmode(struct sis_video_info *ivideo);
858c2ecf20Sopenharmony_cistatic void	sisfb_post_setmode(struct sis_video_info *ivideo);
868c2ecf20Sopenharmony_cistatic bool	sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
878c2ecf20Sopenharmony_cistatic bool	sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
888c2ecf20Sopenharmony_cistatic bool	sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
898c2ecf20Sopenharmony_cistatic bool	sisfb_bridgeisslave(struct sis_video_info *ivideo);
908c2ecf20Sopenharmony_cistatic void	sisfb_detect_VB_connect(struct sis_video_info *ivideo);
918c2ecf20Sopenharmony_cistatic void	sisfb_get_VB_type(struct sis_video_info *ivideo);
928c2ecf20Sopenharmony_cistatic void	sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
938c2ecf20Sopenharmony_cistatic void	sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/* Internal heap routines */
968c2ecf20Sopenharmony_cistatic int		sisfb_heap_init(struct sis_video_info *ivideo);
978c2ecf20Sopenharmony_cistatic struct SIS_OH *	sisfb_poh_new_node(struct SIS_HEAP *memheap);
988c2ecf20Sopenharmony_cistatic struct SIS_OH *	sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
998c2ecf20Sopenharmony_cistatic void		sisfb_delete_node(struct SIS_OH *poh);
1008c2ecf20Sopenharmony_cistatic void		sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
1018c2ecf20Sopenharmony_cistatic struct SIS_OH *	sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
1028c2ecf20Sopenharmony_cistatic void		sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/* ------------------ Internal helper routines ----------------- */
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic void __init
1088c2ecf20Sopenharmony_cisisfb_setdefaultparms(void)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	sisfb_off		= 0;
1118c2ecf20Sopenharmony_ci	sisfb_parm_mem		= 0;
1128c2ecf20Sopenharmony_ci	sisfb_accel		= -1;
1138c2ecf20Sopenharmony_ci	sisfb_ypan		= -1;
1148c2ecf20Sopenharmony_ci	sisfb_max		= -1;
1158c2ecf20Sopenharmony_ci	sisfb_userom		= -1;
1168c2ecf20Sopenharmony_ci	sisfb_useoem		= -1;
1178c2ecf20Sopenharmony_ci	sisfb_mode_idx		= -1;
1188c2ecf20Sopenharmony_ci	sisfb_parm_rate		= -1;
1198c2ecf20Sopenharmony_ci	sisfb_crt1off		= 0;
1208c2ecf20Sopenharmony_ci	sisfb_forcecrt1		= -1;
1218c2ecf20Sopenharmony_ci	sisfb_crt2type		= -1;
1228c2ecf20Sopenharmony_ci	sisfb_crt2flags		= 0;
1238c2ecf20Sopenharmony_ci	sisfb_pdc		= 0xff;
1248c2ecf20Sopenharmony_ci	sisfb_pdca		= 0xff;
1258c2ecf20Sopenharmony_ci	sisfb_scalelcd		= -1;
1268c2ecf20Sopenharmony_ci	sisfb_specialtiming 	= CUT_NONE;
1278c2ecf20Sopenharmony_ci	sisfb_lvdshl		= -1;
1288c2ecf20Sopenharmony_ci	sisfb_dstn		= 0;
1298c2ecf20Sopenharmony_ci	sisfb_fstn		= 0;
1308c2ecf20Sopenharmony_ci	sisfb_tvplug		= -1;
1318c2ecf20Sopenharmony_ci	sisfb_tvstd		= -1;
1328c2ecf20Sopenharmony_ci	sisfb_tvxposoffset	= 0;
1338c2ecf20Sopenharmony_ci	sisfb_tvyposoffset	= 0;
1348c2ecf20Sopenharmony_ci	sisfb_nocrt2rate	= 0;
1358c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
1368c2ecf20Sopenharmony_ci	sisfb_resetcard		= 0;
1378c2ecf20Sopenharmony_ci	sisfb_videoram		= 0;
1388c2ecf20Sopenharmony_ci#endif
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci/* ------------- Parameter parsing -------------- */
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	int i = 0, j = 0;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	/* We don't know the hardware specs yet and there is no ivideo */
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	if(vesamode == 0) {
1508c2ecf20Sopenharmony_ci		if(!quiet)
1518c2ecf20Sopenharmony_ci			printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci		sisfb_mode_idx = DEFAULT_MODE;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci		return;
1568c2ecf20Sopenharmony_ci	}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	while(sisbios_mode[i++].mode_no[0] != 0) {
1618c2ecf20Sopenharmony_ci		if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
1628c2ecf20Sopenharmony_ci		    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
1638c2ecf20Sopenharmony_ci			if(sisfb_fstn) {
1648c2ecf20Sopenharmony_ci				if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
1658c2ecf20Sopenharmony_ci				   sisbios_mode[i-1].mode_no[1] == 0x56 ||
1668c2ecf20Sopenharmony_ci				   sisbios_mode[i-1].mode_no[1] == 0x53)
1678c2ecf20Sopenharmony_ci					continue;
1688c2ecf20Sopenharmony_ci			} else {
1698c2ecf20Sopenharmony_ci				if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
1708c2ecf20Sopenharmony_ci				   sisbios_mode[i-1].mode_no[1] == 0x5b)
1718c2ecf20Sopenharmony_ci					continue;
1728c2ecf20Sopenharmony_ci			}
1738c2ecf20Sopenharmony_ci			sisfb_mode_idx = i - 1;
1748c2ecf20Sopenharmony_ci			j = 1;
1758c2ecf20Sopenharmony_ci			break;
1768c2ecf20Sopenharmony_ci		}
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci	if((!j) && !quiet)
1798c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic void sisfb_search_mode(char *name, bool quiet)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
1858c2ecf20Sopenharmony_ci	int i = 0;
1868c2ecf20Sopenharmony_ci	char strbuf[16], strbuf1[20];
1878c2ecf20Sopenharmony_ci	char *nameptr = name;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	/* We don't know the hardware specs yet and there is no ivideo */
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	if(name == NULL) {
1928c2ecf20Sopenharmony_ci		if(!quiet)
1938c2ecf20Sopenharmony_ci			printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci		sisfb_mode_idx = DEFAULT_MODE;
1968c2ecf20Sopenharmony_ci		return;
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
2008c2ecf20Sopenharmony_ci		if(!quiet)
2018c2ecf20Sopenharmony_ci			printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci		sisfb_mode_idx = DEFAULT_MODE;
2048c2ecf20Sopenharmony_ci		return;
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	if(strlen(name) <= 19) {
2088c2ecf20Sopenharmony_ci		strcpy(strbuf1, name);
2098c2ecf20Sopenharmony_ci		for(i = 0; i < strlen(strbuf1); i++) {
2108c2ecf20Sopenharmony_ci			if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
2118c2ecf20Sopenharmony_ci		}
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci		/* This does some fuzzy mode naming detection */
2148c2ecf20Sopenharmony_ci		if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
2158c2ecf20Sopenharmony_ci			if((rate <= 32) || (depth > 32)) {
2168c2ecf20Sopenharmony_ci				j = rate; rate = depth; depth = j;
2178c2ecf20Sopenharmony_ci			}
2188c2ecf20Sopenharmony_ci			sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
2198c2ecf20Sopenharmony_ci			nameptr = strbuf;
2208c2ecf20Sopenharmony_ci			sisfb_parm_rate = rate;
2218c2ecf20Sopenharmony_ci		} else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
2228c2ecf20Sopenharmony_ci			sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
2238c2ecf20Sopenharmony_ci			nameptr = strbuf;
2248c2ecf20Sopenharmony_ci		} else {
2258c2ecf20Sopenharmony_ci			xres = 0;
2268c2ecf20Sopenharmony_ci			if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
2278c2ecf20Sopenharmony_ci				sprintf(strbuf, "%ux%ux8", xres, yres);
2288c2ecf20Sopenharmony_ci				nameptr = strbuf;
2298c2ecf20Sopenharmony_ci			} else {
2308c2ecf20Sopenharmony_ci				sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
2318c2ecf20Sopenharmony_ci				return;
2328c2ecf20Sopenharmony_ci			}
2338c2ecf20Sopenharmony_ci		}
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	i = 0; j = 0;
2378c2ecf20Sopenharmony_ci	while(sisbios_mode[i].mode_no[0] != 0) {
2388c2ecf20Sopenharmony_ci		if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
2398c2ecf20Sopenharmony_ci			if(sisfb_fstn) {
2408c2ecf20Sopenharmony_ci				if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
2418c2ecf20Sopenharmony_ci				   sisbios_mode[i-1].mode_no[1] == 0x56 ||
2428c2ecf20Sopenharmony_ci				   sisbios_mode[i-1].mode_no[1] == 0x53)
2438c2ecf20Sopenharmony_ci					continue;
2448c2ecf20Sopenharmony_ci			} else {
2458c2ecf20Sopenharmony_ci				if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
2468c2ecf20Sopenharmony_ci				   sisbios_mode[i-1].mode_no[1] == 0x5b)
2478c2ecf20Sopenharmony_ci					continue;
2488c2ecf20Sopenharmony_ci			}
2498c2ecf20Sopenharmony_ci			sisfb_mode_idx = i - 1;
2508c2ecf20Sopenharmony_ci			j = 1;
2518c2ecf20Sopenharmony_ci			break;
2528c2ecf20Sopenharmony_ci		}
2538c2ecf20Sopenharmony_ci	}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	if((!j) && !quiet)
2568c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
2578c2ecf20Sopenharmony_ci}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci#ifndef MODULE
2608c2ecf20Sopenharmony_cistatic void sisfb_get_vga_mode_from_kernel(void)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci#ifdef CONFIG_X86
2638c2ecf20Sopenharmony_ci	char mymode[32];
2648c2ecf20Sopenharmony_ci	int  mydepth = screen_info.lfb_depth;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
2698c2ecf20Sopenharmony_ci	    (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
2708c2ecf20Sopenharmony_ci	    (mydepth >= 8) && (mydepth <= 32) ) {
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci		if(mydepth == 24) mydepth = 32;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci		sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
2758c2ecf20Sopenharmony_ci					screen_info.lfb_height,
2768c2ecf20Sopenharmony_ci					mydepth);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci		printk(KERN_DEBUG
2798c2ecf20Sopenharmony_ci			"sisfb: Using vga mode %s pre-set by kernel as default\n",
2808c2ecf20Sopenharmony_ci			mymode);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci		sisfb_search_mode(mymode, true);
2838c2ecf20Sopenharmony_ci	}
2848c2ecf20Sopenharmony_ci#endif
2858c2ecf20Sopenharmony_ci	return;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci#endif
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_cistatic void __init
2908c2ecf20Sopenharmony_cisisfb_search_crt2type(const char *name)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	int i = 0;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/* We don't know the hardware specs yet and there is no ivideo */
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	if(name == NULL) return;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	while(sis_crt2type[i].type_no != -1) {
2998c2ecf20Sopenharmony_ci		if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
3008c2ecf20Sopenharmony_ci			sisfb_crt2type = sis_crt2type[i].type_no;
3018c2ecf20Sopenharmony_ci			sisfb_tvplug = sis_crt2type[i].tvplug_no;
3028c2ecf20Sopenharmony_ci			sisfb_crt2flags = sis_crt2type[i].flags;
3038c2ecf20Sopenharmony_ci			break;
3048c2ecf20Sopenharmony_ci		}
3058c2ecf20Sopenharmony_ci		i++;
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
3098c2ecf20Sopenharmony_ci	sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	if(sisfb_crt2type < 0)
3128c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic void __init
3168c2ecf20Sopenharmony_cisisfb_search_tvstd(const char *name)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci	int i = 0;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	/* We don't know the hardware specs yet and there is no ivideo */
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	if(name == NULL)
3238c2ecf20Sopenharmony_ci		return;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	while(sis_tvtype[i].type_no != -1) {
3268c2ecf20Sopenharmony_ci		if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
3278c2ecf20Sopenharmony_ci			sisfb_tvstd = sis_tvtype[i].type_no;
3288c2ecf20Sopenharmony_ci			break;
3298c2ecf20Sopenharmony_ci		}
3308c2ecf20Sopenharmony_ci		i++;
3318c2ecf20Sopenharmony_ci	}
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_cistatic void __init
3358c2ecf20Sopenharmony_cisisfb_search_specialtiming(const char *name)
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	int i = 0;
3388c2ecf20Sopenharmony_ci	bool found = false;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	/* We don't know the hardware specs yet and there is no ivideo */
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if(name == NULL)
3438c2ecf20Sopenharmony_ci		return;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	if(!strncasecmp(name, "none", 4)) {
3468c2ecf20Sopenharmony_ci		sisfb_specialtiming = CUT_FORCENONE;
3478c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
3488c2ecf20Sopenharmony_ci	} else {
3498c2ecf20Sopenharmony_ci		while(mycustomttable[i].chipID != 0) {
3508c2ecf20Sopenharmony_ci			if(!strncasecmp(name,mycustomttable[i].optionName,
3518c2ecf20Sopenharmony_ci			   strlen(mycustomttable[i].optionName))) {
3528c2ecf20Sopenharmony_ci				sisfb_specialtiming = mycustomttable[i].SpecialID;
3538c2ecf20Sopenharmony_ci				found = true;
3548c2ecf20Sopenharmony_ci				printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
3558c2ecf20Sopenharmony_ci					mycustomttable[i].vendorName,
3568c2ecf20Sopenharmony_ci					mycustomttable[i].cardName,
3578c2ecf20Sopenharmony_ci					mycustomttable[i].optionName);
3588c2ecf20Sopenharmony_ci				break;
3598c2ecf20Sopenharmony_ci			}
3608c2ecf20Sopenharmony_ci			i++;
3618c2ecf20Sopenharmony_ci		}
3628c2ecf20Sopenharmony_ci		if(!found) {
3638c2ecf20Sopenharmony_ci			printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
3648c2ecf20Sopenharmony_ci			printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
3658c2ecf20Sopenharmony_ci			i = 0;
3668c2ecf20Sopenharmony_ci			while(mycustomttable[i].chipID != 0) {
3678c2ecf20Sopenharmony_ci				printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
3688c2ecf20Sopenharmony_ci					mycustomttable[i].optionName,
3698c2ecf20Sopenharmony_ci					mycustomttable[i].vendorName,
3708c2ecf20Sopenharmony_ci					mycustomttable[i].cardName);
3718c2ecf20Sopenharmony_ci				i++;
3728c2ecf20Sopenharmony_ci			}
3738c2ecf20Sopenharmony_ci		}
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci/* ----------- Various detection routines ----------- */
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	unsigned char *biosver = NULL;
3828c2ecf20Sopenharmony_ci	unsigned char *biosdate = NULL;
3838c2ecf20Sopenharmony_ci	bool footprint;
3848c2ecf20Sopenharmony_ci	u32 chksum = 0;
3858c2ecf20Sopenharmony_ci	int i, j;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	if(ivideo->SiS_Pr.UseROM) {
3888c2ecf20Sopenharmony_ci		biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
3898c2ecf20Sopenharmony_ci		biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
3908c2ecf20Sopenharmony_ci		for(i = 0; i < 32768; i++)
3918c2ecf20Sopenharmony_ci			chksum += ivideo->SiS_Pr.VirtualRomBase[i];
3928c2ecf20Sopenharmony_ci	}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	i = 0;
3958c2ecf20Sopenharmony_ci	do {
3968c2ecf20Sopenharmony_ci		if( (mycustomttable[i].chipID == ivideo->chip)			&&
3978c2ecf20Sopenharmony_ci		    ((!strlen(mycustomttable[i].biosversion)) ||
3988c2ecf20Sopenharmony_ci		     (ivideo->SiS_Pr.UseROM &&
3998c2ecf20Sopenharmony_ci		      (!strncmp(mycustomttable[i].biosversion, biosver,
4008c2ecf20Sopenharmony_ci				strlen(mycustomttable[i].biosversion)))))	&&
4018c2ecf20Sopenharmony_ci		    ((!strlen(mycustomttable[i].biosdate)) ||
4028c2ecf20Sopenharmony_ci		     (ivideo->SiS_Pr.UseROM &&
4038c2ecf20Sopenharmony_ci		      (!strncmp(mycustomttable[i].biosdate, biosdate,
4048c2ecf20Sopenharmony_ci				strlen(mycustomttable[i].biosdate)))))		&&
4058c2ecf20Sopenharmony_ci		    ((!mycustomttable[i].bioschksum) ||
4068c2ecf20Sopenharmony_ci		     (ivideo->SiS_Pr.UseROM &&
4078c2ecf20Sopenharmony_ci		      (mycustomttable[i].bioschksum == chksum)))		&&
4088c2ecf20Sopenharmony_ci		    (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
4098c2ecf20Sopenharmony_ci		    (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
4108c2ecf20Sopenharmony_ci			footprint = true;
4118c2ecf20Sopenharmony_ci			for(j = 0; j < 5; j++) {
4128c2ecf20Sopenharmony_ci				if(mycustomttable[i].biosFootprintAddr[j]) {
4138c2ecf20Sopenharmony_ci					if(ivideo->SiS_Pr.UseROM) {
4148c2ecf20Sopenharmony_ci						if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
4158c2ecf20Sopenharmony_ci							mycustomttable[i].biosFootprintData[j]) {
4168c2ecf20Sopenharmony_ci							footprint = false;
4178c2ecf20Sopenharmony_ci						}
4188c2ecf20Sopenharmony_ci					} else
4198c2ecf20Sopenharmony_ci						footprint = false;
4208c2ecf20Sopenharmony_ci				}
4218c2ecf20Sopenharmony_ci			}
4228c2ecf20Sopenharmony_ci			if(footprint) {
4238c2ecf20Sopenharmony_ci				ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
4248c2ecf20Sopenharmony_ci				printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
4258c2ecf20Sopenharmony_ci					mycustomttable[i].vendorName,
4268c2ecf20Sopenharmony_ci				mycustomttable[i].cardName);
4278c2ecf20Sopenharmony_ci				printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
4288c2ecf20Sopenharmony_ci					mycustomttable[i].optionName);
4298c2ecf20Sopenharmony_ci				break;
4308c2ecf20Sopenharmony_ci			}
4318c2ecf20Sopenharmony_ci		}
4328c2ecf20Sopenharmony_ci		i++;
4338c2ecf20Sopenharmony_ci	} while(mycustomttable[i].chipID);
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_cistatic bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
4378c2ecf20Sopenharmony_ci{
4388c2ecf20Sopenharmony_ci	int i, j, xres, yres, refresh, index;
4398c2ecf20Sopenharmony_ci	u32 emodes;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	if(buffer[0] != 0x00 || buffer[1] != 0xff ||
4428c2ecf20Sopenharmony_ci	   buffer[2] != 0xff || buffer[3] != 0xff ||
4438c2ecf20Sopenharmony_ci	   buffer[4] != 0xff || buffer[5] != 0xff ||
4448c2ecf20Sopenharmony_ci	   buffer[6] != 0xff || buffer[7] != 0x00) {
4458c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "sisfb: Bad EDID header\n");
4468c2ecf20Sopenharmony_ci		return false;
4478c2ecf20Sopenharmony_ci	}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	if(buffer[0x12] != 0x01) {
4508c2ecf20Sopenharmony_ci		printk(KERN_INFO "sisfb: EDID version %d not supported\n",
4518c2ecf20Sopenharmony_ci			buffer[0x12]);
4528c2ecf20Sopenharmony_ci		return false;
4538c2ecf20Sopenharmony_ci	}
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	monitor->feature = buffer[0x18];
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	if(!(buffer[0x14] & 0x80)) {
4588c2ecf20Sopenharmony_ci		if(!(buffer[0x14] & 0x08)) {
4598c2ecf20Sopenharmony_ci			printk(KERN_INFO
4608c2ecf20Sopenharmony_ci				"sisfb: WARNING: Monitor does not support separate syncs\n");
4618c2ecf20Sopenharmony_ci		}
4628c2ecf20Sopenharmony_ci	}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if(buffer[0x13] >= 0x01) {
4658c2ecf20Sopenharmony_ci	   /* EDID V1 rev 1 and 2: Search for monitor descriptor
4668c2ecf20Sopenharmony_ci	    * to extract ranges
4678c2ecf20Sopenharmony_ci	    */
4688c2ecf20Sopenharmony_ci	    j = 0x36;
4698c2ecf20Sopenharmony_ci	    for(i=0; i<4; i++) {
4708c2ecf20Sopenharmony_ci	       if(buffer[j]     == 0x00 && buffer[j + 1] == 0x00 &&
4718c2ecf20Sopenharmony_ci		  buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
4728c2ecf20Sopenharmony_ci		  buffer[j + 4] == 0x00) {
4738c2ecf20Sopenharmony_ci		  monitor->hmin = buffer[j + 7];
4748c2ecf20Sopenharmony_ci		  monitor->hmax = buffer[j + 8];
4758c2ecf20Sopenharmony_ci		  monitor->vmin = buffer[j + 5];
4768c2ecf20Sopenharmony_ci		  monitor->vmax = buffer[j + 6];
4778c2ecf20Sopenharmony_ci		  monitor->dclockmax = buffer[j + 9] * 10 * 1000;
4788c2ecf20Sopenharmony_ci		  monitor->datavalid = true;
4798c2ecf20Sopenharmony_ci		  break;
4808c2ecf20Sopenharmony_ci	       }
4818c2ecf20Sopenharmony_ci	       j += 18;
4828c2ecf20Sopenharmony_ci	    }
4838c2ecf20Sopenharmony_ci	}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	if(!monitor->datavalid) {
4868c2ecf20Sopenharmony_ci	   /* Otherwise: Get a range from the list of supported
4878c2ecf20Sopenharmony_ci	    * Estabished Timings. This is not entirely accurate,
4888c2ecf20Sopenharmony_ci	    * because fixed frequency monitors are not supported
4898c2ecf20Sopenharmony_ci	    * that way.
4908c2ecf20Sopenharmony_ci	    */
4918c2ecf20Sopenharmony_ci	   monitor->hmin = 65535; monitor->hmax = 0;
4928c2ecf20Sopenharmony_ci	   monitor->vmin = 65535; monitor->vmax = 0;
4938c2ecf20Sopenharmony_ci	   monitor->dclockmax = 0;
4948c2ecf20Sopenharmony_ci	   emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
4958c2ecf20Sopenharmony_ci	   for(i = 0; i < 13; i++) {
4968c2ecf20Sopenharmony_ci	      if(emodes & sisfb_ddcsmodes[i].mask) {
4978c2ecf20Sopenharmony_ci		 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
4988c2ecf20Sopenharmony_ci		 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
4998c2ecf20Sopenharmony_ci		 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
5008c2ecf20Sopenharmony_ci		 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
5018c2ecf20Sopenharmony_ci		 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
5028c2ecf20Sopenharmony_ci	      }
5038c2ecf20Sopenharmony_ci	   }
5048c2ecf20Sopenharmony_ci	   index = 0x26;
5058c2ecf20Sopenharmony_ci	   for(i = 0; i < 8; i++) {
5068c2ecf20Sopenharmony_ci	      xres = (buffer[index] + 31) * 8;
5078c2ecf20Sopenharmony_ci	      switch(buffer[index + 1] & 0xc0) {
5088c2ecf20Sopenharmony_ci		 case 0xc0: yres = (xres * 9) / 16; break;
5098c2ecf20Sopenharmony_ci		 case 0x80: yres = (xres * 4) /  5; break;
5108c2ecf20Sopenharmony_ci		 case 0x40: yres = (xres * 3) /  4; break;
5118c2ecf20Sopenharmony_ci		 default:   yres = xres;	    break;
5128c2ecf20Sopenharmony_ci	      }
5138c2ecf20Sopenharmony_ci	      refresh = (buffer[index + 1] & 0x3f) + 60;
5148c2ecf20Sopenharmony_ci	      if((xres >= 640) && (yres >= 480)) {
5158c2ecf20Sopenharmony_ci		 for(j = 0; j < 8; j++) {
5168c2ecf20Sopenharmony_ci		    if((xres == sisfb_ddcfmodes[j].x) &&
5178c2ecf20Sopenharmony_ci		       (yres == sisfb_ddcfmodes[j].y) &&
5188c2ecf20Sopenharmony_ci		       (refresh == sisfb_ddcfmodes[j].v)) {
5198c2ecf20Sopenharmony_ci		      if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
5208c2ecf20Sopenharmony_ci		      if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
5218c2ecf20Sopenharmony_ci		      if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
5228c2ecf20Sopenharmony_ci		      if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
5238c2ecf20Sopenharmony_ci		      if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
5248c2ecf20Sopenharmony_ci		    }
5258c2ecf20Sopenharmony_ci		 }
5268c2ecf20Sopenharmony_ci	      }
5278c2ecf20Sopenharmony_ci	      index += 2;
5288c2ecf20Sopenharmony_ci	   }
5298c2ecf20Sopenharmony_ci	   if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
5308c2ecf20Sopenharmony_ci	      monitor->datavalid = true;
5318c2ecf20Sopenharmony_ci	   }
5328c2ecf20Sopenharmony_ci	}
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	return monitor->datavalid;
5358c2ecf20Sopenharmony_ci}
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_cistatic void sisfb_handle_ddc(struct sis_video_info *ivideo,
5388c2ecf20Sopenharmony_ci			     struct sisfb_monitor *monitor, int crtno)
5398c2ecf20Sopenharmony_ci{
5408c2ecf20Sopenharmony_ci	unsigned short temp, i, realcrtno = crtno;
5418c2ecf20Sopenharmony_ci	unsigned char  buffer[256];
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	monitor->datavalid = false;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	if(crtno) {
5468c2ecf20Sopenharmony_ci	   if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
5478c2ecf20Sopenharmony_ci	   else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
5488c2ecf20Sopenharmony_ci	   else return;
5498c2ecf20Sopenharmony_ci	}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	if((ivideo->sisfb_crt1off) && (!crtno))
5528c2ecf20Sopenharmony_ci		return;
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
5558c2ecf20Sopenharmony_ci				realcrtno, 0, &buffer[0], ivideo->vbflags2);
5568c2ecf20Sopenharmony_ci	if((!temp) || (temp == 0xffff)) {
5578c2ecf20Sopenharmony_ci	   printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
5588c2ecf20Sopenharmony_ci	   return;
5598c2ecf20Sopenharmony_ci	} else {
5608c2ecf20Sopenharmony_ci	   printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
5618c2ecf20Sopenharmony_ci	   printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
5628c2ecf20Sopenharmony_ci		crtno + 1,
5638c2ecf20Sopenharmony_ci		(temp & 0x1a) ? "" : "[none of the supported]",
5648c2ecf20Sopenharmony_ci		(temp & 0x02) ? "2 " : "",
5658c2ecf20Sopenharmony_ci		(temp & 0x08) ? "D&P" : "",
5668c2ecf20Sopenharmony_ci		(temp & 0x10) ? "FPDI-2" : "");
5678c2ecf20Sopenharmony_ci	   if(temp & 0x02) {
5688c2ecf20Sopenharmony_ci	      i = 3;  /* Number of retrys */
5698c2ecf20Sopenharmony_ci	      do {
5708c2ecf20Sopenharmony_ci		 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
5718c2ecf20Sopenharmony_ci				     realcrtno, 1, &buffer[0], ivideo->vbflags2);
5728c2ecf20Sopenharmony_ci	      } while((temp) && i--);
5738c2ecf20Sopenharmony_ci	      if(!temp) {
5748c2ecf20Sopenharmony_ci		 if(sisfb_interpret_edid(monitor, &buffer[0])) {
5758c2ecf20Sopenharmony_ci		    printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
5768c2ecf20Sopenharmony_ci			monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
5778c2ecf20Sopenharmony_ci			monitor->dclockmax / 1000);
5788c2ecf20Sopenharmony_ci		 } else {
5798c2ecf20Sopenharmony_ci		    printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
5808c2ecf20Sopenharmony_ci		 }
5818c2ecf20Sopenharmony_ci	      } else {
5828c2ecf20Sopenharmony_ci		 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
5838c2ecf20Sopenharmony_ci	      }
5848c2ecf20Sopenharmony_ci	   } else {
5858c2ecf20Sopenharmony_ci	      printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
5868c2ecf20Sopenharmony_ci	   }
5878c2ecf20Sopenharmony_ci	}
5888c2ecf20Sopenharmony_ci}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci/* -------------- Mode validation --------------- */
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_cistatic bool
5938c2ecf20Sopenharmony_cisisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
5948c2ecf20Sopenharmony_ci		int mode_idx, int rate_idx, int rate)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	int htotal, vtotal;
5978c2ecf20Sopenharmony_ci	unsigned int dclock, hsync;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	if(!monitor->datavalid)
6008c2ecf20Sopenharmony_ci		return true;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	if(mode_idx < 0)
6038c2ecf20Sopenharmony_ci		return false;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	/* Skip for 320x200, 320x240, 640x400 */
6068c2ecf20Sopenharmony_ci	switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
6078c2ecf20Sopenharmony_ci	case 0x59:
6088c2ecf20Sopenharmony_ci	case 0x41:
6098c2ecf20Sopenharmony_ci	case 0x4f:
6108c2ecf20Sopenharmony_ci	case 0x50:
6118c2ecf20Sopenharmony_ci	case 0x56:
6128c2ecf20Sopenharmony_ci	case 0x53:
6138c2ecf20Sopenharmony_ci	case 0x2f:
6148c2ecf20Sopenharmony_ci	case 0x5d:
6158c2ecf20Sopenharmony_ci	case 0x5e:
6168c2ecf20Sopenharmony_ci		return true;
6178c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
6188c2ecf20Sopenharmony_ci	case 0x5a:
6198c2ecf20Sopenharmony_ci	case 0x5b:
6208c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_315_VGA) return true;
6218c2ecf20Sopenharmony_ci#endif
6228c2ecf20Sopenharmony_ci	}
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	if(rate < (monitor->vmin - 1))
6258c2ecf20Sopenharmony_ci		return false;
6268c2ecf20Sopenharmony_ci	if(rate > (monitor->vmax + 1))
6278c2ecf20Sopenharmony_ci		return false;
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
6308c2ecf20Sopenharmony_ci				  sisbios_mode[mode_idx].mode_no[ivideo->mni],
6318c2ecf20Sopenharmony_ci				  &htotal, &vtotal, rate_idx)) {
6328c2ecf20Sopenharmony_ci		dclock = (htotal * vtotal * rate) / 1000;
6338c2ecf20Sopenharmony_ci		if(dclock > (monitor->dclockmax + 1000))
6348c2ecf20Sopenharmony_ci			return false;
6358c2ecf20Sopenharmony_ci		hsync = dclock / htotal;
6368c2ecf20Sopenharmony_ci		if(hsync < (monitor->hmin - 1))
6378c2ecf20Sopenharmony_ci			return false;
6388c2ecf20Sopenharmony_ci		if(hsync > (monitor->hmax + 1))
6398c2ecf20Sopenharmony_ci			return false;
6408c2ecf20Sopenharmony_ci        } else {
6418c2ecf20Sopenharmony_ci		return false;
6428c2ecf20Sopenharmony_ci	}
6438c2ecf20Sopenharmony_ci	return true;
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_cistatic int
6478c2ecf20Sopenharmony_cisisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	u16 xres=0, yres, myres;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
6528c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
6538c2ecf20Sopenharmony_ci		if(!(sisbios_mode[myindex].chipset & MD_SIS300))
6548c2ecf20Sopenharmony_ci			return -1 ;
6558c2ecf20Sopenharmony_ci	}
6568c2ecf20Sopenharmony_ci#endif
6578c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
6588c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_315_VGA) {
6598c2ecf20Sopenharmony_ci		if(!(sisbios_mode[myindex].chipset & MD_SIS315))
6608c2ecf20Sopenharmony_ci			return -1;
6618c2ecf20Sopenharmony_ci	}
6628c2ecf20Sopenharmony_ci#endif
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	myres = sisbios_mode[myindex].yres;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	switch(vbflags & VB_DISPTYPE_DISP2) {
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	case CRT2_LCD:
6698c2ecf20Sopenharmony_ci		xres = ivideo->lcdxres; yres = ivideo->lcdyres;
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci		if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
6728c2ecf20Sopenharmony_ci		   (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
6738c2ecf20Sopenharmony_ci			if(sisbios_mode[myindex].xres > xres)
6748c2ecf20Sopenharmony_ci				return -1;
6758c2ecf20Sopenharmony_ci			if(myres > yres)
6768c2ecf20Sopenharmony_ci				return -1;
6778c2ecf20Sopenharmony_ci		}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci		if(ivideo->sisfb_fstn) {
6808c2ecf20Sopenharmony_ci			if(sisbios_mode[myindex].xres == 320) {
6818c2ecf20Sopenharmony_ci				if(myres == 240) {
6828c2ecf20Sopenharmony_ci					switch(sisbios_mode[myindex].mode_no[1]) {
6838c2ecf20Sopenharmony_ci						case 0x50: myindex = MODE_FSTN_8;  break;
6848c2ecf20Sopenharmony_ci						case 0x56: myindex = MODE_FSTN_16; break;
6858c2ecf20Sopenharmony_ci						case 0x53: return -1;
6868c2ecf20Sopenharmony_ci					}
6878c2ecf20Sopenharmony_ci				}
6888c2ecf20Sopenharmony_ci			}
6898c2ecf20Sopenharmony_ci		}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci		if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
6928c2ecf20Sopenharmony_ci			 	sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
6938c2ecf20Sopenharmony_ci			 	ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
6948c2ecf20Sopenharmony_ci			return -1;
6958c2ecf20Sopenharmony_ci		}
6968c2ecf20Sopenharmony_ci		break;
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	case CRT2_TV:
6998c2ecf20Sopenharmony_ci		if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
7008c2ecf20Sopenharmony_ci				sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
7018c2ecf20Sopenharmony_ci			return -1;
7028c2ecf20Sopenharmony_ci		}
7038c2ecf20Sopenharmony_ci		break;
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	case CRT2_VGA:
7068c2ecf20Sopenharmony_ci		if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
7078c2ecf20Sopenharmony_ci				sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
7088c2ecf20Sopenharmony_ci			return -1;
7098c2ecf20Sopenharmony_ci		}
7108c2ecf20Sopenharmony_ci		break;
7118c2ecf20Sopenharmony_ci	}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	return myindex;
7148c2ecf20Sopenharmony_ci}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_cistatic u8
7178c2ecf20Sopenharmony_cisisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
7188c2ecf20Sopenharmony_ci{
7198c2ecf20Sopenharmony_ci	int i = 0;
7208c2ecf20Sopenharmony_ci	u16 xres = sisbios_mode[mode_idx].xres;
7218c2ecf20Sopenharmony_ci	u16 yres = sisbios_mode[mode_idx].yres;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	ivideo->rate_idx = 0;
7248c2ecf20Sopenharmony_ci	while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
7258c2ecf20Sopenharmony_ci		if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
7268c2ecf20Sopenharmony_ci			if(sisfb_vrate[i].refresh == rate) {
7278c2ecf20Sopenharmony_ci				ivideo->rate_idx = sisfb_vrate[i].idx;
7288c2ecf20Sopenharmony_ci				break;
7298c2ecf20Sopenharmony_ci			} else if(sisfb_vrate[i].refresh > rate) {
7308c2ecf20Sopenharmony_ci				if((sisfb_vrate[i].refresh - rate) <= 3) {
7318c2ecf20Sopenharmony_ci					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
7328c2ecf20Sopenharmony_ci						rate, sisfb_vrate[i].refresh);
7338c2ecf20Sopenharmony_ci					ivideo->rate_idx = sisfb_vrate[i].idx;
7348c2ecf20Sopenharmony_ci					ivideo->refresh_rate = sisfb_vrate[i].refresh;
7358c2ecf20Sopenharmony_ci				} else if((sisfb_vrate[i].idx != 1) &&
7368c2ecf20Sopenharmony_ci						((rate - sisfb_vrate[i-1].refresh) <= 2)) {
7378c2ecf20Sopenharmony_ci					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
7388c2ecf20Sopenharmony_ci						rate, sisfb_vrate[i-1].refresh);
7398c2ecf20Sopenharmony_ci					ivideo->rate_idx = sisfb_vrate[i-1].idx;
7408c2ecf20Sopenharmony_ci					ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
7418c2ecf20Sopenharmony_ci				}
7428c2ecf20Sopenharmony_ci				break;
7438c2ecf20Sopenharmony_ci			} else if((rate - sisfb_vrate[i].refresh) <= 2) {
7448c2ecf20Sopenharmony_ci				DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
7458c2ecf20Sopenharmony_ci						rate, sisfb_vrate[i].refresh);
7468c2ecf20Sopenharmony_ci				ivideo->rate_idx = sisfb_vrate[i].idx;
7478c2ecf20Sopenharmony_ci				break;
7488c2ecf20Sopenharmony_ci			}
7498c2ecf20Sopenharmony_ci		}
7508c2ecf20Sopenharmony_ci		i++;
7518c2ecf20Sopenharmony_ci	}
7528c2ecf20Sopenharmony_ci	if(ivideo->rate_idx > 0) {
7538c2ecf20Sopenharmony_ci		return ivideo->rate_idx;
7548c2ecf20Sopenharmony_ci	} else {
7558c2ecf20Sopenharmony_ci		printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
7568c2ecf20Sopenharmony_ci				rate, xres, yres);
7578c2ecf20Sopenharmony_ci		return 0;
7588c2ecf20Sopenharmony_ci	}
7598c2ecf20Sopenharmony_ci}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_cistatic bool
7628c2ecf20Sopenharmony_cisisfb_bridgeisslave(struct sis_video_info *ivideo)
7638c2ecf20Sopenharmony_ci{
7648c2ecf20Sopenharmony_ci	unsigned char P1_00;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
7678c2ecf20Sopenharmony_ci		return false;
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	P1_00 = SiS_GetReg(SISPART1, 0x00);
7708c2ecf20Sopenharmony_ci	if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
7718c2ecf20Sopenharmony_ci	    ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
7728c2ecf20Sopenharmony_ci		return true;
7738c2ecf20Sopenharmony_ci	} else {
7748c2ecf20Sopenharmony_ci		return false;
7758c2ecf20Sopenharmony_ci	}
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_cistatic bool
7798c2ecf20Sopenharmony_cisisfballowretracecrt1(struct sis_video_info *ivideo)
7808c2ecf20Sopenharmony_ci{
7818c2ecf20Sopenharmony_ci	u8 temp;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	temp = SiS_GetReg(SISCR, 0x17);
7848c2ecf20Sopenharmony_ci	if(!(temp & 0x80))
7858c2ecf20Sopenharmony_ci		return false;
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	temp = SiS_GetReg(SISSR, 0x1f);
7888c2ecf20Sopenharmony_ci	if(temp & 0xc0)
7898c2ecf20Sopenharmony_ci		return false;
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	return true;
7928c2ecf20Sopenharmony_ci}
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_cistatic bool
7958c2ecf20Sopenharmony_cisisfbcheckvretracecrt1(struct sis_video_info *ivideo)
7968c2ecf20Sopenharmony_ci{
7978c2ecf20Sopenharmony_ci	if(!sisfballowretracecrt1(ivideo))
7988c2ecf20Sopenharmony_ci		return false;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	if (SiS_GetRegByte(SISINPSTAT) & 0x08)
8018c2ecf20Sopenharmony_ci		return true;
8028c2ecf20Sopenharmony_ci	else
8038c2ecf20Sopenharmony_ci		return false;
8048c2ecf20Sopenharmony_ci}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_cistatic void
8078c2ecf20Sopenharmony_cisisfbwaitretracecrt1(struct sis_video_info *ivideo)
8088c2ecf20Sopenharmony_ci{
8098c2ecf20Sopenharmony_ci	int watchdog;
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	if(!sisfballowretracecrt1(ivideo))
8128c2ecf20Sopenharmony_ci		return;
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	watchdog = 65536;
8158c2ecf20Sopenharmony_ci	while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
8168c2ecf20Sopenharmony_ci	watchdog = 65536;
8178c2ecf20Sopenharmony_ci	while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
8188c2ecf20Sopenharmony_ci}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_cistatic bool
8218c2ecf20Sopenharmony_cisisfbcheckvretracecrt2(struct sis_video_info *ivideo)
8228c2ecf20Sopenharmony_ci{
8238c2ecf20Sopenharmony_ci	unsigned char temp, reg;
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	switch(ivideo->sisvga_engine) {
8268c2ecf20Sopenharmony_ci	case SIS_300_VGA: reg = 0x25; break;
8278c2ecf20Sopenharmony_ci	case SIS_315_VGA: reg = 0x30; break;
8288c2ecf20Sopenharmony_ci	default:	  return false;
8298c2ecf20Sopenharmony_ci	}
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	temp = SiS_GetReg(SISPART1, reg);
8328c2ecf20Sopenharmony_ci	if(temp & 0x02)
8338c2ecf20Sopenharmony_ci		return true;
8348c2ecf20Sopenharmony_ci	else
8358c2ecf20Sopenharmony_ci		return false;
8368c2ecf20Sopenharmony_ci}
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_cistatic bool
8398c2ecf20Sopenharmony_cisisfb_CheckVBRetrace(struct sis_video_info *ivideo)
8408c2ecf20Sopenharmony_ci{
8418c2ecf20Sopenharmony_ci	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
8428c2ecf20Sopenharmony_ci		if(!sisfb_bridgeisslave(ivideo)) {
8438c2ecf20Sopenharmony_ci			return sisfbcheckvretracecrt2(ivideo);
8448c2ecf20Sopenharmony_ci		}
8458c2ecf20Sopenharmony_ci	}
8468c2ecf20Sopenharmony_ci	return sisfbcheckvretracecrt1(ivideo);
8478c2ecf20Sopenharmony_ci}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_cistatic u32
8508c2ecf20Sopenharmony_cisisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
8518c2ecf20Sopenharmony_ci{
8528c2ecf20Sopenharmony_ci	u8 idx, reg1, reg2, reg3, reg4;
8538c2ecf20Sopenharmony_ci	u32 ret = 0;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	(*vcount) = (*hcount) = 0;
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_ci	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci		ret |= (FB_VBLANK_HAVE_VSYNC  |
8608c2ecf20Sopenharmony_ci			FB_VBLANK_HAVE_HBLANK |
8618c2ecf20Sopenharmony_ci			FB_VBLANK_HAVE_VBLANK |
8628c2ecf20Sopenharmony_ci			FB_VBLANK_HAVE_VCOUNT |
8638c2ecf20Sopenharmony_ci			FB_VBLANK_HAVE_HCOUNT);
8648c2ecf20Sopenharmony_ci		switch(ivideo->sisvga_engine) {
8658c2ecf20Sopenharmony_ci			case SIS_300_VGA: idx = 0x25; break;
8668c2ecf20Sopenharmony_ci			default:
8678c2ecf20Sopenharmony_ci			case SIS_315_VGA: idx = 0x30; break;
8688c2ecf20Sopenharmony_ci		}
8698c2ecf20Sopenharmony_ci		reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
8708c2ecf20Sopenharmony_ci		reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
8718c2ecf20Sopenharmony_ci		reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
8728c2ecf20Sopenharmony_ci		reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
8738c2ecf20Sopenharmony_ci		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
8748c2ecf20Sopenharmony_ci		if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
8758c2ecf20Sopenharmony_ci		if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
8768c2ecf20Sopenharmony_ci		(*vcount) = reg3 | ((reg4 & 0x70) << 4);
8778c2ecf20Sopenharmony_ci		(*hcount) = reg2 | ((reg4 & 0x0f) << 8);
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	} else if(sisfballowretracecrt1(ivideo)) {
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_ci		ret |= (FB_VBLANK_HAVE_VSYNC  |
8828c2ecf20Sopenharmony_ci			FB_VBLANK_HAVE_VBLANK |
8838c2ecf20Sopenharmony_ci			FB_VBLANK_HAVE_VCOUNT |
8848c2ecf20Sopenharmony_ci			FB_VBLANK_HAVE_HCOUNT);
8858c2ecf20Sopenharmony_ci		reg1 = SiS_GetRegByte(SISINPSTAT);
8868c2ecf20Sopenharmony_ci		if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
8878c2ecf20Sopenharmony_ci		if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
8888c2ecf20Sopenharmony_ci		reg1 = SiS_GetReg(SISCR, 0x20);
8898c2ecf20Sopenharmony_ci		reg1 = SiS_GetReg(SISCR, 0x1b);
8908c2ecf20Sopenharmony_ci		reg2 = SiS_GetReg(SISCR, 0x1c);
8918c2ecf20Sopenharmony_ci		reg3 = SiS_GetReg(SISCR, 0x1d);
8928c2ecf20Sopenharmony_ci		(*vcount) = reg2 | ((reg3 & 0x07) << 8);
8938c2ecf20Sopenharmony_ci		(*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
8948c2ecf20Sopenharmony_ci	}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	return ret;
8978c2ecf20Sopenharmony_ci}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_cistatic int
9008c2ecf20Sopenharmony_cisisfb_myblank(struct sis_video_info *ivideo, int blank)
9018c2ecf20Sopenharmony_ci{
9028c2ecf20Sopenharmony_ci	u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
9038c2ecf20Sopenharmony_ci	bool backlight = true;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	switch(blank) {
9068c2ecf20Sopenharmony_ci		case FB_BLANK_UNBLANK:	/* on */
9078c2ecf20Sopenharmony_ci			sr01  = 0x00;
9088c2ecf20Sopenharmony_ci			sr11  = 0x00;
9098c2ecf20Sopenharmony_ci			sr1f  = 0x00;
9108c2ecf20Sopenharmony_ci			cr63  = 0x00;
9118c2ecf20Sopenharmony_ci			p2_0  = 0x20;
9128c2ecf20Sopenharmony_ci			p1_13 = 0x00;
9138c2ecf20Sopenharmony_ci			backlight = true;
9148c2ecf20Sopenharmony_ci			break;
9158c2ecf20Sopenharmony_ci		case FB_BLANK_NORMAL:	/* blank */
9168c2ecf20Sopenharmony_ci			sr01  = 0x20;
9178c2ecf20Sopenharmony_ci			sr11  = 0x00;
9188c2ecf20Sopenharmony_ci			sr1f  = 0x00;
9198c2ecf20Sopenharmony_ci			cr63  = 0x00;
9208c2ecf20Sopenharmony_ci			p2_0  = 0x20;
9218c2ecf20Sopenharmony_ci			p1_13 = 0x00;
9228c2ecf20Sopenharmony_ci			backlight = true;
9238c2ecf20Sopenharmony_ci			break;
9248c2ecf20Sopenharmony_ci		case FB_BLANK_VSYNC_SUSPEND:	/* no vsync */
9258c2ecf20Sopenharmony_ci			sr01  = 0x20;
9268c2ecf20Sopenharmony_ci			sr11  = 0x08;
9278c2ecf20Sopenharmony_ci			sr1f  = 0x80;
9288c2ecf20Sopenharmony_ci			cr63  = 0x40;
9298c2ecf20Sopenharmony_ci			p2_0  = 0x40;
9308c2ecf20Sopenharmony_ci			p1_13 = 0x80;
9318c2ecf20Sopenharmony_ci			backlight = false;
9328c2ecf20Sopenharmony_ci			break;
9338c2ecf20Sopenharmony_ci		case FB_BLANK_HSYNC_SUSPEND:	/* no hsync */
9348c2ecf20Sopenharmony_ci			sr01  = 0x20;
9358c2ecf20Sopenharmony_ci			sr11  = 0x08;
9368c2ecf20Sopenharmony_ci			sr1f  = 0x40;
9378c2ecf20Sopenharmony_ci			cr63  = 0x40;
9388c2ecf20Sopenharmony_ci			p2_0  = 0x80;
9398c2ecf20Sopenharmony_ci			p1_13 = 0x40;
9408c2ecf20Sopenharmony_ci			backlight = false;
9418c2ecf20Sopenharmony_ci			break;
9428c2ecf20Sopenharmony_ci		case FB_BLANK_POWERDOWN:	/* off */
9438c2ecf20Sopenharmony_ci			sr01  = 0x20;
9448c2ecf20Sopenharmony_ci			sr11  = 0x08;
9458c2ecf20Sopenharmony_ci			sr1f  = 0xc0;
9468c2ecf20Sopenharmony_ci			cr63  = 0x40;
9478c2ecf20Sopenharmony_ci			p2_0  = 0xc0;
9488c2ecf20Sopenharmony_ci			p1_13 = 0xc0;
9498c2ecf20Sopenharmony_ci			backlight = false;
9508c2ecf20Sopenharmony_ci			break;
9518c2ecf20Sopenharmony_ci		default:
9528c2ecf20Sopenharmony_ci			return 1;
9538c2ecf20Sopenharmony_ci	}
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_ci		if( (!ivideo->sisfb_thismonitor.datavalid) ||
9588c2ecf20Sopenharmony_ci		    ((ivideo->sisfb_thismonitor.datavalid) &&
9598c2ecf20Sopenharmony_ci		     (ivideo->sisfb_thismonitor.feature & 0xe0))) {
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci			if(ivideo->sisvga_engine == SIS_315_VGA) {
9628c2ecf20Sopenharmony_ci				SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
9638c2ecf20Sopenharmony_ci			}
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci			if(!(sisfb_bridgeisslave(ivideo))) {
9668c2ecf20Sopenharmony_ci				SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
9678c2ecf20Sopenharmony_ci				SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
9688c2ecf20Sopenharmony_ci			}
9698c2ecf20Sopenharmony_ci		}
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	}
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	if(ivideo->currentvbflags & CRT2_LCD) {
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
9768c2ecf20Sopenharmony_ci			if(backlight) {
9778c2ecf20Sopenharmony_ci				SiS_SiS30xBLOn(&ivideo->SiS_Pr);
9788c2ecf20Sopenharmony_ci			} else {
9798c2ecf20Sopenharmony_ci				SiS_SiS30xBLOff(&ivideo->SiS_Pr);
9808c2ecf20Sopenharmony_ci			}
9818c2ecf20Sopenharmony_ci		} else if(ivideo->sisvga_engine == SIS_315_VGA) {
9828c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
9838c2ecf20Sopenharmony_ci			if(ivideo->vbflags2 & VB2_CHRONTEL) {
9848c2ecf20Sopenharmony_ci				if(backlight) {
9858c2ecf20Sopenharmony_ci					SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
9868c2ecf20Sopenharmony_ci				} else {
9878c2ecf20Sopenharmony_ci					SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
9888c2ecf20Sopenharmony_ci				}
9898c2ecf20Sopenharmony_ci			}
9908c2ecf20Sopenharmony_ci#endif
9918c2ecf20Sopenharmony_ci		}
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci		if(((ivideo->sisvga_engine == SIS_300_VGA) &&
9948c2ecf20Sopenharmony_ci		    (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
9958c2ecf20Sopenharmony_ci		   ((ivideo->sisvga_engine == SIS_315_VGA) &&
9968c2ecf20Sopenharmony_ci		    ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
9978c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
9988c2ecf20Sopenharmony_ci		}
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_300_VGA) {
10018c2ecf20Sopenharmony_ci			if((ivideo->vbflags2 & VB2_30xB) &&
10028c2ecf20Sopenharmony_ci			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
10038c2ecf20Sopenharmony_ci				SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
10048c2ecf20Sopenharmony_ci			}
10058c2ecf20Sopenharmony_ci		} else if(ivideo->sisvga_engine == SIS_315_VGA) {
10068c2ecf20Sopenharmony_ci			if((ivideo->vbflags2 & VB2_30xB) &&
10078c2ecf20Sopenharmony_ci			   (!(ivideo->vbflags2 & VB2_30xBDH))) {
10088c2ecf20Sopenharmony_ci				SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
10098c2ecf20Sopenharmony_ci			}
10108c2ecf20Sopenharmony_ci		}
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	} else if(ivideo->currentvbflags & CRT2_VGA) {
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_30xB) {
10158c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
10168c2ecf20Sopenharmony_ci		}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	return 0;
10218c2ecf20Sopenharmony_ci}
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci/* ------------- Callbacks from init.c/init301.c  -------------- */
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
10268c2ecf20Sopenharmony_ciunsigned int
10278c2ecf20Sopenharmony_cisisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
10288c2ecf20Sopenharmony_ci{
10298c2ecf20Sopenharmony_ci   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
10308c2ecf20Sopenharmony_ci   u32 val = 0;
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci   pci_read_config_dword(ivideo->nbridge, reg, &val);
10338c2ecf20Sopenharmony_ci   return (unsigned int)val;
10348c2ecf20Sopenharmony_ci}
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_civoid
10378c2ecf20Sopenharmony_cisisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci   pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
10428c2ecf20Sopenharmony_ci}
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ciunsigned int
10458c2ecf20Sopenharmony_cisisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
10468c2ecf20Sopenharmony_ci{
10478c2ecf20Sopenharmony_ci   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
10488c2ecf20Sopenharmony_ci   u32 val = 0;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci   if(!ivideo->lpcdev) return 0;
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci   pci_read_config_dword(ivideo->lpcdev, reg, &val);
10538c2ecf20Sopenharmony_ci   return (unsigned int)val;
10548c2ecf20Sopenharmony_ci}
10558c2ecf20Sopenharmony_ci#endif
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
10588c2ecf20Sopenharmony_civoid
10598c2ecf20Sopenharmony_cisisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
10608c2ecf20Sopenharmony_ci{
10618c2ecf20Sopenharmony_ci   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci   pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
10648c2ecf20Sopenharmony_ci}
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ciunsigned int
10678c2ecf20Sopenharmony_cisisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
10688c2ecf20Sopenharmony_ci{
10698c2ecf20Sopenharmony_ci   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
10708c2ecf20Sopenharmony_ci   u16 val = 0;
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci   if(!ivideo->lpcdev) return 0;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci   pci_read_config_word(ivideo->lpcdev, reg, &val);
10758c2ecf20Sopenharmony_ci   return (unsigned int)val;
10768c2ecf20Sopenharmony_ci}
10778c2ecf20Sopenharmony_ci#endif
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci/* ----------- FBDev related routines for all series ----------- */
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_cistatic int
10828c2ecf20Sopenharmony_cisisfb_get_cmap_len(const struct fb_var_screeninfo *var)
10838c2ecf20Sopenharmony_ci{
10848c2ecf20Sopenharmony_ci	return (var->bits_per_pixel == 8) ? 256 : 16;
10858c2ecf20Sopenharmony_ci}
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_cistatic void
10888c2ecf20Sopenharmony_cisisfb_set_vparms(struct sis_video_info *ivideo)
10898c2ecf20Sopenharmony_ci{
10908c2ecf20Sopenharmony_ci	switch(ivideo->video_bpp) {
10918c2ecf20Sopenharmony_ci	case 8:
10928c2ecf20Sopenharmony_ci		ivideo->DstColor = 0x0000;
10938c2ecf20Sopenharmony_ci		ivideo->SiS310_AccelDepth = 0x00000000;
10948c2ecf20Sopenharmony_ci		ivideo->video_cmap_len = 256;
10958c2ecf20Sopenharmony_ci		break;
10968c2ecf20Sopenharmony_ci	case 16:
10978c2ecf20Sopenharmony_ci		ivideo->DstColor = 0x8000;
10988c2ecf20Sopenharmony_ci		ivideo->SiS310_AccelDepth = 0x00010000;
10998c2ecf20Sopenharmony_ci		ivideo->video_cmap_len = 16;
11008c2ecf20Sopenharmony_ci		break;
11018c2ecf20Sopenharmony_ci	case 32:
11028c2ecf20Sopenharmony_ci		ivideo->DstColor = 0xC000;
11038c2ecf20Sopenharmony_ci		ivideo->SiS310_AccelDepth = 0x00020000;
11048c2ecf20Sopenharmony_ci		ivideo->video_cmap_len = 16;
11058c2ecf20Sopenharmony_ci		break;
11068c2ecf20Sopenharmony_ci	default:
11078c2ecf20Sopenharmony_ci		ivideo->video_cmap_len = 16;
11088c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
11098c2ecf20Sopenharmony_ci		ivideo->accel = 0;
11108c2ecf20Sopenharmony_ci	}
11118c2ecf20Sopenharmony_ci}
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_cistatic int
11148c2ecf20Sopenharmony_cisisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
11158c2ecf20Sopenharmony_ci{
11168c2ecf20Sopenharmony_ci	int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	if(maxyres > 32767) maxyres = 32767;
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	return maxyres;
11218c2ecf20Sopenharmony_ci}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_cistatic void
11248c2ecf20Sopenharmony_cisisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
11258c2ecf20Sopenharmony_ci{
11268c2ecf20Sopenharmony_ci	ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
11278c2ecf20Sopenharmony_ci	ivideo->scrnpitchCRT1 = ivideo->video_linelength;
11288c2ecf20Sopenharmony_ci	if(!(ivideo->currentvbflags & CRT1_LCDA)) {
11298c2ecf20Sopenharmony_ci		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
11308c2ecf20Sopenharmony_ci			ivideo->scrnpitchCRT1 <<= 1;
11318c2ecf20Sopenharmony_ci		}
11328c2ecf20Sopenharmony_ci	}
11338c2ecf20Sopenharmony_ci}
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_cistatic void
11368c2ecf20Sopenharmony_cisisfb_set_pitch(struct sis_video_info *ivideo)
11378c2ecf20Sopenharmony_ci{
11388c2ecf20Sopenharmony_ci	bool isslavemode = false;
11398c2ecf20Sopenharmony_ci	unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
11408c2ecf20Sopenharmony_ci	unsigned short HDisplay2 = ivideo->video_linelength >> 3;
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ci	if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci	/* We need to set pitch for CRT1 if bridge is in slave mode, too */
11458c2ecf20Sopenharmony_ci	if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
11468c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
11478c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
11488c2ecf20Sopenharmony_ci	}
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	/* We must not set the pitch for CRT2 if bridge is in slave mode */
11518c2ecf20Sopenharmony_ci	if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
11528c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
11538c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
11548c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
11558c2ecf20Sopenharmony_ci	}
11568c2ecf20Sopenharmony_ci}
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_cistatic void
11598c2ecf20Sopenharmony_cisisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
11608c2ecf20Sopenharmony_ci{
11618c2ecf20Sopenharmony_ci	ivideo->video_cmap_len = sisfb_get_cmap_len(var);
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	switch(var->bits_per_pixel) {
11648c2ecf20Sopenharmony_ci	case 8:
11658c2ecf20Sopenharmony_ci		var->red.offset = var->green.offset = var->blue.offset = 0;
11668c2ecf20Sopenharmony_ci		var->red.length = var->green.length = var->blue.length = 8;
11678c2ecf20Sopenharmony_ci		break;
11688c2ecf20Sopenharmony_ci	case 16:
11698c2ecf20Sopenharmony_ci		var->red.offset = 11;
11708c2ecf20Sopenharmony_ci		var->red.length = 5;
11718c2ecf20Sopenharmony_ci		var->green.offset = 5;
11728c2ecf20Sopenharmony_ci		var->green.length = 6;
11738c2ecf20Sopenharmony_ci		var->blue.offset = 0;
11748c2ecf20Sopenharmony_ci		var->blue.length = 5;
11758c2ecf20Sopenharmony_ci		var->transp.offset = 0;
11768c2ecf20Sopenharmony_ci		var->transp.length = 0;
11778c2ecf20Sopenharmony_ci		break;
11788c2ecf20Sopenharmony_ci	case 32:
11798c2ecf20Sopenharmony_ci		var->red.offset = 16;
11808c2ecf20Sopenharmony_ci		var->red.length = 8;
11818c2ecf20Sopenharmony_ci		var->green.offset = 8;
11828c2ecf20Sopenharmony_ci		var->green.length = 8;
11838c2ecf20Sopenharmony_ci		var->blue.offset = 0;
11848c2ecf20Sopenharmony_ci		var->blue.length = 8;
11858c2ecf20Sopenharmony_ci		var->transp.offset = 24;
11868c2ecf20Sopenharmony_ci		var->transp.length = 8;
11878c2ecf20Sopenharmony_ci		break;
11888c2ecf20Sopenharmony_ci	}
11898c2ecf20Sopenharmony_ci}
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_cistatic int
11928c2ecf20Sopenharmony_cisisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
11938c2ecf20Sopenharmony_ci{
11948c2ecf20Sopenharmony_ci	unsigned short modeno = ivideo->mode_no;
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	/* >=2.6.12's fbcon clears the screen anyway */
11978c2ecf20Sopenharmony_ci	modeno |= 0x80;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	sisfb_pre_setmode(ivideo);
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
12048c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
12058c2ecf20Sopenharmony_ci		return -EINVAL;
12068c2ecf20Sopenharmony_ci	}
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	sisfb_post_setmode(ivideo);
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	return 0;
12138c2ecf20Sopenharmony_ci}
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_cistatic int
12178c2ecf20Sopenharmony_cisisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
12188c2ecf20Sopenharmony_ci{
12198c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
12208c2ecf20Sopenharmony_ci	unsigned int htotal = 0, vtotal = 0;
12218c2ecf20Sopenharmony_ci	unsigned int drate = 0, hrate = 0;
12228c2ecf20Sopenharmony_ci	int found_mode = 0, ret;
12238c2ecf20Sopenharmony_ci	int old_mode;
12248c2ecf20Sopenharmony_ci	u32 pixclock;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	pixclock = var->pixclock;
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
12338c2ecf20Sopenharmony_ci		vtotal += var->yres;
12348c2ecf20Sopenharmony_ci		vtotal <<= 1;
12358c2ecf20Sopenharmony_ci	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
12368c2ecf20Sopenharmony_ci		vtotal += var->yres;
12378c2ecf20Sopenharmony_ci		vtotal <<= 2;
12388c2ecf20Sopenharmony_ci	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
12398c2ecf20Sopenharmony_ci		vtotal += var->yres;
12408c2ecf20Sopenharmony_ci		vtotal <<= 1;
12418c2ecf20Sopenharmony_ci	} else 	vtotal += var->yres;
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	if(!(htotal) || !(vtotal)) {
12448c2ecf20Sopenharmony_ci		DPRINTK("sisfb: Invalid 'var' information\n");
12458c2ecf20Sopenharmony_ci		return -EINVAL;
12468c2ecf20Sopenharmony_ci	}
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	if(pixclock && htotal && vtotal) {
12498c2ecf20Sopenharmony_ci		drate = 1000000000 / pixclock;
12508c2ecf20Sopenharmony_ci		hrate = (drate * 1000) / htotal;
12518c2ecf20Sopenharmony_ci		ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
12528c2ecf20Sopenharmony_ci	} else {
12538c2ecf20Sopenharmony_ci		ivideo->refresh_rate = 60;
12548c2ecf20Sopenharmony_ci	}
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	old_mode = ivideo->sisfb_mode_idx;
12578c2ecf20Sopenharmony_ci	ivideo->sisfb_mode_idx = 0;
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_ci	while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
12608c2ecf20Sopenharmony_ci	       (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
12618c2ecf20Sopenharmony_ci		if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
12628c2ecf20Sopenharmony_ci		    (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
12638c2ecf20Sopenharmony_ci		    (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
12648c2ecf20Sopenharmony_ci			ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
12658c2ecf20Sopenharmony_ci			found_mode = 1;
12668c2ecf20Sopenharmony_ci			break;
12678c2ecf20Sopenharmony_ci		}
12688c2ecf20Sopenharmony_ci		ivideo->sisfb_mode_idx++;
12698c2ecf20Sopenharmony_ci	}
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	if(found_mode) {
12728c2ecf20Sopenharmony_ci		ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
12738c2ecf20Sopenharmony_ci				ivideo->sisfb_mode_idx, ivideo->currentvbflags);
12748c2ecf20Sopenharmony_ci	} else {
12758c2ecf20Sopenharmony_ci		ivideo->sisfb_mode_idx = -1;
12768c2ecf20Sopenharmony_ci	}
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci       	if(ivideo->sisfb_mode_idx < 0) {
12798c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
12808c2ecf20Sopenharmony_ci		       var->yres, var->bits_per_pixel);
12818c2ecf20Sopenharmony_ci		ivideo->sisfb_mode_idx = old_mode;
12828c2ecf20Sopenharmony_ci		return -EINVAL;
12838c2ecf20Sopenharmony_ci	}
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
12888c2ecf20Sopenharmony_ci		ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
12898c2ecf20Sopenharmony_ci		ivideo->refresh_rate = 60;
12908c2ecf20Sopenharmony_ci	}
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci	if(isactive) {
12938c2ecf20Sopenharmony_ci		/* If acceleration to be used? Need to know
12948c2ecf20Sopenharmony_ci		 * before pre/post_set_mode()
12958c2ecf20Sopenharmony_ci		 */
12968c2ecf20Sopenharmony_ci		ivideo->accel = 0;
12978c2ecf20Sopenharmony_ci#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
12988c2ecf20Sopenharmony_ci#ifdef STUPID_ACCELF_TEXT_SHIT
12998c2ecf20Sopenharmony_ci		if(var->accel_flags & FB_ACCELF_TEXT) {
13008c2ecf20Sopenharmony_ci			info->flags &= ~FBINFO_HWACCEL_DISABLED;
13018c2ecf20Sopenharmony_ci		} else {
13028c2ecf20Sopenharmony_ci			info->flags |= FBINFO_HWACCEL_DISABLED;
13038c2ecf20Sopenharmony_ci		}
13048c2ecf20Sopenharmony_ci#endif
13058c2ecf20Sopenharmony_ci		if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
13068c2ecf20Sopenharmony_ci#else
13078c2ecf20Sopenharmony_ci		if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
13088c2ecf20Sopenharmony_ci#endif
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci		if((ret = sisfb_set_mode(ivideo, 1))) {
13118c2ecf20Sopenharmony_ci			return ret;
13128c2ecf20Sopenharmony_ci		}
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci		ivideo->video_bpp    = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
13158c2ecf20Sopenharmony_ci		ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
13168c2ecf20Sopenharmony_ci		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_ci		sisfb_calc_pitch(ivideo, var);
13198c2ecf20Sopenharmony_ci		sisfb_set_pitch(ivideo);
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci		sisfb_set_vparms(ivideo);
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci		ivideo->current_width = ivideo->video_width;
13248c2ecf20Sopenharmony_ci		ivideo->current_height = ivideo->video_height;
13258c2ecf20Sopenharmony_ci		ivideo->current_bpp = ivideo->video_bpp;
13268c2ecf20Sopenharmony_ci		ivideo->current_htotal = htotal;
13278c2ecf20Sopenharmony_ci		ivideo->current_vtotal = vtotal;
13288c2ecf20Sopenharmony_ci		ivideo->current_linelength = ivideo->video_linelength;
13298c2ecf20Sopenharmony_ci		ivideo->current_pixclock = var->pixclock;
13308c2ecf20Sopenharmony_ci		ivideo->current_refresh_rate = ivideo->refresh_rate;
13318c2ecf20Sopenharmony_ci		ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
13328c2ecf20Sopenharmony_ci	}
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	return 0;
13358c2ecf20Sopenharmony_ci}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_cistatic void
13388c2ecf20Sopenharmony_cisisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
13398c2ecf20Sopenharmony_ci{
13408c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x0D, base & 0xFF);
13438c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
13448c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
13458c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_315_VGA) {
13468c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
13478c2ecf20Sopenharmony_ci	}
13488c2ecf20Sopenharmony_ci}
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_cistatic void
13518c2ecf20Sopenharmony_cisisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
13528c2ecf20Sopenharmony_ci{
13538c2ecf20Sopenharmony_ci	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
13548c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
13558c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
13568c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
13578c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
13588c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_315_VGA) {
13598c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
13608c2ecf20Sopenharmony_ci		}
13618c2ecf20Sopenharmony_ci	}
13628c2ecf20Sopenharmony_ci}
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_cistatic int
13658c2ecf20Sopenharmony_cisisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
13668c2ecf20Sopenharmony_ci	      struct fb_var_screeninfo *var)
13678c2ecf20Sopenharmony_ci{
13688c2ecf20Sopenharmony_ci	ivideo->current_base = var->yoffset * info->var.xres_virtual
13698c2ecf20Sopenharmony_ci			     + var->xoffset;
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	/* calculate base bpp dep. */
13728c2ecf20Sopenharmony_ci	switch (info->var.bits_per_pixel) {
13738c2ecf20Sopenharmony_ci	case 32:
13748c2ecf20Sopenharmony_ci		break;
13758c2ecf20Sopenharmony_ci	case 16:
13768c2ecf20Sopenharmony_ci		ivideo->current_base >>= 1;
13778c2ecf20Sopenharmony_ci		break;
13788c2ecf20Sopenharmony_ci	case 8:
13798c2ecf20Sopenharmony_ci	default:
13808c2ecf20Sopenharmony_ci		ivideo->current_base >>= 2;
13818c2ecf20Sopenharmony_ci		break;
13828c2ecf20Sopenharmony_ci	}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	ivideo->current_base += (ivideo->video_offset >> 2);
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci	sisfb_set_base_CRT1(ivideo, ivideo->current_base);
13878c2ecf20Sopenharmony_ci	sisfb_set_base_CRT2(ivideo, ivideo->current_base);
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	return 0;
13908c2ecf20Sopenharmony_ci}
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_cistatic int
13938c2ecf20Sopenharmony_cisisfb_open(struct fb_info *info, int user)
13948c2ecf20Sopenharmony_ci{
13958c2ecf20Sopenharmony_ci	return 0;
13968c2ecf20Sopenharmony_ci}
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_cistatic int
13998c2ecf20Sopenharmony_cisisfb_release(struct fb_info *info, int user)
14008c2ecf20Sopenharmony_ci{
14018c2ecf20Sopenharmony_ci	return 0;
14028c2ecf20Sopenharmony_ci}
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_cistatic int
14058c2ecf20Sopenharmony_cisisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
14068c2ecf20Sopenharmony_ci		unsigned transp, struct fb_info *info)
14078c2ecf20Sopenharmony_ci{
14088c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_ci	if(regno >= sisfb_get_cmap_len(&info->var))
14118c2ecf20Sopenharmony_ci		return 1;
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	switch(info->var.bits_per_pixel) {
14148c2ecf20Sopenharmony_ci	case 8:
14158c2ecf20Sopenharmony_ci		SiS_SetRegByte(SISDACA, regno);
14168c2ecf20Sopenharmony_ci		SiS_SetRegByte(SISDACD, (red >> 10));
14178c2ecf20Sopenharmony_ci		SiS_SetRegByte(SISDACD, (green >> 10));
14188c2ecf20Sopenharmony_ci		SiS_SetRegByte(SISDACD, (blue >> 10));
14198c2ecf20Sopenharmony_ci		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
14208c2ecf20Sopenharmony_ci			SiS_SetRegByte(SISDAC2A, regno);
14218c2ecf20Sopenharmony_ci			SiS_SetRegByte(SISDAC2D, (red >> 8));
14228c2ecf20Sopenharmony_ci			SiS_SetRegByte(SISDAC2D, (green >> 8));
14238c2ecf20Sopenharmony_ci			SiS_SetRegByte(SISDAC2D, (blue >> 8));
14248c2ecf20Sopenharmony_ci		}
14258c2ecf20Sopenharmony_ci		break;
14268c2ecf20Sopenharmony_ci	case 16:
14278c2ecf20Sopenharmony_ci		if (regno >= 16)
14288c2ecf20Sopenharmony_ci			break;
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci		((u32 *)(info->pseudo_palette))[regno] =
14318c2ecf20Sopenharmony_ci				(red & 0xf800)          |
14328c2ecf20Sopenharmony_ci				((green & 0xfc00) >> 5) |
14338c2ecf20Sopenharmony_ci				((blue & 0xf800) >> 11);
14348c2ecf20Sopenharmony_ci		break;
14358c2ecf20Sopenharmony_ci	case 32:
14368c2ecf20Sopenharmony_ci		if (regno >= 16)
14378c2ecf20Sopenharmony_ci			break;
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci		red >>= 8;
14408c2ecf20Sopenharmony_ci		green >>= 8;
14418c2ecf20Sopenharmony_ci		blue >>= 8;
14428c2ecf20Sopenharmony_ci		((u32 *)(info->pseudo_palette))[regno] =
14438c2ecf20Sopenharmony_ci				(red << 16) | (green << 8) | (blue);
14448c2ecf20Sopenharmony_ci		break;
14458c2ecf20Sopenharmony_ci	}
14468c2ecf20Sopenharmony_ci	return 0;
14478c2ecf20Sopenharmony_ci}
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_cistatic int
14508c2ecf20Sopenharmony_cisisfb_set_par(struct fb_info *info)
14518c2ecf20Sopenharmony_ci{
14528c2ecf20Sopenharmony_ci	int err;
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci	if((err = sisfb_do_set_var(&info->var, 1, info)))
14558c2ecf20Sopenharmony_ci		return err;
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	sisfb_get_fix(&info->fix, -1, info);
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci	return 0;
14608c2ecf20Sopenharmony_ci}
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_cistatic int
14638c2ecf20Sopenharmony_cisisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
14648c2ecf20Sopenharmony_ci{
14658c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
14668c2ecf20Sopenharmony_ci	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
14678c2ecf20Sopenharmony_ci	unsigned int drate = 0, hrate = 0, maxyres;
14688c2ecf20Sopenharmony_ci	int found_mode = 0;
14698c2ecf20Sopenharmony_ci	int refresh_rate, search_idx, tidx;
14708c2ecf20Sopenharmony_ci	bool recalc_clock = false;
14718c2ecf20Sopenharmony_ci	u32 pixclock;
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci	pixclock = var->pixclock;
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
14808c2ecf20Sopenharmony_ci		vtotal += var->yres;
14818c2ecf20Sopenharmony_ci		vtotal <<= 1;
14828c2ecf20Sopenharmony_ci	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
14838c2ecf20Sopenharmony_ci		vtotal += var->yres;
14848c2ecf20Sopenharmony_ci		vtotal <<= 2;
14858c2ecf20Sopenharmony_ci	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
14868c2ecf20Sopenharmony_ci		vtotal += var->yres;
14878c2ecf20Sopenharmony_ci		vtotal <<= 1;
14888c2ecf20Sopenharmony_ci	} else
14898c2ecf20Sopenharmony_ci		vtotal += var->yres;
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci	if(!(htotal) || !(vtotal)) {
14928c2ecf20Sopenharmony_ci		SISFAIL("sisfb: no valid timing data");
14938c2ecf20Sopenharmony_ci	}
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	search_idx = 0;
14968c2ecf20Sopenharmony_ci	while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
14978c2ecf20Sopenharmony_ci	       (sisbios_mode[search_idx].xres <= var->xres) ) {
14988c2ecf20Sopenharmony_ci		if( (sisbios_mode[search_idx].xres == var->xres) &&
14998c2ecf20Sopenharmony_ci		    (sisbios_mode[search_idx].yres == var->yres) &&
15008c2ecf20Sopenharmony_ci		    (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
15018c2ecf20Sopenharmony_ci			if((tidx = sisfb_validate_mode(ivideo, search_idx,
15028c2ecf20Sopenharmony_ci						ivideo->currentvbflags)) > 0) {
15038c2ecf20Sopenharmony_ci				found_mode = 1;
15048c2ecf20Sopenharmony_ci				search_idx = tidx;
15058c2ecf20Sopenharmony_ci				break;
15068c2ecf20Sopenharmony_ci			}
15078c2ecf20Sopenharmony_ci		}
15088c2ecf20Sopenharmony_ci		search_idx++;
15098c2ecf20Sopenharmony_ci	}
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci	if(!found_mode) {
15128c2ecf20Sopenharmony_ci		search_idx = 0;
15138c2ecf20Sopenharmony_ci		while(sisbios_mode[search_idx].mode_no[0] != 0) {
15148c2ecf20Sopenharmony_ci		   if( (var->xres <= sisbios_mode[search_idx].xres) &&
15158c2ecf20Sopenharmony_ci		       (var->yres <= sisbios_mode[search_idx].yres) &&
15168c2ecf20Sopenharmony_ci		       (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
15178c2ecf20Sopenharmony_ci			if((tidx = sisfb_validate_mode(ivideo,search_idx,
15188c2ecf20Sopenharmony_ci						ivideo->currentvbflags)) > 0) {
15198c2ecf20Sopenharmony_ci				found_mode = 1;
15208c2ecf20Sopenharmony_ci				search_idx = tidx;
15218c2ecf20Sopenharmony_ci				break;
15228c2ecf20Sopenharmony_ci			}
15238c2ecf20Sopenharmony_ci		   }
15248c2ecf20Sopenharmony_ci		   search_idx++;
15258c2ecf20Sopenharmony_ci		}
15268c2ecf20Sopenharmony_ci		if(found_mode) {
15278c2ecf20Sopenharmony_ci			printk(KERN_DEBUG
15288c2ecf20Sopenharmony_ci				"sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
15298c2ecf20Sopenharmony_ci				var->xres, var->yres, var->bits_per_pixel,
15308c2ecf20Sopenharmony_ci				sisbios_mode[search_idx].xres,
15318c2ecf20Sopenharmony_ci				sisbios_mode[search_idx].yres,
15328c2ecf20Sopenharmony_ci				var->bits_per_pixel);
15338c2ecf20Sopenharmony_ci			var->xres = sisbios_mode[search_idx].xres;
15348c2ecf20Sopenharmony_ci			var->yres = sisbios_mode[search_idx].yres;
15358c2ecf20Sopenharmony_ci		} else {
15368c2ecf20Sopenharmony_ci			printk(KERN_ERR
15378c2ecf20Sopenharmony_ci				"sisfb: Failed to find supported mode near %dx%dx%d\n",
15388c2ecf20Sopenharmony_ci				var->xres, var->yres, var->bits_per_pixel);
15398c2ecf20Sopenharmony_ci			return -EINVAL;
15408c2ecf20Sopenharmony_ci		}
15418c2ecf20Sopenharmony_ci	}
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci	if( ((ivideo->vbflags2 & VB2_LVDS) ||
15448c2ecf20Sopenharmony_ci	     ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
15458c2ecf20Sopenharmony_ci	    (var->bits_per_pixel == 8) ) {
15468c2ecf20Sopenharmony_ci		/* Slave modes on LVDS and 301B-DH */
15478c2ecf20Sopenharmony_ci		refresh_rate = 60;
15488c2ecf20Sopenharmony_ci		recalc_clock = true;
15498c2ecf20Sopenharmony_ci	} else if( (ivideo->current_htotal == htotal) &&
15508c2ecf20Sopenharmony_ci		   (ivideo->current_vtotal == vtotal) &&
15518c2ecf20Sopenharmony_ci		   (ivideo->current_pixclock == pixclock) ) {
15528c2ecf20Sopenharmony_ci		/* x=x & y=y & c=c -> assume depth change */
15538c2ecf20Sopenharmony_ci		drate = 1000000000 / pixclock;
15548c2ecf20Sopenharmony_ci		hrate = (drate * 1000) / htotal;
15558c2ecf20Sopenharmony_ci		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
15568c2ecf20Sopenharmony_ci	} else if( ( (ivideo->current_htotal != htotal) ||
15578c2ecf20Sopenharmony_ci		     (ivideo->current_vtotal != vtotal) ) &&
15588c2ecf20Sopenharmony_ci		   (ivideo->current_pixclock == var->pixclock) ) {
15598c2ecf20Sopenharmony_ci		/* x!=x | y!=y & c=c -> invalid pixclock */
15608c2ecf20Sopenharmony_ci		if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
15618c2ecf20Sopenharmony_ci			refresh_rate =
15628c2ecf20Sopenharmony_ci				ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
15638c2ecf20Sopenharmony_ci		} else if(ivideo->sisfb_parm_rate != -1) {
15648c2ecf20Sopenharmony_ci			/* Sic, sisfb_parm_rate - want to know originally desired rate here */
15658c2ecf20Sopenharmony_ci			refresh_rate = ivideo->sisfb_parm_rate;
15668c2ecf20Sopenharmony_ci		} else {
15678c2ecf20Sopenharmony_ci			refresh_rate = 60;
15688c2ecf20Sopenharmony_ci		}
15698c2ecf20Sopenharmony_ci		recalc_clock = true;
15708c2ecf20Sopenharmony_ci	} else if((pixclock) && (htotal) && (vtotal)) {
15718c2ecf20Sopenharmony_ci		drate = 1000000000 / pixclock;
15728c2ecf20Sopenharmony_ci		hrate = (drate * 1000) / htotal;
15738c2ecf20Sopenharmony_ci		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
15748c2ecf20Sopenharmony_ci	} else if(ivideo->current_refresh_rate) {
15758c2ecf20Sopenharmony_ci		refresh_rate = ivideo->current_refresh_rate;
15768c2ecf20Sopenharmony_ci		recalc_clock = true;
15778c2ecf20Sopenharmony_ci	} else {
15788c2ecf20Sopenharmony_ci		refresh_rate = 60;
15798c2ecf20Sopenharmony_ci		recalc_clock = true;
15808c2ecf20Sopenharmony_ci	}
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci	/* Eventually recalculate timing and clock */
15858c2ecf20Sopenharmony_ci	if(recalc_clock) {
15868c2ecf20Sopenharmony_ci		if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
15878c2ecf20Sopenharmony_ci		var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
15888c2ecf20Sopenharmony_ci						sisbios_mode[search_idx].mode_no[ivideo->mni],
15898c2ecf20Sopenharmony_ci						myrateindex));
15908c2ecf20Sopenharmony_ci		sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
15918c2ecf20Sopenharmony_ci					sisbios_mode[search_idx].mode_no[ivideo->mni],
15928c2ecf20Sopenharmony_ci					myrateindex, var);
15938c2ecf20Sopenharmony_ci		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
15948c2ecf20Sopenharmony_ci			var->pixclock <<= 1;
15958c2ecf20Sopenharmony_ci		}
15968c2ecf20Sopenharmony_ci	}
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	if(ivideo->sisfb_thismonitor.datavalid) {
15998c2ecf20Sopenharmony_ci		if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
16008c2ecf20Sopenharmony_ci				myrateindex, refresh_rate)) {
16018c2ecf20Sopenharmony_ci			printk(KERN_INFO
16028c2ecf20Sopenharmony_ci				"sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
16038c2ecf20Sopenharmony_ci		}
16048c2ecf20Sopenharmony_ci	}
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	/* Adapt RGB settings */
16078c2ecf20Sopenharmony_ci	sisfb_bpp_to_var(ivideo, var);
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci	if(var->xres > var->xres_virtual)
16108c2ecf20Sopenharmony_ci		var->xres_virtual = var->xres;
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_ci	if(ivideo->sisfb_ypan) {
16138c2ecf20Sopenharmony_ci		maxyres = sisfb_calc_maxyres(ivideo, var);
16148c2ecf20Sopenharmony_ci		if(ivideo->sisfb_max) {
16158c2ecf20Sopenharmony_ci			var->yres_virtual = maxyres;
16168c2ecf20Sopenharmony_ci		} else {
16178c2ecf20Sopenharmony_ci			if(var->yres_virtual > maxyres) {
16188c2ecf20Sopenharmony_ci				var->yres_virtual = maxyres;
16198c2ecf20Sopenharmony_ci			}
16208c2ecf20Sopenharmony_ci		}
16218c2ecf20Sopenharmony_ci		if(var->yres_virtual <= var->yres) {
16228c2ecf20Sopenharmony_ci			var->yres_virtual = var->yres;
16238c2ecf20Sopenharmony_ci		}
16248c2ecf20Sopenharmony_ci	} else {
16258c2ecf20Sopenharmony_ci		if(var->yres != var->yres_virtual) {
16268c2ecf20Sopenharmony_ci			var->yres_virtual = var->yres;
16278c2ecf20Sopenharmony_ci		}
16288c2ecf20Sopenharmony_ci		var->xoffset = 0;
16298c2ecf20Sopenharmony_ci		var->yoffset = 0;
16308c2ecf20Sopenharmony_ci	}
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ci	/* Truncate offsets to maximum if too high */
16338c2ecf20Sopenharmony_ci	if(var->xoffset > var->xres_virtual - var->xres) {
16348c2ecf20Sopenharmony_ci		var->xoffset = var->xres_virtual - var->xres - 1;
16358c2ecf20Sopenharmony_ci	}
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci	if(var->yoffset > var->yres_virtual - var->yres) {
16388c2ecf20Sopenharmony_ci		var->yoffset = var->yres_virtual - var->yres - 1;
16398c2ecf20Sopenharmony_ci	}
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	/* Set everything else to 0 */
16428c2ecf20Sopenharmony_ci	var->red.msb_right =
16438c2ecf20Sopenharmony_ci		var->green.msb_right =
16448c2ecf20Sopenharmony_ci		var->blue.msb_right =
16458c2ecf20Sopenharmony_ci		var->transp.offset =
16468c2ecf20Sopenharmony_ci		var->transp.length =
16478c2ecf20Sopenharmony_ci		var->transp.msb_right = 0;
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	return 0;
16508c2ecf20Sopenharmony_ci}
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_cistatic int
16538c2ecf20Sopenharmony_cisisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
16548c2ecf20Sopenharmony_ci{
16558c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
16568c2ecf20Sopenharmony_ci	int err;
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	if (var->vmode & FB_VMODE_YWRAP)
16598c2ecf20Sopenharmony_ci		return -EINVAL;
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	if (var->xoffset + info->var.xres > info->var.xres_virtual ||
16628c2ecf20Sopenharmony_ci	    var->yoffset + info->var.yres > info->var.yres_virtual)
16638c2ecf20Sopenharmony_ci		return -EINVAL;
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	err = sisfb_pan_var(ivideo, info, var);
16668c2ecf20Sopenharmony_ci	if (err < 0)
16678c2ecf20Sopenharmony_ci		return err;
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	info->var.xoffset = var->xoffset;
16708c2ecf20Sopenharmony_ci	info->var.yoffset = var->yoffset;
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	return 0;
16738c2ecf20Sopenharmony_ci}
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_cistatic int
16768c2ecf20Sopenharmony_cisisfb_blank(int blank, struct fb_info *info)
16778c2ecf20Sopenharmony_ci{
16788c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci	return sisfb_myblank(ivideo, blank);
16818c2ecf20Sopenharmony_ci}
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci/* ----------- FBDev related routines for all series ---------- */
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_cistatic int	sisfb_ioctl(struct fb_info *info, unsigned int cmd,
16868c2ecf20Sopenharmony_ci			    unsigned long arg)
16878c2ecf20Sopenharmony_ci{
16888c2ecf20Sopenharmony_ci	struct sis_video_info	*ivideo = (struct sis_video_info *)info->par;
16898c2ecf20Sopenharmony_ci	struct sis_memreq	sismemreq;
16908c2ecf20Sopenharmony_ci	struct fb_vblank	sisvbblank;
16918c2ecf20Sopenharmony_ci	u32			gpu32 = 0;
16928c2ecf20Sopenharmony_ci#ifndef __user
16938c2ecf20Sopenharmony_ci#define __user
16948c2ecf20Sopenharmony_ci#endif
16958c2ecf20Sopenharmony_ci	u32 __user 		*argp = (u32 __user *)arg;
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci	switch(cmd) {
16988c2ecf20Sopenharmony_ci	   case FBIO_ALLOC:
16998c2ecf20Sopenharmony_ci		if(!capable(CAP_SYS_RAWIO))
17008c2ecf20Sopenharmony_ci			return -EPERM;
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci		if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
17038c2ecf20Sopenharmony_ci			return -EFAULT;
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci		sis_malloc(&sismemreq);
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci		if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
17088c2ecf20Sopenharmony_ci			sis_free((u32)sismemreq.offset);
17098c2ecf20Sopenharmony_ci			return -EFAULT;
17108c2ecf20Sopenharmony_ci		}
17118c2ecf20Sopenharmony_ci		break;
17128c2ecf20Sopenharmony_ci
17138c2ecf20Sopenharmony_ci	   case FBIO_FREE:
17148c2ecf20Sopenharmony_ci		if(!capable(CAP_SYS_RAWIO))
17158c2ecf20Sopenharmony_ci			return -EPERM;
17168c2ecf20Sopenharmony_ci
17178c2ecf20Sopenharmony_ci		if(get_user(gpu32, argp))
17188c2ecf20Sopenharmony_ci			return -EFAULT;
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci		sis_free(gpu32);
17218c2ecf20Sopenharmony_ci		break;
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci	   case FBIOGET_VBLANK:
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci		memset(&sisvbblank, 0, sizeof(struct fb_vblank));
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci		sisvbblank.count = 0;
17288c2ecf20Sopenharmony_ci		sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci		if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
17318c2ecf20Sopenharmony_ci			return -EFAULT;
17328c2ecf20Sopenharmony_ci
17338c2ecf20Sopenharmony_ci		break;
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci	   case SISFB_GET_INFO_SIZE:
17368c2ecf20Sopenharmony_ci		return put_user(sizeof(struct sisfb_info), argp);
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ci	   case SISFB_GET_INFO_OLD:
17398c2ecf20Sopenharmony_ci		if(ivideo->warncount++ < 10)
17408c2ecf20Sopenharmony_ci			printk(KERN_INFO
17418c2ecf20Sopenharmony_ci				"sisfb: Deprecated ioctl call received - update your application!\n");
17428c2ecf20Sopenharmony_ci		fallthrough;
17438c2ecf20Sopenharmony_ci	   case SISFB_GET_INFO:  /* For communication with X driver */
17448c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_id         = SISFB_ID;
17458c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_version    = VER_MAJOR;
17468c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_revision   = VER_MINOR;
17478c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
17488c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
17498c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
17508c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
17518c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
17528c2ecf20Sopenharmony_ci		if(ivideo->modechanged) {
17538c2ecf20Sopenharmony_ci			ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
17548c2ecf20Sopenharmony_ci		} else {
17558c2ecf20Sopenharmony_ci			ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
17568c2ecf20Sopenharmony_ci		}
17578c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
17588c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
17598c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
17608c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
17618c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
17628c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
17638c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
17648c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
17658c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
17668c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
17678c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
17688c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
17698c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
17708c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
17718c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
17728c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
17738c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
17748c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
17758c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
17768c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
17778c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
17788c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
17798c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
17808c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
17818c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
17828c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
17838c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
17848c2ecf20Sopenharmony_ci		ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
17858c2ecf20Sopenharmony_ci
17868c2ecf20Sopenharmony_ci		if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
17878c2ecf20Sopenharmony_ci						sizeof(ivideo->sisfb_infoblock)))
17888c2ecf20Sopenharmony_ci			return -EFAULT;
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci	        break;
17918c2ecf20Sopenharmony_ci
17928c2ecf20Sopenharmony_ci	   case SISFB_GET_VBRSTATUS_OLD:
17938c2ecf20Sopenharmony_ci		if(ivideo->warncount++ < 10)
17948c2ecf20Sopenharmony_ci			printk(KERN_INFO
17958c2ecf20Sopenharmony_ci				"sisfb: Deprecated ioctl call received - update your application!\n");
17968c2ecf20Sopenharmony_ci		fallthrough;
17978c2ecf20Sopenharmony_ci	   case SISFB_GET_VBRSTATUS:
17988c2ecf20Sopenharmony_ci		if(sisfb_CheckVBRetrace(ivideo))
17998c2ecf20Sopenharmony_ci			return put_user((u32)1, argp);
18008c2ecf20Sopenharmony_ci		else
18018c2ecf20Sopenharmony_ci			return put_user((u32)0, argp);
18028c2ecf20Sopenharmony_ci
18038c2ecf20Sopenharmony_ci	   case SISFB_GET_AUTOMAXIMIZE_OLD:
18048c2ecf20Sopenharmony_ci		if(ivideo->warncount++ < 10)
18058c2ecf20Sopenharmony_ci			printk(KERN_INFO
18068c2ecf20Sopenharmony_ci				"sisfb: Deprecated ioctl call received - update your application!\n");
18078c2ecf20Sopenharmony_ci		fallthrough;
18088c2ecf20Sopenharmony_ci	   case SISFB_GET_AUTOMAXIMIZE:
18098c2ecf20Sopenharmony_ci		if(ivideo->sisfb_max)
18108c2ecf20Sopenharmony_ci			return put_user((u32)1, argp);
18118c2ecf20Sopenharmony_ci		else
18128c2ecf20Sopenharmony_ci			return put_user((u32)0, argp);
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci	   case SISFB_SET_AUTOMAXIMIZE_OLD:
18158c2ecf20Sopenharmony_ci		if(ivideo->warncount++ < 10)
18168c2ecf20Sopenharmony_ci			printk(KERN_INFO
18178c2ecf20Sopenharmony_ci				"sisfb: Deprecated ioctl call received - update your application!\n");
18188c2ecf20Sopenharmony_ci		fallthrough;
18198c2ecf20Sopenharmony_ci	   case SISFB_SET_AUTOMAXIMIZE:
18208c2ecf20Sopenharmony_ci		if(get_user(gpu32, argp))
18218c2ecf20Sopenharmony_ci			return -EFAULT;
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci		ivideo->sisfb_max = (gpu32) ? 1 : 0;
18248c2ecf20Sopenharmony_ci		break;
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	   case SISFB_SET_TVPOSOFFSET:
18278c2ecf20Sopenharmony_ci		if(get_user(gpu32, argp))
18288c2ecf20Sopenharmony_ci			return -EFAULT;
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci		sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
18318c2ecf20Sopenharmony_ci		sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
18328c2ecf20Sopenharmony_ci		break;
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_ci	   case SISFB_GET_TVPOSOFFSET:
18358c2ecf20Sopenharmony_ci		return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
18368c2ecf20Sopenharmony_ci							argp);
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci	   case SISFB_COMMAND:
18398c2ecf20Sopenharmony_ci		if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
18408c2ecf20Sopenharmony_ci							sizeof(struct sisfb_cmd)))
18418c2ecf20Sopenharmony_ci			return -EFAULT;
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci		sisfb_handle_command(ivideo, &ivideo->sisfb_command);
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci		if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
18468c2ecf20Sopenharmony_ci							sizeof(struct sisfb_cmd)))
18478c2ecf20Sopenharmony_ci			return -EFAULT;
18488c2ecf20Sopenharmony_ci
18498c2ecf20Sopenharmony_ci		break;
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci	   case SISFB_SET_LOCK:
18528c2ecf20Sopenharmony_ci		if(get_user(gpu32, argp))
18538c2ecf20Sopenharmony_ci			return -EFAULT;
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci		ivideo->sisfblocked = (gpu32) ? 1 : 0;
18568c2ecf20Sopenharmony_ci		break;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	   default:
18598c2ecf20Sopenharmony_ci#ifdef SIS_NEW_CONFIG_COMPAT
18608c2ecf20Sopenharmony_ci		return -ENOIOCTLCMD;
18618c2ecf20Sopenharmony_ci#else
18628c2ecf20Sopenharmony_ci		return -EINVAL;
18638c2ecf20Sopenharmony_ci#endif
18648c2ecf20Sopenharmony_ci	}
18658c2ecf20Sopenharmony_ci	return 0;
18668c2ecf20Sopenharmony_ci}
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_cistatic int
18698c2ecf20Sopenharmony_cisisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
18708c2ecf20Sopenharmony_ci{
18718c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_ci	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
18748c2ecf20Sopenharmony_ci
18758c2ecf20Sopenharmony_ci	strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci	mutex_lock(&info->mm_lock);
18788c2ecf20Sopenharmony_ci	fix->smem_start  = ivideo->video_base + ivideo->video_offset;
18798c2ecf20Sopenharmony_ci	fix->smem_len    = ivideo->sisfb_mem;
18808c2ecf20Sopenharmony_ci	mutex_unlock(&info->mm_lock);
18818c2ecf20Sopenharmony_ci	fix->type        = FB_TYPE_PACKED_PIXELS;
18828c2ecf20Sopenharmony_ci	fix->type_aux    = 0;
18838c2ecf20Sopenharmony_ci	fix->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
18848c2ecf20Sopenharmony_ci	fix->xpanstep    = 1;
18858c2ecf20Sopenharmony_ci	fix->ypanstep 	 = (ivideo->sisfb_ypan) ? 1 : 0;
18868c2ecf20Sopenharmony_ci	fix->ywrapstep   = 0;
18878c2ecf20Sopenharmony_ci	fix->line_length = ivideo->video_linelength;
18888c2ecf20Sopenharmony_ci	fix->mmio_start  = ivideo->mmio_base;
18898c2ecf20Sopenharmony_ci	fix->mmio_len    = ivideo->mmio_size;
18908c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
18918c2ecf20Sopenharmony_ci		fix->accel = FB_ACCEL_SIS_GLAMOUR;
18928c2ecf20Sopenharmony_ci	} else if((ivideo->chip == SIS_330) ||
18938c2ecf20Sopenharmony_ci		  (ivideo->chip == SIS_760) ||
18948c2ecf20Sopenharmony_ci		  (ivideo->chip == SIS_761)) {
18958c2ecf20Sopenharmony_ci		fix->accel = FB_ACCEL_SIS_XABRE;
18968c2ecf20Sopenharmony_ci	} else if(ivideo->chip == XGI_20) {
18978c2ecf20Sopenharmony_ci		fix->accel = FB_ACCEL_XGI_VOLARI_Z;
18988c2ecf20Sopenharmony_ci	} else if(ivideo->chip >= XGI_40) {
18998c2ecf20Sopenharmony_ci		fix->accel = FB_ACCEL_XGI_VOLARI_V;
19008c2ecf20Sopenharmony_ci	} else {
19018c2ecf20Sopenharmony_ci		fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
19028c2ecf20Sopenharmony_ci	}
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci	return 0;
19058c2ecf20Sopenharmony_ci}
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci/* ----------------  fb_ops structures ----------------- */
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_cistatic const struct fb_ops sisfb_ops = {
19108c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
19118c2ecf20Sopenharmony_ci	.fb_open	= sisfb_open,
19128c2ecf20Sopenharmony_ci	.fb_release	= sisfb_release,
19138c2ecf20Sopenharmony_ci	.fb_check_var	= sisfb_check_var,
19148c2ecf20Sopenharmony_ci	.fb_set_par	= sisfb_set_par,
19158c2ecf20Sopenharmony_ci	.fb_setcolreg	= sisfb_setcolreg,
19168c2ecf20Sopenharmony_ci	.fb_pan_display	= sisfb_pan_display,
19178c2ecf20Sopenharmony_ci	.fb_blank	= sisfb_blank,
19188c2ecf20Sopenharmony_ci	.fb_fillrect	= fbcon_sis_fillrect,
19198c2ecf20Sopenharmony_ci	.fb_copyarea	= fbcon_sis_copyarea,
19208c2ecf20Sopenharmony_ci	.fb_imageblit	= cfb_imageblit,
19218c2ecf20Sopenharmony_ci	.fb_sync	= fbcon_sis_sync,
19228c2ecf20Sopenharmony_ci#ifdef SIS_NEW_CONFIG_COMPAT
19238c2ecf20Sopenharmony_ci	.fb_compat_ioctl= sisfb_ioctl,
19248c2ecf20Sopenharmony_ci#endif
19258c2ecf20Sopenharmony_ci	.fb_ioctl	= sisfb_ioctl
19268c2ecf20Sopenharmony_ci};
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ci/* ---------------- Chip generation dependent routines ---------------- */
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_cistatic struct pci_dev *sisfb_get_northbridge(int basechipid)
19318c2ecf20Sopenharmony_ci{
19328c2ecf20Sopenharmony_ci	struct pci_dev *pdev = NULL;
19338c2ecf20Sopenharmony_ci	int nbridgenum, nbridgeidx, i;
19348c2ecf20Sopenharmony_ci	static const unsigned short nbridgeids[] = {
19358c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_540,	/* for SiS 540 VGA */
19368c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_630,	/* for SiS 630/730 VGA */
19378c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_730,
19388c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_550,   /* for SiS 550 VGA */
19398c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */
19408c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_651,
19418c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_740,
19428c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_661,	/* for SiS 661/741/660/760/761 VGA */
19438c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_741,
19448c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_660,
19458c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_760,
19468c2ecf20Sopenharmony_ci		PCI_DEVICE_ID_SI_761
19478c2ecf20Sopenharmony_ci	};
19488c2ecf20Sopenharmony_ci
19498c2ecf20Sopenharmony_ci	switch(basechipid) {
19508c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
19518c2ecf20Sopenharmony_ci	case SIS_540:	nbridgeidx = 0; nbridgenum = 1; break;
19528c2ecf20Sopenharmony_ci	case SIS_630:	nbridgeidx = 1; nbridgenum = 2; break;
19538c2ecf20Sopenharmony_ci#endif
19548c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
19558c2ecf20Sopenharmony_ci	case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;
19568c2ecf20Sopenharmony_ci	case SIS_650:	nbridgeidx = 4; nbridgenum = 3; break;
19578c2ecf20Sopenharmony_ci	case SIS_660:	nbridgeidx = 7; nbridgenum = 5; break;
19588c2ecf20Sopenharmony_ci#endif
19598c2ecf20Sopenharmony_ci	default:	return NULL;
19608c2ecf20Sopenharmony_ci	}
19618c2ecf20Sopenharmony_ci	for(i = 0; i < nbridgenum; i++) {
19628c2ecf20Sopenharmony_ci		if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
19638c2ecf20Sopenharmony_ci				nbridgeids[nbridgeidx+i], NULL)))
19648c2ecf20Sopenharmony_ci			break;
19658c2ecf20Sopenharmony_ci	}
19668c2ecf20Sopenharmony_ci	return pdev;
19678c2ecf20Sopenharmony_ci}
19688c2ecf20Sopenharmony_ci
19698c2ecf20Sopenharmony_cistatic int sisfb_get_dram_size(struct sis_video_info *ivideo)
19708c2ecf20Sopenharmony_ci{
19718c2ecf20Sopenharmony_ci#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
19728c2ecf20Sopenharmony_ci	u8 reg;
19738c2ecf20Sopenharmony_ci#endif
19748c2ecf20Sopenharmony_ci
19758c2ecf20Sopenharmony_ci	ivideo->video_size = 0;
19768c2ecf20Sopenharmony_ci	ivideo->UMAsize = ivideo->LFBsize = 0;
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_ci	switch(ivideo->chip) {
19798c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
19808c2ecf20Sopenharmony_ci	case SIS_300:
19818c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x14);
19828c2ecf20Sopenharmony_ci		ivideo->video_size = ((reg & 0x3F) + 1) << 20;
19838c2ecf20Sopenharmony_ci		break;
19848c2ecf20Sopenharmony_ci	case SIS_540:
19858c2ecf20Sopenharmony_ci	case SIS_630:
19868c2ecf20Sopenharmony_ci	case SIS_730:
19878c2ecf20Sopenharmony_ci		if(!ivideo->nbridge)
19888c2ecf20Sopenharmony_ci			return -1;
19898c2ecf20Sopenharmony_ci		pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
19908c2ecf20Sopenharmony_ci		ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
19918c2ecf20Sopenharmony_ci		break;
19928c2ecf20Sopenharmony_ci#endif
19938c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
19948c2ecf20Sopenharmony_ci	case SIS_315H:
19958c2ecf20Sopenharmony_ci	case SIS_315PRO:
19968c2ecf20Sopenharmony_ci	case SIS_315:
19978c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x14);
19988c2ecf20Sopenharmony_ci		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
19998c2ecf20Sopenharmony_ci		switch((reg >> 2) & 0x03) {
20008c2ecf20Sopenharmony_ci		case 0x01:
20018c2ecf20Sopenharmony_ci		case 0x03:
20028c2ecf20Sopenharmony_ci			ivideo->video_size <<= 1;
20038c2ecf20Sopenharmony_ci			break;
20048c2ecf20Sopenharmony_ci		case 0x02:
20058c2ecf20Sopenharmony_ci			ivideo->video_size += (ivideo->video_size/2);
20068c2ecf20Sopenharmony_ci		}
20078c2ecf20Sopenharmony_ci		break;
20088c2ecf20Sopenharmony_ci	case SIS_330:
20098c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x14);
20108c2ecf20Sopenharmony_ci		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
20118c2ecf20Sopenharmony_ci		if(reg & 0x0c) ivideo->video_size <<= 1;
20128c2ecf20Sopenharmony_ci		break;
20138c2ecf20Sopenharmony_ci	case SIS_550:
20148c2ecf20Sopenharmony_ci	case SIS_650:
20158c2ecf20Sopenharmony_ci	case SIS_740:
20168c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x14);
20178c2ecf20Sopenharmony_ci		ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
20188c2ecf20Sopenharmony_ci		break;
20198c2ecf20Sopenharmony_ci	case SIS_661:
20208c2ecf20Sopenharmony_ci	case SIS_741:
20218c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0x79);
20228c2ecf20Sopenharmony_ci		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
20238c2ecf20Sopenharmony_ci		break;
20248c2ecf20Sopenharmony_ci	case SIS_660:
20258c2ecf20Sopenharmony_ci	case SIS_760:
20268c2ecf20Sopenharmony_ci	case SIS_761:
20278c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0x79);
20288c2ecf20Sopenharmony_ci		reg = (reg & 0xf0) >> 4;
20298c2ecf20Sopenharmony_ci		if(reg)	{
20308c2ecf20Sopenharmony_ci			ivideo->video_size = (1 << reg) << 20;
20318c2ecf20Sopenharmony_ci			ivideo->UMAsize = ivideo->video_size;
20328c2ecf20Sopenharmony_ci		}
20338c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0x78);
20348c2ecf20Sopenharmony_ci		reg &= 0x30;
20358c2ecf20Sopenharmony_ci		if(reg) {
20368c2ecf20Sopenharmony_ci			if(reg == 0x10) {
20378c2ecf20Sopenharmony_ci				ivideo->LFBsize = (32 << 20);
20388c2ecf20Sopenharmony_ci			} else {
20398c2ecf20Sopenharmony_ci				ivideo->LFBsize = (64 << 20);
20408c2ecf20Sopenharmony_ci			}
20418c2ecf20Sopenharmony_ci			ivideo->video_size += ivideo->LFBsize;
20428c2ecf20Sopenharmony_ci		}
20438c2ecf20Sopenharmony_ci		break;
20448c2ecf20Sopenharmony_ci	case SIS_340:
20458c2ecf20Sopenharmony_ci	case XGI_20:
20468c2ecf20Sopenharmony_ci	case XGI_40:
20478c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x14);
20488c2ecf20Sopenharmony_ci		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
20498c2ecf20Sopenharmony_ci		if(ivideo->chip != XGI_20) {
20508c2ecf20Sopenharmony_ci			reg = (reg & 0x0c) >> 2;
20518c2ecf20Sopenharmony_ci			if(ivideo->revision_id == 2) {
20528c2ecf20Sopenharmony_ci				if(reg & 0x01) reg = 0x02;
20538c2ecf20Sopenharmony_ci				else	       reg = 0x00;
20548c2ecf20Sopenharmony_ci			}
20558c2ecf20Sopenharmony_ci			if(reg == 0x02)		ivideo->video_size <<= 1;
20568c2ecf20Sopenharmony_ci			else if(reg == 0x03)	ivideo->video_size <<= 2;
20578c2ecf20Sopenharmony_ci		}
20588c2ecf20Sopenharmony_ci		break;
20598c2ecf20Sopenharmony_ci#endif
20608c2ecf20Sopenharmony_ci	default:
20618c2ecf20Sopenharmony_ci		return -1;
20628c2ecf20Sopenharmony_ci	}
20638c2ecf20Sopenharmony_ci	return 0;
20648c2ecf20Sopenharmony_ci}
20658c2ecf20Sopenharmony_ci
20668c2ecf20Sopenharmony_ci/* -------------- video bridge device detection --------------- */
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_cistatic void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
20698c2ecf20Sopenharmony_ci{
20708c2ecf20Sopenharmony_ci	u8 cr32, temp;
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_ci	/* No CRT2 on XGI Z7 */
20738c2ecf20Sopenharmony_ci	if(ivideo->chip == XGI_20) {
20748c2ecf20Sopenharmony_ci		ivideo->sisfb_crt1off = 0;
20758c2ecf20Sopenharmony_ci		return;
20768c2ecf20Sopenharmony_ci	}
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
20798c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
20808c2ecf20Sopenharmony_ci		temp = SiS_GetReg(SISSR, 0x17);
20818c2ecf20Sopenharmony_ci		if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
20828c2ecf20Sopenharmony_ci			/* PAL/NTSC is stored on SR16 on such machines */
20838c2ecf20Sopenharmony_ci			if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
20848c2ecf20Sopenharmony_ci				temp = SiS_GetReg(SISSR, 0x16);
20858c2ecf20Sopenharmony_ci				if(temp & 0x20)
20868c2ecf20Sopenharmony_ci					ivideo->vbflags |= TV_PAL;
20878c2ecf20Sopenharmony_ci				else
20888c2ecf20Sopenharmony_ci					ivideo->vbflags |= TV_NTSC;
20898c2ecf20Sopenharmony_ci			}
20908c2ecf20Sopenharmony_ci		}
20918c2ecf20Sopenharmony_ci	}
20928c2ecf20Sopenharmony_ci#endif
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_ci	cr32 = SiS_GetReg(SISCR, 0x32);
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci	if(cr32 & SIS_CRT1) {
20978c2ecf20Sopenharmony_ci		ivideo->sisfb_crt1off = 0;
20988c2ecf20Sopenharmony_ci	} else {
20998c2ecf20Sopenharmony_ci		ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
21008c2ecf20Sopenharmony_ci	}
21018c2ecf20Sopenharmony_ci
21028c2ecf20Sopenharmony_ci	ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
21038c2ecf20Sopenharmony_ci
21048c2ecf20Sopenharmony_ci	if(cr32 & SIS_VB_TV)   ivideo->vbflags |= CRT2_TV;
21058c2ecf20Sopenharmony_ci	if(cr32 & SIS_VB_LCD)  ivideo->vbflags |= CRT2_LCD;
21068c2ecf20Sopenharmony_ci	if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_ci	/* Check given parms for hardware compatibility.
21098c2ecf20Sopenharmony_ci	 * (Cannot do this in the search_xx routines since we don't
21108c2ecf20Sopenharmony_ci	 * know what hardware we are running on then)
21118c2ecf20Sopenharmony_ci	 */
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci	if(ivideo->chip != SIS_550) {
21148c2ecf20Sopenharmony_ci	   ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
21158c2ecf20Sopenharmony_ci	}
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_ci	if(ivideo->sisfb_tvplug != -1) {
21188c2ecf20Sopenharmony_ci	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
21198c2ecf20Sopenharmony_ci	       (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
21208c2ecf20Sopenharmony_ci	      if(ivideo->sisfb_tvplug & TV_YPBPR) {
21218c2ecf20Sopenharmony_ci		 ivideo->sisfb_tvplug = -1;
21228c2ecf20Sopenharmony_ci		 printk(KERN_ERR "sisfb: YPbPr not supported\n");
21238c2ecf20Sopenharmony_ci	      }
21248c2ecf20Sopenharmony_ci	   }
21258c2ecf20Sopenharmony_ci	}
21268c2ecf20Sopenharmony_ci	if(ivideo->sisfb_tvplug != -1) {
21278c2ecf20Sopenharmony_ci	   if( (ivideo->sisvga_engine != SIS_315_VGA) ||
21288c2ecf20Sopenharmony_ci	       (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
21298c2ecf20Sopenharmony_ci	      if(ivideo->sisfb_tvplug & TV_HIVISION) {
21308c2ecf20Sopenharmony_ci		 ivideo->sisfb_tvplug = -1;
21318c2ecf20Sopenharmony_ci		 printk(KERN_ERR "sisfb: HiVision not supported\n");
21328c2ecf20Sopenharmony_ci	      }
21338c2ecf20Sopenharmony_ci	   }
21348c2ecf20Sopenharmony_ci	}
21358c2ecf20Sopenharmony_ci	if(ivideo->sisfb_tvstd != -1) {
21368c2ecf20Sopenharmony_ci	   if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
21378c2ecf20Sopenharmony_ci	       (!((ivideo->sisvga_engine == SIS_315_VGA) &&
21388c2ecf20Sopenharmony_ci			(ivideo->vbflags2 & VB2_CHRONTEL))) ) {
21398c2ecf20Sopenharmony_ci	      if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
21408c2ecf20Sopenharmony_ci		 ivideo->sisfb_tvstd = -1;
21418c2ecf20Sopenharmony_ci		 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
21428c2ecf20Sopenharmony_ci	      }
21438c2ecf20Sopenharmony_ci	   }
21448c2ecf20Sopenharmony_ci	}
21458c2ecf20Sopenharmony_ci
21468c2ecf20Sopenharmony_ci	/* Detect/set TV plug & type */
21478c2ecf20Sopenharmony_ci	if(ivideo->sisfb_tvplug != -1) {
21488c2ecf20Sopenharmony_ci		ivideo->vbflags |= ivideo->sisfb_tvplug;
21498c2ecf20Sopenharmony_ci	} else {
21508c2ecf20Sopenharmony_ci		if(cr32 & SIS_VB_YPBPR)     	 ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
21518c2ecf20Sopenharmony_ci		else if(cr32 & SIS_VB_HIVISION)  ivideo->vbflags |= TV_HIVISION;
21528c2ecf20Sopenharmony_ci		else if(cr32 & SIS_VB_SCART)     ivideo->vbflags |= TV_SCART;
21538c2ecf20Sopenharmony_ci		else {
21548c2ecf20Sopenharmony_ci			if(cr32 & SIS_VB_SVIDEO)    ivideo->vbflags |= TV_SVIDEO;
21558c2ecf20Sopenharmony_ci			if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
21568c2ecf20Sopenharmony_ci		}
21578c2ecf20Sopenharmony_ci	}
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ci	if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
21608c2ecf20Sopenharmony_ci	    if(ivideo->sisfb_tvstd != -1) {
21618c2ecf20Sopenharmony_ci	       ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
21628c2ecf20Sopenharmony_ci	       ivideo->vbflags |= ivideo->sisfb_tvstd;
21638c2ecf20Sopenharmony_ci	    }
21648c2ecf20Sopenharmony_ci	    if(ivideo->vbflags & TV_SCART) {
21658c2ecf20Sopenharmony_ci	       ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
21668c2ecf20Sopenharmony_ci	       ivideo->vbflags |= TV_PAL;
21678c2ecf20Sopenharmony_ci	    }
21688c2ecf20Sopenharmony_ci	    if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
21698c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_300_VGA) {
21708c2ecf20Sopenharmony_ci			temp = SiS_GetReg(SISSR, 0x38);
21718c2ecf20Sopenharmony_ci			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
21728c2ecf20Sopenharmony_ci			else		ivideo->vbflags |= TV_NTSC;
21738c2ecf20Sopenharmony_ci		} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
21748c2ecf20Sopenharmony_ci			temp = SiS_GetReg(SISSR, 0x38);
21758c2ecf20Sopenharmony_ci			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
21768c2ecf20Sopenharmony_ci			else		ivideo->vbflags |= TV_NTSC;
21778c2ecf20Sopenharmony_ci		} else {
21788c2ecf20Sopenharmony_ci			temp = SiS_GetReg(SISCR, 0x79);
21798c2ecf20Sopenharmony_ci			if(temp & 0x20)	ivideo->vbflags |= TV_PAL;
21808c2ecf20Sopenharmony_ci			else		ivideo->vbflags |= TV_NTSC;
21818c2ecf20Sopenharmony_ci		}
21828c2ecf20Sopenharmony_ci	    }
21838c2ecf20Sopenharmony_ci	}
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_ci	/* Copy forceCRT1 option to CRT1off if option is given */
21868c2ecf20Sopenharmony_ci	if(ivideo->sisfb_forcecrt1 != -1) {
21878c2ecf20Sopenharmony_ci	   ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
21888c2ecf20Sopenharmony_ci	}
21898c2ecf20Sopenharmony_ci}
21908c2ecf20Sopenharmony_ci
21918c2ecf20Sopenharmony_ci/* ------------------ Sensing routines ------------------ */
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_cistatic bool sisfb_test_DDC1(struct sis_video_info *ivideo)
21948c2ecf20Sopenharmony_ci{
21958c2ecf20Sopenharmony_ci    unsigned short old;
21968c2ecf20Sopenharmony_ci    int count = 48;
21978c2ecf20Sopenharmony_ci
21988c2ecf20Sopenharmony_ci    old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
21998c2ecf20Sopenharmony_ci    do {
22008c2ecf20Sopenharmony_ci	if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
22018c2ecf20Sopenharmony_ci    } while(count--);
22028c2ecf20Sopenharmony_ci    return (count != -1);
22038c2ecf20Sopenharmony_ci}
22048c2ecf20Sopenharmony_ci
22058c2ecf20Sopenharmony_cistatic void sisfb_sense_crt1(struct sis_video_info *ivideo)
22068c2ecf20Sopenharmony_ci{
22078c2ecf20Sopenharmony_ci    bool mustwait = false;
22088c2ecf20Sopenharmony_ci    u8  sr1F, cr17;
22098c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
22108c2ecf20Sopenharmony_ci    u8  cr63=0;
22118c2ecf20Sopenharmony_ci#endif
22128c2ecf20Sopenharmony_ci    u16 temp = 0xffff;
22138c2ecf20Sopenharmony_ci    int i;
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_ci    sr1F = SiS_GetReg(SISSR, 0x1F);
22168c2ecf20Sopenharmony_ci    SiS_SetRegOR(SISSR, 0x1F, 0x04);
22178c2ecf20Sopenharmony_ci    SiS_SetRegAND(SISSR, 0x1F, 0x3F);
22188c2ecf20Sopenharmony_ci    if(sr1F & 0xc0) mustwait = true;
22198c2ecf20Sopenharmony_ci
22208c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
22218c2ecf20Sopenharmony_ci    if(ivideo->sisvga_engine == SIS_315_VGA) {
22228c2ecf20Sopenharmony_ci       cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
22238c2ecf20Sopenharmony_ci       cr63 &= 0x40;
22248c2ecf20Sopenharmony_ci       SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
22258c2ecf20Sopenharmony_ci    }
22268c2ecf20Sopenharmony_ci#endif
22278c2ecf20Sopenharmony_ci
22288c2ecf20Sopenharmony_ci    cr17 = SiS_GetReg(SISCR, 0x17);
22298c2ecf20Sopenharmony_ci    cr17 &= 0x80;
22308c2ecf20Sopenharmony_ci    if(!cr17) {
22318c2ecf20Sopenharmony_ci       SiS_SetRegOR(SISCR, 0x17, 0x80);
22328c2ecf20Sopenharmony_ci       mustwait = true;
22338c2ecf20Sopenharmony_ci       SiS_SetReg(SISSR, 0x00, 0x01);
22348c2ecf20Sopenharmony_ci       SiS_SetReg(SISSR, 0x00, 0x03);
22358c2ecf20Sopenharmony_ci    }
22368c2ecf20Sopenharmony_ci
22378c2ecf20Sopenharmony_ci    if(mustwait) {
22388c2ecf20Sopenharmony_ci       for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
22398c2ecf20Sopenharmony_ci    }
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
22428c2ecf20Sopenharmony_ci    if(ivideo->chip >= SIS_330) {
22438c2ecf20Sopenharmony_ci       SiS_SetRegAND(SISCR, 0x32, ~0x20);
22448c2ecf20Sopenharmony_ci       if(ivideo->chip >= SIS_340) {
22458c2ecf20Sopenharmony_ci	   SiS_SetReg(SISCR, 0x57, 0x4a);
22468c2ecf20Sopenharmony_ci       } else {
22478c2ecf20Sopenharmony_ci	   SiS_SetReg(SISCR, 0x57, 0x5f);
22488c2ecf20Sopenharmony_ci       }
22498c2ecf20Sopenharmony_ci	SiS_SetRegOR(SISCR, 0x53, 0x02);
22508c2ecf20Sopenharmony_ci	while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)    break;
22518c2ecf20Sopenharmony_ci	while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
22528c2ecf20Sopenharmony_ci	if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
22538c2ecf20Sopenharmony_ci	SiS_SetRegAND(SISCR, 0x53, 0xfd);
22548c2ecf20Sopenharmony_ci	SiS_SetRegAND(SISCR, 0x57, 0x00);
22558c2ecf20Sopenharmony_ci    }
22568c2ecf20Sopenharmony_ci#endif
22578c2ecf20Sopenharmony_ci
22588c2ecf20Sopenharmony_ci    if(temp == 0xffff) {
22598c2ecf20Sopenharmony_ci       i = 3;
22608c2ecf20Sopenharmony_ci       do {
22618c2ecf20Sopenharmony_ci	  temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
22628c2ecf20Sopenharmony_ci		ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
22638c2ecf20Sopenharmony_ci       } while(((temp == 0) || (temp == 0xffff)) && i--);
22648c2ecf20Sopenharmony_ci
22658c2ecf20Sopenharmony_ci       if((temp == 0) || (temp == 0xffff)) {
22668c2ecf20Sopenharmony_ci          if(sisfb_test_DDC1(ivideo)) temp = 1;
22678c2ecf20Sopenharmony_ci       }
22688c2ecf20Sopenharmony_ci    }
22698c2ecf20Sopenharmony_ci
22708c2ecf20Sopenharmony_ci    if((temp) && (temp != 0xffff)) {
22718c2ecf20Sopenharmony_ci       SiS_SetRegOR(SISCR, 0x32, 0x20);
22728c2ecf20Sopenharmony_ci    }
22738c2ecf20Sopenharmony_ci
22748c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
22758c2ecf20Sopenharmony_ci    if(ivideo->sisvga_engine == SIS_315_VGA) {
22768c2ecf20Sopenharmony_ci	SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
22778c2ecf20Sopenharmony_ci    }
22788c2ecf20Sopenharmony_ci#endif
22798c2ecf20Sopenharmony_ci
22808c2ecf20Sopenharmony_ci    SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_ci    SiS_SetReg(SISSR, 0x1F, sr1F);
22838c2ecf20Sopenharmony_ci}
22848c2ecf20Sopenharmony_ci
22858c2ecf20Sopenharmony_ci/* Determine and detect attached devices on SiS30x */
22868c2ecf20Sopenharmony_cistatic void SiS_SenseLCD(struct sis_video_info *ivideo)
22878c2ecf20Sopenharmony_ci{
22888c2ecf20Sopenharmony_ci	unsigned char buffer[256];
22898c2ecf20Sopenharmony_ci	unsigned short temp, realcrtno, i;
22908c2ecf20Sopenharmony_ci	u8 reg, cr37 = 0, paneltype = 0;
22918c2ecf20Sopenharmony_ci	u16 xres, yres;
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.PanelSelfDetected = false;
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_ci	/* LCD detection only for TMDS bridges */
22968c2ecf20Sopenharmony_ci	if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
22978c2ecf20Sopenharmony_ci		return;
22988c2ecf20Sopenharmony_ci	if(ivideo->vbflags2 & VB2_30xBDH)
22998c2ecf20Sopenharmony_ci		return;
23008c2ecf20Sopenharmony_ci
23018c2ecf20Sopenharmony_ci	/* If LCD already set up by BIOS, skip it */
23028c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISCR, 0x32);
23038c2ecf20Sopenharmony_ci	if(reg & 0x08)
23048c2ecf20Sopenharmony_ci		return;
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_ci	realcrtno = 1;
23078c2ecf20Sopenharmony_ci	if(ivideo->SiS_Pr.DDCPortMixup)
23088c2ecf20Sopenharmony_ci		realcrtno = 0;
23098c2ecf20Sopenharmony_ci
23108c2ecf20Sopenharmony_ci	/* Check DDC capabilities */
23118c2ecf20Sopenharmony_ci	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
23128c2ecf20Sopenharmony_ci				realcrtno, 0, &buffer[0], ivideo->vbflags2);
23138c2ecf20Sopenharmony_ci
23148c2ecf20Sopenharmony_ci	if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
23158c2ecf20Sopenharmony_ci		return;
23168c2ecf20Sopenharmony_ci
23178c2ecf20Sopenharmony_ci	/* Read DDC data */
23188c2ecf20Sopenharmony_ci	i = 3;  /* Number of retrys */
23198c2ecf20Sopenharmony_ci	do {
23208c2ecf20Sopenharmony_ci		temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
23218c2ecf20Sopenharmony_ci				ivideo->sisvga_engine, realcrtno, 1,
23228c2ecf20Sopenharmony_ci				&buffer[0], ivideo->vbflags2);
23238c2ecf20Sopenharmony_ci	} while((temp) && i--);
23248c2ecf20Sopenharmony_ci
23258c2ecf20Sopenharmony_ci	if(temp)
23268c2ecf20Sopenharmony_ci		return;
23278c2ecf20Sopenharmony_ci
23288c2ecf20Sopenharmony_ci	/* No digital device */
23298c2ecf20Sopenharmony_ci	if(!(buffer[0x14] & 0x80))
23308c2ecf20Sopenharmony_ci		return;
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_ci	/* First detailed timing preferred timing? */
23338c2ecf20Sopenharmony_ci	if(!(buffer[0x18] & 0x02))
23348c2ecf20Sopenharmony_ci		return;
23358c2ecf20Sopenharmony_ci
23368c2ecf20Sopenharmony_ci	xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
23378c2ecf20Sopenharmony_ci	yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_ci	switch(xres) {
23408c2ecf20Sopenharmony_ci		case 1024:
23418c2ecf20Sopenharmony_ci			if(yres == 768)
23428c2ecf20Sopenharmony_ci				paneltype = 0x02;
23438c2ecf20Sopenharmony_ci			break;
23448c2ecf20Sopenharmony_ci		case 1280:
23458c2ecf20Sopenharmony_ci			if(yres == 1024)
23468c2ecf20Sopenharmony_ci				paneltype = 0x03;
23478c2ecf20Sopenharmony_ci			break;
23488c2ecf20Sopenharmony_ci		case 1600:
23498c2ecf20Sopenharmony_ci			if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
23508c2ecf20Sopenharmony_ci				paneltype = 0x0b;
23518c2ecf20Sopenharmony_ci			break;
23528c2ecf20Sopenharmony_ci	}
23538c2ecf20Sopenharmony_ci
23548c2ecf20Sopenharmony_ci	if(!paneltype)
23558c2ecf20Sopenharmony_ci		return;
23568c2ecf20Sopenharmony_ci
23578c2ecf20Sopenharmony_ci	if(buffer[0x23])
23588c2ecf20Sopenharmony_ci		cr37 |= 0x10;
23598c2ecf20Sopenharmony_ci
23608c2ecf20Sopenharmony_ci	if((buffer[0x47] & 0x18) == 0x18)
23618c2ecf20Sopenharmony_ci		cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
23628c2ecf20Sopenharmony_ci	else
23638c2ecf20Sopenharmony_ci		cr37 |= 0xc0;
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x36, paneltype);
23668c2ecf20Sopenharmony_ci	cr37 &= 0xf1;
23678c2ecf20Sopenharmony_ci	SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
23688c2ecf20Sopenharmony_ci	SiS_SetRegOR(SISCR, 0x32, 0x08);
23698c2ecf20Sopenharmony_ci
23708c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.PanelSelfDetected = true;
23718c2ecf20Sopenharmony_ci}
23728c2ecf20Sopenharmony_ci
23738c2ecf20Sopenharmony_cistatic int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
23748c2ecf20Sopenharmony_ci{
23758c2ecf20Sopenharmony_ci    int temp, mytest, result, i, j;
23768c2ecf20Sopenharmony_ci
23778c2ecf20Sopenharmony_ci    for(j = 0; j < 10; j++) {
23788c2ecf20Sopenharmony_ci       result = 0;
23798c2ecf20Sopenharmony_ci       for(i = 0; i < 3; i++) {
23808c2ecf20Sopenharmony_ci          mytest = test;
23818c2ecf20Sopenharmony_ci	   SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
23828c2ecf20Sopenharmony_ci          temp = (type >> 8) | (mytest & 0x00ff);
23838c2ecf20Sopenharmony_ci	  SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
23848c2ecf20Sopenharmony_ci          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
23858c2ecf20Sopenharmony_ci          mytest >>= 8;
23868c2ecf20Sopenharmony_ci          mytest &= 0x7f;
23878c2ecf20Sopenharmony_ci	   temp = SiS_GetReg(SISPART4, 0x03);
23888c2ecf20Sopenharmony_ci          temp ^= 0x0e;
23898c2ecf20Sopenharmony_ci          temp &= mytest;
23908c2ecf20Sopenharmony_ci          if(temp == mytest) result++;
23918c2ecf20Sopenharmony_ci#if 1
23928c2ecf20Sopenharmony_ci	  SiS_SetReg(SISPART4, 0x11, 0x00);
23938c2ecf20Sopenharmony_ci	  SiS_SetRegAND(SISPART4, 0x10, 0xe0);
23948c2ecf20Sopenharmony_ci	  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
23958c2ecf20Sopenharmony_ci#endif
23968c2ecf20Sopenharmony_ci       }
23978c2ecf20Sopenharmony_ci       if((result == 0) || (result >= 2)) break;
23988c2ecf20Sopenharmony_ci    }
23998c2ecf20Sopenharmony_ci    return result;
24008c2ecf20Sopenharmony_ci}
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_cistatic void SiS_Sense30x(struct sis_video_info *ivideo)
24038c2ecf20Sopenharmony_ci{
24048c2ecf20Sopenharmony_ci    u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
24058c2ecf20Sopenharmony_ci    u16 svhs=0, svhs_c=0;
24068c2ecf20Sopenharmony_ci    u16 cvbs=0, cvbs_c=0;
24078c2ecf20Sopenharmony_ci    u16 vga2=0, vga2_c=0;
24088c2ecf20Sopenharmony_ci    int myflag, result;
24098c2ecf20Sopenharmony_ci    char stdstr[] = "sisfb: Detected";
24108c2ecf20Sopenharmony_ci    char tvstr[]  = "TV connected to";
24118c2ecf20Sopenharmony_ci
24128c2ecf20Sopenharmony_ci    if(ivideo->vbflags2 & VB2_301) {
24138c2ecf20Sopenharmony_ci       svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
24148c2ecf20Sopenharmony_ci       myflag = SiS_GetReg(SISPART4, 0x01);
24158c2ecf20Sopenharmony_ci       if(myflag & 0x04) {
24168c2ecf20Sopenharmony_ci	  svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
24178c2ecf20Sopenharmony_ci       }
24188c2ecf20Sopenharmony_ci    } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
24198c2ecf20Sopenharmony_ci       svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
24208c2ecf20Sopenharmony_ci    } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
24218c2ecf20Sopenharmony_ci       svhs = 0x0200; cvbs = 0x0100;
24228c2ecf20Sopenharmony_ci    } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
24238c2ecf20Sopenharmony_ci       svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
24248c2ecf20Sopenharmony_ci    } else
24258c2ecf20Sopenharmony_ci       return;
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_ci    vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
24288c2ecf20Sopenharmony_ci    if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
24298c2ecf20Sopenharmony_ci       svhs_c = 0x0408; cvbs_c = 0x0808;
24308c2ecf20Sopenharmony_ci    }
24318c2ecf20Sopenharmony_ci
24328c2ecf20Sopenharmony_ci    biosflag = 2;
24338c2ecf20Sopenharmony_ci    if(ivideo->haveXGIROM) {
24348c2ecf20Sopenharmony_ci       biosflag = ivideo->bios_abase[0x58] & 0x03;
24358c2ecf20Sopenharmony_ci    } else if(ivideo->newrom) {
24368c2ecf20Sopenharmony_ci       if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
24378c2ecf20Sopenharmony_ci    } else if(ivideo->sisvga_engine == SIS_300_VGA) {
24388c2ecf20Sopenharmony_ci       if(ivideo->bios_abase) {
24398c2ecf20Sopenharmony_ci          biosflag = ivideo->bios_abase[0xfe] & 0x03;
24408c2ecf20Sopenharmony_ci       }
24418c2ecf20Sopenharmony_ci    }
24428c2ecf20Sopenharmony_ci
24438c2ecf20Sopenharmony_ci    if(ivideo->chip == SIS_300) {
24448c2ecf20Sopenharmony_ci       myflag = SiS_GetReg(SISSR, 0x3b);
24458c2ecf20Sopenharmony_ci       if(!(myflag & 0x01)) vga2 = vga2_c = 0;
24468c2ecf20Sopenharmony_ci    }
24478c2ecf20Sopenharmony_ci
24488c2ecf20Sopenharmony_ci    if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
24498c2ecf20Sopenharmony_ci       vga2 = vga2_c = 0;
24508c2ecf20Sopenharmony_ci    }
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_ci    backupSR_1e = SiS_GetReg(SISSR, 0x1e);
24538c2ecf20Sopenharmony_ci    SiS_SetRegOR(SISSR, 0x1e, 0x20);
24548c2ecf20Sopenharmony_ci
24558c2ecf20Sopenharmony_ci    backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
24568c2ecf20Sopenharmony_ci    if(ivideo->vbflags2 & VB2_30xC) {
24578c2ecf20Sopenharmony_ci	SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
24588c2ecf20Sopenharmony_ci    } else {
24598c2ecf20Sopenharmony_ci       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
24608c2ecf20Sopenharmony_ci    }
24618c2ecf20Sopenharmony_ci    SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_ci    backupP2_00 = SiS_GetReg(SISPART2, 0x00);
24648c2ecf20Sopenharmony_ci    SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
24658c2ecf20Sopenharmony_ci
24668c2ecf20Sopenharmony_ci    backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
24678c2ecf20Sopenharmony_ci    if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
24688c2ecf20Sopenharmony_ci	SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
24698c2ecf20Sopenharmony_ci    }
24708c2ecf20Sopenharmony_ci
24718c2ecf20Sopenharmony_ci    if(!(ivideo->vbflags2 & VB2_30xCLV)) {
24728c2ecf20Sopenharmony_ci       SISDoSense(ivideo, 0, 0);
24738c2ecf20Sopenharmony_ci    }
24748c2ecf20Sopenharmony_ci
24758c2ecf20Sopenharmony_ci    SiS_SetRegAND(SISCR, 0x32, ~0x14);
24768c2ecf20Sopenharmony_ci
24778c2ecf20Sopenharmony_ci    if(vga2_c || vga2) {
24788c2ecf20Sopenharmony_ci       if(SISDoSense(ivideo, vga2, vga2_c)) {
24798c2ecf20Sopenharmony_ci          if(biosflag & 0x01) {
24808c2ecf20Sopenharmony_ci	     printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
24818c2ecf20Sopenharmony_ci	     SiS_SetRegOR(SISCR, 0x32, 0x04);
24828c2ecf20Sopenharmony_ci	  } else {
24838c2ecf20Sopenharmony_ci	     printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
24848c2ecf20Sopenharmony_ci	     SiS_SetRegOR(SISCR, 0x32, 0x10);
24858c2ecf20Sopenharmony_ci	  }
24868c2ecf20Sopenharmony_ci       }
24878c2ecf20Sopenharmony_ci    }
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_ci    SiS_SetRegAND(SISCR, 0x32, 0x3f);
24908c2ecf20Sopenharmony_ci
24918c2ecf20Sopenharmony_ci    if(ivideo->vbflags2 & VB2_30xCLV) {
24928c2ecf20Sopenharmony_ci       SiS_SetRegOR(SISPART4, 0x0d, 0x04);
24938c2ecf20Sopenharmony_ci    }
24948c2ecf20Sopenharmony_ci
24958c2ecf20Sopenharmony_ci    if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
24968c2ecf20Sopenharmony_ci       SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
24978c2ecf20Sopenharmony_ci       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
24988c2ecf20Sopenharmony_ci       if((result = SISDoSense(ivideo, svhs, 0x0604))) {
24998c2ecf20Sopenharmony_ci          if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
25008c2ecf20Sopenharmony_ci	     printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
25018c2ecf20Sopenharmony_ci	     SiS_SetRegOR(SISCR, 0x32, 0x80);
25028c2ecf20Sopenharmony_ci	  }
25038c2ecf20Sopenharmony_ci       }
25048c2ecf20Sopenharmony_ci       SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
25058c2ecf20Sopenharmony_ci    }
25068c2ecf20Sopenharmony_ci
25078c2ecf20Sopenharmony_ci    SiS_SetRegAND(SISCR, 0x32, ~0x03);
25088c2ecf20Sopenharmony_ci
25098c2ecf20Sopenharmony_ci    if(!(ivideo->vbflags & TV_YPBPR)) {
25108c2ecf20Sopenharmony_ci       if((result = SISDoSense(ivideo, svhs, svhs_c))) {
25118c2ecf20Sopenharmony_ci          printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
25128c2ecf20Sopenharmony_ci	   SiS_SetRegOR(SISCR, 0x32, 0x02);
25138c2ecf20Sopenharmony_ci       }
25148c2ecf20Sopenharmony_ci       if((biosflag & 0x02) || (!result)) {
25158c2ecf20Sopenharmony_ci          if(SISDoSense(ivideo, cvbs, cvbs_c)) {
25168c2ecf20Sopenharmony_ci	     printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
25178c2ecf20Sopenharmony_ci	     SiS_SetRegOR(SISCR, 0x32, 0x01);
25188c2ecf20Sopenharmony_ci          }
25198c2ecf20Sopenharmony_ci       }
25208c2ecf20Sopenharmony_ci    }
25218c2ecf20Sopenharmony_ci
25228c2ecf20Sopenharmony_ci    SISDoSense(ivideo, 0, 0);
25238c2ecf20Sopenharmony_ci
25248c2ecf20Sopenharmony_ci    SiS_SetReg(SISPART2, 0x00, backupP2_00);
25258c2ecf20Sopenharmony_ci    SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
25268c2ecf20Sopenharmony_ci    SiS_SetReg(SISSR, 0x1e, backupSR_1e);
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_ci    if(ivideo->vbflags2 & VB2_30xCLV) {
25298c2ecf20Sopenharmony_ci	biosflag = SiS_GetReg(SISPART2, 0x00);
25308c2ecf20Sopenharmony_ci       if(biosflag & 0x20) {
25318c2ecf20Sopenharmony_ci          for(myflag = 2; myflag > 0; myflag--) {
25328c2ecf20Sopenharmony_ci	     biosflag ^= 0x20;
25338c2ecf20Sopenharmony_ci	     SiS_SetReg(SISPART2, 0x00, biosflag);
25348c2ecf20Sopenharmony_ci	  }
25358c2ecf20Sopenharmony_ci       }
25368c2ecf20Sopenharmony_ci    }
25378c2ecf20Sopenharmony_ci
25388c2ecf20Sopenharmony_ci    SiS_SetReg(SISPART2, 0x00, backupP2_00);
25398c2ecf20Sopenharmony_ci}
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci/* Determine and detect attached TV's on Chrontel */
25428c2ecf20Sopenharmony_cistatic void SiS_SenseCh(struct sis_video_info *ivideo)
25438c2ecf20Sopenharmony_ci{
25448c2ecf20Sopenharmony_ci#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
25458c2ecf20Sopenharmony_ci    u8 temp1, temp2;
25468c2ecf20Sopenharmony_ci    char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
25478c2ecf20Sopenharmony_ci#endif
25488c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
25498c2ecf20Sopenharmony_ci    unsigned char test[3];
25508c2ecf20Sopenharmony_ci    int i;
25518c2ecf20Sopenharmony_ci#endif
25528c2ecf20Sopenharmony_ci
25538c2ecf20Sopenharmony_ci    if(ivideo->chip < SIS_315H) {
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
25568c2ecf20Sopenharmony_ci       ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* Chrontel 700x */
25578c2ecf20Sopenharmony_ci       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c);	/* Set general purpose IO for Chrontel communication */
25588c2ecf20Sopenharmony_ci       SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
25598c2ecf20Sopenharmony_ci       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
25608c2ecf20Sopenharmony_ci       /* See Chrontel TB31 for explanation */
25618c2ecf20Sopenharmony_ci       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
25628c2ecf20Sopenharmony_ci       if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
25638c2ecf20Sopenharmony_ci	  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
25648c2ecf20Sopenharmony_ci	  SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
25658c2ecf20Sopenharmony_ci       }
25668c2ecf20Sopenharmony_ci       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
25678c2ecf20Sopenharmony_ci       if(temp2 != temp1) temp1 = temp2;
25688c2ecf20Sopenharmony_ci
25698c2ecf20Sopenharmony_ci       if((temp1 >= 0x22) && (temp1 <= 0x50)) {
25708c2ecf20Sopenharmony_ci	   /* Read power status */
25718c2ecf20Sopenharmony_ci	   temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
25728c2ecf20Sopenharmony_ci	   if((temp1 & 0x03) != 0x03) {
25738c2ecf20Sopenharmony_ci		/* Power all outputs */
25748c2ecf20Sopenharmony_ci		SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
25758c2ecf20Sopenharmony_ci		SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
25768c2ecf20Sopenharmony_ci	   }
25778c2ecf20Sopenharmony_ci	   /* Sense connected TV devices */
25788c2ecf20Sopenharmony_ci	   for(i = 0; i < 3; i++) {
25798c2ecf20Sopenharmony_ci	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
25808c2ecf20Sopenharmony_ci	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
25818c2ecf20Sopenharmony_ci	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
25828c2ecf20Sopenharmony_ci	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
25838c2ecf20Sopenharmony_ci	       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
25848c2ecf20Sopenharmony_ci	       if(!(temp1 & 0x08))       test[i] = 0x02;
25858c2ecf20Sopenharmony_ci	       else if(!(temp1 & 0x02))  test[i] = 0x01;
25868c2ecf20Sopenharmony_ci	       else                      test[i] = 0;
25878c2ecf20Sopenharmony_ci	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
25888c2ecf20Sopenharmony_ci	   }
25898c2ecf20Sopenharmony_ci
25908c2ecf20Sopenharmony_ci	   if(test[0] == test[1])      temp1 = test[0];
25918c2ecf20Sopenharmony_ci	   else if(test[0] == test[2]) temp1 = test[0];
25928c2ecf20Sopenharmony_ci	   else if(test[1] == test[2]) temp1 = test[1];
25938c2ecf20Sopenharmony_ci	   else {
25948c2ecf20Sopenharmony_ci		printk(KERN_INFO
25958c2ecf20Sopenharmony_ci			"sisfb: TV detection unreliable - test results varied\n");
25968c2ecf20Sopenharmony_ci		temp1 = test[2];
25978c2ecf20Sopenharmony_ci	   }
25988c2ecf20Sopenharmony_ci	   if(temp1 == 0x02) {
25998c2ecf20Sopenharmony_ci		printk(KERN_INFO "%s SVIDEO output\n", stdstr);
26008c2ecf20Sopenharmony_ci		ivideo->vbflags |= TV_SVIDEO;
26018c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISCR, 0x32, 0x02);
26028c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISCR, 0x32, ~0x05);
26038c2ecf20Sopenharmony_ci	   } else if (temp1 == 0x01) {
26048c2ecf20Sopenharmony_ci		printk(KERN_INFO "%s CVBS output\n", stdstr);
26058c2ecf20Sopenharmony_ci		ivideo->vbflags |= TV_AVIDEO;
26068c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISCR, 0x32, 0x01);
26078c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISCR, 0x32, ~0x06);
26088c2ecf20Sopenharmony_ci	   } else {
26098c2ecf20Sopenharmony_ci		SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
26108c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISCR, 0x32, ~0x07);
26118c2ecf20Sopenharmony_ci	   }
26128c2ecf20Sopenharmony_ci       } else if(temp1 == 0) {
26138c2ecf20Sopenharmony_ci	  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
26148c2ecf20Sopenharmony_ci	  SiS_SetRegAND(SISCR, 0x32, ~0x07);
26158c2ecf20Sopenharmony_ci       }
26168c2ecf20Sopenharmony_ci       /* Set general purpose IO for Chrontel communication */
26178c2ecf20Sopenharmony_ci       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
26188c2ecf20Sopenharmony_ci#endif
26198c2ecf20Sopenharmony_ci
26208c2ecf20Sopenharmony_ci    } else {
26218c2ecf20Sopenharmony_ci
26228c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
26238c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* Chrontel 7019 */
26248c2ecf20Sopenharmony_ci	temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
26258c2ecf20Sopenharmony_ci	SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
26268c2ecf20Sopenharmony_ci	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
26278c2ecf20Sopenharmony_ci	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
26288c2ecf20Sopenharmony_ci	temp2 |= 0x01;
26298c2ecf20Sopenharmony_ci	SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
26308c2ecf20Sopenharmony_ci	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
26318c2ecf20Sopenharmony_ci	temp2 ^= 0x01;
26328c2ecf20Sopenharmony_ci	SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
26338c2ecf20Sopenharmony_ci	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
26348c2ecf20Sopenharmony_ci	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
26358c2ecf20Sopenharmony_ci	SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
26368c2ecf20Sopenharmony_ci	temp1 = 0;
26378c2ecf20Sopenharmony_ci	if(temp2 & 0x02) temp1 |= 0x01;
26388c2ecf20Sopenharmony_ci	if(temp2 & 0x10) temp1 |= 0x01;
26398c2ecf20Sopenharmony_ci	if(temp2 & 0x04) temp1 |= 0x02;
26408c2ecf20Sopenharmony_ci	if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
26418c2ecf20Sopenharmony_ci	switch(temp1) {
26428c2ecf20Sopenharmony_ci	case 0x01:
26438c2ecf20Sopenharmony_ci	     printk(KERN_INFO "%s CVBS output\n", stdstr);
26448c2ecf20Sopenharmony_ci	     ivideo->vbflags |= TV_AVIDEO;
26458c2ecf20Sopenharmony_ci	     SiS_SetRegOR(SISCR, 0x32, 0x01);
26468c2ecf20Sopenharmony_ci	     SiS_SetRegAND(SISCR, 0x32, ~0x06);
26478c2ecf20Sopenharmony_ci	     break;
26488c2ecf20Sopenharmony_ci	case 0x02:
26498c2ecf20Sopenharmony_ci	     printk(KERN_INFO "%s SVIDEO output\n", stdstr);
26508c2ecf20Sopenharmony_ci	     ivideo->vbflags |= TV_SVIDEO;
26518c2ecf20Sopenharmony_ci	     SiS_SetRegOR(SISCR, 0x32, 0x02);
26528c2ecf20Sopenharmony_ci	     SiS_SetRegAND(SISCR, 0x32, ~0x05);
26538c2ecf20Sopenharmony_ci	     break;
26548c2ecf20Sopenharmony_ci	case 0x04:
26558c2ecf20Sopenharmony_ci	     printk(KERN_INFO "%s SCART output\n", stdstr);
26568c2ecf20Sopenharmony_ci	     SiS_SetRegOR(SISCR, 0x32, 0x04);
26578c2ecf20Sopenharmony_ci	     SiS_SetRegAND(SISCR, 0x32, ~0x03);
26588c2ecf20Sopenharmony_ci	     break;
26598c2ecf20Sopenharmony_ci	default:
26608c2ecf20Sopenharmony_ci	     SiS_SetRegAND(SISCR, 0x32, ~0x07);
26618c2ecf20Sopenharmony_ci	}
26628c2ecf20Sopenharmony_ci#endif
26638c2ecf20Sopenharmony_ci    }
26648c2ecf20Sopenharmony_ci}
26658c2ecf20Sopenharmony_ci
26668c2ecf20Sopenharmony_cistatic void sisfb_get_VB_type(struct sis_video_info *ivideo)
26678c2ecf20Sopenharmony_ci{
26688c2ecf20Sopenharmony_ci	char stdstr[]    = "sisfb: Detected";
26698c2ecf20Sopenharmony_ci	char bridgestr[] = "video bridge";
26708c2ecf20Sopenharmony_ci	u8 vb_chipid;
26718c2ecf20Sopenharmony_ci	u8 reg;
26728c2ecf20Sopenharmony_ci
26738c2ecf20Sopenharmony_ci	/* No CRT2 on XGI Z7 */
26748c2ecf20Sopenharmony_ci	if(ivideo->chip == XGI_20)
26758c2ecf20Sopenharmony_ci		return;
26768c2ecf20Sopenharmony_ci
26778c2ecf20Sopenharmony_ci	vb_chipid = SiS_GetReg(SISPART4, 0x00);
26788c2ecf20Sopenharmony_ci	switch(vb_chipid) {
26798c2ecf20Sopenharmony_ci	case 0x01:
26808c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISPART4, 0x01);
26818c2ecf20Sopenharmony_ci		if(reg < 0xb0) {
26828c2ecf20Sopenharmony_ci			ivideo->vbflags |= VB_301;	/* Deprecated */
26838c2ecf20Sopenharmony_ci			ivideo->vbflags2 |= VB2_301;
26848c2ecf20Sopenharmony_ci			printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
26858c2ecf20Sopenharmony_ci		} else if(reg < 0xc0) {
26868c2ecf20Sopenharmony_ci			ivideo->vbflags |= VB_301B;	/* Deprecated */
26878c2ecf20Sopenharmony_ci			ivideo->vbflags2 |= VB2_301B;
26888c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISPART4, 0x23);
26898c2ecf20Sopenharmony_ci			if(!(reg & 0x02)) {
26908c2ecf20Sopenharmony_ci			   ivideo->vbflags |= VB_30xBDH;	/* Deprecated */
26918c2ecf20Sopenharmony_ci			   ivideo->vbflags2 |= VB2_30xBDH;
26928c2ecf20Sopenharmony_ci			   printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
26938c2ecf20Sopenharmony_ci			} else {
26948c2ecf20Sopenharmony_ci			   printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
26958c2ecf20Sopenharmony_ci			}
26968c2ecf20Sopenharmony_ci		} else if(reg < 0xd0) {
26978c2ecf20Sopenharmony_ci			ivideo->vbflags |= VB_301C;	/* Deprecated */
26988c2ecf20Sopenharmony_ci			ivideo->vbflags2 |= VB2_301C;
26998c2ecf20Sopenharmony_ci			printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
27008c2ecf20Sopenharmony_ci		} else if(reg < 0xe0) {
27018c2ecf20Sopenharmony_ci			ivideo->vbflags |= VB_301LV;	/* Deprecated */
27028c2ecf20Sopenharmony_ci			ivideo->vbflags2 |= VB2_301LV;
27038c2ecf20Sopenharmony_ci			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
27048c2ecf20Sopenharmony_ci		} else if(reg <= 0xe1) {
27058c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISPART4, 0x39);
27068c2ecf20Sopenharmony_ci			if(reg == 0xff) {
27078c2ecf20Sopenharmony_ci			   ivideo->vbflags |= VB_302LV;	/* Deprecated */
27088c2ecf20Sopenharmony_ci			   ivideo->vbflags2 |= VB2_302LV;
27098c2ecf20Sopenharmony_ci			   printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
27108c2ecf20Sopenharmony_ci			} else {
27118c2ecf20Sopenharmony_ci			   ivideo->vbflags |= VB_301C;	/* Deprecated */
27128c2ecf20Sopenharmony_ci			   ivideo->vbflags2 |= VB2_301C;
27138c2ecf20Sopenharmony_ci			   printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
27148c2ecf20Sopenharmony_ci#if 0
27158c2ecf20Sopenharmony_ci			   ivideo->vbflags |= VB_302ELV;	/* Deprecated */
27168c2ecf20Sopenharmony_ci			   ivideo->vbflags2 |= VB2_302ELV;
27178c2ecf20Sopenharmony_ci			   printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
27188c2ecf20Sopenharmony_ci#endif
27198c2ecf20Sopenharmony_ci			}
27208c2ecf20Sopenharmony_ci		}
27218c2ecf20Sopenharmony_ci		break;
27228c2ecf20Sopenharmony_ci	case 0x02:
27238c2ecf20Sopenharmony_ci		ivideo->vbflags |= VB_302B;	/* Deprecated */
27248c2ecf20Sopenharmony_ci		ivideo->vbflags2 |= VB2_302B;
27258c2ecf20Sopenharmony_ci		printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
27268c2ecf20Sopenharmony_ci		break;
27278c2ecf20Sopenharmony_ci	}
27288c2ecf20Sopenharmony_ci
27298c2ecf20Sopenharmony_ci	if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
27308c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0x37);
27318c2ecf20Sopenharmony_ci		reg &= SIS_EXTERNAL_CHIP_MASK;
27328c2ecf20Sopenharmony_ci		reg >>= 1;
27338c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_300_VGA) {
27348c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
27358c2ecf20Sopenharmony_ci			switch(reg) {
27368c2ecf20Sopenharmony_ci			   case SIS_EXTERNAL_CHIP_LVDS:
27378c2ecf20Sopenharmony_ci				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
27388c2ecf20Sopenharmony_ci				ivideo->vbflags2 |= VB2_LVDS;
27398c2ecf20Sopenharmony_ci				break;
27408c2ecf20Sopenharmony_ci			   case SIS_EXTERNAL_CHIP_TRUMPION:
27418c2ecf20Sopenharmony_ci				ivideo->vbflags |= (VB_LVDS | VB_TRUMPION);	/* Deprecated */
27428c2ecf20Sopenharmony_ci				ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
27438c2ecf20Sopenharmony_ci				break;
27448c2ecf20Sopenharmony_ci			   case SIS_EXTERNAL_CHIP_CHRONTEL:
27458c2ecf20Sopenharmony_ci				ivideo->vbflags |= VB_CHRONTEL;	/* Deprecated */
27468c2ecf20Sopenharmony_ci				ivideo->vbflags2 |= VB2_CHRONTEL;
27478c2ecf20Sopenharmony_ci				break;
27488c2ecf20Sopenharmony_ci			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
27498c2ecf20Sopenharmony_ci				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
27508c2ecf20Sopenharmony_ci				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
27518c2ecf20Sopenharmony_ci				break;
27528c2ecf20Sopenharmony_ci			}
27538c2ecf20Sopenharmony_ci			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
27548c2ecf20Sopenharmony_ci#endif
27558c2ecf20Sopenharmony_ci		} else if(ivideo->chip < SIS_661) {
27568c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
27578c2ecf20Sopenharmony_ci			switch (reg) {
27588c2ecf20Sopenharmony_ci			   case SIS310_EXTERNAL_CHIP_LVDS:
27598c2ecf20Sopenharmony_ci				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
27608c2ecf20Sopenharmony_ci				ivideo->vbflags2 |= VB2_LVDS;
27618c2ecf20Sopenharmony_ci				break;
27628c2ecf20Sopenharmony_ci			   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
27638c2ecf20Sopenharmony_ci				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
27648c2ecf20Sopenharmony_ci				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
27658c2ecf20Sopenharmony_ci				break;
27668c2ecf20Sopenharmony_ci			}
27678c2ecf20Sopenharmony_ci			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
27688c2ecf20Sopenharmony_ci#endif
27698c2ecf20Sopenharmony_ci		} else if(ivideo->chip >= SIS_661) {
27708c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
27718c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x38);
27728c2ecf20Sopenharmony_ci			reg >>= 5;
27738c2ecf20Sopenharmony_ci			switch(reg) {
27748c2ecf20Sopenharmony_ci			   case 0x02:
27758c2ecf20Sopenharmony_ci				ivideo->vbflags |= VB_LVDS;	/* Deprecated */
27768c2ecf20Sopenharmony_ci				ivideo->vbflags2 |= VB2_LVDS;
27778c2ecf20Sopenharmony_ci				break;
27788c2ecf20Sopenharmony_ci			   case 0x03:
27798c2ecf20Sopenharmony_ci				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);	/* Deprecated */
27808c2ecf20Sopenharmony_ci				ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
27818c2ecf20Sopenharmony_ci				break;
27828c2ecf20Sopenharmony_ci			   case 0x04:
27838c2ecf20Sopenharmony_ci				ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);	/* Deprecated */
27848c2ecf20Sopenharmony_ci				ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
27858c2ecf20Sopenharmony_ci				break;
27868c2ecf20Sopenharmony_ci			}
27878c2ecf20Sopenharmony_ci			if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
27888c2ecf20Sopenharmony_ci#endif
27898c2ecf20Sopenharmony_ci		}
27908c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_LVDS) {
27918c2ecf20Sopenharmony_ci		   printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
27928c2ecf20Sopenharmony_ci		}
27938c2ecf20Sopenharmony_ci		if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
27948c2ecf20Sopenharmony_ci		   printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
27958c2ecf20Sopenharmony_ci		}
27968c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_CHRONTEL) {
27978c2ecf20Sopenharmony_ci		   printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
27988c2ecf20Sopenharmony_ci		}
27998c2ecf20Sopenharmony_ci		if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
28008c2ecf20Sopenharmony_ci		   printk(KERN_INFO "%s Conexant external device\n", stdstr);
28018c2ecf20Sopenharmony_ci		}
28028c2ecf20Sopenharmony_ci	}
28038c2ecf20Sopenharmony_ci
28048c2ecf20Sopenharmony_ci	if(ivideo->vbflags2 & VB2_SISBRIDGE) {
28058c2ecf20Sopenharmony_ci		SiS_SenseLCD(ivideo);
28068c2ecf20Sopenharmony_ci		SiS_Sense30x(ivideo);
28078c2ecf20Sopenharmony_ci	} else if(ivideo->vbflags2 & VB2_CHRONTEL) {
28088c2ecf20Sopenharmony_ci		SiS_SenseCh(ivideo);
28098c2ecf20Sopenharmony_ci	}
28108c2ecf20Sopenharmony_ci}
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_ci/* ---------- Engine initialization routines ------------ */
28138c2ecf20Sopenharmony_ci
28148c2ecf20Sopenharmony_cistatic void
28158c2ecf20Sopenharmony_cisisfb_engine_init(struct sis_video_info *ivideo)
28168c2ecf20Sopenharmony_ci{
28178c2ecf20Sopenharmony_ci
28188c2ecf20Sopenharmony_ci	/* Initialize command queue (we use MMIO only) */
28198c2ecf20Sopenharmony_ci
28208c2ecf20Sopenharmony_ci	/* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
28218c2ecf20Sopenharmony_ci
28228c2ecf20Sopenharmony_ci	ivideo->caps &= ~(TURBO_QUEUE_CAP    |
28238c2ecf20Sopenharmony_ci			  MMIO_CMD_QUEUE_CAP |
28248c2ecf20Sopenharmony_ci			  VM_CMD_QUEUE_CAP   |
28258c2ecf20Sopenharmony_ci			  AGP_CMD_QUEUE_CAP);
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
28288c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
28298c2ecf20Sopenharmony_ci		u32 tqueue_pos;
28308c2ecf20Sopenharmony_ci		u8 tq_state;
28318c2ecf20Sopenharmony_ci
28328c2ecf20Sopenharmony_ci		tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
28338c2ecf20Sopenharmony_ci
28348c2ecf20Sopenharmony_ci		tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
28358c2ecf20Sopenharmony_ci		tq_state |= 0xf0;
28368c2ecf20Sopenharmony_ci		tq_state &= 0xfc;
28378c2ecf20Sopenharmony_ci		tq_state |= (u8)(tqueue_pos >> 8);
28388c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
28398c2ecf20Sopenharmony_ci
28408c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
28418c2ecf20Sopenharmony_ci
28428c2ecf20Sopenharmony_ci		ivideo->caps |= TURBO_QUEUE_CAP;
28438c2ecf20Sopenharmony_ci	}
28448c2ecf20Sopenharmony_ci#endif
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
28478c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_315_VGA) {
28488c2ecf20Sopenharmony_ci		u32 tempq = 0, templ;
28498c2ecf20Sopenharmony_ci		u8  temp;
28508c2ecf20Sopenharmony_ci
28518c2ecf20Sopenharmony_ci		if(ivideo->chip == XGI_20) {
28528c2ecf20Sopenharmony_ci			switch(ivideo->cmdQueueSize) {
28538c2ecf20Sopenharmony_ci			case (64 * 1024):
28548c2ecf20Sopenharmony_ci				temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
28558c2ecf20Sopenharmony_ci				break;
28568c2ecf20Sopenharmony_ci			case (128 * 1024):
28578c2ecf20Sopenharmony_ci			default:
28588c2ecf20Sopenharmony_ci				temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
28598c2ecf20Sopenharmony_ci			}
28608c2ecf20Sopenharmony_ci		} else {
28618c2ecf20Sopenharmony_ci			switch(ivideo->cmdQueueSize) {
28628c2ecf20Sopenharmony_ci			case (4 * 1024 * 1024):
28638c2ecf20Sopenharmony_ci				temp = SIS_CMD_QUEUE_SIZE_4M;
28648c2ecf20Sopenharmony_ci				break;
28658c2ecf20Sopenharmony_ci			case (2 * 1024 * 1024):
28668c2ecf20Sopenharmony_ci				temp = SIS_CMD_QUEUE_SIZE_2M;
28678c2ecf20Sopenharmony_ci				break;
28688c2ecf20Sopenharmony_ci			case (1 * 1024 * 1024):
28698c2ecf20Sopenharmony_ci				temp = SIS_CMD_QUEUE_SIZE_1M;
28708c2ecf20Sopenharmony_ci				break;
28718c2ecf20Sopenharmony_ci			default:
28728c2ecf20Sopenharmony_ci			case (512 * 1024):
28738c2ecf20Sopenharmony_ci				temp = SIS_CMD_QUEUE_SIZE_512k;
28748c2ecf20Sopenharmony_ci			}
28758c2ecf20Sopenharmony_ci		}
28768c2ecf20Sopenharmony_ci
28778c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
28788c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
28798c2ecf20Sopenharmony_ci
28808c2ecf20Sopenharmony_ci		if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
28818c2ecf20Sopenharmony_ci			/* Must disable dual pipe on XGI_40. Can't do
28828c2ecf20Sopenharmony_ci			 * this in MMIO mode, because it requires
28838c2ecf20Sopenharmony_ci			 * setting/clearing a bit in the MMIO fire trigger
28848c2ecf20Sopenharmony_ci			 * register.
28858c2ecf20Sopenharmony_ci			 */
28868c2ecf20Sopenharmony_ci			if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
28878c2ecf20Sopenharmony_ci
28888c2ecf20Sopenharmony_ci				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
28898c2ecf20Sopenharmony_ci
28908c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
28918c2ecf20Sopenharmony_ci
28928c2ecf20Sopenharmony_ci				tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
28938c2ecf20Sopenharmony_ci				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
28948c2ecf20Sopenharmony_ci
28958c2ecf20Sopenharmony_ci				tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
28968c2ecf20Sopenharmony_ci				MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
28978c2ecf20Sopenharmony_ci
28988c2ecf20Sopenharmony_ci				writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
28998c2ecf20Sopenharmony_ci				writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
29008c2ecf20Sopenharmony_ci				writel(0x168F0000, ivideo->video_vbase + tempq + 8);
29018c2ecf20Sopenharmony_ci				writel(0x168F0000, ivideo->video_vbase + tempq + 12);
29028c2ecf20Sopenharmony_ci
29038c2ecf20Sopenharmony_ci				MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
29048c2ecf20Sopenharmony_ci
29058c2ecf20Sopenharmony_ci				sisfb_syncaccel(ivideo);
29068c2ecf20Sopenharmony_ci
29078c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci			}
29108c2ecf20Sopenharmony_ci		}
29118c2ecf20Sopenharmony_ci
29128c2ecf20Sopenharmony_ci		tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
29138c2ecf20Sopenharmony_ci		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
29148c2ecf20Sopenharmony_ci
29158c2ecf20Sopenharmony_ci		temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
29168c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ci		tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
29198c2ecf20Sopenharmony_ci		MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
29208c2ecf20Sopenharmony_ci
29218c2ecf20Sopenharmony_ci		ivideo->caps |= MMIO_CMD_QUEUE_CAP;
29228c2ecf20Sopenharmony_ci	}
29238c2ecf20Sopenharmony_ci#endif
29248c2ecf20Sopenharmony_ci
29258c2ecf20Sopenharmony_ci	ivideo->engineok = 1;
29268c2ecf20Sopenharmony_ci}
29278c2ecf20Sopenharmony_ci
29288c2ecf20Sopenharmony_cistatic void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
29298c2ecf20Sopenharmony_ci{
29308c2ecf20Sopenharmony_ci	u8 reg;
29318c2ecf20Sopenharmony_ci	int i;
29328c2ecf20Sopenharmony_ci
29338c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISCR, 0x36);
29348c2ecf20Sopenharmony_ci	reg &= 0x0f;
29358c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
29368c2ecf20Sopenharmony_ci		ivideo->CRT2LCDType = sis300paneltype[reg];
29378c2ecf20Sopenharmony_ci	} else if(ivideo->chip >= SIS_661) {
29388c2ecf20Sopenharmony_ci		ivideo->CRT2LCDType = sis661paneltype[reg];
29398c2ecf20Sopenharmony_ci	} else {
29408c2ecf20Sopenharmony_ci		ivideo->CRT2LCDType = sis310paneltype[reg];
29418c2ecf20Sopenharmony_ci		if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
29428c2ecf20Sopenharmony_ci			if((ivideo->CRT2LCDType != LCD_320x240_2) &&
29438c2ecf20Sopenharmony_ci			   (ivideo->CRT2LCDType != LCD_320x240_3)) {
29448c2ecf20Sopenharmony_ci				ivideo->CRT2LCDType = LCD_320x240;
29458c2ecf20Sopenharmony_ci			}
29468c2ecf20Sopenharmony_ci		}
29478c2ecf20Sopenharmony_ci	}
29488c2ecf20Sopenharmony_ci
29498c2ecf20Sopenharmony_ci	if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
29508c2ecf20Sopenharmony_ci		/* For broken BIOSes: Assume 1024x768, RGB18 */
29518c2ecf20Sopenharmony_ci		ivideo->CRT2LCDType = LCD_1024x768;
29528c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
29538c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
29548c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
29558c2ecf20Sopenharmony_ci	}
29568c2ecf20Sopenharmony_ci
29578c2ecf20Sopenharmony_ci	for(i = 0; i < SIS_LCD_NUMBER; i++) {
29588c2ecf20Sopenharmony_ci		if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
29598c2ecf20Sopenharmony_ci			ivideo->lcdxres = sis_lcd_data[i].xres;
29608c2ecf20Sopenharmony_ci			ivideo->lcdyres = sis_lcd_data[i].yres;
29618c2ecf20Sopenharmony_ci			ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
29628c2ecf20Sopenharmony_ci			break;
29638c2ecf20Sopenharmony_ci		}
29648c2ecf20Sopenharmony_ci	}
29658c2ecf20Sopenharmony_ci
29668c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
29678c2ecf20Sopenharmony_ci	if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
29688c2ecf20Sopenharmony_ci		ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
29698c2ecf20Sopenharmony_ci		ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
29708c2ecf20Sopenharmony_ci	} else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
29718c2ecf20Sopenharmony_ci		ivideo->lcdxres =  848; ivideo->lcdyres =  480;
29728c2ecf20Sopenharmony_ci		ivideo->lcddefmodeidx = DEFAULT_MODE_848;
29738c2ecf20Sopenharmony_ci	} else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
29748c2ecf20Sopenharmony_ci		ivideo->lcdxres =  856; ivideo->lcdyres =  480;
29758c2ecf20Sopenharmony_ci		ivideo->lcddefmodeidx = DEFAULT_MODE_856;
29768c2ecf20Sopenharmony_ci	}
29778c2ecf20Sopenharmony_ci#endif
29788c2ecf20Sopenharmony_ci
29798c2ecf20Sopenharmony_ci	printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
29808c2ecf20Sopenharmony_ci			ivideo->lcdxres, ivideo->lcdyres);
29818c2ecf20Sopenharmony_ci}
29828c2ecf20Sopenharmony_ci
29838c2ecf20Sopenharmony_cistatic void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
29848c2ecf20Sopenharmony_ci{
29858c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
29868c2ecf20Sopenharmony_ci	/* Save the current PanelDelayCompensation if the LCD is currently used */
29878c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
29888c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
29898c2ecf20Sopenharmony_ci			int tmp;
29908c2ecf20Sopenharmony_ci			tmp = SiS_GetReg(SISCR, 0x30);
29918c2ecf20Sopenharmony_ci			if(tmp & 0x20) {
29928c2ecf20Sopenharmony_ci				/* Currently on LCD? If yes, read current pdc */
29938c2ecf20Sopenharmony_ci				ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
29948c2ecf20Sopenharmony_ci				ivideo->detectedpdc &= 0x3c;
29958c2ecf20Sopenharmony_ci				if(ivideo->SiS_Pr.PDC == -1) {
29968c2ecf20Sopenharmony_ci					/* Let option override detection */
29978c2ecf20Sopenharmony_ci					ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
29988c2ecf20Sopenharmony_ci				}
29998c2ecf20Sopenharmony_ci				printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
30008c2ecf20Sopenharmony_ci					ivideo->detectedpdc);
30018c2ecf20Sopenharmony_ci			}
30028c2ecf20Sopenharmony_ci			if((ivideo->SiS_Pr.PDC != -1) &&
30038c2ecf20Sopenharmony_ci			   (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
30048c2ecf20Sopenharmony_ci				printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
30058c2ecf20Sopenharmony_ci					ivideo->SiS_Pr.PDC);
30068c2ecf20Sopenharmony_ci			}
30078c2ecf20Sopenharmony_ci		}
30088c2ecf20Sopenharmony_ci	}
30098c2ecf20Sopenharmony_ci#endif
30108c2ecf20Sopenharmony_ci
30118c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
30128c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_315_VGA) {
30138c2ecf20Sopenharmony_ci
30148c2ecf20Sopenharmony_ci		/* Try to find about LCDA */
30158c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
30168c2ecf20Sopenharmony_ci			int tmp;
30178c2ecf20Sopenharmony_ci			tmp = SiS_GetReg(SISPART1, 0x13);
30188c2ecf20Sopenharmony_ci			if(tmp & 0x04) {
30198c2ecf20Sopenharmony_ci				ivideo->SiS_Pr.SiS_UseLCDA = true;
30208c2ecf20Sopenharmony_ci				ivideo->detectedlcda = 0x03;
30218c2ecf20Sopenharmony_ci			}
30228c2ecf20Sopenharmony_ci		}
30238c2ecf20Sopenharmony_ci
30248c2ecf20Sopenharmony_ci		/* Save PDC */
30258c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
30268c2ecf20Sopenharmony_ci			int tmp;
30278c2ecf20Sopenharmony_ci			tmp = SiS_GetReg(SISCR, 0x30);
30288c2ecf20Sopenharmony_ci			if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
30298c2ecf20Sopenharmony_ci				/* Currently on LCD? If yes, read current pdc */
30308c2ecf20Sopenharmony_ci				u8 pdc;
30318c2ecf20Sopenharmony_ci				pdc = SiS_GetReg(SISPART1, 0x2D);
30328c2ecf20Sopenharmony_ci				ivideo->detectedpdc  = (pdc & 0x0f) << 1;
30338c2ecf20Sopenharmony_ci				ivideo->detectedpdca = (pdc & 0xf0) >> 3;
30348c2ecf20Sopenharmony_ci				pdc = SiS_GetReg(SISPART1, 0x35);
30358c2ecf20Sopenharmony_ci				ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
30368c2ecf20Sopenharmony_ci				pdc = SiS_GetReg(SISPART1, 0x20);
30378c2ecf20Sopenharmony_ci				ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
30388c2ecf20Sopenharmony_ci				if(ivideo->newrom) {
30398c2ecf20Sopenharmony_ci					/* New ROM invalidates other PDC resp. */
30408c2ecf20Sopenharmony_ci					if(ivideo->detectedlcda != 0xff) {
30418c2ecf20Sopenharmony_ci						ivideo->detectedpdc = 0xff;
30428c2ecf20Sopenharmony_ci					} else {
30438c2ecf20Sopenharmony_ci						ivideo->detectedpdca = 0xff;
30448c2ecf20Sopenharmony_ci					}
30458c2ecf20Sopenharmony_ci				}
30468c2ecf20Sopenharmony_ci				if(ivideo->SiS_Pr.PDC == -1) {
30478c2ecf20Sopenharmony_ci					if(ivideo->detectedpdc != 0xff) {
30488c2ecf20Sopenharmony_ci						ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
30498c2ecf20Sopenharmony_ci					}
30508c2ecf20Sopenharmony_ci				}
30518c2ecf20Sopenharmony_ci				if(ivideo->SiS_Pr.PDCA == -1) {
30528c2ecf20Sopenharmony_ci					if(ivideo->detectedpdca != 0xff) {
30538c2ecf20Sopenharmony_ci						ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
30548c2ecf20Sopenharmony_ci					}
30558c2ecf20Sopenharmony_ci				}
30568c2ecf20Sopenharmony_ci				if(ivideo->detectedpdc != 0xff) {
30578c2ecf20Sopenharmony_ci					printk(KERN_INFO
30588c2ecf20Sopenharmony_ci						"sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
30598c2ecf20Sopenharmony_ci						ivideo->detectedpdc);
30608c2ecf20Sopenharmony_ci				}
30618c2ecf20Sopenharmony_ci				if(ivideo->detectedpdca != 0xff) {
30628c2ecf20Sopenharmony_ci					printk(KERN_INFO
30638c2ecf20Sopenharmony_ci						"sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
30648c2ecf20Sopenharmony_ci						ivideo->detectedpdca);
30658c2ecf20Sopenharmony_ci				}
30668c2ecf20Sopenharmony_ci			}
30678c2ecf20Sopenharmony_ci
30688c2ecf20Sopenharmony_ci			/* Save EMI */
30698c2ecf20Sopenharmony_ci			if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
30708c2ecf20Sopenharmony_ci				ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
30718c2ecf20Sopenharmony_ci				ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
30728c2ecf20Sopenharmony_ci				ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
30738c2ecf20Sopenharmony_ci				ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
30748c2ecf20Sopenharmony_ci				ivideo->SiS_Pr.HaveEMI = true;
30758c2ecf20Sopenharmony_ci				if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
30768c2ecf20Sopenharmony_ci					ivideo->SiS_Pr.HaveEMILCD = true;
30778c2ecf20Sopenharmony_ci				}
30788c2ecf20Sopenharmony_ci			}
30798c2ecf20Sopenharmony_ci		}
30808c2ecf20Sopenharmony_ci
30818c2ecf20Sopenharmony_ci		/* Let user override detected PDCs (all bridges) */
30828c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_30xBLV) {
30838c2ecf20Sopenharmony_ci			if((ivideo->SiS_Pr.PDC != -1) &&
30848c2ecf20Sopenharmony_ci			   (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
30858c2ecf20Sopenharmony_ci				printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
30868c2ecf20Sopenharmony_ci					ivideo->SiS_Pr.PDC);
30878c2ecf20Sopenharmony_ci			}
30888c2ecf20Sopenharmony_ci			if((ivideo->SiS_Pr.PDCA != -1) &&
30898c2ecf20Sopenharmony_ci			   (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
30908c2ecf20Sopenharmony_ci				printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
30918c2ecf20Sopenharmony_ci				 ivideo->SiS_Pr.PDCA);
30928c2ecf20Sopenharmony_ci			}
30938c2ecf20Sopenharmony_ci		}
30948c2ecf20Sopenharmony_ci
30958c2ecf20Sopenharmony_ci	}
30968c2ecf20Sopenharmony_ci#endif
30978c2ecf20Sopenharmony_ci}
30988c2ecf20Sopenharmony_ci
30998c2ecf20Sopenharmony_ci/* -------------------- Memory manager routines ---------------------- */
31008c2ecf20Sopenharmony_ci
31018c2ecf20Sopenharmony_cistatic u32 sisfb_getheapstart(struct sis_video_info *ivideo)
31028c2ecf20Sopenharmony_ci{
31038c2ecf20Sopenharmony_ci	u32 ret = ivideo->sisfb_parm_mem * 1024;
31048c2ecf20Sopenharmony_ci	u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
31058c2ecf20Sopenharmony_ci	u32 def;
31068c2ecf20Sopenharmony_ci
31078c2ecf20Sopenharmony_ci	/* Calculate heap start = end of memory for console
31088c2ecf20Sopenharmony_ci	 *
31098c2ecf20Sopenharmony_ci	 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
31108c2ecf20Sopenharmony_ci	 * C = console, D = heap, H = HWCursor, Q = cmd-queue
31118c2ecf20Sopenharmony_ci	 *
31128c2ecf20Sopenharmony_ci	 * On 76x in UMA+LFB mode, the layout is as follows:
31138c2ecf20Sopenharmony_ci	 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
31148c2ecf20Sopenharmony_ci	 * where the heap is the entire UMA area, eventually
31158c2ecf20Sopenharmony_ci	 * into the LFB area if the given mem parameter is
31168c2ecf20Sopenharmony_ci	 * higher than the size of the UMA memory.
31178c2ecf20Sopenharmony_ci	 *
31188c2ecf20Sopenharmony_ci	 * Basically given by "mem" parameter
31198c2ecf20Sopenharmony_ci	 *
31208c2ecf20Sopenharmony_ci	 * maximum = videosize - cmd_queue - hwcursor
31218c2ecf20Sopenharmony_ci	 *           (results in a heap of size 0)
31228c2ecf20Sopenharmony_ci	 * default = SiS 300: depends on videosize
31238c2ecf20Sopenharmony_ci	 *           SiS 315/330/340/XGI: 32k below max
31248c2ecf20Sopenharmony_ci	 */
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
31278c2ecf20Sopenharmony_ci		if(ivideo->video_size > 0x1000000) {
31288c2ecf20Sopenharmony_ci			def = 0xc00000;
31298c2ecf20Sopenharmony_ci		} else if(ivideo->video_size > 0x800000) {
31308c2ecf20Sopenharmony_ci			def = 0x800000;
31318c2ecf20Sopenharmony_ci		} else {
31328c2ecf20Sopenharmony_ci			def = 0x400000;
31338c2ecf20Sopenharmony_ci		}
31348c2ecf20Sopenharmony_ci	} else if(ivideo->UMAsize && ivideo->LFBsize) {
31358c2ecf20Sopenharmony_ci		ret = def = 0;
31368c2ecf20Sopenharmony_ci	} else {
31378c2ecf20Sopenharmony_ci		def = maxoffs - 0x8000;
31388c2ecf20Sopenharmony_ci	}
31398c2ecf20Sopenharmony_ci
31408c2ecf20Sopenharmony_ci	/* Use default for secondary card for now (FIXME) */
31418c2ecf20Sopenharmony_ci	if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
31428c2ecf20Sopenharmony_ci		ret = def;
31438c2ecf20Sopenharmony_ci
31448c2ecf20Sopenharmony_ci	return ret;
31458c2ecf20Sopenharmony_ci}
31468c2ecf20Sopenharmony_ci
31478c2ecf20Sopenharmony_cistatic u32 sisfb_getheapsize(struct sis_video_info *ivideo)
31488c2ecf20Sopenharmony_ci{
31498c2ecf20Sopenharmony_ci	u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
31508c2ecf20Sopenharmony_ci	u32 ret = 0;
31518c2ecf20Sopenharmony_ci
31528c2ecf20Sopenharmony_ci	if(ivideo->UMAsize && ivideo->LFBsize) {
31538c2ecf20Sopenharmony_ci		if( (!ivideo->sisfb_parm_mem)			||
31548c2ecf20Sopenharmony_ci		    ((ivideo->sisfb_parm_mem * 1024) > max)	||
31558c2ecf20Sopenharmony_ci		    ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
31568c2ecf20Sopenharmony_ci			ret = ivideo->UMAsize;
31578c2ecf20Sopenharmony_ci			max -= ivideo->UMAsize;
31588c2ecf20Sopenharmony_ci		} else {
31598c2ecf20Sopenharmony_ci			ret = max - (ivideo->sisfb_parm_mem * 1024);
31608c2ecf20Sopenharmony_ci			max = ivideo->sisfb_parm_mem * 1024;
31618c2ecf20Sopenharmony_ci		}
31628c2ecf20Sopenharmony_ci		ivideo->video_offset = ret;
31638c2ecf20Sopenharmony_ci		ivideo->sisfb_mem = max;
31648c2ecf20Sopenharmony_ci	} else {
31658c2ecf20Sopenharmony_ci		ret = max - ivideo->heapstart;
31668c2ecf20Sopenharmony_ci		ivideo->sisfb_mem = ivideo->heapstart;
31678c2ecf20Sopenharmony_ci	}
31688c2ecf20Sopenharmony_ci
31698c2ecf20Sopenharmony_ci	return ret;
31708c2ecf20Sopenharmony_ci}
31718c2ecf20Sopenharmony_ci
31728c2ecf20Sopenharmony_cistatic int sisfb_heap_init(struct sis_video_info *ivideo)
31738c2ecf20Sopenharmony_ci{
31748c2ecf20Sopenharmony_ci	struct SIS_OH *poh;
31758c2ecf20Sopenharmony_ci
31768c2ecf20Sopenharmony_ci	ivideo->video_offset = 0;
31778c2ecf20Sopenharmony_ci	if(ivideo->sisfb_parm_mem) {
31788c2ecf20Sopenharmony_ci		if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
31798c2ecf20Sopenharmony_ci		    (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
31808c2ecf20Sopenharmony_ci			ivideo->sisfb_parm_mem = 0;
31818c2ecf20Sopenharmony_ci		}
31828c2ecf20Sopenharmony_ci	}
31838c2ecf20Sopenharmony_ci
31848c2ecf20Sopenharmony_ci	ivideo->heapstart = sisfb_getheapstart(ivideo);
31858c2ecf20Sopenharmony_ci	ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
31868c2ecf20Sopenharmony_ci
31878c2ecf20Sopenharmony_ci	ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
31888c2ecf20Sopenharmony_ci	ivideo->sisfb_heap_end   = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
31898c2ecf20Sopenharmony_ci
31908c2ecf20Sopenharmony_ci	printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
31918c2ecf20Sopenharmony_ci		(int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
31928c2ecf20Sopenharmony_ci
31938c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.vinfo = ivideo;
31948c2ecf20Sopenharmony_ci
31958c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.poha_chain = NULL;
31968c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.poh_freelist = NULL;
31978c2ecf20Sopenharmony_ci
31988c2ecf20Sopenharmony_ci	poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
31998c2ecf20Sopenharmony_ci	if(poh == NULL)
32008c2ecf20Sopenharmony_ci		return 1;
32018c2ecf20Sopenharmony_ci
32028c2ecf20Sopenharmony_ci	poh->poh_next = &ivideo->sisfb_heap.oh_free;
32038c2ecf20Sopenharmony_ci	poh->poh_prev = &ivideo->sisfb_heap.oh_free;
32048c2ecf20Sopenharmony_ci	poh->size = ivideo->sisfb_heap_size;
32058c2ecf20Sopenharmony_ci	poh->offset = ivideo->heapstart;
32068c2ecf20Sopenharmony_ci
32078c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.oh_free.poh_next = poh;
32088c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.oh_free.poh_prev = poh;
32098c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.oh_free.size = 0;
32108c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.max_freesize = poh->size;
32118c2ecf20Sopenharmony_ci
32128c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
32138c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
32148c2ecf20Sopenharmony_ci	ivideo->sisfb_heap.oh_used.size = SENTINEL;
32158c2ecf20Sopenharmony_ci
32168c2ecf20Sopenharmony_ci	if(ivideo->cardnumber == 0) {
32178c2ecf20Sopenharmony_ci		/* For the first card, make this heap the "global" one
32188c2ecf20Sopenharmony_ci		 * for old DRM (which could handle only one card)
32198c2ecf20Sopenharmony_ci		 */
32208c2ecf20Sopenharmony_ci		sisfb_heap = &ivideo->sisfb_heap;
32218c2ecf20Sopenharmony_ci	}
32228c2ecf20Sopenharmony_ci
32238c2ecf20Sopenharmony_ci	return 0;
32248c2ecf20Sopenharmony_ci}
32258c2ecf20Sopenharmony_ci
32268c2ecf20Sopenharmony_cistatic struct SIS_OH *
32278c2ecf20Sopenharmony_cisisfb_poh_new_node(struct SIS_HEAP *memheap)
32288c2ecf20Sopenharmony_ci{
32298c2ecf20Sopenharmony_ci	struct SIS_OHALLOC	*poha;
32308c2ecf20Sopenharmony_ci	struct SIS_OH		*poh;
32318c2ecf20Sopenharmony_ci	unsigned long		cOhs;
32328c2ecf20Sopenharmony_ci	int			i;
32338c2ecf20Sopenharmony_ci
32348c2ecf20Sopenharmony_ci	if(memheap->poh_freelist == NULL) {
32358c2ecf20Sopenharmony_ci		poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
32368c2ecf20Sopenharmony_ci		if(!poha)
32378c2ecf20Sopenharmony_ci			return NULL;
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci		poha->poha_next = memheap->poha_chain;
32408c2ecf20Sopenharmony_ci		memheap->poha_chain = poha;
32418c2ecf20Sopenharmony_ci
32428c2ecf20Sopenharmony_ci		cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
32438c2ecf20Sopenharmony_ci
32448c2ecf20Sopenharmony_ci		poh = &poha->aoh[0];
32458c2ecf20Sopenharmony_ci		for(i = cOhs - 1; i != 0; i--) {
32468c2ecf20Sopenharmony_ci			poh->poh_next = poh + 1;
32478c2ecf20Sopenharmony_ci			poh = poh + 1;
32488c2ecf20Sopenharmony_ci		}
32498c2ecf20Sopenharmony_ci
32508c2ecf20Sopenharmony_ci		poh->poh_next = NULL;
32518c2ecf20Sopenharmony_ci		memheap->poh_freelist = &poha->aoh[0];
32528c2ecf20Sopenharmony_ci	}
32538c2ecf20Sopenharmony_ci
32548c2ecf20Sopenharmony_ci	poh = memheap->poh_freelist;
32558c2ecf20Sopenharmony_ci	memheap->poh_freelist = poh->poh_next;
32568c2ecf20Sopenharmony_ci
32578c2ecf20Sopenharmony_ci	return poh;
32588c2ecf20Sopenharmony_ci}
32598c2ecf20Sopenharmony_ci
32608c2ecf20Sopenharmony_cistatic struct SIS_OH *
32618c2ecf20Sopenharmony_cisisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
32628c2ecf20Sopenharmony_ci{
32638c2ecf20Sopenharmony_ci	struct SIS_OH	*pohThis;
32648c2ecf20Sopenharmony_ci	struct SIS_OH	*pohRoot;
32658c2ecf20Sopenharmony_ci	int		bAllocated = 0;
32668c2ecf20Sopenharmony_ci
32678c2ecf20Sopenharmony_ci	if(size > memheap->max_freesize) {
32688c2ecf20Sopenharmony_ci		DPRINTK("sisfb: Can't allocate %dk video memory\n",
32698c2ecf20Sopenharmony_ci			(unsigned int) size / 1024);
32708c2ecf20Sopenharmony_ci		return NULL;
32718c2ecf20Sopenharmony_ci	}
32728c2ecf20Sopenharmony_ci
32738c2ecf20Sopenharmony_ci	pohThis = memheap->oh_free.poh_next;
32748c2ecf20Sopenharmony_ci
32758c2ecf20Sopenharmony_ci	while(pohThis != &memheap->oh_free) {
32768c2ecf20Sopenharmony_ci		if(size <= pohThis->size) {
32778c2ecf20Sopenharmony_ci			bAllocated = 1;
32788c2ecf20Sopenharmony_ci			break;
32798c2ecf20Sopenharmony_ci		}
32808c2ecf20Sopenharmony_ci		pohThis = pohThis->poh_next;
32818c2ecf20Sopenharmony_ci	}
32828c2ecf20Sopenharmony_ci
32838c2ecf20Sopenharmony_ci	if(!bAllocated) {
32848c2ecf20Sopenharmony_ci		DPRINTK("sisfb: Can't allocate %dk video memory\n",
32858c2ecf20Sopenharmony_ci			(unsigned int) size / 1024);
32868c2ecf20Sopenharmony_ci		return NULL;
32878c2ecf20Sopenharmony_ci	}
32888c2ecf20Sopenharmony_ci
32898c2ecf20Sopenharmony_ci	if(size == pohThis->size) {
32908c2ecf20Sopenharmony_ci		pohRoot = pohThis;
32918c2ecf20Sopenharmony_ci		sisfb_delete_node(pohThis);
32928c2ecf20Sopenharmony_ci	} else {
32938c2ecf20Sopenharmony_ci		pohRoot = sisfb_poh_new_node(memheap);
32948c2ecf20Sopenharmony_ci		if(pohRoot == NULL)
32958c2ecf20Sopenharmony_ci			return NULL;
32968c2ecf20Sopenharmony_ci
32978c2ecf20Sopenharmony_ci		pohRoot->offset = pohThis->offset;
32988c2ecf20Sopenharmony_ci		pohRoot->size = size;
32998c2ecf20Sopenharmony_ci
33008c2ecf20Sopenharmony_ci		pohThis->offset += size;
33018c2ecf20Sopenharmony_ci		pohThis->size -= size;
33028c2ecf20Sopenharmony_ci	}
33038c2ecf20Sopenharmony_ci
33048c2ecf20Sopenharmony_ci	memheap->max_freesize -= size;
33058c2ecf20Sopenharmony_ci
33068c2ecf20Sopenharmony_ci	pohThis = &memheap->oh_used;
33078c2ecf20Sopenharmony_ci	sisfb_insert_node(pohThis, pohRoot);
33088c2ecf20Sopenharmony_ci
33098c2ecf20Sopenharmony_ci	return pohRoot;
33108c2ecf20Sopenharmony_ci}
33118c2ecf20Sopenharmony_ci
33128c2ecf20Sopenharmony_cistatic void
33138c2ecf20Sopenharmony_cisisfb_delete_node(struct SIS_OH *poh)
33148c2ecf20Sopenharmony_ci{
33158c2ecf20Sopenharmony_ci	poh->poh_prev->poh_next = poh->poh_next;
33168c2ecf20Sopenharmony_ci	poh->poh_next->poh_prev = poh->poh_prev;
33178c2ecf20Sopenharmony_ci}
33188c2ecf20Sopenharmony_ci
33198c2ecf20Sopenharmony_cistatic void
33208c2ecf20Sopenharmony_cisisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
33218c2ecf20Sopenharmony_ci{
33228c2ecf20Sopenharmony_ci	struct SIS_OH *pohTemp = pohList->poh_next;
33238c2ecf20Sopenharmony_ci
33248c2ecf20Sopenharmony_ci	pohList->poh_next = poh;
33258c2ecf20Sopenharmony_ci	pohTemp->poh_prev = poh;
33268c2ecf20Sopenharmony_ci
33278c2ecf20Sopenharmony_ci	poh->poh_prev = pohList;
33288c2ecf20Sopenharmony_ci	poh->poh_next = pohTemp;
33298c2ecf20Sopenharmony_ci}
33308c2ecf20Sopenharmony_ci
33318c2ecf20Sopenharmony_cistatic struct SIS_OH *
33328c2ecf20Sopenharmony_cisisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
33338c2ecf20Sopenharmony_ci{
33348c2ecf20Sopenharmony_ci	struct SIS_OH *pohThis;
33358c2ecf20Sopenharmony_ci	struct SIS_OH *poh_freed;
33368c2ecf20Sopenharmony_ci	struct SIS_OH *poh_prev;
33378c2ecf20Sopenharmony_ci	struct SIS_OH *poh_next;
33388c2ecf20Sopenharmony_ci	u32    ulUpper;
33398c2ecf20Sopenharmony_ci	u32    ulLower;
33408c2ecf20Sopenharmony_ci	int    foundNode = 0;
33418c2ecf20Sopenharmony_ci
33428c2ecf20Sopenharmony_ci	poh_freed = memheap->oh_used.poh_next;
33438c2ecf20Sopenharmony_ci
33448c2ecf20Sopenharmony_ci	while(poh_freed != &memheap->oh_used) {
33458c2ecf20Sopenharmony_ci		if(poh_freed->offset == base) {
33468c2ecf20Sopenharmony_ci			foundNode = 1;
33478c2ecf20Sopenharmony_ci			break;
33488c2ecf20Sopenharmony_ci		}
33498c2ecf20Sopenharmony_ci
33508c2ecf20Sopenharmony_ci		poh_freed = poh_freed->poh_next;
33518c2ecf20Sopenharmony_ci	}
33528c2ecf20Sopenharmony_ci
33538c2ecf20Sopenharmony_ci	if(!foundNode)
33548c2ecf20Sopenharmony_ci		return NULL;
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci	memheap->max_freesize += poh_freed->size;
33578c2ecf20Sopenharmony_ci
33588c2ecf20Sopenharmony_ci	poh_prev = poh_next = NULL;
33598c2ecf20Sopenharmony_ci	ulUpper = poh_freed->offset + poh_freed->size;
33608c2ecf20Sopenharmony_ci	ulLower = poh_freed->offset;
33618c2ecf20Sopenharmony_ci
33628c2ecf20Sopenharmony_ci	pohThis = memheap->oh_free.poh_next;
33638c2ecf20Sopenharmony_ci
33648c2ecf20Sopenharmony_ci	while(pohThis != &memheap->oh_free) {
33658c2ecf20Sopenharmony_ci		if(pohThis->offset == ulUpper) {
33668c2ecf20Sopenharmony_ci			poh_next = pohThis;
33678c2ecf20Sopenharmony_ci		} else if((pohThis->offset + pohThis->size) == ulLower) {
33688c2ecf20Sopenharmony_ci			poh_prev = pohThis;
33698c2ecf20Sopenharmony_ci		}
33708c2ecf20Sopenharmony_ci		pohThis = pohThis->poh_next;
33718c2ecf20Sopenharmony_ci	}
33728c2ecf20Sopenharmony_ci
33738c2ecf20Sopenharmony_ci	sisfb_delete_node(poh_freed);
33748c2ecf20Sopenharmony_ci
33758c2ecf20Sopenharmony_ci	if(poh_prev && poh_next) {
33768c2ecf20Sopenharmony_ci		poh_prev->size += (poh_freed->size + poh_next->size);
33778c2ecf20Sopenharmony_ci		sisfb_delete_node(poh_next);
33788c2ecf20Sopenharmony_ci		sisfb_free_node(memheap, poh_freed);
33798c2ecf20Sopenharmony_ci		sisfb_free_node(memheap, poh_next);
33808c2ecf20Sopenharmony_ci		return poh_prev;
33818c2ecf20Sopenharmony_ci	}
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_ci	if(poh_prev) {
33848c2ecf20Sopenharmony_ci		poh_prev->size += poh_freed->size;
33858c2ecf20Sopenharmony_ci		sisfb_free_node(memheap, poh_freed);
33868c2ecf20Sopenharmony_ci		return poh_prev;
33878c2ecf20Sopenharmony_ci	}
33888c2ecf20Sopenharmony_ci
33898c2ecf20Sopenharmony_ci	if(poh_next) {
33908c2ecf20Sopenharmony_ci		poh_next->size += poh_freed->size;
33918c2ecf20Sopenharmony_ci		poh_next->offset = poh_freed->offset;
33928c2ecf20Sopenharmony_ci		sisfb_free_node(memheap, poh_freed);
33938c2ecf20Sopenharmony_ci		return poh_next;
33948c2ecf20Sopenharmony_ci	}
33958c2ecf20Sopenharmony_ci
33968c2ecf20Sopenharmony_ci	sisfb_insert_node(&memheap->oh_free, poh_freed);
33978c2ecf20Sopenharmony_ci
33988c2ecf20Sopenharmony_ci	return poh_freed;
33998c2ecf20Sopenharmony_ci}
34008c2ecf20Sopenharmony_ci
34018c2ecf20Sopenharmony_cistatic void
34028c2ecf20Sopenharmony_cisisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
34038c2ecf20Sopenharmony_ci{
34048c2ecf20Sopenharmony_ci	if(poh == NULL)
34058c2ecf20Sopenharmony_ci		return;
34068c2ecf20Sopenharmony_ci
34078c2ecf20Sopenharmony_ci	poh->poh_next = memheap->poh_freelist;
34088c2ecf20Sopenharmony_ci	memheap->poh_freelist = poh;
34098c2ecf20Sopenharmony_ci}
34108c2ecf20Sopenharmony_ci
34118c2ecf20Sopenharmony_cistatic void
34128c2ecf20Sopenharmony_cisis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
34138c2ecf20Sopenharmony_ci{
34148c2ecf20Sopenharmony_ci	struct SIS_OH *poh = NULL;
34158c2ecf20Sopenharmony_ci
34168c2ecf20Sopenharmony_ci	if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
34178c2ecf20Sopenharmony_ci		poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
34188c2ecf20Sopenharmony_ci
34198c2ecf20Sopenharmony_ci	if(poh == NULL) {
34208c2ecf20Sopenharmony_ci		req->offset = req->size = 0;
34218c2ecf20Sopenharmony_ci		DPRINTK("sisfb: Video RAM allocation failed\n");
34228c2ecf20Sopenharmony_ci	} else {
34238c2ecf20Sopenharmony_ci		req->offset = poh->offset;
34248c2ecf20Sopenharmony_ci		req->size = poh->size;
34258c2ecf20Sopenharmony_ci		DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
34268c2ecf20Sopenharmony_ci			(poh->offset + ivideo->video_vbase));
34278c2ecf20Sopenharmony_ci	}
34288c2ecf20Sopenharmony_ci}
34298c2ecf20Sopenharmony_ci
34308c2ecf20Sopenharmony_civoid
34318c2ecf20Sopenharmony_cisis_malloc(struct sis_memreq *req)
34328c2ecf20Sopenharmony_ci{
34338c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = sisfb_heap->vinfo;
34348c2ecf20Sopenharmony_ci
34358c2ecf20Sopenharmony_ci	if(&ivideo->sisfb_heap == sisfb_heap)
34368c2ecf20Sopenharmony_ci		sis_int_malloc(ivideo, req);
34378c2ecf20Sopenharmony_ci	else
34388c2ecf20Sopenharmony_ci		req->offset = req->size = 0;
34398c2ecf20Sopenharmony_ci}
34408c2ecf20Sopenharmony_ci
34418c2ecf20Sopenharmony_civoid
34428c2ecf20Sopenharmony_cisis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
34438c2ecf20Sopenharmony_ci{
34448c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
34458c2ecf20Sopenharmony_ci
34468c2ecf20Sopenharmony_ci	sis_int_malloc(ivideo, req);
34478c2ecf20Sopenharmony_ci}
34488c2ecf20Sopenharmony_ci
34498c2ecf20Sopenharmony_ci/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
34508c2ecf20Sopenharmony_ci
34518c2ecf20Sopenharmony_cistatic void
34528c2ecf20Sopenharmony_cisis_int_free(struct sis_video_info *ivideo, u32 base)
34538c2ecf20Sopenharmony_ci{
34548c2ecf20Sopenharmony_ci	struct SIS_OH *poh;
34558c2ecf20Sopenharmony_ci
34568c2ecf20Sopenharmony_ci	if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
34578c2ecf20Sopenharmony_ci		return;
34588c2ecf20Sopenharmony_ci
34598c2ecf20Sopenharmony_ci	poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
34608c2ecf20Sopenharmony_ci
34618c2ecf20Sopenharmony_ci	if(poh == NULL) {
34628c2ecf20Sopenharmony_ci		DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
34638c2ecf20Sopenharmony_ci			(unsigned int) base);
34648c2ecf20Sopenharmony_ci	}
34658c2ecf20Sopenharmony_ci}
34668c2ecf20Sopenharmony_ci
34678c2ecf20Sopenharmony_civoid
34688c2ecf20Sopenharmony_cisis_free(u32 base)
34698c2ecf20Sopenharmony_ci{
34708c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = sisfb_heap->vinfo;
34718c2ecf20Sopenharmony_ci
34728c2ecf20Sopenharmony_ci	sis_int_free(ivideo, base);
34738c2ecf20Sopenharmony_ci}
34748c2ecf20Sopenharmony_ci
34758c2ecf20Sopenharmony_civoid
34768c2ecf20Sopenharmony_cisis_free_new(struct pci_dev *pdev, u32 base)
34778c2ecf20Sopenharmony_ci{
34788c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
34798c2ecf20Sopenharmony_ci
34808c2ecf20Sopenharmony_ci	sis_int_free(ivideo, base);
34818c2ecf20Sopenharmony_ci}
34828c2ecf20Sopenharmony_ci
34838c2ecf20Sopenharmony_ci/* --------------------- SetMode routines ------------------------- */
34848c2ecf20Sopenharmony_ci
34858c2ecf20Sopenharmony_cistatic void
34868c2ecf20Sopenharmony_cisisfb_check_engine_and_sync(struct sis_video_info *ivideo)
34878c2ecf20Sopenharmony_ci{
34888c2ecf20Sopenharmony_ci	u8 cr30, cr31;
34898c2ecf20Sopenharmony_ci
34908c2ecf20Sopenharmony_ci	/* Check if MMIO and engines are enabled,
34918c2ecf20Sopenharmony_ci	 * and sync in case they are. Can't use
34928c2ecf20Sopenharmony_ci	 * ivideo->accel here, as this might have
34938c2ecf20Sopenharmony_ci	 * been changed before this is called.
34948c2ecf20Sopenharmony_ci	 */
34958c2ecf20Sopenharmony_ci	cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
34968c2ecf20Sopenharmony_ci	cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
34978c2ecf20Sopenharmony_ci	/* MMIO and 2D/3D engine enabled? */
34988c2ecf20Sopenharmony_ci	if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
34998c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
35008c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_300_VGA) {
35018c2ecf20Sopenharmony_ci			/* Don't care about TurboQueue. It's
35028c2ecf20Sopenharmony_ci			 * enough to know that the engines
35038c2ecf20Sopenharmony_ci			 * are enabled
35048c2ecf20Sopenharmony_ci			 */
35058c2ecf20Sopenharmony_ci			sisfb_syncaccel(ivideo);
35068c2ecf20Sopenharmony_ci		}
35078c2ecf20Sopenharmony_ci#endif
35088c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
35098c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_315_VGA) {
35108c2ecf20Sopenharmony_ci			/* Check that any queue mode is
35118c2ecf20Sopenharmony_ci			 * enabled, and that the queue
35128c2ecf20Sopenharmony_ci			 * is not in the state of "reset"
35138c2ecf20Sopenharmony_ci			 */
35148c2ecf20Sopenharmony_ci			cr30 = SiS_GetReg(SISSR, 0x26);
35158c2ecf20Sopenharmony_ci			if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
35168c2ecf20Sopenharmony_ci				sisfb_syncaccel(ivideo);
35178c2ecf20Sopenharmony_ci			}
35188c2ecf20Sopenharmony_ci		}
35198c2ecf20Sopenharmony_ci#endif
35208c2ecf20Sopenharmony_ci	}
35218c2ecf20Sopenharmony_ci}
35228c2ecf20Sopenharmony_ci
35238c2ecf20Sopenharmony_cistatic void
35248c2ecf20Sopenharmony_cisisfb_pre_setmode(struct sis_video_info *ivideo)
35258c2ecf20Sopenharmony_ci{
35268c2ecf20Sopenharmony_ci	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
35278c2ecf20Sopenharmony_ci	int tvregnum = 0;
35288c2ecf20Sopenharmony_ci
35298c2ecf20Sopenharmony_ci	ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
35308c2ecf20Sopenharmony_ci
35318c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x05, 0x86);
35328c2ecf20Sopenharmony_ci
35338c2ecf20Sopenharmony_ci	cr31 = SiS_GetReg(SISCR, 0x31);
35348c2ecf20Sopenharmony_ci	cr31 &= ~0x60;
35358c2ecf20Sopenharmony_ci	cr31 |= 0x04;
35368c2ecf20Sopenharmony_ci
35378c2ecf20Sopenharmony_ci	cr33 = ivideo->rate_idx & 0x0F;
35388c2ecf20Sopenharmony_ci
35398c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
35408c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_315_VGA) {
35418c2ecf20Sopenharmony_ci	   if(ivideo->chip >= SIS_661) {
35428c2ecf20Sopenharmony_ci	      cr38 = SiS_GetReg(SISCR, 0x38);
35438c2ecf20Sopenharmony_ci	      cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
35448c2ecf20Sopenharmony_ci	   } else {
35458c2ecf20Sopenharmony_ci	      tvregnum = 0x38;
35468c2ecf20Sopenharmony_ci	      cr38 = SiS_GetReg(SISCR, tvregnum);
35478c2ecf20Sopenharmony_ci	      cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
35488c2ecf20Sopenharmony_ci	   }
35498c2ecf20Sopenharmony_ci	}
35508c2ecf20Sopenharmony_ci#endif
35518c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
35528c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
35538c2ecf20Sopenharmony_ci	   tvregnum = 0x35;
35548c2ecf20Sopenharmony_ci	   cr38 = SiS_GetReg(SISCR, tvregnum);
35558c2ecf20Sopenharmony_ci	}
35568c2ecf20Sopenharmony_ci#endif
35578c2ecf20Sopenharmony_ci
35588c2ecf20Sopenharmony_ci	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
35598c2ecf20Sopenharmony_ci	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
35608c2ecf20Sopenharmony_ci	ivideo->curFSTN = ivideo->curDSTN = 0;
35618c2ecf20Sopenharmony_ci
35628c2ecf20Sopenharmony_ci	switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
35638c2ecf20Sopenharmony_ci
35648c2ecf20Sopenharmony_ci	   case CRT2_TV:
35658c2ecf20Sopenharmony_ci	      cr38 &= ~0xc0;   /* Clear PAL-M / PAL-N bits */
35668c2ecf20Sopenharmony_ci	      if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
35678c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
35688c2ecf20Sopenharmony_ci		 if(ivideo->chip >= SIS_661) {
35698c2ecf20Sopenharmony_ci		    cr38 |= 0x04;
35708c2ecf20Sopenharmony_ci		    if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
35718c2ecf20Sopenharmony_ci		    else if(ivideo->vbflags & TV_YPBPR750P)  cr35 |= 0x40;
35728c2ecf20Sopenharmony_ci		    else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
35738c2ecf20Sopenharmony_ci		    cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
35748c2ecf20Sopenharmony_ci		    cr35 &= ~0x01;
35758c2ecf20Sopenharmony_ci		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
35768c2ecf20Sopenharmony_ci		 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
35778c2ecf20Sopenharmony_ci		    cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
35788c2ecf20Sopenharmony_ci		    cr38 |= 0x08;
35798c2ecf20Sopenharmony_ci		    if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
35808c2ecf20Sopenharmony_ci		    else if(ivideo->vbflags & TV_YPBPR750P)  cr38 |= 0x20;
35818c2ecf20Sopenharmony_ci		    else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
35828c2ecf20Sopenharmony_ci		    cr31 &= ~0x01;
35838c2ecf20Sopenharmony_ci		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
35848c2ecf20Sopenharmony_ci		 }
35858c2ecf20Sopenharmony_ci#endif
35868c2ecf20Sopenharmony_ci	      } else if((ivideo->vbflags & TV_HIVISION) &&
35878c2ecf20Sopenharmony_ci				(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
35888c2ecf20Sopenharmony_ci		 if(ivideo->chip >= SIS_661) {
35898c2ecf20Sopenharmony_ci		    cr38 |= 0x04;
35908c2ecf20Sopenharmony_ci		    cr35 |= 0x60;
35918c2ecf20Sopenharmony_ci		 } else {
35928c2ecf20Sopenharmony_ci		    cr30 |= 0x80;
35938c2ecf20Sopenharmony_ci		 }
35948c2ecf20Sopenharmony_ci		 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
35958c2ecf20Sopenharmony_ci		 cr31 |= 0x01;
35968c2ecf20Sopenharmony_ci		 cr35 |= 0x01;
35978c2ecf20Sopenharmony_ci		 ivideo->currentvbflags |= TV_HIVISION;
35988c2ecf20Sopenharmony_ci	      } else if(ivideo->vbflags & TV_SCART) {
35998c2ecf20Sopenharmony_ci		 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
36008c2ecf20Sopenharmony_ci		 cr31 |= 0x01;
36018c2ecf20Sopenharmony_ci		 cr35 |= 0x01;
36028c2ecf20Sopenharmony_ci		 ivideo->currentvbflags |= TV_SCART;
36038c2ecf20Sopenharmony_ci	      } else {
36048c2ecf20Sopenharmony_ci		 if(ivideo->vbflags & TV_SVIDEO) {
36058c2ecf20Sopenharmony_ci		    cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
36068c2ecf20Sopenharmony_ci		    ivideo->currentvbflags |= TV_SVIDEO;
36078c2ecf20Sopenharmony_ci		 }
36088c2ecf20Sopenharmony_ci		 if(ivideo->vbflags & TV_AVIDEO) {
36098c2ecf20Sopenharmony_ci		    cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
36108c2ecf20Sopenharmony_ci		    ivideo->currentvbflags |= TV_AVIDEO;
36118c2ecf20Sopenharmony_ci		 }
36128c2ecf20Sopenharmony_ci	      }
36138c2ecf20Sopenharmony_ci	      cr31 |= SIS_DRIVER_MODE;
36148c2ecf20Sopenharmony_ci
36158c2ecf20Sopenharmony_ci	      if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
36168c2ecf20Sopenharmony_ci		 if(ivideo->vbflags & TV_PAL) {
36178c2ecf20Sopenharmony_ci		    cr31 |= 0x01; cr35 |= 0x01;
36188c2ecf20Sopenharmony_ci		    ivideo->currentvbflags |= TV_PAL;
36198c2ecf20Sopenharmony_ci		    if(ivideo->vbflags & TV_PALM) {
36208c2ecf20Sopenharmony_ci		       cr38 |= 0x40; cr35 |= 0x04;
36218c2ecf20Sopenharmony_ci		       ivideo->currentvbflags |= TV_PALM;
36228c2ecf20Sopenharmony_ci		    } else if(ivideo->vbflags & TV_PALN) {
36238c2ecf20Sopenharmony_ci		       cr38 |= 0x80; cr35 |= 0x08;
36248c2ecf20Sopenharmony_ci		       ivideo->currentvbflags |= TV_PALN;
36258c2ecf20Sopenharmony_ci		    }
36268c2ecf20Sopenharmony_ci		 } else {
36278c2ecf20Sopenharmony_ci		    cr31 &= ~0x01; cr35 &= ~0x01;
36288c2ecf20Sopenharmony_ci		    ivideo->currentvbflags |= TV_NTSC;
36298c2ecf20Sopenharmony_ci		    if(ivideo->vbflags & TV_NTSCJ) {
36308c2ecf20Sopenharmony_ci		       cr38 |= 0x40; cr35 |= 0x02;
36318c2ecf20Sopenharmony_ci		       ivideo->currentvbflags |= TV_NTSCJ;
36328c2ecf20Sopenharmony_ci		    }
36338c2ecf20Sopenharmony_ci		 }
36348c2ecf20Sopenharmony_ci	      }
36358c2ecf20Sopenharmony_ci	      break;
36368c2ecf20Sopenharmony_ci
36378c2ecf20Sopenharmony_ci	   case CRT2_LCD:
36388c2ecf20Sopenharmony_ci	      cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
36398c2ecf20Sopenharmony_ci	      cr31 |= SIS_DRIVER_MODE;
36408c2ecf20Sopenharmony_ci	      SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
36418c2ecf20Sopenharmony_ci	      SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
36428c2ecf20Sopenharmony_ci	      ivideo->curFSTN = ivideo->sisfb_fstn;
36438c2ecf20Sopenharmony_ci	      ivideo->curDSTN = ivideo->sisfb_dstn;
36448c2ecf20Sopenharmony_ci	      break;
36458c2ecf20Sopenharmony_ci
36468c2ecf20Sopenharmony_ci	   case CRT2_VGA:
36478c2ecf20Sopenharmony_ci	      cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
36488c2ecf20Sopenharmony_ci	      cr31 |= SIS_DRIVER_MODE;
36498c2ecf20Sopenharmony_ci	      if(ivideo->sisfb_nocrt2rate) {
36508c2ecf20Sopenharmony_ci		 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
36518c2ecf20Sopenharmony_ci	      } else {
36528c2ecf20Sopenharmony_ci		 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
36538c2ecf20Sopenharmony_ci	      }
36548c2ecf20Sopenharmony_ci	      break;
36558c2ecf20Sopenharmony_ci
36568c2ecf20Sopenharmony_ci	   default:	/* disable CRT2 */
36578c2ecf20Sopenharmony_ci	      cr30 = 0x00;
36588c2ecf20Sopenharmony_ci	      cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
36598c2ecf20Sopenharmony_ci	}
36608c2ecf20Sopenharmony_ci
36618c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x30, cr30);
36628c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x33, cr33);
36638c2ecf20Sopenharmony_ci
36648c2ecf20Sopenharmony_ci	if(ivideo->chip >= SIS_661) {
36658c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
36668c2ecf20Sopenharmony_ci	   cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
36678c2ecf20Sopenharmony_ci	   SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
36688c2ecf20Sopenharmony_ci	   cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
36698c2ecf20Sopenharmony_ci	   SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
36708c2ecf20Sopenharmony_ci#endif
36718c2ecf20Sopenharmony_ci	} else if(ivideo->chip != SIS_300) {
36728c2ecf20Sopenharmony_ci	   SiS_SetReg(SISCR, tvregnum, cr38);
36738c2ecf20Sopenharmony_ci	}
36748c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x31, cr31);
36758c2ecf20Sopenharmony_ci
36768c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
36778c2ecf20Sopenharmony_ci
36788c2ecf20Sopenharmony_ci	sisfb_check_engine_and_sync(ivideo);
36798c2ecf20Sopenharmony_ci}
36808c2ecf20Sopenharmony_ci
36818c2ecf20Sopenharmony_ci/* Fix SR11 for 661 and later */
36828c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
36838c2ecf20Sopenharmony_cistatic void
36848c2ecf20Sopenharmony_cisisfb_fixup_SR11(struct sis_video_info *ivideo)
36858c2ecf20Sopenharmony_ci{
36868c2ecf20Sopenharmony_ci	u8  tmpreg;
36878c2ecf20Sopenharmony_ci
36888c2ecf20Sopenharmony_ci	if(ivideo->chip >= SIS_661) {
36898c2ecf20Sopenharmony_ci		tmpreg = SiS_GetReg(SISSR, 0x11);
36908c2ecf20Sopenharmony_ci		if(tmpreg & 0x20) {
36918c2ecf20Sopenharmony_ci			tmpreg = SiS_GetReg(SISSR, 0x3e);
36928c2ecf20Sopenharmony_ci			tmpreg = (tmpreg + 1) & 0xff;
36938c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x3e, tmpreg);
36948c2ecf20Sopenharmony_ci			tmpreg = SiS_GetReg(SISSR, 0x11);
36958c2ecf20Sopenharmony_ci		}
36968c2ecf20Sopenharmony_ci		if(tmpreg & 0xf0) {
36978c2ecf20Sopenharmony_ci			SiS_SetRegAND(SISSR, 0x11, 0x0f);
36988c2ecf20Sopenharmony_ci		}
36998c2ecf20Sopenharmony_ci	}
37008c2ecf20Sopenharmony_ci}
37018c2ecf20Sopenharmony_ci#endif
37028c2ecf20Sopenharmony_ci
37038c2ecf20Sopenharmony_cistatic void
37048c2ecf20Sopenharmony_cisisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
37058c2ecf20Sopenharmony_ci{
37068c2ecf20Sopenharmony_ci	if(val > 32) val = 32;
37078c2ecf20Sopenharmony_ci	if(val < -32) val = -32;
37088c2ecf20Sopenharmony_ci	ivideo->tvxpos = val;
37098c2ecf20Sopenharmony_ci
37108c2ecf20Sopenharmony_ci	if(ivideo->sisfblocked) return;
37118c2ecf20Sopenharmony_ci	if(!ivideo->modechanged) return;
37128c2ecf20Sopenharmony_ci
37138c2ecf20Sopenharmony_ci	if(ivideo->currentvbflags & CRT2_TV) {
37148c2ecf20Sopenharmony_ci
37158c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_CHRONTEL) {
37168c2ecf20Sopenharmony_ci
37178c2ecf20Sopenharmony_ci			int x = ivideo->tvx;
37188c2ecf20Sopenharmony_ci
37198c2ecf20Sopenharmony_ci			switch(ivideo->chronteltype) {
37208c2ecf20Sopenharmony_ci			case 1:
37218c2ecf20Sopenharmony_ci				x += val;
37228c2ecf20Sopenharmony_ci				if(x < 0) x = 0;
37238c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x05, 0x86);
37248c2ecf20Sopenharmony_ci				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
37258c2ecf20Sopenharmony_ci				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
37268c2ecf20Sopenharmony_ci				break;
37278c2ecf20Sopenharmony_ci			case 2:
37288c2ecf20Sopenharmony_ci				/* Not supported by hardware */
37298c2ecf20Sopenharmony_ci				break;
37308c2ecf20Sopenharmony_ci			}
37318c2ecf20Sopenharmony_ci
37328c2ecf20Sopenharmony_ci		} else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
37338c2ecf20Sopenharmony_ci
37348c2ecf20Sopenharmony_ci			u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
37358c2ecf20Sopenharmony_ci			unsigned short temp;
37368c2ecf20Sopenharmony_ci
37378c2ecf20Sopenharmony_ci			p2_1f = ivideo->p2_1f;
37388c2ecf20Sopenharmony_ci			p2_20 = ivideo->p2_20;
37398c2ecf20Sopenharmony_ci			p2_2b = ivideo->p2_2b;
37408c2ecf20Sopenharmony_ci			p2_42 = ivideo->p2_42;
37418c2ecf20Sopenharmony_ci			p2_43 = ivideo->p2_43;
37428c2ecf20Sopenharmony_ci
37438c2ecf20Sopenharmony_ci			temp = p2_1f | ((p2_20 & 0xf0) << 4);
37448c2ecf20Sopenharmony_ci			temp += (val * 2);
37458c2ecf20Sopenharmony_ci			p2_1f = temp & 0xff;
37468c2ecf20Sopenharmony_ci			p2_20 = (temp & 0xf00) >> 4;
37478c2ecf20Sopenharmony_ci			p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
37488c2ecf20Sopenharmony_ci			temp = p2_43 | ((p2_42 & 0xf0) << 4);
37498c2ecf20Sopenharmony_ci			temp += (val * 2);
37508c2ecf20Sopenharmony_ci			p2_43 = temp & 0xff;
37518c2ecf20Sopenharmony_ci			p2_42 = (temp & 0xf00) >> 4;
37528c2ecf20Sopenharmony_ci			SiS_SetReg(SISPART2, 0x1f, p2_1f);
37538c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
37548c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
37558c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
37568c2ecf20Sopenharmony_ci			SiS_SetReg(SISPART2, 0x43, p2_43);
37578c2ecf20Sopenharmony_ci		}
37588c2ecf20Sopenharmony_ci	}
37598c2ecf20Sopenharmony_ci}
37608c2ecf20Sopenharmony_ci
37618c2ecf20Sopenharmony_cistatic void
37628c2ecf20Sopenharmony_cisisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
37638c2ecf20Sopenharmony_ci{
37648c2ecf20Sopenharmony_ci	if(val > 32) val = 32;
37658c2ecf20Sopenharmony_ci	if(val < -32) val = -32;
37668c2ecf20Sopenharmony_ci	ivideo->tvypos = val;
37678c2ecf20Sopenharmony_ci
37688c2ecf20Sopenharmony_ci	if(ivideo->sisfblocked) return;
37698c2ecf20Sopenharmony_ci	if(!ivideo->modechanged) return;
37708c2ecf20Sopenharmony_ci
37718c2ecf20Sopenharmony_ci	if(ivideo->currentvbflags & CRT2_TV) {
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_CHRONTEL) {
37748c2ecf20Sopenharmony_ci
37758c2ecf20Sopenharmony_ci			int y = ivideo->tvy;
37768c2ecf20Sopenharmony_ci
37778c2ecf20Sopenharmony_ci			switch(ivideo->chronteltype) {
37788c2ecf20Sopenharmony_ci			case 1:
37798c2ecf20Sopenharmony_ci				y -= val;
37808c2ecf20Sopenharmony_ci				if(y < 0) y = 0;
37818c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x05, 0x86);
37828c2ecf20Sopenharmony_ci				SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
37838c2ecf20Sopenharmony_ci				SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
37848c2ecf20Sopenharmony_ci				break;
37858c2ecf20Sopenharmony_ci			case 2:
37868c2ecf20Sopenharmony_ci				/* Not supported by hardware */
37878c2ecf20Sopenharmony_ci				break;
37888c2ecf20Sopenharmony_ci			}
37898c2ecf20Sopenharmony_ci
37908c2ecf20Sopenharmony_ci		} else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
37918c2ecf20Sopenharmony_ci
37928c2ecf20Sopenharmony_ci			char p2_01, p2_02;
37938c2ecf20Sopenharmony_ci			val /= 2;
37948c2ecf20Sopenharmony_ci			p2_01 = ivideo->p2_01;
37958c2ecf20Sopenharmony_ci			p2_02 = ivideo->p2_02;
37968c2ecf20Sopenharmony_ci
37978c2ecf20Sopenharmony_ci			p2_01 += val;
37988c2ecf20Sopenharmony_ci			p2_02 += val;
37998c2ecf20Sopenharmony_ci			if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
38008c2ecf20Sopenharmony_ci				while((p2_01 <= 0) || (p2_02 <= 0)) {
38018c2ecf20Sopenharmony_ci					p2_01 += 2;
38028c2ecf20Sopenharmony_ci					p2_02 += 2;
38038c2ecf20Sopenharmony_ci				}
38048c2ecf20Sopenharmony_ci			}
38058c2ecf20Sopenharmony_ci			SiS_SetReg(SISPART2, 0x01, p2_01);
38068c2ecf20Sopenharmony_ci			SiS_SetReg(SISPART2, 0x02, p2_02);
38078c2ecf20Sopenharmony_ci		}
38088c2ecf20Sopenharmony_ci	}
38098c2ecf20Sopenharmony_ci}
38108c2ecf20Sopenharmony_ci
38118c2ecf20Sopenharmony_cistatic void
38128c2ecf20Sopenharmony_cisisfb_post_setmode(struct sis_video_info *ivideo)
38138c2ecf20Sopenharmony_ci{
38148c2ecf20Sopenharmony_ci	bool crt1isoff = false;
38158c2ecf20Sopenharmony_ci	bool doit = true;
38168c2ecf20Sopenharmony_ci#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
38178c2ecf20Sopenharmony_ci	u8 reg;
38188c2ecf20Sopenharmony_ci#endif
38198c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
38208c2ecf20Sopenharmony_ci	u8 reg1;
38218c2ecf20Sopenharmony_ci#endif
38228c2ecf20Sopenharmony_ci
38238c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x05, 0x86);
38248c2ecf20Sopenharmony_ci
38258c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
38268c2ecf20Sopenharmony_ci	sisfb_fixup_SR11(ivideo);
38278c2ecf20Sopenharmony_ci#endif
38288c2ecf20Sopenharmony_ci
38298c2ecf20Sopenharmony_ci	/* Now we actually HAVE changed the display mode */
38308c2ecf20Sopenharmony_ci	ivideo->modechanged = 1;
38318c2ecf20Sopenharmony_ci
38328c2ecf20Sopenharmony_ci	/* We can't switch off CRT1 if bridge is in slave mode */
38338c2ecf20Sopenharmony_ci	if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
38348c2ecf20Sopenharmony_ci		if(sisfb_bridgeisslave(ivideo)) doit = false;
38358c2ecf20Sopenharmony_ci	} else
38368c2ecf20Sopenharmony_ci		ivideo->sisfb_crt1off = 0;
38378c2ecf20Sopenharmony_ci
38388c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
38398c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
38408c2ecf20Sopenharmony_ci		if((ivideo->sisfb_crt1off) && (doit)) {
38418c2ecf20Sopenharmony_ci			crt1isoff = true;
38428c2ecf20Sopenharmony_ci			reg = 0x00;
38438c2ecf20Sopenharmony_ci		} else {
38448c2ecf20Sopenharmony_ci			crt1isoff = false;
38458c2ecf20Sopenharmony_ci			reg = 0x80;
38468c2ecf20Sopenharmony_ci		}
38478c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
38488c2ecf20Sopenharmony_ci	}
38498c2ecf20Sopenharmony_ci#endif
38508c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
38518c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_315_VGA) {
38528c2ecf20Sopenharmony_ci		if((ivideo->sisfb_crt1off) && (doit)) {
38538c2ecf20Sopenharmony_ci			crt1isoff = true;
38548c2ecf20Sopenharmony_ci			reg  = 0x40;
38558c2ecf20Sopenharmony_ci			reg1 = 0xc0;
38568c2ecf20Sopenharmony_ci		} else {
38578c2ecf20Sopenharmony_ci			crt1isoff = false;
38588c2ecf20Sopenharmony_ci			reg  = 0x00;
38598c2ecf20Sopenharmony_ci			reg1 = 0x00;
38608c2ecf20Sopenharmony_ci		}
38618c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
38628c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
38638c2ecf20Sopenharmony_ci	}
38648c2ecf20Sopenharmony_ci#endif
38658c2ecf20Sopenharmony_ci
38668c2ecf20Sopenharmony_ci	if(crt1isoff) {
38678c2ecf20Sopenharmony_ci		ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
38688c2ecf20Sopenharmony_ci		ivideo->currentvbflags |= VB_SINGLE_MODE;
38698c2ecf20Sopenharmony_ci	} else {
38708c2ecf20Sopenharmony_ci		ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
38718c2ecf20Sopenharmony_ci		if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
38728c2ecf20Sopenharmony_ci			ivideo->currentvbflags |= VB_MIRROR_MODE;
38738c2ecf20Sopenharmony_ci		} else {
38748c2ecf20Sopenharmony_ci			ivideo->currentvbflags |= VB_SINGLE_MODE;
38758c2ecf20Sopenharmony_ci		}
38768c2ecf20Sopenharmony_ci	}
38778c2ecf20Sopenharmony_ci
38788c2ecf20Sopenharmony_ci	SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
38798c2ecf20Sopenharmony_ci
38808c2ecf20Sopenharmony_ci	if(ivideo->currentvbflags & CRT2_TV) {
38818c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_SISBRIDGE) {
38828c2ecf20Sopenharmony_ci			ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
38838c2ecf20Sopenharmony_ci			ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
38848c2ecf20Sopenharmony_ci			ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
38858c2ecf20Sopenharmony_ci			ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
38868c2ecf20Sopenharmony_ci			ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
38878c2ecf20Sopenharmony_ci			ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
38888c2ecf20Sopenharmony_ci			ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
38898c2ecf20Sopenharmony_ci		} else if(ivideo->vbflags2 & VB2_CHRONTEL) {
38908c2ecf20Sopenharmony_ci			if(ivideo->chronteltype == 1) {
38918c2ecf20Sopenharmony_ci				ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
38928c2ecf20Sopenharmony_ci				ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
38938c2ecf20Sopenharmony_ci				ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
38948c2ecf20Sopenharmony_ci				ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
38958c2ecf20Sopenharmony_ci			}
38968c2ecf20Sopenharmony_ci		}
38978c2ecf20Sopenharmony_ci	}
38988c2ecf20Sopenharmony_ci
38998c2ecf20Sopenharmony_ci	if(ivideo->tvxpos) {
39008c2ecf20Sopenharmony_ci		sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
39018c2ecf20Sopenharmony_ci	}
39028c2ecf20Sopenharmony_ci	if(ivideo->tvypos) {
39038c2ecf20Sopenharmony_ci		sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
39048c2ecf20Sopenharmony_ci	}
39058c2ecf20Sopenharmony_ci
39068c2ecf20Sopenharmony_ci	/* Eventually sync engines */
39078c2ecf20Sopenharmony_ci	sisfb_check_engine_and_sync(ivideo);
39088c2ecf20Sopenharmony_ci
39098c2ecf20Sopenharmony_ci	/* (Re-)Initialize chip engines */
39108c2ecf20Sopenharmony_ci	if(ivideo->accel) {
39118c2ecf20Sopenharmony_ci		sisfb_engine_init(ivideo);
39128c2ecf20Sopenharmony_ci	} else {
39138c2ecf20Sopenharmony_ci		ivideo->engineok = 0;
39148c2ecf20Sopenharmony_ci	}
39158c2ecf20Sopenharmony_ci}
39168c2ecf20Sopenharmony_ci
39178c2ecf20Sopenharmony_cistatic int
39188c2ecf20Sopenharmony_cisisfb_reset_mode(struct sis_video_info *ivideo)
39198c2ecf20Sopenharmony_ci{
39208c2ecf20Sopenharmony_ci	if(sisfb_set_mode(ivideo, 0))
39218c2ecf20Sopenharmony_ci		return 1;
39228c2ecf20Sopenharmony_ci
39238c2ecf20Sopenharmony_ci	sisfb_set_pitch(ivideo);
39248c2ecf20Sopenharmony_ci	sisfb_set_base_CRT1(ivideo, ivideo->current_base);
39258c2ecf20Sopenharmony_ci	sisfb_set_base_CRT2(ivideo, ivideo->current_base);
39268c2ecf20Sopenharmony_ci
39278c2ecf20Sopenharmony_ci	return 0;
39288c2ecf20Sopenharmony_ci}
39298c2ecf20Sopenharmony_ci
39308c2ecf20Sopenharmony_cistatic void
39318c2ecf20Sopenharmony_cisisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
39328c2ecf20Sopenharmony_ci{
39338c2ecf20Sopenharmony_ci	int mycrt1off;
39348c2ecf20Sopenharmony_ci
39358c2ecf20Sopenharmony_ci	switch(sisfb_command->sisfb_cmd) {
39368c2ecf20Sopenharmony_ci	case SISFB_CMD_GETVBFLAGS:
39378c2ecf20Sopenharmony_ci		if(!ivideo->modechanged) {
39388c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
39398c2ecf20Sopenharmony_ci		} else {
39408c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
39418c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
39428c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[2] = ivideo->vbflags2;
39438c2ecf20Sopenharmony_ci		}
39448c2ecf20Sopenharmony_ci		break;
39458c2ecf20Sopenharmony_ci	case SISFB_CMD_SWITCHCRT1:
39468c2ecf20Sopenharmony_ci		/* arg[0]: 0 = off, 1 = on, 99 = query */
39478c2ecf20Sopenharmony_ci		if(!ivideo->modechanged) {
39488c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
39498c2ecf20Sopenharmony_ci		} else if(sisfb_command->sisfb_arg[0] == 99) {
39508c2ecf20Sopenharmony_ci			/* Query */
39518c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
39528c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
39538c2ecf20Sopenharmony_ci		} else if(ivideo->sisfblocked) {
39548c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
39558c2ecf20Sopenharmony_ci		} else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
39568c2ecf20Sopenharmony_ci					(sisfb_command->sisfb_arg[0] == 0)) {
39578c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
39588c2ecf20Sopenharmony_ci		} else {
39598c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
39608c2ecf20Sopenharmony_ci			mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
39618c2ecf20Sopenharmony_ci			if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
39628c2ecf20Sopenharmony_ci			    ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
39638c2ecf20Sopenharmony_ci				ivideo->sisfb_crt1off = mycrt1off;
39648c2ecf20Sopenharmony_ci				if(sisfb_reset_mode(ivideo)) {
39658c2ecf20Sopenharmony_ci					sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
39668c2ecf20Sopenharmony_ci				}
39678c2ecf20Sopenharmony_ci			}
39688c2ecf20Sopenharmony_ci			sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
39698c2ecf20Sopenharmony_ci		}
39708c2ecf20Sopenharmony_ci		break;
39718c2ecf20Sopenharmony_ci	/* more to come */
39728c2ecf20Sopenharmony_ci	default:
39738c2ecf20Sopenharmony_ci		sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
39748c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
39758c2ecf20Sopenharmony_ci			sisfb_command->sisfb_cmd);
39768c2ecf20Sopenharmony_ci	}
39778c2ecf20Sopenharmony_ci}
39788c2ecf20Sopenharmony_ci
39798c2ecf20Sopenharmony_ci#ifndef MODULE
39808c2ecf20Sopenharmony_cistatic int __init sisfb_setup(char *options)
39818c2ecf20Sopenharmony_ci{
39828c2ecf20Sopenharmony_ci	char *this_opt;
39838c2ecf20Sopenharmony_ci
39848c2ecf20Sopenharmony_ci	sisfb_setdefaultparms();
39858c2ecf20Sopenharmony_ci
39868c2ecf20Sopenharmony_ci	if(!options || !(*options))
39878c2ecf20Sopenharmony_ci		return 0;
39888c2ecf20Sopenharmony_ci
39898c2ecf20Sopenharmony_ci	while((this_opt = strsep(&options, ",")) != NULL) {
39908c2ecf20Sopenharmony_ci
39918c2ecf20Sopenharmony_ci		if(!(*this_opt)) continue;
39928c2ecf20Sopenharmony_ci
39938c2ecf20Sopenharmony_ci		if(!strncasecmp(this_opt, "off", 3)) {
39948c2ecf20Sopenharmony_ci			sisfb_off = 1;
39958c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
39968c2ecf20Sopenharmony_ci			/* Need to check crt2 type first for fstn/dstn */
39978c2ecf20Sopenharmony_ci			sisfb_search_crt2type(this_opt + 14);
39988c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "tvmode:",7)) {
39998c2ecf20Sopenharmony_ci			sisfb_search_tvstd(this_opt + 7);
40008c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "tvstandard:",11)) {
40018c2ecf20Sopenharmony_ci			sisfb_search_tvstd(this_opt + 11);
40028c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "mode:", 5)) {
40038c2ecf20Sopenharmony_ci			sisfb_search_mode(this_opt + 5, false);
40048c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "vesa:", 5)) {
40058c2ecf20Sopenharmony_ci			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
40068c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "rate:", 5)) {
40078c2ecf20Sopenharmony_ci			sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
40088c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
40098c2ecf20Sopenharmony_ci			sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
40108c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "mem:",4)) {
40118c2ecf20Sopenharmony_ci			sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
40128c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "pdc:", 4)) {
40138c2ecf20Sopenharmony_ci			sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
40148c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "pdc1:", 5)) {
40158c2ecf20Sopenharmony_ci			sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
40168c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "noaccel", 7)) {
40178c2ecf20Sopenharmony_ci			sisfb_accel = 0;
40188c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "accel", 5)) {
40198c2ecf20Sopenharmony_ci			sisfb_accel = -1;
40208c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "noypan", 6)) {
40218c2ecf20Sopenharmony_ci			sisfb_ypan = 0;
40228c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "ypan", 4)) {
40238c2ecf20Sopenharmony_ci			sisfb_ypan = -1;
40248c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "nomax", 5)) {
40258c2ecf20Sopenharmony_ci			sisfb_max = 0;
40268c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "max", 3)) {
40278c2ecf20Sopenharmony_ci			sisfb_max = -1;
40288c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "userom:", 7)) {
40298c2ecf20Sopenharmony_ci			sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
40308c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "useoem:", 7)) {
40318c2ecf20Sopenharmony_ci			sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
40328c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
40338c2ecf20Sopenharmony_ci			sisfb_nocrt2rate = 1;
40348c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
40358c2ecf20Sopenharmony_ci			unsigned long temp = 2;
40368c2ecf20Sopenharmony_ci			temp = simple_strtoul(this_opt + 9, NULL, 0);
40378c2ecf20Sopenharmony_ci			if((temp == 0) || (temp == 1)) {
40388c2ecf20Sopenharmony_ci			   sisfb_scalelcd = temp ^ 1;
40398c2ecf20Sopenharmony_ci			}
40408c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
40418c2ecf20Sopenharmony_ci			int temp = 0;
40428c2ecf20Sopenharmony_ci			temp = (int)simple_strtol(this_opt + 13, NULL, 0);
40438c2ecf20Sopenharmony_ci			if((temp >= -32) && (temp <= 32)) {
40448c2ecf20Sopenharmony_ci			   sisfb_tvxposoffset = temp;
40458c2ecf20Sopenharmony_ci			}
40468c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
40478c2ecf20Sopenharmony_ci			int temp = 0;
40488c2ecf20Sopenharmony_ci			temp = (int)simple_strtol(this_opt + 13, NULL, 0);
40498c2ecf20Sopenharmony_ci			if((temp >= -32) && (temp <= 32)) {
40508c2ecf20Sopenharmony_ci			   sisfb_tvyposoffset = temp;
40518c2ecf20Sopenharmony_ci			}
40528c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
40538c2ecf20Sopenharmony_ci			sisfb_search_specialtiming(this_opt + 14);
40548c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
40558c2ecf20Sopenharmony_ci			int temp = 4;
40568c2ecf20Sopenharmony_ci			temp = simple_strtoul(this_opt + 7, NULL, 0);
40578c2ecf20Sopenharmony_ci			if((temp >= 0) && (temp <= 3)) {
40588c2ecf20Sopenharmony_ci			   sisfb_lvdshl = temp;
40598c2ecf20Sopenharmony_ci			}
40608c2ecf20Sopenharmony_ci		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
40618c2ecf20Sopenharmony_ci			sisfb_search_mode(this_opt, true);
40628c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
40638c2ecf20Sopenharmony_ci		} else if(!strncasecmp(this_opt, "resetcard", 9)) {
40648c2ecf20Sopenharmony_ci			sisfb_resetcard = 1;
40658c2ecf20Sopenharmony_ci	        } else if(!strncasecmp(this_opt, "videoram:", 9)) {
40668c2ecf20Sopenharmony_ci			sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
40678c2ecf20Sopenharmony_ci#endif
40688c2ecf20Sopenharmony_ci		} else {
40698c2ecf20Sopenharmony_ci			printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
40708c2ecf20Sopenharmony_ci		}
40718c2ecf20Sopenharmony_ci
40728c2ecf20Sopenharmony_ci	}
40738c2ecf20Sopenharmony_ci
40748c2ecf20Sopenharmony_ci	return 0;
40758c2ecf20Sopenharmony_ci}
40768c2ecf20Sopenharmony_ci#endif
40778c2ecf20Sopenharmony_ci
40788c2ecf20Sopenharmony_cistatic int sisfb_check_rom(void __iomem *rom_base,
40798c2ecf20Sopenharmony_ci			   struct sis_video_info *ivideo)
40808c2ecf20Sopenharmony_ci{
40818c2ecf20Sopenharmony_ci	void __iomem *rom;
40828c2ecf20Sopenharmony_ci	int romptr;
40838c2ecf20Sopenharmony_ci
40848c2ecf20Sopenharmony_ci	if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
40858c2ecf20Sopenharmony_ci		return 0;
40868c2ecf20Sopenharmony_ci
40878c2ecf20Sopenharmony_ci	romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
40888c2ecf20Sopenharmony_ci	if(romptr > (0x10000 - 8))
40898c2ecf20Sopenharmony_ci		return 0;
40908c2ecf20Sopenharmony_ci
40918c2ecf20Sopenharmony_ci	rom = rom_base + romptr;
40928c2ecf20Sopenharmony_ci
40938c2ecf20Sopenharmony_ci	if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
40948c2ecf20Sopenharmony_ci	   (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
40958c2ecf20Sopenharmony_ci		return 0;
40968c2ecf20Sopenharmony_ci
40978c2ecf20Sopenharmony_ci	if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
40988c2ecf20Sopenharmony_ci		return 0;
40998c2ecf20Sopenharmony_ci
41008c2ecf20Sopenharmony_ci	if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
41018c2ecf20Sopenharmony_ci		return 0;
41028c2ecf20Sopenharmony_ci
41038c2ecf20Sopenharmony_ci	return 1;
41048c2ecf20Sopenharmony_ci}
41058c2ecf20Sopenharmony_ci
41068c2ecf20Sopenharmony_cistatic unsigned char *sisfb_find_rom(struct pci_dev *pdev)
41078c2ecf20Sopenharmony_ci{
41088c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
41098c2ecf20Sopenharmony_ci	void __iomem *rom_base;
41108c2ecf20Sopenharmony_ci	unsigned char *myrombase = NULL;
41118c2ecf20Sopenharmony_ci	size_t romsize;
41128c2ecf20Sopenharmony_ci
41138c2ecf20Sopenharmony_ci	/* First, try the official pci ROM functions (except
41148c2ecf20Sopenharmony_ci	 * on integrated chipsets which have no ROM).
41158c2ecf20Sopenharmony_ci	 */
41168c2ecf20Sopenharmony_ci
41178c2ecf20Sopenharmony_ci	if(!ivideo->nbridge) {
41188c2ecf20Sopenharmony_ci
41198c2ecf20Sopenharmony_ci		if((rom_base = pci_map_rom(pdev, &romsize))) {
41208c2ecf20Sopenharmony_ci
41218c2ecf20Sopenharmony_ci			if(sisfb_check_rom(rom_base, ivideo)) {
41228c2ecf20Sopenharmony_ci
41238c2ecf20Sopenharmony_ci				if((myrombase = vmalloc(65536))) {
41248c2ecf20Sopenharmony_ci					memcpy_fromio(myrombase, rom_base,
41258c2ecf20Sopenharmony_ci							(romsize > 65536) ? 65536 : romsize);
41268c2ecf20Sopenharmony_ci				}
41278c2ecf20Sopenharmony_ci			}
41288c2ecf20Sopenharmony_ci			pci_unmap_rom(pdev, rom_base);
41298c2ecf20Sopenharmony_ci		}
41308c2ecf20Sopenharmony_ci	}
41318c2ecf20Sopenharmony_ci
41328c2ecf20Sopenharmony_ci	if(myrombase) return myrombase;
41338c2ecf20Sopenharmony_ci
41348c2ecf20Sopenharmony_ci	/* Otherwise do it the conventional way. */
41358c2ecf20Sopenharmony_ci
41368c2ecf20Sopenharmony_ci#if defined(__i386__) || defined(__x86_64__)
41378c2ecf20Sopenharmony_ci	{
41388c2ecf20Sopenharmony_ci		u32 temp;
41398c2ecf20Sopenharmony_ci
41408c2ecf20Sopenharmony_ci		for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
41418c2ecf20Sopenharmony_ci
41428c2ecf20Sopenharmony_ci			rom_base = ioremap(temp, 65536);
41438c2ecf20Sopenharmony_ci			if (!rom_base)
41448c2ecf20Sopenharmony_ci				continue;
41458c2ecf20Sopenharmony_ci
41468c2ecf20Sopenharmony_ci			if (!sisfb_check_rom(rom_base, ivideo)) {
41478c2ecf20Sopenharmony_ci				iounmap(rom_base);
41488c2ecf20Sopenharmony_ci				continue;
41498c2ecf20Sopenharmony_ci			}
41508c2ecf20Sopenharmony_ci
41518c2ecf20Sopenharmony_ci			if ((myrombase = vmalloc(65536)))
41528c2ecf20Sopenharmony_ci				memcpy_fromio(myrombase, rom_base, 65536);
41538c2ecf20Sopenharmony_ci
41548c2ecf20Sopenharmony_ci			iounmap(rom_base);
41558c2ecf20Sopenharmony_ci			break;
41568c2ecf20Sopenharmony_ci
41578c2ecf20Sopenharmony_ci		}
41588c2ecf20Sopenharmony_ci
41598c2ecf20Sopenharmony_ci	}
41608c2ecf20Sopenharmony_ci#endif
41618c2ecf20Sopenharmony_ci
41628c2ecf20Sopenharmony_ci	return myrombase;
41638c2ecf20Sopenharmony_ci}
41648c2ecf20Sopenharmony_ci
41658c2ecf20Sopenharmony_cistatic void sisfb_post_map_vram(struct sis_video_info *ivideo,
41668c2ecf20Sopenharmony_ci				unsigned int *mapsize, unsigned int min)
41678c2ecf20Sopenharmony_ci{
41688c2ecf20Sopenharmony_ci	if (*mapsize < (min << 20))
41698c2ecf20Sopenharmony_ci		return;
41708c2ecf20Sopenharmony_ci
41718c2ecf20Sopenharmony_ci	ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize));
41728c2ecf20Sopenharmony_ci
41738c2ecf20Sopenharmony_ci	if(!ivideo->video_vbase) {
41748c2ecf20Sopenharmony_ci		printk(KERN_ERR
41758c2ecf20Sopenharmony_ci			"sisfb: Unable to map maximum video RAM for size detection\n");
41768c2ecf20Sopenharmony_ci		(*mapsize) >>= 1;
41778c2ecf20Sopenharmony_ci		while((!(ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize))))) {
41788c2ecf20Sopenharmony_ci			(*mapsize) >>= 1;
41798c2ecf20Sopenharmony_ci			if((*mapsize) < (min << 20))
41808c2ecf20Sopenharmony_ci				break;
41818c2ecf20Sopenharmony_ci		}
41828c2ecf20Sopenharmony_ci		if(ivideo->video_vbase) {
41838c2ecf20Sopenharmony_ci			printk(KERN_ERR
41848c2ecf20Sopenharmony_ci				"sisfb: Video RAM size detection limited to %dMB\n",
41858c2ecf20Sopenharmony_ci				(int)((*mapsize) >> 20));
41868c2ecf20Sopenharmony_ci		}
41878c2ecf20Sopenharmony_ci	}
41888c2ecf20Sopenharmony_ci}
41898c2ecf20Sopenharmony_ci
41908c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
41918c2ecf20Sopenharmony_cistatic int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
41928c2ecf20Sopenharmony_ci{
41938c2ecf20Sopenharmony_ci	void __iomem *FBAddress = ivideo->video_vbase;
41948c2ecf20Sopenharmony_ci	unsigned short temp;
41958c2ecf20Sopenharmony_ci	unsigned char reg;
41968c2ecf20Sopenharmony_ci	int i, j;
41978c2ecf20Sopenharmony_ci
41988c2ecf20Sopenharmony_ci	SiS_SetRegAND(SISSR, 0x15, 0xFB);
41998c2ecf20Sopenharmony_ci	SiS_SetRegOR(SISSR, 0x15, 0x04);
42008c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x13, 0x00);
42018c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x14, 0xBF);
42028c2ecf20Sopenharmony_ci
42038c2ecf20Sopenharmony_ci	for(i = 0; i < 2; i++) {
42048c2ecf20Sopenharmony_ci		temp = 0x1234;
42058c2ecf20Sopenharmony_ci		for(j = 0; j < 4; j++) {
42068c2ecf20Sopenharmony_ci			writew(temp, FBAddress);
42078c2ecf20Sopenharmony_ci			if(readw(FBAddress) == temp)
42088c2ecf20Sopenharmony_ci				break;
42098c2ecf20Sopenharmony_ci			SiS_SetRegOR(SISSR, 0x3c, 0x01);
42108c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISSR, 0x05);
42118c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISSR, 0x05);
42128c2ecf20Sopenharmony_ci			SiS_SetRegAND(SISSR, 0x3c, 0xfe);
42138c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISSR, 0x05);
42148c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISSR, 0x05);
42158c2ecf20Sopenharmony_ci			temp++;
42168c2ecf20Sopenharmony_ci		}
42178c2ecf20Sopenharmony_ci	}
42188c2ecf20Sopenharmony_ci
42198c2ecf20Sopenharmony_ci	writel(0x01234567L, FBAddress);
42208c2ecf20Sopenharmony_ci	writel(0x456789ABL, (FBAddress + 4));
42218c2ecf20Sopenharmony_ci	writel(0x89ABCDEFL, (FBAddress + 8));
42228c2ecf20Sopenharmony_ci	writel(0xCDEF0123L, (FBAddress + 12));
42238c2ecf20Sopenharmony_ci
42248c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISSR, 0x3b);
42258c2ecf20Sopenharmony_ci	if(reg & 0x01) {
42268c2ecf20Sopenharmony_ci		if(readl((FBAddress + 12)) == 0xCDEF0123L)
42278c2ecf20Sopenharmony_ci			return 4;	/* Channel A 128bit */
42288c2ecf20Sopenharmony_ci	}
42298c2ecf20Sopenharmony_ci
42308c2ecf20Sopenharmony_ci	if(readl((FBAddress + 4)) == 0x456789ABL)
42318c2ecf20Sopenharmony_ci		return 2;		/* Channel B 64bit */
42328c2ecf20Sopenharmony_ci
42338c2ecf20Sopenharmony_ci	return 1;			/* 32bit */
42348c2ecf20Sopenharmony_ci}
42358c2ecf20Sopenharmony_ci
42368c2ecf20Sopenharmony_cistatic const unsigned short SiS_DRAMType[17][5] = {
42378c2ecf20Sopenharmony_ci	{0x0C,0x0A,0x02,0x40,0x39},
42388c2ecf20Sopenharmony_ci	{0x0D,0x0A,0x01,0x40,0x48},
42398c2ecf20Sopenharmony_ci	{0x0C,0x09,0x02,0x20,0x35},
42408c2ecf20Sopenharmony_ci	{0x0D,0x09,0x01,0x20,0x44},
42418c2ecf20Sopenharmony_ci	{0x0C,0x08,0x02,0x10,0x31},
42428c2ecf20Sopenharmony_ci	{0x0D,0x08,0x01,0x10,0x40},
42438c2ecf20Sopenharmony_ci	{0x0C,0x0A,0x01,0x20,0x34},
42448c2ecf20Sopenharmony_ci	{0x0C,0x09,0x01,0x08,0x32},
42458c2ecf20Sopenharmony_ci	{0x0B,0x08,0x02,0x08,0x21},
42468c2ecf20Sopenharmony_ci	{0x0C,0x08,0x01,0x08,0x30},
42478c2ecf20Sopenharmony_ci	{0x0A,0x08,0x02,0x04,0x11},
42488c2ecf20Sopenharmony_ci	{0x0B,0x0A,0x01,0x10,0x28},
42498c2ecf20Sopenharmony_ci	{0x09,0x08,0x02,0x02,0x01},
42508c2ecf20Sopenharmony_ci	{0x0B,0x09,0x01,0x08,0x24},
42518c2ecf20Sopenharmony_ci	{0x0B,0x08,0x01,0x04,0x20},
42528c2ecf20Sopenharmony_ci	{0x0A,0x08,0x01,0x02,0x10},
42538c2ecf20Sopenharmony_ci	{0x09,0x08,0x01,0x01,0x00}
42548c2ecf20Sopenharmony_ci};
42558c2ecf20Sopenharmony_ci
42568c2ecf20Sopenharmony_cistatic int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
42578c2ecf20Sopenharmony_ci				 int buswidth, int PseudoRankCapacity,
42588c2ecf20Sopenharmony_ci				 int PseudoAdrPinCount, unsigned int mapsize)
42598c2ecf20Sopenharmony_ci{
42608c2ecf20Sopenharmony_ci	void __iomem *FBAddr = ivideo->video_vbase;
42618c2ecf20Sopenharmony_ci	unsigned short sr14;
42628c2ecf20Sopenharmony_ci	unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
42638c2ecf20Sopenharmony_ci	unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
42648c2ecf20Sopenharmony_ci
42658c2ecf20Sopenharmony_ci	 for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
42668c2ecf20Sopenharmony_ci
42678c2ecf20Sopenharmony_ci		RankCapacity = buswidth * SiS_DRAMType[k][3];
42688c2ecf20Sopenharmony_ci
42698c2ecf20Sopenharmony_ci		if(RankCapacity != PseudoRankCapacity)
42708c2ecf20Sopenharmony_ci			continue;
42718c2ecf20Sopenharmony_ci
42728c2ecf20Sopenharmony_ci		if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
42738c2ecf20Sopenharmony_ci			continue;
42748c2ecf20Sopenharmony_ci
42758c2ecf20Sopenharmony_ci		BankNumHigh = RankCapacity * 16 * iteration - 1;
42768c2ecf20Sopenharmony_ci		if(iteration == 3) {             /* Rank No */
42778c2ecf20Sopenharmony_ci			BankNumMid  = RankCapacity * 16 - 1;
42788c2ecf20Sopenharmony_ci		} else {
42798c2ecf20Sopenharmony_ci			BankNumMid  = RankCapacity * 16 * iteration / 2 - 1;
42808c2ecf20Sopenharmony_ci		}
42818c2ecf20Sopenharmony_ci
42828c2ecf20Sopenharmony_ci		PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
42838c2ecf20Sopenharmony_ci		PhysicalAdrHigh = BankNumHigh;
42848c2ecf20Sopenharmony_ci		PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
42858c2ecf20Sopenharmony_ci		PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
42868c2ecf20Sopenharmony_ci
42878c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
42888c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISSR, 0x15, 0x04);  /* Test */
42898c2ecf20Sopenharmony_ci		sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
42908c2ecf20Sopenharmony_ci		if(buswidth == 4)      sr14 |= 0x80;
42918c2ecf20Sopenharmony_ci		else if(buswidth == 2) sr14 |= 0x40;
42928c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
42938c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x14, sr14);
42948c2ecf20Sopenharmony_ci
42958c2ecf20Sopenharmony_ci		BankNumHigh <<= 16;
42968c2ecf20Sopenharmony_ci		BankNumMid <<= 16;
42978c2ecf20Sopenharmony_ci
42988c2ecf20Sopenharmony_ci		if((BankNumHigh + PhysicalAdrHigh      >= mapsize) ||
42998c2ecf20Sopenharmony_ci		   (BankNumMid  + PhysicalAdrHigh      >= mapsize) ||
43008c2ecf20Sopenharmony_ci		   (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
43018c2ecf20Sopenharmony_ci		   (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
43028c2ecf20Sopenharmony_ci			continue;
43038c2ecf20Sopenharmony_ci
43048c2ecf20Sopenharmony_ci		/* Write data */
43058c2ecf20Sopenharmony_ci		writew(((unsigned short)PhysicalAdrHigh),
43068c2ecf20Sopenharmony_ci				(FBAddr + BankNumHigh + PhysicalAdrHigh));
43078c2ecf20Sopenharmony_ci		writew(((unsigned short)BankNumMid),
43088c2ecf20Sopenharmony_ci				(FBAddr + BankNumMid  + PhysicalAdrHigh));
43098c2ecf20Sopenharmony_ci		writew(((unsigned short)PhysicalAdrHalfPage),
43108c2ecf20Sopenharmony_ci				(FBAddr + BankNumHigh + PhysicalAdrHalfPage));
43118c2ecf20Sopenharmony_ci		writew(((unsigned short)PhysicalAdrOtherPage),
43128c2ecf20Sopenharmony_ci				(FBAddr + BankNumHigh + PhysicalAdrOtherPage));
43138c2ecf20Sopenharmony_ci
43148c2ecf20Sopenharmony_ci		/* Read data */
43158c2ecf20Sopenharmony_ci		if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
43168c2ecf20Sopenharmony_ci			return 1;
43178c2ecf20Sopenharmony_ci	}
43188c2ecf20Sopenharmony_ci
43198c2ecf20Sopenharmony_ci	return 0;
43208c2ecf20Sopenharmony_ci}
43218c2ecf20Sopenharmony_ci
43228c2ecf20Sopenharmony_cistatic void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
43238c2ecf20Sopenharmony_ci{
43248c2ecf20Sopenharmony_ci	struct	sis_video_info *ivideo = pci_get_drvdata(pdev);
43258c2ecf20Sopenharmony_ci	int	i, j, buswidth;
43268c2ecf20Sopenharmony_ci	int	PseudoRankCapacity, PseudoAdrPinCount;
43278c2ecf20Sopenharmony_ci
43288c2ecf20Sopenharmony_ci	buswidth = sisfb_post_300_buswidth(ivideo);
43298c2ecf20Sopenharmony_ci
43308c2ecf20Sopenharmony_ci	for(i = 6; i >= 0; i--) {
43318c2ecf20Sopenharmony_ci		PseudoRankCapacity = 1 << i;
43328c2ecf20Sopenharmony_ci		for(j = 4; j >= 1; j--) {
43338c2ecf20Sopenharmony_ci			PseudoAdrPinCount = 15 - j;
43348c2ecf20Sopenharmony_ci			if((PseudoRankCapacity * j) <= 64) {
43358c2ecf20Sopenharmony_ci				if(sisfb_post_300_rwtest(ivideo,
43368c2ecf20Sopenharmony_ci						j,
43378c2ecf20Sopenharmony_ci						buswidth,
43388c2ecf20Sopenharmony_ci						PseudoRankCapacity,
43398c2ecf20Sopenharmony_ci						PseudoAdrPinCount,
43408c2ecf20Sopenharmony_ci						mapsize))
43418c2ecf20Sopenharmony_ci					return;
43428c2ecf20Sopenharmony_ci			}
43438c2ecf20Sopenharmony_ci		}
43448c2ecf20Sopenharmony_ci	}
43458c2ecf20Sopenharmony_ci}
43468c2ecf20Sopenharmony_ci
43478c2ecf20Sopenharmony_cistatic void sisfb_post_sis300(struct pci_dev *pdev)
43488c2ecf20Sopenharmony_ci{
43498c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
43508c2ecf20Sopenharmony_ci	unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
43518c2ecf20Sopenharmony_ci	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
43528c2ecf20Sopenharmony_ci	u16 index, rindex, memtype = 0;
43538c2ecf20Sopenharmony_ci	unsigned int mapsize;
43548c2ecf20Sopenharmony_ci
43558c2ecf20Sopenharmony_ci	if(!ivideo->SiS_Pr.UseROM)
43568c2ecf20Sopenharmony_ci		bios = NULL;
43578c2ecf20Sopenharmony_ci
43588c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x05, 0x86);
43598c2ecf20Sopenharmony_ci
43608c2ecf20Sopenharmony_ci	if(bios) {
43618c2ecf20Sopenharmony_ci		if(bios[0x52] & 0x80) {
43628c2ecf20Sopenharmony_ci			memtype = bios[0x52];
43638c2ecf20Sopenharmony_ci		} else {
43648c2ecf20Sopenharmony_ci			memtype = SiS_GetReg(SISSR, 0x3a);
43658c2ecf20Sopenharmony_ci		}
43668c2ecf20Sopenharmony_ci		memtype &= 0x07;
43678c2ecf20Sopenharmony_ci	}
43688c2ecf20Sopenharmony_ci
43698c2ecf20Sopenharmony_ci	v3 = 0x80; v6 = 0x80;
43708c2ecf20Sopenharmony_ci	if(ivideo->revision_id <= 0x13) {
43718c2ecf20Sopenharmony_ci		v1 = 0x44; v2 = 0x42;
43728c2ecf20Sopenharmony_ci		v4 = 0x44; v5 = 0x42;
43738c2ecf20Sopenharmony_ci	} else {
43748c2ecf20Sopenharmony_ci		v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
43758c2ecf20Sopenharmony_ci		v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
43768c2ecf20Sopenharmony_ci		if(bios) {
43778c2ecf20Sopenharmony_ci			index = memtype * 5;
43788c2ecf20Sopenharmony_ci			rindex = index + 0x54;
43798c2ecf20Sopenharmony_ci			v1 = bios[rindex++];
43808c2ecf20Sopenharmony_ci			v2 = bios[rindex++];
43818c2ecf20Sopenharmony_ci			v3 = bios[rindex++];
43828c2ecf20Sopenharmony_ci			rindex = index + 0x7c;
43838c2ecf20Sopenharmony_ci			v4 = bios[rindex++];
43848c2ecf20Sopenharmony_ci			v5 = bios[rindex++];
43858c2ecf20Sopenharmony_ci			v6 = bios[rindex++];
43868c2ecf20Sopenharmony_ci		}
43878c2ecf20Sopenharmony_ci	}
43888c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x28, v1);
43898c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x29, v2);
43908c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x2a, v3);
43918c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x2e, v4);
43928c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x2f, v5);
43938c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x30, v6);
43948c2ecf20Sopenharmony_ci
43958c2ecf20Sopenharmony_ci	v1 = 0x10;
43968c2ecf20Sopenharmony_ci	if(bios)
43978c2ecf20Sopenharmony_ci		v1 = bios[0xa4];
43988c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x07, v1);       /* DAC speed */
43998c2ecf20Sopenharmony_ci
44008c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x11, 0x0f);     /* DDC, power save */
44018c2ecf20Sopenharmony_ci
44028c2ecf20Sopenharmony_ci	v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
44038c2ecf20Sopenharmony_ci	v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
44048c2ecf20Sopenharmony_ci	if(bios) {
44058c2ecf20Sopenharmony_ci		memtype += 0xa5;
44068c2ecf20Sopenharmony_ci		v1 = bios[memtype];
44078c2ecf20Sopenharmony_ci		v2 = bios[memtype + 8];
44088c2ecf20Sopenharmony_ci		v3 = bios[memtype + 16];
44098c2ecf20Sopenharmony_ci		v4 = bios[memtype + 24];
44108c2ecf20Sopenharmony_ci		v5 = bios[memtype + 32];
44118c2ecf20Sopenharmony_ci		v6 = bios[memtype + 40];
44128c2ecf20Sopenharmony_ci		v7 = bios[memtype + 48];
44138c2ecf20Sopenharmony_ci		v8 = bios[memtype + 56];
44148c2ecf20Sopenharmony_ci	}
44158c2ecf20Sopenharmony_ci	if(ivideo->revision_id >= 0x80)
44168c2ecf20Sopenharmony_ci		v3 &= 0xfd;
44178c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
44188c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, v2);
44198c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x17, v3);
44208c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, v4);
44218c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, v5);
44228c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1a, v6);
44238c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1b, v7);
44248c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1c, v8);	   /* ---- */
44258c2ecf20Sopenharmony_ci	SiS_SetRegAND(SISSR, 0x15, 0xfb);
44268c2ecf20Sopenharmony_ci	SiS_SetRegOR(SISSR, 0x15, 0x04);
44278c2ecf20Sopenharmony_ci	if(bios) {
44288c2ecf20Sopenharmony_ci		if(bios[0x53] & 0x02) {
44298c2ecf20Sopenharmony_ci			SiS_SetRegOR(SISSR, 0x19, 0x20);
44308c2ecf20Sopenharmony_ci		}
44318c2ecf20Sopenharmony_ci	}
44328c2ecf20Sopenharmony_ci	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
44338c2ecf20Sopenharmony_ci	if(ivideo->revision_id >= 0x80)
44348c2ecf20Sopenharmony_ci		v1 |= 0x01;
44358c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1f, v1);
44368c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
44378c2ecf20Sopenharmony_ci	v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
44388c2ecf20Sopenharmony_ci	if(bios) {
44398c2ecf20Sopenharmony_ci		v1 = bios[0xe8];
44408c2ecf20Sopenharmony_ci		v2 = bios[0xe9];
44418c2ecf20Sopenharmony_ci		v3 = bios[0xea];
44428c2ecf20Sopenharmony_ci	}
44438c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x23, v1);
44448c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x24, v2);
44458c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x25, v3);
44468c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x21, 0x84);
44478c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x22, 0x00);
44488c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x37, 0x00);
44498c2ecf20Sopenharmony_ci	SiS_SetRegOR(SISPART1, 0x24, 0x01);   /* unlock crt2 */
44508c2ecf20Sopenharmony_ci	SiS_SetReg(SISPART1, 0x00, 0x00);
44518c2ecf20Sopenharmony_ci	v1 = 0x40; v2 = 0x11;
44528c2ecf20Sopenharmony_ci	if(bios) {
44538c2ecf20Sopenharmony_ci		v1 = bios[0xec];
44548c2ecf20Sopenharmony_ci		v2 = bios[0xeb];
44558c2ecf20Sopenharmony_ci	}
44568c2ecf20Sopenharmony_ci	SiS_SetReg(SISPART1, 0x02, v1);
44578c2ecf20Sopenharmony_ci
44588c2ecf20Sopenharmony_ci	if(ivideo->revision_id >= 0x80)
44598c2ecf20Sopenharmony_ci		v2 &= ~0x01;
44608c2ecf20Sopenharmony_ci
44618c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISPART4, 0x00);
44628c2ecf20Sopenharmony_ci	if((reg == 1) || (reg == 2)) {
44638c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x37, 0x02);
44648c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART2, 0x00, 0x1c);
44658c2ecf20Sopenharmony_ci		v4 = 0x00; v5 = 0x00; v6 = 0x10;
44668c2ecf20Sopenharmony_ci		if(ivideo->SiS_Pr.UseROM) {
44678c2ecf20Sopenharmony_ci			v4 = bios[0xf5];
44688c2ecf20Sopenharmony_ci			v5 = bios[0xf6];
44698c2ecf20Sopenharmony_ci			v6 = bios[0xf7];
44708c2ecf20Sopenharmony_ci		}
44718c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART4, 0x0d, v4);
44728c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART4, 0x0e, v5);
44738c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART4, 0x10, v6);
44748c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART4, 0x0f, 0x3f);
44758c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISPART4, 0x01);
44768c2ecf20Sopenharmony_ci		if(reg >= 0xb0) {
44778c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISPART4, 0x23);
44788c2ecf20Sopenharmony_ci			reg &= 0x20;
44798c2ecf20Sopenharmony_ci			reg <<= 1;
44808c2ecf20Sopenharmony_ci			SiS_SetReg(SISPART4, 0x23, reg);
44818c2ecf20Sopenharmony_ci		}
44828c2ecf20Sopenharmony_ci	} else {
44838c2ecf20Sopenharmony_ci		v2 &= ~0x10;
44848c2ecf20Sopenharmony_ci	}
44858c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x32, v2);
44868c2ecf20Sopenharmony_ci
44878c2ecf20Sopenharmony_ci	SiS_SetRegAND(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
44888c2ecf20Sopenharmony_ci
44898c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISSR, 0x16);
44908c2ecf20Sopenharmony_ci	reg &= 0xc3;
44918c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x35, reg);
44928c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x83, 0x00);
44938c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
44948c2ecf20Sopenharmony_ci	if(sisfb_videoram) {
44958c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
44968c2ecf20Sopenharmony_ci		reg = ((sisfb_videoram >> 10) - 1) | 0x40;
44978c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x14, reg);
44988c2ecf20Sopenharmony_ci	} else {
44998c2ecf20Sopenharmony_ci#endif
45008c2ecf20Sopenharmony_ci		/* Need to map max FB size for finding out about RAM size */
45018c2ecf20Sopenharmony_ci		mapsize = ivideo->video_size;
45028c2ecf20Sopenharmony_ci		sisfb_post_map_vram(ivideo, &mapsize, 4);
45038c2ecf20Sopenharmony_ci
45048c2ecf20Sopenharmony_ci		if(ivideo->video_vbase) {
45058c2ecf20Sopenharmony_ci			sisfb_post_300_ramsize(pdev, mapsize);
45068c2ecf20Sopenharmony_ci			iounmap(ivideo->video_vbase);
45078c2ecf20Sopenharmony_ci		} else {
45088c2ecf20Sopenharmony_ci			printk(KERN_DEBUG
45098c2ecf20Sopenharmony_ci				"sisfb: Failed to map memory for size detection, assuming 8MB\n");
45108c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x13, 0x28);  /* ? */
45118c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
45128c2ecf20Sopenharmony_ci		}
45138c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
45148c2ecf20Sopenharmony_ci	}
45158c2ecf20Sopenharmony_ci#endif
45168c2ecf20Sopenharmony_ci	if(bios) {
45178c2ecf20Sopenharmony_ci		v1 = bios[0xe6];
45188c2ecf20Sopenharmony_ci		v2 = bios[0xe7];
45198c2ecf20Sopenharmony_ci	} else {
45208c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x3a);
45218c2ecf20Sopenharmony_ci		if((reg & 0x30) == 0x30) {
45228c2ecf20Sopenharmony_ci			v1 = 0x04; /* PCI */
45238c2ecf20Sopenharmony_ci			v2 = 0x92;
45248c2ecf20Sopenharmony_ci		} else {
45258c2ecf20Sopenharmony_ci			v1 = 0x14; /* AGP */
45268c2ecf20Sopenharmony_ci			v2 = 0xb2;
45278c2ecf20Sopenharmony_ci		}
45288c2ecf20Sopenharmony_ci	}
45298c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x21, v1);
45308c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x22, v2);
45318c2ecf20Sopenharmony_ci
45328c2ecf20Sopenharmony_ci	/* Sense CRT1 */
45338c2ecf20Sopenharmony_ci	sisfb_sense_crt1(ivideo);
45348c2ecf20Sopenharmony_ci
45358c2ecf20Sopenharmony_ci	/* Set default mode, don't clear screen */
45368c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_UseOEM = false;
45378c2ecf20Sopenharmony_ci	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
45388c2ecf20Sopenharmony_ci	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
45398c2ecf20Sopenharmony_ci	ivideo->curFSTN = ivideo->curDSTN = 0;
45408c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
45418c2ecf20Sopenharmony_ci	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
45428c2ecf20Sopenharmony_ci
45438c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x05, 0x86);
45448c2ecf20Sopenharmony_ci
45458c2ecf20Sopenharmony_ci	/* Display off */
45468c2ecf20Sopenharmony_ci	SiS_SetRegOR(SISSR, 0x01, 0x20);
45478c2ecf20Sopenharmony_ci
45488c2ecf20Sopenharmony_ci	/* Save mode number in CR34 */
45498c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x34, 0x2e);
45508c2ecf20Sopenharmony_ci
45518c2ecf20Sopenharmony_ci	/* Let everyone know what the current mode is */
45528c2ecf20Sopenharmony_ci	ivideo->modeprechange = 0x2e;
45538c2ecf20Sopenharmony_ci}
45548c2ecf20Sopenharmony_ci#endif
45558c2ecf20Sopenharmony_ci
45568c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
45578c2ecf20Sopenharmony_ci#if 0
45588c2ecf20Sopenharmony_cistatic void sisfb_post_sis315330(struct pci_dev *pdev)
45598c2ecf20Sopenharmony_ci{
45608c2ecf20Sopenharmony_ci	/* TODO */
45618c2ecf20Sopenharmony_ci}
45628c2ecf20Sopenharmony_ci#endif
45638c2ecf20Sopenharmony_ci
45648c2ecf20Sopenharmony_cistatic inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
45658c2ecf20Sopenharmony_ci{
45668c2ecf20Sopenharmony_ci	return ivideo->chip_real_id == XGI_21;
45678c2ecf20Sopenharmony_ci}
45688c2ecf20Sopenharmony_ci
45698c2ecf20Sopenharmony_cistatic void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
45708c2ecf20Sopenharmony_ci{
45718c2ecf20Sopenharmony_ci	unsigned int i;
45728c2ecf20Sopenharmony_ci	u8 reg;
45738c2ecf20Sopenharmony_ci
45748c2ecf20Sopenharmony_ci	for(i = 0; i <= (delay * 10 * 36); i++) {
45758c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x05);
45768c2ecf20Sopenharmony_ci		reg++;
45778c2ecf20Sopenharmony_ci	}
45788c2ecf20Sopenharmony_ci}
45798c2ecf20Sopenharmony_ci
45808c2ecf20Sopenharmony_cistatic int sisfb_find_host_bridge(struct sis_video_info *ivideo,
45818c2ecf20Sopenharmony_ci				  struct pci_dev *mypdev,
45828c2ecf20Sopenharmony_ci				  unsigned short pcivendor)
45838c2ecf20Sopenharmony_ci{
45848c2ecf20Sopenharmony_ci	struct pci_dev *pdev = NULL;
45858c2ecf20Sopenharmony_ci	unsigned short temp;
45868c2ecf20Sopenharmony_ci	int ret = 0;
45878c2ecf20Sopenharmony_ci
45888c2ecf20Sopenharmony_ci	while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
45898c2ecf20Sopenharmony_ci		temp = pdev->vendor;
45908c2ecf20Sopenharmony_ci		if(temp == pcivendor) {
45918c2ecf20Sopenharmony_ci			ret = 1;
45928c2ecf20Sopenharmony_ci			pci_dev_put(pdev);
45938c2ecf20Sopenharmony_ci			break;
45948c2ecf20Sopenharmony_ci		}
45958c2ecf20Sopenharmony_ci	}
45968c2ecf20Sopenharmony_ci
45978c2ecf20Sopenharmony_ci	return ret;
45988c2ecf20Sopenharmony_ci}
45998c2ecf20Sopenharmony_ci
46008c2ecf20Sopenharmony_cistatic int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
46018c2ecf20Sopenharmony_ci				 unsigned int enda, unsigned int mapsize)
46028c2ecf20Sopenharmony_ci{
46038c2ecf20Sopenharmony_ci	unsigned int pos;
46048c2ecf20Sopenharmony_ci	int i;
46058c2ecf20Sopenharmony_ci
46068c2ecf20Sopenharmony_ci	writel(0, ivideo->video_vbase);
46078c2ecf20Sopenharmony_ci
46088c2ecf20Sopenharmony_ci	for(i = starta; i <= enda; i++) {
46098c2ecf20Sopenharmony_ci		pos = 1 << i;
46108c2ecf20Sopenharmony_ci		if(pos < mapsize)
46118c2ecf20Sopenharmony_ci			writel(pos, ivideo->video_vbase + pos);
46128c2ecf20Sopenharmony_ci	}
46138c2ecf20Sopenharmony_ci
46148c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 150);
46158c2ecf20Sopenharmony_ci
46168c2ecf20Sopenharmony_ci	if(readl(ivideo->video_vbase) != 0)
46178c2ecf20Sopenharmony_ci		return 0;
46188c2ecf20Sopenharmony_ci
46198c2ecf20Sopenharmony_ci	for(i = starta; i <= enda; i++) {
46208c2ecf20Sopenharmony_ci		pos = 1 << i;
46218c2ecf20Sopenharmony_ci		if(pos < mapsize) {
46228c2ecf20Sopenharmony_ci			if(readl(ivideo->video_vbase + pos) != pos)
46238c2ecf20Sopenharmony_ci				return 0;
46248c2ecf20Sopenharmony_ci		} else
46258c2ecf20Sopenharmony_ci			return 0;
46268c2ecf20Sopenharmony_ci	}
46278c2ecf20Sopenharmony_ci
46288c2ecf20Sopenharmony_ci	return 1;
46298c2ecf20Sopenharmony_ci}
46308c2ecf20Sopenharmony_ci
46318c2ecf20Sopenharmony_cistatic int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
46328c2ecf20Sopenharmony_ci{
46338c2ecf20Sopenharmony_ci	unsigned int buswidth, ranksize, channelab, mapsize;
46348c2ecf20Sopenharmony_ci	int i, j, k, l, status;
46358c2ecf20Sopenharmony_ci	u8 reg, sr14;
46368c2ecf20Sopenharmony_ci	static const u8 dramsr13[12 * 5] = {
46378c2ecf20Sopenharmony_ci		0x02, 0x0e, 0x0b, 0x80, 0x5d,
46388c2ecf20Sopenharmony_ci		0x02, 0x0e, 0x0a, 0x40, 0x59,
46398c2ecf20Sopenharmony_ci		0x02, 0x0d, 0x0b, 0x40, 0x4d,
46408c2ecf20Sopenharmony_ci		0x02, 0x0e, 0x09, 0x20, 0x55,
46418c2ecf20Sopenharmony_ci		0x02, 0x0d, 0x0a, 0x20, 0x49,
46428c2ecf20Sopenharmony_ci		0x02, 0x0c, 0x0b, 0x20, 0x3d,
46438c2ecf20Sopenharmony_ci		0x02, 0x0e, 0x08, 0x10, 0x51,
46448c2ecf20Sopenharmony_ci		0x02, 0x0d, 0x09, 0x10, 0x45,
46458c2ecf20Sopenharmony_ci		0x02, 0x0c, 0x0a, 0x10, 0x39,
46468c2ecf20Sopenharmony_ci		0x02, 0x0d, 0x08, 0x08, 0x41,
46478c2ecf20Sopenharmony_ci		0x02, 0x0c, 0x09, 0x08, 0x35,
46488c2ecf20Sopenharmony_ci		0x02, 0x0c, 0x08, 0x04, 0x31
46498c2ecf20Sopenharmony_ci	};
46508c2ecf20Sopenharmony_ci	static const u8 dramsr13_4[4 * 5] = {
46518c2ecf20Sopenharmony_ci		0x02, 0x0d, 0x09, 0x40, 0x45,
46528c2ecf20Sopenharmony_ci		0x02, 0x0c, 0x09, 0x20, 0x35,
46538c2ecf20Sopenharmony_ci		0x02, 0x0c, 0x08, 0x10, 0x31,
46548c2ecf20Sopenharmony_ci		0x02, 0x0b, 0x08, 0x08, 0x21
46558c2ecf20Sopenharmony_ci	};
46568c2ecf20Sopenharmony_ci
46578c2ecf20Sopenharmony_ci	/* Enable linear mode, disable 0xa0000 address decoding */
46588c2ecf20Sopenharmony_ci	/* We disable a0000 address decoding, because
46598c2ecf20Sopenharmony_ci	 * - if running on x86, if the card is disabled, it means
46608c2ecf20Sopenharmony_ci	 *   that another card is in the system. We don't want
46618c2ecf20Sopenharmony_ci	 *   to interphere with that primary card's textmode.
46628c2ecf20Sopenharmony_ci	 * - if running on non-x86, there usually is no VGA window
46638c2ecf20Sopenharmony_ci	 *   at a0000.
46648c2ecf20Sopenharmony_ci	 */
46658c2ecf20Sopenharmony_ci	SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
46668c2ecf20Sopenharmony_ci
46678c2ecf20Sopenharmony_ci	/* Need to map max FB size for finding out about RAM size */
46688c2ecf20Sopenharmony_ci	mapsize = ivideo->video_size;
46698c2ecf20Sopenharmony_ci	sisfb_post_map_vram(ivideo, &mapsize, 32);
46708c2ecf20Sopenharmony_ci
46718c2ecf20Sopenharmony_ci	if(!ivideo->video_vbase) {
46728c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
46738c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x13, 0x35);
46748c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x14, 0x41);
46758c2ecf20Sopenharmony_ci		/* TODO */
46768c2ecf20Sopenharmony_ci		return -ENOMEM;
46778c2ecf20Sopenharmony_ci	}
46788c2ecf20Sopenharmony_ci
46798c2ecf20Sopenharmony_ci	/* Non-interleaving */
46808c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x15, 0x00);
46818c2ecf20Sopenharmony_ci	/* No tiling */
46828c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1c, 0x00);
46838c2ecf20Sopenharmony_ci
46848c2ecf20Sopenharmony_ci	if(ivideo->chip == XGI_20) {
46858c2ecf20Sopenharmony_ci
46868c2ecf20Sopenharmony_ci		channelab = 1;
46878c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0x97);
46888c2ecf20Sopenharmony_ci		if(!(reg & 0x01)) {	/* Single 32/16 */
46898c2ecf20Sopenharmony_ci			buswidth = 32;
46908c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x13, 0xb1);
46918c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x14, 0x52);
46928c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 1);
46938c2ecf20Sopenharmony_ci			sr14 = 0x02;
46948c2ecf20Sopenharmony_ci			if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
46958c2ecf20Sopenharmony_ci				goto bail_out;
46968c2ecf20Sopenharmony_ci
46978c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x13, 0x31);
46988c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x14, 0x42);
46998c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 1);
47008c2ecf20Sopenharmony_ci			if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
47018c2ecf20Sopenharmony_ci				goto bail_out;
47028c2ecf20Sopenharmony_ci
47038c2ecf20Sopenharmony_ci			buswidth = 16;
47048c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x13, 0xb1);
47058c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x14, 0x41);
47068c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 1);
47078c2ecf20Sopenharmony_ci			sr14 = 0x01;
47088c2ecf20Sopenharmony_ci			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
47098c2ecf20Sopenharmony_ci				goto bail_out;
47108c2ecf20Sopenharmony_ci			else
47118c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0x31);
47128c2ecf20Sopenharmony_ci		} else {		/* Dual 16/8 */
47138c2ecf20Sopenharmony_ci			buswidth = 16;
47148c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x13, 0xb1);
47158c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x14, 0x41);
47168c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 1);
47178c2ecf20Sopenharmony_ci			sr14 = 0x01;
47188c2ecf20Sopenharmony_ci			if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
47198c2ecf20Sopenharmony_ci				goto bail_out;
47208c2ecf20Sopenharmony_ci
47218c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x13, 0x31);
47228c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x14, 0x31);
47238c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 1);
47248c2ecf20Sopenharmony_ci			if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
47258c2ecf20Sopenharmony_ci				goto bail_out;
47268c2ecf20Sopenharmony_ci
47278c2ecf20Sopenharmony_ci			buswidth = 8;
47288c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x13, 0xb1);
47298c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x14, 0x30);
47308c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 1);
47318c2ecf20Sopenharmony_ci			sr14 = 0x00;
47328c2ecf20Sopenharmony_ci			if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
47338c2ecf20Sopenharmony_ci				goto bail_out;
47348c2ecf20Sopenharmony_ci			else
47358c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0x31);
47368c2ecf20Sopenharmony_ci		}
47378c2ecf20Sopenharmony_ci
47388c2ecf20Sopenharmony_ci	} else {	/* XGI_40 */
47398c2ecf20Sopenharmony_ci
47408c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0x97);
47418c2ecf20Sopenharmony_ci		if(!(reg & 0x10)) {
47428c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISSR, 0x39);
47438c2ecf20Sopenharmony_ci			reg >>= 1;
47448c2ecf20Sopenharmony_ci		}
47458c2ecf20Sopenharmony_ci
47468c2ecf20Sopenharmony_ci		if(reg & 0x01) {	/* DDRII */
47478c2ecf20Sopenharmony_ci			buswidth = 32;
47488c2ecf20Sopenharmony_ci			if(ivideo->revision_id == 2) {
47498c2ecf20Sopenharmony_ci				channelab = 2;
47508c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0xa1);
47518c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x44);
47528c2ecf20Sopenharmony_ci				sr14 = 0x04;
47538c2ecf20Sopenharmony_ci				sisfb_post_xgi_delay(ivideo, 1);
47548c2ecf20Sopenharmony_ci				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
47558c2ecf20Sopenharmony_ci					goto bail_out;
47568c2ecf20Sopenharmony_ci
47578c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0x21);
47588c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x34);
47598c2ecf20Sopenharmony_ci				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
47608c2ecf20Sopenharmony_ci					goto bail_out;
47618c2ecf20Sopenharmony_ci
47628c2ecf20Sopenharmony_ci				channelab = 1;
47638c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0xa1);
47648c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x40);
47658c2ecf20Sopenharmony_ci				sr14 = 0x00;
47668c2ecf20Sopenharmony_ci				if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
47678c2ecf20Sopenharmony_ci					goto bail_out;
47688c2ecf20Sopenharmony_ci
47698c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0x21);
47708c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x30);
47718c2ecf20Sopenharmony_ci			} else {
47728c2ecf20Sopenharmony_ci				channelab = 3;
47738c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0xa1);
47748c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x4c);
47758c2ecf20Sopenharmony_ci				sr14 = 0x0c;
47768c2ecf20Sopenharmony_ci				sisfb_post_xgi_delay(ivideo, 1);
47778c2ecf20Sopenharmony_ci				if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
47788c2ecf20Sopenharmony_ci					goto bail_out;
47798c2ecf20Sopenharmony_ci
47808c2ecf20Sopenharmony_ci				channelab = 2;
47818c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x48);
47828c2ecf20Sopenharmony_ci				sisfb_post_xgi_delay(ivideo, 1);
47838c2ecf20Sopenharmony_ci				sr14 = 0x08;
47848c2ecf20Sopenharmony_ci				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
47858c2ecf20Sopenharmony_ci					goto bail_out;
47868c2ecf20Sopenharmony_ci
47878c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0x21);
47888c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x3c);
47898c2ecf20Sopenharmony_ci				sr14 = 0x0c;
47908c2ecf20Sopenharmony_ci
47918c2ecf20Sopenharmony_ci				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
47928c2ecf20Sopenharmony_ci					channelab = 3;
47938c2ecf20Sopenharmony_ci				} else {
47948c2ecf20Sopenharmony_ci					channelab = 2;
47958c2ecf20Sopenharmony_ci					SiS_SetReg(SISSR, 0x14, 0x38);
47968c2ecf20Sopenharmony_ci					sr14 = 0x08;
47978c2ecf20Sopenharmony_ci				}
47988c2ecf20Sopenharmony_ci			}
47998c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 1);
48008c2ecf20Sopenharmony_ci
48018c2ecf20Sopenharmony_ci		} else {	/* DDR */
48028c2ecf20Sopenharmony_ci
48038c2ecf20Sopenharmony_ci			buswidth = 64;
48048c2ecf20Sopenharmony_ci			if(ivideo->revision_id == 2) {
48058c2ecf20Sopenharmony_ci				channelab = 1;
48068c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0xa1);
48078c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x52);
48088c2ecf20Sopenharmony_ci				sisfb_post_xgi_delay(ivideo, 1);
48098c2ecf20Sopenharmony_ci				sr14 = 0x02;
48108c2ecf20Sopenharmony_ci				if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
48118c2ecf20Sopenharmony_ci					goto bail_out;
48128c2ecf20Sopenharmony_ci
48138c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0x21);
48148c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x42);
48158c2ecf20Sopenharmony_ci			} else {
48168c2ecf20Sopenharmony_ci				channelab = 2;
48178c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0xa1);
48188c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x5a);
48198c2ecf20Sopenharmony_ci				sisfb_post_xgi_delay(ivideo, 1);
48208c2ecf20Sopenharmony_ci				sr14 = 0x0a;
48218c2ecf20Sopenharmony_ci				if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
48228c2ecf20Sopenharmony_ci					goto bail_out;
48238c2ecf20Sopenharmony_ci
48248c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x13, 0x21);
48258c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x14, 0x4a);
48268c2ecf20Sopenharmony_ci			}
48278c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 1);
48288c2ecf20Sopenharmony_ci
48298c2ecf20Sopenharmony_ci		}
48308c2ecf20Sopenharmony_ci	}
48318c2ecf20Sopenharmony_ci
48328c2ecf20Sopenharmony_cibail_out:
48338c2ecf20Sopenharmony_ci	SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
48348c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
48358c2ecf20Sopenharmony_ci
48368c2ecf20Sopenharmony_ci	j = (ivideo->chip == XGI_20) ? 5 : 9;
48378c2ecf20Sopenharmony_ci	k = (ivideo->chip == XGI_20) ? 12 : 4;
48388c2ecf20Sopenharmony_ci	status = -EIO;
48398c2ecf20Sopenharmony_ci
48408c2ecf20Sopenharmony_ci	for(i = 0; i < k; i++) {
48418c2ecf20Sopenharmony_ci
48428c2ecf20Sopenharmony_ci		reg = (ivideo->chip == XGI_20) ?
48438c2ecf20Sopenharmony_ci				dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
48448c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
48458c2ecf20Sopenharmony_ci		sisfb_post_xgi_delay(ivideo, 50);
48468c2ecf20Sopenharmony_ci
48478c2ecf20Sopenharmony_ci		ranksize = (ivideo->chip == XGI_20) ?
48488c2ecf20Sopenharmony_ci				dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
48498c2ecf20Sopenharmony_ci
48508c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x13);
48518c2ecf20Sopenharmony_ci		if(reg & 0x80) ranksize <<= 1;
48528c2ecf20Sopenharmony_ci
48538c2ecf20Sopenharmony_ci		if(ivideo->chip == XGI_20) {
48548c2ecf20Sopenharmony_ci			if(buswidth == 16)      ranksize <<= 1;
48558c2ecf20Sopenharmony_ci			else if(buswidth == 32) ranksize <<= 2;
48568c2ecf20Sopenharmony_ci		} else {
48578c2ecf20Sopenharmony_ci			if(buswidth == 64)      ranksize <<= 1;
48588c2ecf20Sopenharmony_ci		}
48598c2ecf20Sopenharmony_ci
48608c2ecf20Sopenharmony_ci		reg = 0;
48618c2ecf20Sopenharmony_ci		l = channelab;
48628c2ecf20Sopenharmony_ci		if(l == 3) l = 4;
48638c2ecf20Sopenharmony_ci		if((ranksize * l) <= 256) {
48648c2ecf20Sopenharmony_ci			while((ranksize >>= 1)) reg += 0x10;
48658c2ecf20Sopenharmony_ci		}
48668c2ecf20Sopenharmony_ci
48678c2ecf20Sopenharmony_ci		if(!reg) continue;
48688c2ecf20Sopenharmony_ci
48698c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
48708c2ecf20Sopenharmony_ci		sisfb_post_xgi_delay(ivideo, 1);
48718c2ecf20Sopenharmony_ci
48728c2ecf20Sopenharmony_ci		if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
48738c2ecf20Sopenharmony_ci			status = 0;
48748c2ecf20Sopenharmony_ci			break;
48758c2ecf20Sopenharmony_ci		}
48768c2ecf20Sopenharmony_ci	}
48778c2ecf20Sopenharmony_ci
48788c2ecf20Sopenharmony_ci	iounmap(ivideo->video_vbase);
48798c2ecf20Sopenharmony_ci
48808c2ecf20Sopenharmony_ci	return status;
48818c2ecf20Sopenharmony_ci}
48828c2ecf20Sopenharmony_ci
48838c2ecf20Sopenharmony_cistatic void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
48848c2ecf20Sopenharmony_ci{
48858c2ecf20Sopenharmony_ci	u8 v1, v2, v3;
48868c2ecf20Sopenharmony_ci	int index;
48878c2ecf20Sopenharmony_ci	static const u8 cs90[8 * 3] = {
48888c2ecf20Sopenharmony_ci		0x16, 0x01, 0x01,
48898c2ecf20Sopenharmony_ci		0x3e, 0x03, 0x01,
48908c2ecf20Sopenharmony_ci		0x7c, 0x08, 0x01,
48918c2ecf20Sopenharmony_ci		0x79, 0x06, 0x01,
48928c2ecf20Sopenharmony_ci		0x29, 0x01, 0x81,
48938c2ecf20Sopenharmony_ci		0x5c, 0x23, 0x01,
48948c2ecf20Sopenharmony_ci		0x5c, 0x23, 0x01,
48958c2ecf20Sopenharmony_ci		0x5c, 0x23, 0x01
48968c2ecf20Sopenharmony_ci	};
48978c2ecf20Sopenharmony_ci	static const u8 csb8[8 * 3] = {
48988c2ecf20Sopenharmony_ci		0x5c, 0x23, 0x01,
48998c2ecf20Sopenharmony_ci		0x29, 0x01, 0x01,
49008c2ecf20Sopenharmony_ci		0x7c, 0x08, 0x01,
49018c2ecf20Sopenharmony_ci		0x79, 0x06, 0x01,
49028c2ecf20Sopenharmony_ci		0x29, 0x01, 0x81,
49038c2ecf20Sopenharmony_ci		0x5c, 0x23, 0x01,
49048c2ecf20Sopenharmony_ci		0x5c, 0x23, 0x01,
49058c2ecf20Sopenharmony_ci		0x5c, 0x23, 0x01
49068c2ecf20Sopenharmony_ci	};
49078c2ecf20Sopenharmony_ci
49088c2ecf20Sopenharmony_ci	regb = 0;  /* ! */
49098c2ecf20Sopenharmony_ci
49108c2ecf20Sopenharmony_ci	index = regb * 3;
49118c2ecf20Sopenharmony_ci	v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
49128c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
49138c2ecf20Sopenharmony_ci		v1 = ivideo->bios_abase[0x90 + index];
49148c2ecf20Sopenharmony_ci		v2 = ivideo->bios_abase[0x90 + index + 1];
49158c2ecf20Sopenharmony_ci		v3 = ivideo->bios_abase[0x90 + index + 2];
49168c2ecf20Sopenharmony_ci	}
49178c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x28, v1);
49188c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x29, v2);
49198c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x2a, v3);
49208c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 0x43);
49218c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 0x43);
49228c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 0x43);
49238c2ecf20Sopenharmony_ci	index = regb * 3;
49248c2ecf20Sopenharmony_ci	v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
49258c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
49268c2ecf20Sopenharmony_ci		v1 = ivideo->bios_abase[0xb8 + index];
49278c2ecf20Sopenharmony_ci		v2 = ivideo->bios_abase[0xb8 + index + 1];
49288c2ecf20Sopenharmony_ci		v3 = ivideo->bios_abase[0xb8 + index + 2];
49298c2ecf20Sopenharmony_ci	}
49308c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x2e, v1);
49318c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x2f, v2);
49328c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x30, v3);
49338c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 0x43);
49348c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 0x43);
49358c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 0x43);
49368c2ecf20Sopenharmony_ci}
49378c2ecf20Sopenharmony_ci
49388c2ecf20Sopenharmony_cistatic void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
49398c2ecf20Sopenharmony_ci					    u8 regb)
49408c2ecf20Sopenharmony_ci{
49418c2ecf20Sopenharmony_ci	unsigned char *bios = ivideo->bios_abase;
49428c2ecf20Sopenharmony_ci	u8 v1;
49438c2ecf20Sopenharmony_ci
49448c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x28, 0x64);
49458c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x29, 0x63);
49468c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 15);
49478c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, 0x00);
49488c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, 0x20);
49498c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x00);
49508c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x80);
49518c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, 0xc5);
49528c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, 0x23);
49538c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x00);
49548c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x80);
49558c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
49568c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x97, 0x11);
49578c2ecf20Sopenharmony_ci	sisfb_post_xgi_setclocks(ivideo, regb);
49588c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 0x46);
49598c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, 0xc5);
49608c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, 0x23);
49618c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x00);
49628c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x80);
49638c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
49648c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1b, 0x04);
49658c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
49668c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1b, 0x00);
49678c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
49688c2ecf20Sopenharmony_ci	v1 = 0x31;
49698c2ecf20Sopenharmony_ci	if (ivideo->haveXGIROM) {
49708c2ecf20Sopenharmony_ci		v1 = bios[0xf0];
49718c2ecf20Sopenharmony_ci	}
49728c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, v1);
49738c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, 0x06);
49748c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x04);
49758c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x84);
49768c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
49778c2ecf20Sopenharmony_ci}
49788c2ecf20Sopenharmony_ci
49798c2ecf20Sopenharmony_cistatic void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
49808c2ecf20Sopenharmony_ci{
49818c2ecf20Sopenharmony_ci	sisfb_post_xgi_setclocks(ivideo, 1);
49828c2ecf20Sopenharmony_ci
49838c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x97, 0x11);
49848c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 0x46);
49858c2ecf20Sopenharmony_ci
49868c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS2 */
49878c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, 0x80);
49888c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x05);
49898c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x85);
49908c2ecf20Sopenharmony_ci
49918c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS3 */
49928c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, 0xc0);
49938c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x05);
49948c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x85);
49958c2ecf20Sopenharmony_ci
49968c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, 0x00);	/* EMRS1 */
49978c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, 0x40);
49988c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x05);
49998c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x85);
50008c2ecf20Sopenharmony_ci
50018c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, 0x42);	/* MRS1 */
50028c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, 0x02);
50038c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x05);
50048c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x85);
50058c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
50068c2ecf20Sopenharmony_ci
50078c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1b, 0x04);
50088c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
50098c2ecf20Sopenharmony_ci
50108c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1b, 0x00);
50118c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
50128c2ecf20Sopenharmony_ci
50138c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x18, 0x42);	/* MRS1 */
50148c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x19, 0x00);
50158c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x05);
50168c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x16, 0x85);
50178c2ecf20Sopenharmony_ci	sisfb_post_xgi_delay(ivideo, 1);
50188c2ecf20Sopenharmony_ci}
50198c2ecf20Sopenharmony_ci
50208c2ecf20Sopenharmony_cistatic void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
50218c2ecf20Sopenharmony_ci{
50228c2ecf20Sopenharmony_ci	unsigned char *bios = ivideo->bios_abase;
50238c2ecf20Sopenharmony_ci	static const u8 cs158[8] = {
50248c2ecf20Sopenharmony_ci		0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
50258c2ecf20Sopenharmony_ci	};
50268c2ecf20Sopenharmony_ci	static const u8 cs160[8] = {
50278c2ecf20Sopenharmony_ci		0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
50288c2ecf20Sopenharmony_ci	};
50298c2ecf20Sopenharmony_ci	static const u8 cs168[8] = {
50308c2ecf20Sopenharmony_ci		0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
50318c2ecf20Sopenharmony_ci	};
50328c2ecf20Sopenharmony_ci	u8 reg;
50338c2ecf20Sopenharmony_ci	u8 v1;
50348c2ecf20Sopenharmony_ci	u8 v2;
50358c2ecf20Sopenharmony_ci	u8 v3;
50368c2ecf20Sopenharmony_ci
50378c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
50388c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x82, 0x77);
50398c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x86, 0x00);
50408c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISCR, 0x86);
50418c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x86, 0x88);
50428c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISCR, 0x86);
50438c2ecf20Sopenharmony_ci	v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
50448c2ecf20Sopenharmony_ci	if (ivideo->haveXGIROM) {
50458c2ecf20Sopenharmony_ci		v1 = bios[regb + 0x168];
50468c2ecf20Sopenharmony_ci		v2 = bios[regb + 0x160];
50478c2ecf20Sopenharmony_ci		v3 = bios[regb + 0x158];
50488c2ecf20Sopenharmony_ci	}
50498c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x86, v1);
50508c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x82, 0x77);
50518c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x85, 0x00);
50528c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISCR, 0x85);
50538c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x85, 0x88);
50548c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISCR, 0x85);
50558c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x85, v2);
50568c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x82, v3);
50578c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x98, 0x01);
50588c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x9a, 0x02);
50598c2ecf20Sopenharmony_ci	if (sisfb_xgi_is21(ivideo))
50608c2ecf20Sopenharmony_ci		sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
50618c2ecf20Sopenharmony_ci	else
50628c2ecf20Sopenharmony_ci		sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
50638c2ecf20Sopenharmony_ci}
50648c2ecf20Sopenharmony_ci
50658c2ecf20Sopenharmony_cistatic u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
50668c2ecf20Sopenharmony_ci{
50678c2ecf20Sopenharmony_ci	unsigned char *bios = ivideo->bios_abase;
50688c2ecf20Sopenharmony_ci	u8 ramtype;
50698c2ecf20Sopenharmony_ci	u8 reg;
50708c2ecf20Sopenharmony_ci	u8 v1;
50718c2ecf20Sopenharmony_ci
50728c2ecf20Sopenharmony_ci	ramtype = 0x00; v1 = 0x10;
50738c2ecf20Sopenharmony_ci	if (ivideo->haveXGIROM) {
50748c2ecf20Sopenharmony_ci		ramtype = bios[0x62];
50758c2ecf20Sopenharmony_ci		v1 = bios[0x1d2];
50768c2ecf20Sopenharmony_ci	}
50778c2ecf20Sopenharmony_ci	if (!(ramtype & 0x80)) {
50788c2ecf20Sopenharmony_ci		if (sisfb_xgi_is21(ivideo)) {
50798c2ecf20Sopenharmony_ci			SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
50808c2ecf20Sopenharmony_ci			SiS_SetRegOR(SISCR, 0x4a, 0x80);  /* GPIOH EN */
50818c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x48);
50828c2ecf20Sopenharmony_ci			SiS_SetRegOR(SISCR, 0xb4, 0x02);
50838c2ecf20Sopenharmony_ci			ramtype = reg & 0x01;		  /* GPIOH */
50848c2ecf20Sopenharmony_ci		} else if (ivideo->chip == XGI_20) {
50858c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x97, v1);
50868c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x97);
50878c2ecf20Sopenharmony_ci			if (reg & 0x10) {
50888c2ecf20Sopenharmony_ci				ramtype = (reg & 0x01) << 1;
50898c2ecf20Sopenharmony_ci			}
50908c2ecf20Sopenharmony_ci		} else {
50918c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISSR, 0x39);
50928c2ecf20Sopenharmony_ci			ramtype = reg & 0x02;
50938c2ecf20Sopenharmony_ci			if (!(ramtype)) {
50948c2ecf20Sopenharmony_ci				reg = SiS_GetReg(SISSR, 0x3a);
50958c2ecf20Sopenharmony_ci				ramtype = (reg >> 1) & 0x01;
50968c2ecf20Sopenharmony_ci			}
50978c2ecf20Sopenharmony_ci		}
50988c2ecf20Sopenharmony_ci	}
50998c2ecf20Sopenharmony_ci	ramtype &= 0x07;
51008c2ecf20Sopenharmony_ci
51018c2ecf20Sopenharmony_ci	return ramtype;
51028c2ecf20Sopenharmony_ci}
51038c2ecf20Sopenharmony_ci
51048c2ecf20Sopenharmony_cistatic int sisfb_post_xgi(struct pci_dev *pdev)
51058c2ecf20Sopenharmony_ci{
51068c2ecf20Sopenharmony_ci	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
51078c2ecf20Sopenharmony_ci	unsigned char *bios = ivideo->bios_abase;
51088c2ecf20Sopenharmony_ci	struct pci_dev *mypdev = NULL;
51098c2ecf20Sopenharmony_ci	const u8 *ptr, *ptr2;
51108c2ecf20Sopenharmony_ci	u8 v1, v2, v3, v4, v5, reg, ramtype;
51118c2ecf20Sopenharmony_ci	u32 rega, regb, regd;
51128c2ecf20Sopenharmony_ci	int i, j, k, index;
51138c2ecf20Sopenharmony_ci	static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
51148c2ecf20Sopenharmony_ci	static const u8 cs76[2] = { 0xa3, 0xfb };
51158c2ecf20Sopenharmony_ci	static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
51168c2ecf20Sopenharmony_ci	static const u8 cs158[8] = {
51178c2ecf20Sopenharmony_ci		0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
51188c2ecf20Sopenharmony_ci	};
51198c2ecf20Sopenharmony_ci	static const u8 cs160[8] = {
51208c2ecf20Sopenharmony_ci		0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
51218c2ecf20Sopenharmony_ci	};
51228c2ecf20Sopenharmony_ci	static const u8 cs168[8] = {
51238c2ecf20Sopenharmony_ci		0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
51248c2ecf20Sopenharmony_ci	};
51258c2ecf20Sopenharmony_ci	static const u8 cs128[3 * 8] = {
51268c2ecf20Sopenharmony_ci		0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
51278c2ecf20Sopenharmony_ci		0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
51288c2ecf20Sopenharmony_ci		0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
51298c2ecf20Sopenharmony_ci	};
51308c2ecf20Sopenharmony_ci	static const u8 cs148[2 * 8] = {
51318c2ecf20Sopenharmony_ci		0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
51328c2ecf20Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
51338c2ecf20Sopenharmony_ci	};
51348c2ecf20Sopenharmony_ci	static const u8 cs31a[8 * 4] = {
51358c2ecf20Sopenharmony_ci		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
51368c2ecf20Sopenharmony_ci		0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
51378c2ecf20Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51388c2ecf20Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
51398c2ecf20Sopenharmony_ci	};
51408c2ecf20Sopenharmony_ci	static const u8 cs33a[8 * 4] = {
51418c2ecf20Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51428c2ecf20Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51438c2ecf20Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51448c2ecf20Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
51458c2ecf20Sopenharmony_ci	};
51468c2ecf20Sopenharmony_ci	static const u8 cs45a[8 * 2] = {
51478c2ecf20Sopenharmony_ci		0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
51488c2ecf20Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
51498c2ecf20Sopenharmony_ci	};
51508c2ecf20Sopenharmony_ci	static const u8 cs170[7 * 8] = {
51518c2ecf20Sopenharmony_ci		0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
51528c2ecf20Sopenharmony_ci		0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
51538c2ecf20Sopenharmony_ci		0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
51548c2ecf20Sopenharmony_ci		0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
51558c2ecf20Sopenharmony_ci		0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
51568c2ecf20Sopenharmony_ci		0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
51578c2ecf20Sopenharmony_ci		0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
51588c2ecf20Sopenharmony_ci	};
51598c2ecf20Sopenharmony_ci	static const u8 cs1a8[3 * 8] = {
51608c2ecf20Sopenharmony_ci		0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
51618c2ecf20Sopenharmony_ci		0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
51628c2ecf20Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
51638c2ecf20Sopenharmony_ci	};
51648c2ecf20Sopenharmony_ci	static const u8 cs100[2 * 8] = {
51658c2ecf20Sopenharmony_ci		0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
51668c2ecf20Sopenharmony_ci		0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
51678c2ecf20Sopenharmony_ci	};
51688c2ecf20Sopenharmony_ci
51698c2ecf20Sopenharmony_ci	/* VGA enable */
51708c2ecf20Sopenharmony_ci	reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
51718c2ecf20Sopenharmony_ci	SiS_SetRegByte(SISVGAENABLE, reg);
51728c2ecf20Sopenharmony_ci
51738c2ecf20Sopenharmony_ci	/* Misc */
51748c2ecf20Sopenharmony_ci	reg = SiS_GetRegByte(SISMISCR) | 0x01;
51758c2ecf20Sopenharmony_ci	SiS_SetRegByte(SISMISCW, reg);
51768c2ecf20Sopenharmony_ci
51778c2ecf20Sopenharmony_ci	/* Unlock SR */
51788c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x05, 0x86);
51798c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISSR, 0x05);
51808c2ecf20Sopenharmony_ci	if(reg != 0xa1)
51818c2ecf20Sopenharmony_ci		return 0;
51828c2ecf20Sopenharmony_ci
51838c2ecf20Sopenharmony_ci	/* Clear some regs */
51848c2ecf20Sopenharmony_ci	for(i = 0; i < 0x22; i++) {
51858c2ecf20Sopenharmony_ci		if(0x06 + i == 0x20) continue;
51868c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x06 + i, 0x00);
51878c2ecf20Sopenharmony_ci	}
51888c2ecf20Sopenharmony_ci	for(i = 0; i < 0x0b; i++) {
51898c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x31 + i, 0x00);
51908c2ecf20Sopenharmony_ci	}
51918c2ecf20Sopenharmony_ci	for(i = 0; i < 0x10; i++) {
51928c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x30 + i, 0x00);
51938c2ecf20Sopenharmony_ci	}
51948c2ecf20Sopenharmony_ci
51958c2ecf20Sopenharmony_ci	ptr = cs78;
51968c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
51978c2ecf20Sopenharmony_ci		ptr = (const u8 *)&bios[0x78];
51988c2ecf20Sopenharmony_ci	}
51998c2ecf20Sopenharmony_ci	for(i = 0; i < 3; i++) {
52008c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
52018c2ecf20Sopenharmony_ci	}
52028c2ecf20Sopenharmony_ci
52038c2ecf20Sopenharmony_ci	ptr = cs76;
52048c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
52058c2ecf20Sopenharmony_ci		ptr = (const u8 *)&bios[0x76];
52068c2ecf20Sopenharmony_ci	}
52078c2ecf20Sopenharmony_ci	for(i = 0; i < 2; i++) {
52088c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
52098c2ecf20Sopenharmony_ci	}
52108c2ecf20Sopenharmony_ci
52118c2ecf20Sopenharmony_ci	v1 = 0x18; v2 = 0x00;
52128c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
52138c2ecf20Sopenharmony_ci		v1 = bios[0x74];
52148c2ecf20Sopenharmony_ci		v2 = bios[0x75];
52158c2ecf20Sopenharmony_ci	}
52168c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x07, v1);
52178c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x11, 0x0f);
52188c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1f, v2);
52198c2ecf20Sopenharmony_ci	/* PCI linear mode, RelIO enabled, A0000 decoding disabled */
52208c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
52218c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x27, 0x74);
52228c2ecf20Sopenharmony_ci
52238c2ecf20Sopenharmony_ci	ptr = cs7b;
52248c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
52258c2ecf20Sopenharmony_ci		ptr = (const u8 *)&bios[0x7b];
52268c2ecf20Sopenharmony_ci	}
52278c2ecf20Sopenharmony_ci	for(i = 0; i < 3; i++) {
52288c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
52298c2ecf20Sopenharmony_ci	}
52308c2ecf20Sopenharmony_ci
52318c2ecf20Sopenharmony_ci	if(ivideo->chip == XGI_40) {
52328c2ecf20Sopenharmony_ci		if(ivideo->revision_id == 2) {
52338c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
52348c2ecf20Sopenharmony_ci		}
52358c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x7d, 0xfe);
52368c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x7e, 0x0f);
52378c2ecf20Sopenharmony_ci	}
52388c2ecf20Sopenharmony_ci	if(ivideo->revision_id == 0) {	/* 40 *and* 20? */
52398c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISCR, 0x58, 0xd7);
52408c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0xcb);
52418c2ecf20Sopenharmony_ci		if(reg & 0x20) {
52428c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
52438c2ecf20Sopenharmony_ci		}
52448c2ecf20Sopenharmony_ci	}
52458c2ecf20Sopenharmony_ci
52468c2ecf20Sopenharmony_ci	reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
52478c2ecf20Sopenharmony_ci	SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
52488c2ecf20Sopenharmony_ci
52498c2ecf20Sopenharmony_ci	if(ivideo->chip == XGI_20) {
52508c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x36, 0x70);
52518c2ecf20Sopenharmony_ci	} else {
52528c2ecf20Sopenharmony_ci		SiS_SetReg(SISVID, 0x00, 0x86);
52538c2ecf20Sopenharmony_ci		SiS_SetReg(SISVID, 0x32, 0x00);
52548c2ecf20Sopenharmony_ci		SiS_SetReg(SISVID, 0x30, 0x00);
52558c2ecf20Sopenharmony_ci		SiS_SetReg(SISVID, 0x32, 0x01);
52568c2ecf20Sopenharmony_ci		SiS_SetReg(SISVID, 0x30, 0x00);
52578c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISVID, 0x2f, 0xdf);
52588c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISCAP, 0x00, 0x3f);
52598c2ecf20Sopenharmony_ci
52608c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART1, 0x2f, 0x01);
52618c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART1, 0x00, 0x00);
52628c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
52638c2ecf20Sopenharmony_ci		SiS_SetReg(SISPART1, 0x2e, 0x08);
52648c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISPART1, 0x35, 0x7f);
52658c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISPART1, 0x50, 0xfe);
52668c2ecf20Sopenharmony_ci
52678c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISPART4, 0x00);
52688c2ecf20Sopenharmony_ci		if(reg == 1 || reg == 2) {
52698c2ecf20Sopenharmony_ci			SiS_SetReg(SISPART2, 0x00, 0x1c);
52708c2ecf20Sopenharmony_ci			SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
52718c2ecf20Sopenharmony_ci			SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
52728c2ecf20Sopenharmony_ci			SiS_SetReg(SISPART4, 0x10, bios[0x81]);
52738c2ecf20Sopenharmony_ci			SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
52748c2ecf20Sopenharmony_ci
52758c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISPART4, 0x01);
52768c2ecf20Sopenharmony_ci			if((reg & 0xf0) >= 0xb0) {
52778c2ecf20Sopenharmony_ci				reg = SiS_GetReg(SISPART4, 0x23);
52788c2ecf20Sopenharmony_ci				if(reg & 0x20) reg |= 0x40;
52798c2ecf20Sopenharmony_ci				SiS_SetReg(SISPART4, 0x23, reg);
52808c2ecf20Sopenharmony_ci				reg = (reg & 0x20) ? 0x02 : 0x00;
52818c2ecf20Sopenharmony_ci				SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
52828c2ecf20Sopenharmony_ci			}
52838c2ecf20Sopenharmony_ci		}
52848c2ecf20Sopenharmony_ci
52858c2ecf20Sopenharmony_ci		v1 = bios[0x77];
52868c2ecf20Sopenharmony_ci
52878c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x3b);
52888c2ecf20Sopenharmony_ci		if(reg & 0x02) {
52898c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISSR, 0x3a);
52908c2ecf20Sopenharmony_ci			v2 = (reg & 0x30) >> 3;
52918c2ecf20Sopenharmony_ci			if(!(v2 & 0x04)) v2 ^= 0x02;
52928c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISSR, 0x39);
52938c2ecf20Sopenharmony_ci			if(reg & 0x80) v2 |= 0x80;
52948c2ecf20Sopenharmony_ci			v2 |= 0x01;
52958c2ecf20Sopenharmony_ci
52968c2ecf20Sopenharmony_ci			if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
52978c2ecf20Sopenharmony_ci				pci_dev_put(mypdev);
52988c2ecf20Sopenharmony_ci				if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
52998c2ecf20Sopenharmony_ci					v2 &= 0xf9;
53008c2ecf20Sopenharmony_ci				v2 |= 0x08;
53018c2ecf20Sopenharmony_ci				v1 &= 0xfe;
53028c2ecf20Sopenharmony_ci			} else {
53038c2ecf20Sopenharmony_ci				mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
53048c2ecf20Sopenharmony_ci				if(!mypdev)
53058c2ecf20Sopenharmony_ci					mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
53068c2ecf20Sopenharmony_ci				if(!mypdev)
53078c2ecf20Sopenharmony_ci					mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
53088c2ecf20Sopenharmony_ci				if(mypdev) {
53098c2ecf20Sopenharmony_ci					pci_read_config_dword(mypdev, 0x94, &regd);
53108c2ecf20Sopenharmony_ci					regd &= 0xfffffeff;
53118c2ecf20Sopenharmony_ci					pci_write_config_dword(mypdev, 0x94, regd);
53128c2ecf20Sopenharmony_ci					v1 &= 0xfe;
53138c2ecf20Sopenharmony_ci					pci_dev_put(mypdev);
53148c2ecf20Sopenharmony_ci				} else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
53158c2ecf20Sopenharmony_ci					v1 &= 0xfe;
53168c2ecf20Sopenharmony_ci				} else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
53178c2ecf20Sopenharmony_ci					  sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
53188c2ecf20Sopenharmony_ci					  sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
53198c2ecf20Sopenharmony_ci					  sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
53208c2ecf20Sopenharmony_ci					if((v2 & 0x06) == 4)
53218c2ecf20Sopenharmony_ci						v2 ^= 0x06;
53228c2ecf20Sopenharmony_ci					v2 |= 0x08;
53238c2ecf20Sopenharmony_ci				}
53248c2ecf20Sopenharmony_ci			}
53258c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
53268c2ecf20Sopenharmony_ci		}
53278c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x22, v1);
53288c2ecf20Sopenharmony_ci
53298c2ecf20Sopenharmony_ci		if(ivideo->revision_id == 2) {
53308c2ecf20Sopenharmony_ci			v1 = SiS_GetReg(SISSR, 0x3b);
53318c2ecf20Sopenharmony_ci			v2 = SiS_GetReg(SISSR, 0x3a);
53328c2ecf20Sopenharmony_ci			regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
53338c2ecf20Sopenharmony_ci			if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
53348c2ecf20Sopenharmony_ci				SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
53358c2ecf20Sopenharmony_ci
53368c2ecf20Sopenharmony_ci			if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
53378c2ecf20Sopenharmony_ci				/* TODO: set CR5f &0xf1 | 0x01 for version 6570
53388c2ecf20Sopenharmony_ci				 * of nforce 2 ROM
53398c2ecf20Sopenharmony_ci				 */
53408c2ecf20Sopenharmony_ci				if(0)
53418c2ecf20Sopenharmony_ci					SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
53428c2ecf20Sopenharmony_ci				pci_dev_put(mypdev);
53438c2ecf20Sopenharmony_ci			}
53448c2ecf20Sopenharmony_ci		}
53458c2ecf20Sopenharmony_ci
53468c2ecf20Sopenharmony_ci		v1 = 0x30;
53478c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, 0x3b);
53488c2ecf20Sopenharmony_ci		v2 = SiS_GetReg(SISCR, 0x5f);
53498c2ecf20Sopenharmony_ci		if((!(reg & 0x02)) && (v2 & 0x0e))
53508c2ecf20Sopenharmony_ci			v1 |= 0x08;
53518c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x27, v1);
53528c2ecf20Sopenharmony_ci
53538c2ecf20Sopenharmony_ci		if(bios[0x64] & 0x01) {
53548c2ecf20Sopenharmony_ci			SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
53558c2ecf20Sopenharmony_ci		}
53568c2ecf20Sopenharmony_ci
53578c2ecf20Sopenharmony_ci		v1 = bios[0x4f7];
53588c2ecf20Sopenharmony_ci		pci_read_config_dword(pdev, 0x50, &regd);
53598c2ecf20Sopenharmony_ci		regd = (regd >> 20) & 0x0f;
53608c2ecf20Sopenharmony_ci		if(regd == 1) {
53618c2ecf20Sopenharmony_ci			v1 &= 0xfc;
53628c2ecf20Sopenharmony_ci			SiS_SetRegOR(SISCR, 0x5f, 0x08);
53638c2ecf20Sopenharmony_ci		}
53648c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x48, v1);
53658c2ecf20Sopenharmony_ci
53668c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
53678c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
53688c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
53698c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
53708c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
53718c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
53728c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
53738c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x74, 0xd0);
53748c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
53758c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
53768c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
53778c2ecf20Sopenharmony_ci		v1 = bios[0x501];
53788c2ecf20Sopenharmony_ci		if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
53798c2ecf20Sopenharmony_ci			v1 = 0xf0;
53808c2ecf20Sopenharmony_ci			pci_dev_put(mypdev);
53818c2ecf20Sopenharmony_ci		}
53828c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x77, v1);
53838c2ecf20Sopenharmony_ci	}
53848c2ecf20Sopenharmony_ci
53858c2ecf20Sopenharmony_ci	/* RAM type:
53868c2ecf20Sopenharmony_ci	 *
53878c2ecf20Sopenharmony_ci	 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
53888c2ecf20Sopenharmony_ci	 *
53898c2ecf20Sopenharmony_ci	 * The code seems to written so that regb should equal ramtype,
53908c2ecf20Sopenharmony_ci	 * however, so far it has been hardcoded to 0. Enable other values only
53918c2ecf20Sopenharmony_ci	 * on XGI Z9, as it passes the POST, and add a warning for others.
53928c2ecf20Sopenharmony_ci	 */
53938c2ecf20Sopenharmony_ci	ramtype = sisfb_post_xgi_ramtype(ivideo);
53948c2ecf20Sopenharmony_ci	if (!sisfb_xgi_is21(ivideo) && ramtype) {
53958c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev,
53968c2ecf20Sopenharmony_ci			 "RAM type something else than expected: %d\n",
53978c2ecf20Sopenharmony_ci			 ramtype);
53988c2ecf20Sopenharmony_ci		regb = 0;
53998c2ecf20Sopenharmony_ci	} else {
54008c2ecf20Sopenharmony_ci		regb = ramtype;
54018c2ecf20Sopenharmony_ci	}
54028c2ecf20Sopenharmony_ci
54038c2ecf20Sopenharmony_ci	v1 = 0xff;
54048c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
54058c2ecf20Sopenharmony_ci		v1 = bios[0x140 + regb];
54068c2ecf20Sopenharmony_ci	}
54078c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x6d, v1);
54088c2ecf20Sopenharmony_ci
54098c2ecf20Sopenharmony_ci	ptr = cs128;
54108c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
54118c2ecf20Sopenharmony_ci		ptr = (const u8 *)&bios[0x128];
54128c2ecf20Sopenharmony_ci	}
54138c2ecf20Sopenharmony_ci	for(i = 0, j = 0; i < 3; i++, j += 8) {
54148c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
54158c2ecf20Sopenharmony_ci	}
54168c2ecf20Sopenharmony_ci
54178c2ecf20Sopenharmony_ci	ptr  = cs31a;
54188c2ecf20Sopenharmony_ci	ptr2 = cs33a;
54198c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
54208c2ecf20Sopenharmony_ci		index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
54218c2ecf20Sopenharmony_ci		ptr  = (const u8 *)&bios[index];
54228c2ecf20Sopenharmony_ci		ptr2 = (const u8 *)&bios[index + 0x20];
54238c2ecf20Sopenharmony_ci	}
54248c2ecf20Sopenharmony_ci	for(i = 0; i < 2; i++) {
54258c2ecf20Sopenharmony_ci		if(i == 0) {
54268c2ecf20Sopenharmony_ci			regd = le32_to_cpu(((u32 *)ptr)[regb]);
54278c2ecf20Sopenharmony_ci			rega = 0x6b;
54288c2ecf20Sopenharmony_ci		} else {
54298c2ecf20Sopenharmony_ci			regd = le32_to_cpu(((u32 *)ptr2)[regb]);
54308c2ecf20Sopenharmony_ci			rega = 0x6e;
54318c2ecf20Sopenharmony_ci		}
54328c2ecf20Sopenharmony_ci		reg = 0x00;
54338c2ecf20Sopenharmony_ci		for(j = 0; j < 16; j++) {
54348c2ecf20Sopenharmony_ci			reg &= 0xf3;
54358c2ecf20Sopenharmony_ci			if(regd & 0x01) reg |= 0x04;
54368c2ecf20Sopenharmony_ci			if(regd & 0x02) reg |= 0x08;
54378c2ecf20Sopenharmony_ci			regd >>= 2;
54388c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, rega, reg);
54398c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, rega);
54408c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, rega);
54418c2ecf20Sopenharmony_ci			reg += 0x10;
54428c2ecf20Sopenharmony_ci		}
54438c2ecf20Sopenharmony_ci	}
54448c2ecf20Sopenharmony_ci
54458c2ecf20Sopenharmony_ci	SiS_SetRegAND(SISCR, 0x6e, 0xfc);
54468c2ecf20Sopenharmony_ci
54478c2ecf20Sopenharmony_ci	ptr  = NULL;
54488c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
54498c2ecf20Sopenharmony_ci		index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
54508c2ecf20Sopenharmony_ci		ptr  = (const u8 *)&bios[index];
54518c2ecf20Sopenharmony_ci	}
54528c2ecf20Sopenharmony_ci	for(i = 0; i < 4; i++) {
54538c2ecf20Sopenharmony_ci		SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
54548c2ecf20Sopenharmony_ci		reg = 0x00;
54558c2ecf20Sopenharmony_ci		for(j = 0; j < 2; j++) {
54568c2ecf20Sopenharmony_ci			regd = 0;
54578c2ecf20Sopenharmony_ci			if(ptr) {
54588c2ecf20Sopenharmony_ci				regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
54598c2ecf20Sopenharmony_ci				ptr += 4;
54608c2ecf20Sopenharmony_ci			}
54618c2ecf20Sopenharmony_ci			/* reg = 0x00; */
54628c2ecf20Sopenharmony_ci			for(k = 0; k < 16; k++) {
54638c2ecf20Sopenharmony_ci				reg &= 0xfc;
54648c2ecf20Sopenharmony_ci				if(regd & 0x01) reg |= 0x01;
54658c2ecf20Sopenharmony_ci				if(regd & 0x02) reg |= 0x02;
54668c2ecf20Sopenharmony_ci				regd >>= 2;
54678c2ecf20Sopenharmony_ci				SiS_SetReg(SISCR, 0x6f, reg);
54688c2ecf20Sopenharmony_ci				reg = SiS_GetReg(SISCR, 0x6f);
54698c2ecf20Sopenharmony_ci				reg = SiS_GetReg(SISCR, 0x6f);
54708c2ecf20Sopenharmony_ci				reg += 0x08;
54718c2ecf20Sopenharmony_ci			}
54728c2ecf20Sopenharmony_ci		}
54738c2ecf20Sopenharmony_ci	}
54748c2ecf20Sopenharmony_ci
54758c2ecf20Sopenharmony_ci	ptr  = cs148;
54768c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
54778c2ecf20Sopenharmony_ci		ptr  = (const u8 *)&bios[0x148];
54788c2ecf20Sopenharmony_ci	}
54798c2ecf20Sopenharmony_ci	for(i = 0, j = 0; i < 2; i++, j += 8) {
54808c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
54818c2ecf20Sopenharmony_ci	}
54828c2ecf20Sopenharmony_ci
54838c2ecf20Sopenharmony_ci	SiS_SetRegAND(SISCR, 0x89, 0x8f);
54848c2ecf20Sopenharmony_ci
54858c2ecf20Sopenharmony_ci	ptr  = cs45a;
54868c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
54878c2ecf20Sopenharmony_ci		index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
54888c2ecf20Sopenharmony_ci		ptr  = (const u8 *)&bios[index];
54898c2ecf20Sopenharmony_ci	}
54908c2ecf20Sopenharmony_ci	regd = le16_to_cpu(((const u16 *)ptr)[regb]);
54918c2ecf20Sopenharmony_ci	reg = 0x80;
54928c2ecf20Sopenharmony_ci	for(i = 0; i < 5; i++) {
54938c2ecf20Sopenharmony_ci		reg &= 0xfc;
54948c2ecf20Sopenharmony_ci		if(regd & 0x01) reg |= 0x01;
54958c2ecf20Sopenharmony_ci		if(regd & 0x02) reg |= 0x02;
54968c2ecf20Sopenharmony_ci		regd >>= 2;
54978c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x89, reg);
54988c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0x89);
54998c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0x89);
55008c2ecf20Sopenharmony_ci		reg += 0x10;
55018c2ecf20Sopenharmony_ci	}
55028c2ecf20Sopenharmony_ci
55038c2ecf20Sopenharmony_ci	v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
55048c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
55058c2ecf20Sopenharmony_ci		v1 = bios[0x118 + regb];
55068c2ecf20Sopenharmony_ci		v2 = bios[0xf8 + regb];
55078c2ecf20Sopenharmony_ci		v3 = bios[0x120 + regb];
55088c2ecf20Sopenharmony_ci		v4 = bios[0x1ca];
55098c2ecf20Sopenharmony_ci	}
55108c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
55118c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
55128c2ecf20Sopenharmony_ci	SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
55138c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x41, v2);
55148c2ecf20Sopenharmony_ci
55158c2ecf20Sopenharmony_ci	ptr  = cs170;
55168c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
55178c2ecf20Sopenharmony_ci		ptr  = (const u8 *)&bios[0x170];
55188c2ecf20Sopenharmony_ci	}
55198c2ecf20Sopenharmony_ci	for(i = 0, j = 0; i < 7; i++, j += 8) {
55208c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
55218c2ecf20Sopenharmony_ci	}
55228c2ecf20Sopenharmony_ci
55238c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x59, v3);
55248c2ecf20Sopenharmony_ci
55258c2ecf20Sopenharmony_ci	ptr  = cs1a8;
55268c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
55278c2ecf20Sopenharmony_ci		ptr  = (const u8 *)&bios[0x1a8];
55288c2ecf20Sopenharmony_ci	}
55298c2ecf20Sopenharmony_ci	for(i = 0, j = 0; i < 3; i++, j += 8) {
55308c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
55318c2ecf20Sopenharmony_ci	}
55328c2ecf20Sopenharmony_ci
55338c2ecf20Sopenharmony_ci	ptr  = cs100;
55348c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
55358c2ecf20Sopenharmony_ci		ptr  = (const u8 *)&bios[0x100];
55368c2ecf20Sopenharmony_ci	}
55378c2ecf20Sopenharmony_ci	for(i = 0, j = 0; i < 2; i++, j += 8) {
55388c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
55398c2ecf20Sopenharmony_ci	}
55408c2ecf20Sopenharmony_ci
55418c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0xcf, v4);
55428c2ecf20Sopenharmony_ci
55438c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x83, 0x09);
55448c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x87, 0x00);
55458c2ecf20Sopenharmony_ci
55468c2ecf20Sopenharmony_ci	if(ivideo->chip == XGI_40) {
55478c2ecf20Sopenharmony_ci		if( (ivideo->revision_id == 1) ||
55488c2ecf20Sopenharmony_ci		    (ivideo->revision_id == 2) ) {
55498c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x8c, 0x87);
55508c2ecf20Sopenharmony_ci		}
55518c2ecf20Sopenharmony_ci	}
55528c2ecf20Sopenharmony_ci
55538c2ecf20Sopenharmony_ci	if (regb == 1)
55548c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x17, 0x80);		/* DDR2 */
55558c2ecf20Sopenharmony_ci	else
55568c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x17, 0x00);		/* DDR1 */
55578c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1a, 0x87);
55588c2ecf20Sopenharmony_ci
55598c2ecf20Sopenharmony_ci	if(ivideo->chip == XGI_20) {
55608c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x15, 0x00);
55618c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x1c, 0x00);
55628c2ecf20Sopenharmony_ci	}
55638c2ecf20Sopenharmony_ci
55648c2ecf20Sopenharmony_ci	switch(ramtype) {
55658c2ecf20Sopenharmony_ci	case 0:
55668c2ecf20Sopenharmony_ci		sisfb_post_xgi_setclocks(ivideo, regb);
55678c2ecf20Sopenharmony_ci		if((ivideo->chip == XGI_20) ||
55688c2ecf20Sopenharmony_ci		   (ivideo->revision_id == 1)   ||
55698c2ecf20Sopenharmony_ci		   (ivideo->revision_id == 2)) {
55708c2ecf20Sopenharmony_ci			v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
55718c2ecf20Sopenharmony_ci			if(ivideo->haveXGIROM) {
55728c2ecf20Sopenharmony_ci				v1 = bios[regb + 0x158];
55738c2ecf20Sopenharmony_ci				v2 = bios[regb + 0x160];
55748c2ecf20Sopenharmony_ci				v3 = bios[regb + 0x168];
55758c2ecf20Sopenharmony_ci			}
55768c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x82, v1);
55778c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x85, v2);
55788c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x86, v3);
55798c2ecf20Sopenharmony_ci		} else {
55808c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x82, 0x88);
55818c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x86, 0x00);
55828c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x86);
55838c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x86, 0x88);
55848c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x86);
55858c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
55868c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x82, 0x77);
55878c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x85, 0x00);
55888c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x85);
55898c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x85, 0x88);
55908c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x85);
55918c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
55928c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
55938c2ecf20Sopenharmony_ci		}
55948c2ecf20Sopenharmony_ci		if(ivideo->chip == XGI_40) {
55958c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x97, 0x00);
55968c2ecf20Sopenharmony_ci		}
55978c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x98, 0x01);
55988c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x9a, 0x02);
55998c2ecf20Sopenharmony_ci
56008c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x18, 0x01);
56018c2ecf20Sopenharmony_ci		if((ivideo->chip == XGI_20) ||
56028c2ecf20Sopenharmony_ci		   (ivideo->revision_id == 2)) {
56038c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x19, 0x40);
56048c2ecf20Sopenharmony_ci		} else {
56058c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x19, 0x20);
56068c2ecf20Sopenharmony_ci		}
56078c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, 0x00);
56088c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, 0x80);
56098c2ecf20Sopenharmony_ci		if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
56108c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 0x43);
56118c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 0x43);
56128c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 0x43);
56138c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x18, 0x00);
56148c2ecf20Sopenharmony_ci			if((ivideo->chip == XGI_20) ||
56158c2ecf20Sopenharmony_ci			   (ivideo->revision_id == 2)) {
56168c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x19, 0x40);
56178c2ecf20Sopenharmony_ci			} else {
56188c2ecf20Sopenharmony_ci				SiS_SetReg(SISSR, 0x19, 0x20);
56198c2ecf20Sopenharmony_ci			}
56208c2ecf20Sopenharmony_ci		} else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
56218c2ecf20Sopenharmony_ci			/* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
56228c2ecf20Sopenharmony_ci		}
56238c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, 0x00);
56248c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, 0x80);
56258c2ecf20Sopenharmony_ci		sisfb_post_xgi_delay(ivideo, 4);
56268c2ecf20Sopenharmony_ci		v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
56278c2ecf20Sopenharmony_ci		if(ivideo->haveXGIROM) {
56288c2ecf20Sopenharmony_ci			v1 = bios[0xf0];
56298c2ecf20Sopenharmony_ci			index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
56308c2ecf20Sopenharmony_ci			v2 = bios[index];
56318c2ecf20Sopenharmony_ci			v3 = bios[index + 1];
56328c2ecf20Sopenharmony_ci			v4 = bios[index + 2];
56338c2ecf20Sopenharmony_ci			v5 = bios[index + 3];
56348c2ecf20Sopenharmony_ci		}
56358c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x18, v1);
56368c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
56378c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, v2);
56388c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, v3);
56398c2ecf20Sopenharmony_ci		sisfb_post_xgi_delay(ivideo, 0x43);
56408c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x1b, 0x03);
56418c2ecf20Sopenharmony_ci		sisfb_post_xgi_delay(ivideo, 0x22);
56428c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x18, v1);
56438c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x19, 0x00);
56448c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, v4);
56458c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, v5);
56468c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x1b, 0x00);
56478c2ecf20Sopenharmony_ci		break;
56488c2ecf20Sopenharmony_ci	case 1:
56498c2ecf20Sopenharmony_ci		sisfb_post_xgi_ddr2(ivideo, regb);
56508c2ecf20Sopenharmony_ci		break;
56518c2ecf20Sopenharmony_ci	default:
56528c2ecf20Sopenharmony_ci		sisfb_post_xgi_setclocks(ivideo, regb);
56538c2ecf20Sopenharmony_ci		if((ivideo->chip == XGI_40) &&
56548c2ecf20Sopenharmony_ci		   ((ivideo->revision_id == 1) ||
56558c2ecf20Sopenharmony_ci		    (ivideo->revision_id == 2))) {
56568c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
56578c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
56588c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
56598c2ecf20Sopenharmony_ci		} else {
56608c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x82, 0x88);
56618c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x86, 0x00);
56628c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x86);
56638c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x86, 0x88);
56648c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x82, 0x77);
56658c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x85, 0x00);
56668c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x85);
56678c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x85, 0x88);
56688c2ecf20Sopenharmony_ci			reg = SiS_GetReg(SISCR, 0x85);
56698c2ecf20Sopenharmony_ci			v1 = cs160[regb]; v2 = cs158[regb];
56708c2ecf20Sopenharmony_ci			if(ivideo->haveXGIROM) {
56718c2ecf20Sopenharmony_ci				v1 = bios[regb + 0x160];
56728c2ecf20Sopenharmony_ci				v2 = bios[regb + 0x158];
56738c2ecf20Sopenharmony_ci			}
56748c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x85, v1);
56758c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x82, v2);
56768c2ecf20Sopenharmony_ci		}
56778c2ecf20Sopenharmony_ci		if(ivideo->chip == XGI_40) {
56788c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x97, 0x11);
56798c2ecf20Sopenharmony_ci		}
56808c2ecf20Sopenharmony_ci		if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
56818c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x98, 0x01);
56828c2ecf20Sopenharmony_ci		} else {
56838c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, 0x98, 0x03);
56848c2ecf20Sopenharmony_ci		}
56858c2ecf20Sopenharmony_ci		SiS_SetReg(SISCR, 0x9a, 0x02);
56868c2ecf20Sopenharmony_ci
56878c2ecf20Sopenharmony_ci		if(ivideo->chip == XGI_40) {
56888c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x18, 0x01);
56898c2ecf20Sopenharmony_ci		} else {
56908c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x18, 0x00);
56918c2ecf20Sopenharmony_ci		}
56928c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x19, 0x40);
56938c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, 0x00);
56948c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x16, 0x80);
56958c2ecf20Sopenharmony_ci		if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
56968c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 0x43);
56978c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 0x43);
56988c2ecf20Sopenharmony_ci			sisfb_post_xgi_delay(ivideo, 0x43);
56998c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x18, 0x00);
57008c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x19, 0x40);
57018c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, 0x00);
57028c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, 0x80);
57038c2ecf20Sopenharmony_ci		}
57048c2ecf20Sopenharmony_ci		sisfb_post_xgi_delay(ivideo, 4);
57058c2ecf20Sopenharmony_ci		v1 = 0x31;
57068c2ecf20Sopenharmony_ci		if(ivideo->haveXGIROM) {
57078c2ecf20Sopenharmony_ci			v1 = bios[0xf0];
57088c2ecf20Sopenharmony_ci		}
57098c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x18, v1);
57108c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x19, 0x01);
57118c2ecf20Sopenharmony_ci		if(ivideo->chip == XGI_40) {
57128c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, bios[0x53e]);
57138c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, bios[0x53f]);
57148c2ecf20Sopenharmony_ci		} else {
57158c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, 0x05);
57168c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, 0x85);
57178c2ecf20Sopenharmony_ci		}
57188c2ecf20Sopenharmony_ci		sisfb_post_xgi_delay(ivideo, 0x43);
57198c2ecf20Sopenharmony_ci		if(ivideo->chip == XGI_40) {
57208c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x1b, 0x01);
57218c2ecf20Sopenharmony_ci		} else {
57228c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x1b, 0x03);
57238c2ecf20Sopenharmony_ci		}
57248c2ecf20Sopenharmony_ci		sisfb_post_xgi_delay(ivideo, 0x22);
57258c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x18, v1);
57268c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x19, 0x00);
57278c2ecf20Sopenharmony_ci		if(ivideo->chip == XGI_40) {
57288c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, bios[0x540]);
57298c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, bios[0x541]);
57308c2ecf20Sopenharmony_ci		} else {
57318c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, 0x05);
57328c2ecf20Sopenharmony_ci			SiS_SetReg(SISSR, 0x16, 0x85);
57338c2ecf20Sopenharmony_ci		}
57348c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x1b, 0x00);
57358c2ecf20Sopenharmony_ci	}
57368c2ecf20Sopenharmony_ci
57378c2ecf20Sopenharmony_ci	regb = 0;	/* ! */
57388c2ecf20Sopenharmony_ci	v1 = 0x03;
57398c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
57408c2ecf20Sopenharmony_ci		v1 = bios[0x110 + regb];
57418c2ecf20Sopenharmony_ci	}
57428c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x1b, v1);
57438c2ecf20Sopenharmony_ci
57448c2ecf20Sopenharmony_ci	/* RAM size */
57458c2ecf20Sopenharmony_ci	v1 = 0x00; v2 = 0x00;
57468c2ecf20Sopenharmony_ci	if(ivideo->haveXGIROM) {
57478c2ecf20Sopenharmony_ci		v1 = bios[0x62];
57488c2ecf20Sopenharmony_ci		v2 = bios[0x63];
57498c2ecf20Sopenharmony_ci	}
57508c2ecf20Sopenharmony_ci	regb = 0;	/* ! */
57518c2ecf20Sopenharmony_ci	regd = 1 << regb;
57528c2ecf20Sopenharmony_ci	if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
57538c2ecf20Sopenharmony_ci
57548c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
57558c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
57568c2ecf20Sopenharmony_ci
57578c2ecf20Sopenharmony_ci	} else {
57588c2ecf20Sopenharmony_ci		int err;
57598c2ecf20Sopenharmony_ci
57608c2ecf20Sopenharmony_ci		/* Set default mode, don't clear screen */
57618c2ecf20Sopenharmony_ci		ivideo->SiS_Pr.SiS_UseOEM = false;
57628c2ecf20Sopenharmony_ci		SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
57638c2ecf20Sopenharmony_ci		SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
57648c2ecf20Sopenharmony_ci		ivideo->curFSTN = ivideo->curDSTN = 0;
57658c2ecf20Sopenharmony_ci		ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
57668c2ecf20Sopenharmony_ci		SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
57678c2ecf20Sopenharmony_ci
57688c2ecf20Sopenharmony_ci		SiS_SetReg(SISSR, 0x05, 0x86);
57698c2ecf20Sopenharmony_ci
57708c2ecf20Sopenharmony_ci		/* Disable read-cache */
57718c2ecf20Sopenharmony_ci		SiS_SetRegAND(SISSR, 0x21, 0xdf);
57728c2ecf20Sopenharmony_ci		err = sisfb_post_xgi_ramsize(ivideo);
57738c2ecf20Sopenharmony_ci		/* Enable read-cache */
57748c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISSR, 0x21, 0x20);
57758c2ecf20Sopenharmony_ci
57768c2ecf20Sopenharmony_ci		if (err) {
57778c2ecf20Sopenharmony_ci			dev_err(&pdev->dev,
57788c2ecf20Sopenharmony_ci				"%s: RAM size detection failed: %d\n",
57798c2ecf20Sopenharmony_ci				__func__, err);
57808c2ecf20Sopenharmony_ci			return 0;
57818c2ecf20Sopenharmony_ci		}
57828c2ecf20Sopenharmony_ci	}
57838c2ecf20Sopenharmony_ci
57848c2ecf20Sopenharmony_ci#if 0
57858c2ecf20Sopenharmony_ci	printk(KERN_DEBUG "-----------------\n");
57868c2ecf20Sopenharmony_ci	for(i = 0; i < 0xff; i++) {
57878c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, i);
57888c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
57898c2ecf20Sopenharmony_ci	}
57908c2ecf20Sopenharmony_ci	for(i = 0; i < 0x40; i++) {
57918c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISSR, i);
57928c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
57938c2ecf20Sopenharmony_ci	}
57948c2ecf20Sopenharmony_ci	printk(KERN_DEBUG "-----------------\n");
57958c2ecf20Sopenharmony_ci#endif
57968c2ecf20Sopenharmony_ci
57978c2ecf20Sopenharmony_ci	/* Sense CRT1 */
57988c2ecf20Sopenharmony_ci	if(ivideo->chip == XGI_20) {
57998c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISCR, 0x32, 0x20);
58008c2ecf20Sopenharmony_ci	} else {
58018c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISPART4, 0x00);
58028c2ecf20Sopenharmony_ci		if((reg == 1) || (reg == 2)) {
58038c2ecf20Sopenharmony_ci			sisfb_sense_crt1(ivideo);
58048c2ecf20Sopenharmony_ci		} else {
58058c2ecf20Sopenharmony_ci			SiS_SetRegOR(SISCR, 0x32, 0x20);
58068c2ecf20Sopenharmony_ci		}
58078c2ecf20Sopenharmony_ci	}
58088c2ecf20Sopenharmony_ci
58098c2ecf20Sopenharmony_ci	/* Set default mode, don't clear screen */
58108c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_UseOEM = false;
58118c2ecf20Sopenharmony_ci	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
58128c2ecf20Sopenharmony_ci	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
58138c2ecf20Sopenharmony_ci	ivideo->curFSTN = ivideo->curDSTN = 0;
58148c2ecf20Sopenharmony_ci	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
58158c2ecf20Sopenharmony_ci
58168c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x05, 0x86);
58178c2ecf20Sopenharmony_ci
58188c2ecf20Sopenharmony_ci	/* Display off */
58198c2ecf20Sopenharmony_ci	SiS_SetRegOR(SISSR, 0x01, 0x20);
58208c2ecf20Sopenharmony_ci
58218c2ecf20Sopenharmony_ci	/* Save mode number in CR34 */
58228c2ecf20Sopenharmony_ci	SiS_SetReg(SISCR, 0x34, 0x2e);
58238c2ecf20Sopenharmony_ci
58248c2ecf20Sopenharmony_ci	/* Let everyone know what the current mode is */
58258c2ecf20Sopenharmony_ci	ivideo->modeprechange = 0x2e;
58268c2ecf20Sopenharmony_ci
58278c2ecf20Sopenharmony_ci	if(ivideo->chip == XGI_40) {
58288c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0xca);
58298c2ecf20Sopenharmony_ci		v1 = SiS_GetReg(SISCR, 0xcc);
58308c2ecf20Sopenharmony_ci		if((reg & 0x10) && (!(v1 & 0x04))) {
58318c2ecf20Sopenharmony_ci			printk(KERN_ERR
58328c2ecf20Sopenharmony_ci				"sisfb: Please connect power to the card.\n");
58338c2ecf20Sopenharmony_ci			return 0;
58348c2ecf20Sopenharmony_ci		}
58358c2ecf20Sopenharmony_ci	}
58368c2ecf20Sopenharmony_ci
58378c2ecf20Sopenharmony_ci	return 1;
58388c2ecf20Sopenharmony_ci}
58398c2ecf20Sopenharmony_ci#endif
58408c2ecf20Sopenharmony_ci
58418c2ecf20Sopenharmony_cistatic int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
58428c2ecf20Sopenharmony_ci{
58438c2ecf20Sopenharmony_ci	struct sisfb_chip_info	*chipinfo = &sisfb_chip_info[ent->driver_data];
58448c2ecf20Sopenharmony_ci	struct sis_video_info	*ivideo = NULL;
58458c2ecf20Sopenharmony_ci	struct fb_info		*sis_fb_info = NULL;
58468c2ecf20Sopenharmony_ci	u16 reg16;
58478c2ecf20Sopenharmony_ci	u8  reg;
58488c2ecf20Sopenharmony_ci	int i, ret;
58498c2ecf20Sopenharmony_ci
58508c2ecf20Sopenharmony_ci	if(sisfb_off)
58518c2ecf20Sopenharmony_ci		return -ENXIO;
58528c2ecf20Sopenharmony_ci
58538c2ecf20Sopenharmony_ci	sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
58548c2ecf20Sopenharmony_ci	if(!sis_fb_info)
58558c2ecf20Sopenharmony_ci		return -ENOMEM;
58568c2ecf20Sopenharmony_ci
58578c2ecf20Sopenharmony_ci	ivideo = (struct sis_video_info *)sis_fb_info->par;
58588c2ecf20Sopenharmony_ci	ivideo->memyselfandi = sis_fb_info;
58598c2ecf20Sopenharmony_ci
58608c2ecf20Sopenharmony_ci	ivideo->sisfb_id = SISFB_ID;
58618c2ecf20Sopenharmony_ci
58628c2ecf20Sopenharmony_ci	if(card_list == NULL) {
58638c2ecf20Sopenharmony_ci		ivideo->cardnumber = 0;
58648c2ecf20Sopenharmony_ci	} else {
58658c2ecf20Sopenharmony_ci		struct sis_video_info *countvideo = card_list;
58668c2ecf20Sopenharmony_ci		ivideo->cardnumber = 1;
58678c2ecf20Sopenharmony_ci		while((countvideo = countvideo->next) != NULL)
58688c2ecf20Sopenharmony_ci			ivideo->cardnumber++;
58698c2ecf20Sopenharmony_ci	}
58708c2ecf20Sopenharmony_ci
58718c2ecf20Sopenharmony_ci	strlcpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
58728c2ecf20Sopenharmony_ci
58738c2ecf20Sopenharmony_ci	ivideo->warncount = 0;
58748c2ecf20Sopenharmony_ci	ivideo->chip_id = pdev->device;
58758c2ecf20Sopenharmony_ci	ivideo->chip_vendor = pdev->vendor;
58768c2ecf20Sopenharmony_ci	ivideo->revision_id = pdev->revision;
58778c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
58788c2ecf20Sopenharmony_ci	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
58798c2ecf20Sopenharmony_ci	ivideo->sisvga_enabled = reg16 & 0x01;
58808c2ecf20Sopenharmony_ci	ivideo->pcibus = pdev->bus->number;
58818c2ecf20Sopenharmony_ci	ivideo->pcislot = PCI_SLOT(pdev->devfn);
58828c2ecf20Sopenharmony_ci	ivideo->pcifunc = PCI_FUNC(pdev->devfn);
58838c2ecf20Sopenharmony_ci	ivideo->subsysvendor = pdev->subsystem_vendor;
58848c2ecf20Sopenharmony_ci	ivideo->subsysdevice = pdev->subsystem_device;
58858c2ecf20Sopenharmony_ci
58868c2ecf20Sopenharmony_ci#ifndef MODULE
58878c2ecf20Sopenharmony_ci	if(sisfb_mode_idx == -1) {
58888c2ecf20Sopenharmony_ci		sisfb_get_vga_mode_from_kernel();
58898c2ecf20Sopenharmony_ci	}
58908c2ecf20Sopenharmony_ci#endif
58918c2ecf20Sopenharmony_ci
58928c2ecf20Sopenharmony_ci	ivideo->chip = chipinfo->chip;
58938c2ecf20Sopenharmony_ci	ivideo->chip_real_id = chipinfo->chip;
58948c2ecf20Sopenharmony_ci	ivideo->sisvga_engine = chipinfo->vgaengine;
58958c2ecf20Sopenharmony_ci	ivideo->hwcursor_size = chipinfo->hwcursor_size;
58968c2ecf20Sopenharmony_ci	ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
58978c2ecf20Sopenharmony_ci	ivideo->mni = chipinfo->mni;
58988c2ecf20Sopenharmony_ci
58998c2ecf20Sopenharmony_ci	ivideo->detectedpdc  = 0xff;
59008c2ecf20Sopenharmony_ci	ivideo->detectedpdca = 0xff;
59018c2ecf20Sopenharmony_ci	ivideo->detectedlcda = 0xff;
59028c2ecf20Sopenharmony_ci
59038c2ecf20Sopenharmony_ci	ivideo->sisfb_thismonitor.datavalid = false;
59048c2ecf20Sopenharmony_ci
59058c2ecf20Sopenharmony_ci	ivideo->current_base = 0;
59068c2ecf20Sopenharmony_ci
59078c2ecf20Sopenharmony_ci	ivideo->engineok = 0;
59088c2ecf20Sopenharmony_ci
59098c2ecf20Sopenharmony_ci	ivideo->sisfb_was_boot_device = 0;
59108c2ecf20Sopenharmony_ci
59118c2ecf20Sopenharmony_ci	if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
59128c2ecf20Sopenharmony_ci		if(ivideo->sisvga_enabled)
59138c2ecf20Sopenharmony_ci			ivideo->sisfb_was_boot_device = 1;
59148c2ecf20Sopenharmony_ci		else {
59158c2ecf20Sopenharmony_ci			printk(KERN_DEBUG "sisfb: PCI device is disabled, "
59168c2ecf20Sopenharmony_ci				"but marked as boot video device ???\n");
59178c2ecf20Sopenharmony_ci			printk(KERN_DEBUG "sisfb: I will not accept this "
59188c2ecf20Sopenharmony_ci				"as the primary VGA device\n");
59198c2ecf20Sopenharmony_ci		}
59208c2ecf20Sopenharmony_ci	}
59218c2ecf20Sopenharmony_ci
59228c2ecf20Sopenharmony_ci	ivideo->sisfb_parm_mem = sisfb_parm_mem;
59238c2ecf20Sopenharmony_ci	ivideo->sisfb_accel = sisfb_accel;
59248c2ecf20Sopenharmony_ci	ivideo->sisfb_ypan = sisfb_ypan;
59258c2ecf20Sopenharmony_ci	ivideo->sisfb_max = sisfb_max;
59268c2ecf20Sopenharmony_ci	ivideo->sisfb_userom = sisfb_userom;
59278c2ecf20Sopenharmony_ci	ivideo->sisfb_useoem = sisfb_useoem;
59288c2ecf20Sopenharmony_ci	ivideo->sisfb_mode_idx = sisfb_mode_idx;
59298c2ecf20Sopenharmony_ci	ivideo->sisfb_parm_rate = sisfb_parm_rate;
59308c2ecf20Sopenharmony_ci	ivideo->sisfb_crt1off = sisfb_crt1off;
59318c2ecf20Sopenharmony_ci	ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
59328c2ecf20Sopenharmony_ci	ivideo->sisfb_crt2type = sisfb_crt2type;
59338c2ecf20Sopenharmony_ci	ivideo->sisfb_crt2flags = sisfb_crt2flags;
59348c2ecf20Sopenharmony_ci	/* pdc(a), scalelcd, special timing, lvdshl handled below */
59358c2ecf20Sopenharmony_ci	ivideo->sisfb_dstn = sisfb_dstn;
59368c2ecf20Sopenharmony_ci	ivideo->sisfb_fstn = sisfb_fstn;
59378c2ecf20Sopenharmony_ci	ivideo->sisfb_tvplug = sisfb_tvplug;
59388c2ecf20Sopenharmony_ci	ivideo->sisfb_tvstd = sisfb_tvstd;
59398c2ecf20Sopenharmony_ci	ivideo->tvxpos = sisfb_tvxposoffset;
59408c2ecf20Sopenharmony_ci	ivideo->tvypos = sisfb_tvyposoffset;
59418c2ecf20Sopenharmony_ci	ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
59428c2ecf20Sopenharmony_ci	ivideo->refresh_rate = 0;
59438c2ecf20Sopenharmony_ci	if(ivideo->sisfb_parm_rate != -1) {
59448c2ecf20Sopenharmony_ci		ivideo->refresh_rate = ivideo->sisfb_parm_rate;
59458c2ecf20Sopenharmony_ci	}
59468c2ecf20Sopenharmony_ci
59478c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
59488c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.CenterScreen = -1;
59498c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
59508c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
59518c2ecf20Sopenharmony_ci
59528c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
59538c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_CHOverScan = -1;
59548c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_ChSW = false;
59558c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_UseLCDA = false;
59568c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.HaveEMI = false;
59578c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.HaveEMILCD = false;
59588c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.OverruleEMI = false;
59598c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_SensibleSR11 = false;
59608c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
59618c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.PDC  = -1;
59628c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.PDCA = -1;
59638c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.DDCPortMixup = false;
59648c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
59658c2ecf20Sopenharmony_ci	if(ivideo->chip >= SIS_330) {
59668c2ecf20Sopenharmony_ci		ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
59678c2ecf20Sopenharmony_ci		if(ivideo->chip >= SIS_661) {
59688c2ecf20Sopenharmony_ci			ivideo->SiS_Pr.SiS_SensibleSR11 = true;
59698c2ecf20Sopenharmony_ci		}
59708c2ecf20Sopenharmony_ci	}
59718c2ecf20Sopenharmony_ci#endif
59728c2ecf20Sopenharmony_ci
59738c2ecf20Sopenharmony_ci	memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
59748c2ecf20Sopenharmony_ci
59758c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, ivideo);
59768c2ecf20Sopenharmony_ci
59778c2ecf20Sopenharmony_ci	/* Patch special cases */
59788c2ecf20Sopenharmony_ci	if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
59798c2ecf20Sopenharmony_ci		switch(ivideo->nbridge->device) {
59808c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
59818c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_SI_730:
59828c2ecf20Sopenharmony_ci			ivideo->chip = SIS_730;
59838c2ecf20Sopenharmony_ci			strcpy(ivideo->myid, "SiS 730");
59848c2ecf20Sopenharmony_ci			break;
59858c2ecf20Sopenharmony_ci#endif
59868c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
59878c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_SI_651:
59888c2ecf20Sopenharmony_ci			/* ivideo->chip is ok */
59898c2ecf20Sopenharmony_ci			strcpy(ivideo->myid, "SiS 651");
59908c2ecf20Sopenharmony_ci			break;
59918c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_SI_740:
59928c2ecf20Sopenharmony_ci			ivideo->chip = SIS_740;
59938c2ecf20Sopenharmony_ci			strcpy(ivideo->myid, "SiS 740");
59948c2ecf20Sopenharmony_ci			break;
59958c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_SI_661:
59968c2ecf20Sopenharmony_ci			ivideo->chip = SIS_661;
59978c2ecf20Sopenharmony_ci			strcpy(ivideo->myid, "SiS 661");
59988c2ecf20Sopenharmony_ci			break;
59998c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_SI_741:
60008c2ecf20Sopenharmony_ci			ivideo->chip = SIS_741;
60018c2ecf20Sopenharmony_ci			strcpy(ivideo->myid, "SiS 741");
60028c2ecf20Sopenharmony_ci			break;
60038c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_SI_760:
60048c2ecf20Sopenharmony_ci			ivideo->chip = SIS_760;
60058c2ecf20Sopenharmony_ci			strcpy(ivideo->myid, "SiS 760");
60068c2ecf20Sopenharmony_ci			break;
60078c2ecf20Sopenharmony_ci		case PCI_DEVICE_ID_SI_761:
60088c2ecf20Sopenharmony_ci			ivideo->chip = SIS_761;
60098c2ecf20Sopenharmony_ci			strcpy(ivideo->myid, "SiS 761");
60108c2ecf20Sopenharmony_ci			break;
60118c2ecf20Sopenharmony_ci#endif
60128c2ecf20Sopenharmony_ci		default:
60138c2ecf20Sopenharmony_ci			break;
60148c2ecf20Sopenharmony_ci		}
60158c2ecf20Sopenharmony_ci	}
60168c2ecf20Sopenharmony_ci
60178c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.ChipType = ivideo->chip;
60188c2ecf20Sopenharmony_ci
60198c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.ivideo = (void *)ivideo;
60208c2ecf20Sopenharmony_ci
60218c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
60228c2ecf20Sopenharmony_ci	if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
60238c2ecf20Sopenharmony_ci	   (ivideo->SiS_Pr.ChipType == SIS_315)) {
60248c2ecf20Sopenharmony_ci		ivideo->SiS_Pr.ChipType = SIS_315H;
60258c2ecf20Sopenharmony_ci	}
60268c2ecf20Sopenharmony_ci#endif
60278c2ecf20Sopenharmony_ci
60288c2ecf20Sopenharmony_ci	if(!ivideo->sisvga_enabled) {
60298c2ecf20Sopenharmony_ci		if(pci_enable_device(pdev)) {
60308c2ecf20Sopenharmony_ci			pci_dev_put(ivideo->nbridge);
60318c2ecf20Sopenharmony_ci			framebuffer_release(sis_fb_info);
60328c2ecf20Sopenharmony_ci			return -EIO;
60338c2ecf20Sopenharmony_ci		}
60348c2ecf20Sopenharmony_ci	}
60358c2ecf20Sopenharmony_ci
60368c2ecf20Sopenharmony_ci	ivideo->video_base = pci_resource_start(pdev, 0);
60378c2ecf20Sopenharmony_ci	ivideo->video_size = pci_resource_len(pdev, 0);
60388c2ecf20Sopenharmony_ci	ivideo->mmio_base  = pci_resource_start(pdev, 1);
60398c2ecf20Sopenharmony_ci	ivideo->mmio_size  = pci_resource_len(pdev, 1);
60408c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
60418c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
60428c2ecf20Sopenharmony_ci
60438c2ecf20Sopenharmony_ci	SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
60448c2ecf20Sopenharmony_ci
60458c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
60468c2ecf20Sopenharmony_ci	/* Find PCI systems for Chrontel/GPIO communication setup */
60478c2ecf20Sopenharmony_ci	if(ivideo->chip == SIS_630) {
60488c2ecf20Sopenharmony_ci		i = 0;
60498c2ecf20Sopenharmony_ci        	do {
60508c2ecf20Sopenharmony_ci			if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
60518c2ecf20Sopenharmony_ci			   mychswtable[i].subsysCard   == ivideo->subsysdevice) {
60528c2ecf20Sopenharmony_ci				ivideo->SiS_Pr.SiS_ChSW = true;
60538c2ecf20Sopenharmony_ci				printk(KERN_DEBUG "sisfb: Identified [%s %s] "
60548c2ecf20Sopenharmony_ci					"requiring Chrontel/GPIO setup\n",
60558c2ecf20Sopenharmony_ci					mychswtable[i].vendorName,
60568c2ecf20Sopenharmony_ci					mychswtable[i].cardName);
60578c2ecf20Sopenharmony_ci				ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
60588c2ecf20Sopenharmony_ci				break;
60598c2ecf20Sopenharmony_ci			}
60608c2ecf20Sopenharmony_ci			i++;
60618c2ecf20Sopenharmony_ci		} while(mychswtable[i].subsysVendor != 0);
60628c2ecf20Sopenharmony_ci	}
60638c2ecf20Sopenharmony_ci#endif
60648c2ecf20Sopenharmony_ci
60658c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
60668c2ecf20Sopenharmony_ci	if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
60678c2ecf20Sopenharmony_ci		ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
60688c2ecf20Sopenharmony_ci	}
60698c2ecf20Sopenharmony_ci#endif
60708c2ecf20Sopenharmony_ci
60718c2ecf20Sopenharmony_ci	SiS_SetReg(SISSR, 0x05, 0x86);
60728c2ecf20Sopenharmony_ci
60738c2ecf20Sopenharmony_ci	if( (!ivideo->sisvga_enabled)
60748c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
60758c2ecf20Sopenharmony_ci			      || (sisfb_resetcard)
60768c2ecf20Sopenharmony_ci#endif
60778c2ecf20Sopenharmony_ci						   ) {
60788c2ecf20Sopenharmony_ci		for(i = 0x30; i <= 0x3f; i++) {
60798c2ecf20Sopenharmony_ci			SiS_SetReg(SISCR, i, 0x00);
60808c2ecf20Sopenharmony_ci		}
60818c2ecf20Sopenharmony_ci	}
60828c2ecf20Sopenharmony_ci
60838c2ecf20Sopenharmony_ci	/* Find out about current video mode */
60848c2ecf20Sopenharmony_ci	ivideo->modeprechange = 0x03;
60858c2ecf20Sopenharmony_ci	reg = SiS_GetReg(SISCR, 0x34);
60868c2ecf20Sopenharmony_ci	if(reg & 0x7f) {
60878c2ecf20Sopenharmony_ci		ivideo->modeprechange = reg & 0x7f;
60888c2ecf20Sopenharmony_ci	} else if(ivideo->sisvga_enabled) {
60898c2ecf20Sopenharmony_ci#if defined(__i386__) || defined(__x86_64__)
60908c2ecf20Sopenharmony_ci		unsigned char __iomem *tt = ioremap(0x400, 0x100);
60918c2ecf20Sopenharmony_ci		if(tt) {
60928c2ecf20Sopenharmony_ci			ivideo->modeprechange = readb(tt + 0x49);
60938c2ecf20Sopenharmony_ci			iounmap(tt);
60948c2ecf20Sopenharmony_ci		}
60958c2ecf20Sopenharmony_ci#endif
60968c2ecf20Sopenharmony_ci	}
60978c2ecf20Sopenharmony_ci
60988c2ecf20Sopenharmony_ci	/* Search and copy ROM image */
60998c2ecf20Sopenharmony_ci	ivideo->bios_abase = NULL;
61008c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.VirtualRomBase = NULL;
61018c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.UseROM = false;
61028c2ecf20Sopenharmony_ci	ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
61038c2ecf20Sopenharmony_ci	if(ivideo->sisfb_userom) {
61048c2ecf20Sopenharmony_ci		ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
61058c2ecf20Sopenharmony_ci		ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
61068c2ecf20Sopenharmony_ci		ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
61078c2ecf20Sopenharmony_ci		printk(KERN_INFO "sisfb: Video ROM %sfound\n",
61088c2ecf20Sopenharmony_ci			ivideo->SiS_Pr.UseROM ? "" : "not ");
61098c2ecf20Sopenharmony_ci		if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
61108c2ecf20Sopenharmony_ci		   ivideo->SiS_Pr.UseROM = false;
61118c2ecf20Sopenharmony_ci		   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
61128c2ecf20Sopenharmony_ci		   if( (ivideo->revision_id == 2) &&
61138c2ecf20Sopenharmony_ci		       (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
61148c2ecf20Sopenharmony_ci			ivideo->SiS_Pr.DDCPortMixup = true;
61158c2ecf20Sopenharmony_ci		   }
61168c2ecf20Sopenharmony_ci		}
61178c2ecf20Sopenharmony_ci	} else {
61188c2ecf20Sopenharmony_ci		printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
61198c2ecf20Sopenharmony_ci	}
61208c2ecf20Sopenharmony_ci
61218c2ecf20Sopenharmony_ci	/* Find systems for special custom timing */
61228c2ecf20Sopenharmony_ci	if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
61238c2ecf20Sopenharmony_ci		sisfb_detect_custom_timing(ivideo);
61248c2ecf20Sopenharmony_ci	}
61258c2ecf20Sopenharmony_ci
61268c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
61278c2ecf20Sopenharmony_ci	if (ivideo->chip == XGI_20) {
61288c2ecf20Sopenharmony_ci		/* Check if our Z7 chip is actually Z9 */
61298c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISCR, 0x4a, 0x40);	/* GPIOG EN */
61308c2ecf20Sopenharmony_ci		reg = SiS_GetReg(SISCR, 0x48);
61318c2ecf20Sopenharmony_ci		if (reg & 0x02) {			/* GPIOG */
61328c2ecf20Sopenharmony_ci			ivideo->chip_real_id = XGI_21;
61338c2ecf20Sopenharmony_ci			dev_info(&pdev->dev, "Z9 detected\n");
61348c2ecf20Sopenharmony_ci		}
61358c2ecf20Sopenharmony_ci	}
61368c2ecf20Sopenharmony_ci#endif
61378c2ecf20Sopenharmony_ci
61388c2ecf20Sopenharmony_ci	/* POST card in case this has not been done by the BIOS */
61398c2ecf20Sopenharmony_ci	if( (!ivideo->sisvga_enabled)
61408c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
61418c2ecf20Sopenharmony_ci			     || (sisfb_resetcard)
61428c2ecf20Sopenharmony_ci#endif
61438c2ecf20Sopenharmony_ci						 ) {
61448c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
61458c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_300_VGA) {
61468c2ecf20Sopenharmony_ci			if(ivideo->chip == SIS_300) {
61478c2ecf20Sopenharmony_ci				sisfb_post_sis300(pdev);
61488c2ecf20Sopenharmony_ci				ivideo->sisfb_can_post = 1;
61498c2ecf20Sopenharmony_ci			}
61508c2ecf20Sopenharmony_ci		}
61518c2ecf20Sopenharmony_ci#endif
61528c2ecf20Sopenharmony_ci
61538c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
61548c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_315_VGA) {
61558c2ecf20Sopenharmony_ci			int result = 1;
61568c2ecf20Sopenharmony_ci		/*	if((ivideo->chip == SIS_315H)   ||
61578c2ecf20Sopenharmony_ci			   (ivideo->chip == SIS_315)    ||
61588c2ecf20Sopenharmony_ci			   (ivideo->chip == SIS_315PRO) ||
61598c2ecf20Sopenharmony_ci			   (ivideo->chip == SIS_330)) {
61608c2ecf20Sopenharmony_ci				sisfb_post_sis315330(pdev);
61618c2ecf20Sopenharmony_ci			} else */ if(ivideo->chip == XGI_20) {
61628c2ecf20Sopenharmony_ci				result = sisfb_post_xgi(pdev);
61638c2ecf20Sopenharmony_ci				ivideo->sisfb_can_post = 1;
61648c2ecf20Sopenharmony_ci			} else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
61658c2ecf20Sopenharmony_ci				result = sisfb_post_xgi(pdev);
61668c2ecf20Sopenharmony_ci				ivideo->sisfb_can_post = 1;
61678c2ecf20Sopenharmony_ci			} else {
61688c2ecf20Sopenharmony_ci				printk(KERN_INFO "sisfb: Card is not "
61698c2ecf20Sopenharmony_ci					"POSTed and sisfb can't do this either.\n");
61708c2ecf20Sopenharmony_ci			}
61718c2ecf20Sopenharmony_ci			if(!result) {
61728c2ecf20Sopenharmony_ci				printk(KERN_ERR "sisfb: Failed to POST card\n");
61738c2ecf20Sopenharmony_ci				ret = -ENODEV;
61748c2ecf20Sopenharmony_ci				goto error_3;
61758c2ecf20Sopenharmony_ci			}
61768c2ecf20Sopenharmony_ci		}
61778c2ecf20Sopenharmony_ci#endif
61788c2ecf20Sopenharmony_ci	}
61798c2ecf20Sopenharmony_ci
61808c2ecf20Sopenharmony_ci	ivideo->sisfb_card_posted = 1;
61818c2ecf20Sopenharmony_ci
61828c2ecf20Sopenharmony_ci	/* Find out about RAM size */
61838c2ecf20Sopenharmony_ci	if(sisfb_get_dram_size(ivideo)) {
61848c2ecf20Sopenharmony_ci		printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
61858c2ecf20Sopenharmony_ci		ret = -ENODEV;
61868c2ecf20Sopenharmony_ci		goto error_3;
61878c2ecf20Sopenharmony_ci	}
61888c2ecf20Sopenharmony_ci
61898c2ecf20Sopenharmony_ci
61908c2ecf20Sopenharmony_ci	/* Enable PCI addressing and MMIO */
61918c2ecf20Sopenharmony_ci	if((ivideo->sisfb_mode_idx < 0) ||
61928c2ecf20Sopenharmony_ci	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
61938c2ecf20Sopenharmony_ci		/* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
61948c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
61958c2ecf20Sopenharmony_ci		/* Enable 2D accelerator engine */
61968c2ecf20Sopenharmony_ci		SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
61978c2ecf20Sopenharmony_ci	}
61988c2ecf20Sopenharmony_ci
61998c2ecf20Sopenharmony_ci	if(sisfb_pdc != 0xff) {
62008c2ecf20Sopenharmony_ci		if(ivideo->sisvga_engine == SIS_300_VGA)
62018c2ecf20Sopenharmony_ci			sisfb_pdc &= 0x3c;
62028c2ecf20Sopenharmony_ci		else
62038c2ecf20Sopenharmony_ci			sisfb_pdc &= 0x1f;
62048c2ecf20Sopenharmony_ci		ivideo->SiS_Pr.PDC = sisfb_pdc;
62058c2ecf20Sopenharmony_ci	}
62068c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
62078c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_315_VGA) {
62088c2ecf20Sopenharmony_ci		if(sisfb_pdca != 0xff)
62098c2ecf20Sopenharmony_ci			ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
62108c2ecf20Sopenharmony_ci	}
62118c2ecf20Sopenharmony_ci#endif
62128c2ecf20Sopenharmony_ci
62138c2ecf20Sopenharmony_ci	if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
62148c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
62158c2ecf20Sopenharmony_ci				(int)(ivideo->video_size >> 20));
62168c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
62178c2ecf20Sopenharmony_ci		ret = -ENODEV;
62188c2ecf20Sopenharmony_ci		goto error_3;
62198c2ecf20Sopenharmony_ci	}
62208c2ecf20Sopenharmony_ci
62218c2ecf20Sopenharmony_ci	if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
62228c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
62238c2ecf20Sopenharmony_ci		ret = -ENODEV;
62248c2ecf20Sopenharmony_ci		goto error_2;
62258c2ecf20Sopenharmony_ci	}
62268c2ecf20Sopenharmony_ci
62278c2ecf20Sopenharmony_ci	ivideo->video_vbase = ioremap_wc(ivideo->video_base, ivideo->video_size);
62288c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
62298c2ecf20Sopenharmony_ci	if(!ivideo->video_vbase) {
62308c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
62318c2ecf20Sopenharmony_ci		ret = -ENODEV;
62328c2ecf20Sopenharmony_ci		goto error_1;
62338c2ecf20Sopenharmony_ci	}
62348c2ecf20Sopenharmony_ci
62358c2ecf20Sopenharmony_ci	ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
62368c2ecf20Sopenharmony_ci	if(!ivideo->mmio_vbase) {
62378c2ecf20Sopenharmony_ci		printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
62388c2ecf20Sopenharmony_ci		ret = -ENODEV;
62398c2ecf20Sopenharmony_cierror_0:	iounmap(ivideo->video_vbase);
62408c2ecf20Sopenharmony_cierror_1:	release_mem_region(ivideo->video_base, ivideo->video_size);
62418c2ecf20Sopenharmony_cierror_2:	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
62428c2ecf20Sopenharmony_cierror_3:	vfree(ivideo->bios_abase);
62438c2ecf20Sopenharmony_ci		pci_dev_put(ivideo->lpcdev);
62448c2ecf20Sopenharmony_ci		pci_dev_put(ivideo->nbridge);
62458c2ecf20Sopenharmony_ci		if(!ivideo->sisvga_enabled)
62468c2ecf20Sopenharmony_ci			pci_disable_device(pdev);
62478c2ecf20Sopenharmony_ci		framebuffer_release(sis_fb_info);
62488c2ecf20Sopenharmony_ci		return ret;
62498c2ecf20Sopenharmony_ci	}
62508c2ecf20Sopenharmony_ci
62518c2ecf20Sopenharmony_ci	printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
62528c2ecf20Sopenharmony_ci		ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
62538c2ecf20Sopenharmony_ci
62548c2ecf20Sopenharmony_ci	if(ivideo->video_offset) {
62558c2ecf20Sopenharmony_ci		printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
62568c2ecf20Sopenharmony_ci			ivideo->video_offset / 1024);
62578c2ecf20Sopenharmony_ci	}
62588c2ecf20Sopenharmony_ci
62598c2ecf20Sopenharmony_ci	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
62608c2ecf20Sopenharmony_ci		ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
62618c2ecf20Sopenharmony_ci
62628c2ecf20Sopenharmony_ci
62638c2ecf20Sopenharmony_ci	/* Determine the size of the command queue */
62648c2ecf20Sopenharmony_ci	if(ivideo->sisvga_engine == SIS_300_VGA) {
62658c2ecf20Sopenharmony_ci		ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
62668c2ecf20Sopenharmony_ci	} else {
62678c2ecf20Sopenharmony_ci		if(ivideo->chip == XGI_20) {
62688c2ecf20Sopenharmony_ci			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
62698c2ecf20Sopenharmony_ci		} else {
62708c2ecf20Sopenharmony_ci			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
62718c2ecf20Sopenharmony_ci		}
62728c2ecf20Sopenharmony_ci	}
62738c2ecf20Sopenharmony_ci
62748c2ecf20Sopenharmony_ci	/* Engines are no longer initialized here; this is
62758c2ecf20Sopenharmony_ci	 * now done after the first mode-switch (if the
62768c2ecf20Sopenharmony_ci	 * submitted var has its acceleration flags set).
62778c2ecf20Sopenharmony_ci	 */
62788c2ecf20Sopenharmony_ci
62798c2ecf20Sopenharmony_ci	/* Calculate the base of the (unused) hw cursor */
62808c2ecf20Sopenharmony_ci	ivideo->hwcursor_vbase = ivideo->video_vbase
62818c2ecf20Sopenharmony_ci				 + ivideo->video_size
62828c2ecf20Sopenharmony_ci				 - ivideo->cmdQueueSize
62838c2ecf20Sopenharmony_ci				 - ivideo->hwcursor_size;
62848c2ecf20Sopenharmony_ci	ivideo->caps |= HW_CURSOR_CAP;
62858c2ecf20Sopenharmony_ci
62868c2ecf20Sopenharmony_ci	/* Initialize offscreen memory manager */
62878c2ecf20Sopenharmony_ci	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
62888c2ecf20Sopenharmony_ci		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
62898c2ecf20Sopenharmony_ci	}
62908c2ecf20Sopenharmony_ci
62918c2ecf20Sopenharmony_ci	/* Used for clearing the screen only, therefore respect our mem limit */
62928c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
62938c2ecf20Sopenharmony_ci	ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
62948c2ecf20Sopenharmony_ci
62958c2ecf20Sopenharmony_ci	ivideo->vbflags = 0;
62968c2ecf20Sopenharmony_ci	ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
62978c2ecf20Sopenharmony_ci	ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
62988c2ecf20Sopenharmony_ci	ivideo->defmodeidx    = DEFAULT_MODE;
62998c2ecf20Sopenharmony_ci
63008c2ecf20Sopenharmony_ci	ivideo->newrom = 0;
63018c2ecf20Sopenharmony_ci	if(ivideo->chip < XGI_20) {
63028c2ecf20Sopenharmony_ci		if(ivideo->bios_abase) {
63038c2ecf20Sopenharmony_ci			ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
63048c2ecf20Sopenharmony_ci		}
63058c2ecf20Sopenharmony_ci	}
63068c2ecf20Sopenharmony_ci
63078c2ecf20Sopenharmony_ci	if((ivideo->sisfb_mode_idx < 0) ||
63088c2ecf20Sopenharmony_ci	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
63098c2ecf20Sopenharmony_ci
63108c2ecf20Sopenharmony_ci		sisfb_sense_crt1(ivideo);
63118c2ecf20Sopenharmony_ci
63128c2ecf20Sopenharmony_ci		sisfb_get_VB_type(ivideo);
63138c2ecf20Sopenharmony_ci
63148c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
63158c2ecf20Sopenharmony_ci			sisfb_detect_VB_connect(ivideo);
63168c2ecf20Sopenharmony_ci		}
63178c2ecf20Sopenharmony_ci
63188c2ecf20Sopenharmony_ci		ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
63198c2ecf20Sopenharmony_ci
63208c2ecf20Sopenharmony_ci		/* Decide on which CRT2 device to use */
63218c2ecf20Sopenharmony_ci		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
63228c2ecf20Sopenharmony_ci			if(ivideo->sisfb_crt2type != -1) {
63238c2ecf20Sopenharmony_ci				if((ivideo->sisfb_crt2type == CRT2_LCD) &&
63248c2ecf20Sopenharmony_ci				   (ivideo->vbflags & CRT2_LCD)) {
63258c2ecf20Sopenharmony_ci					ivideo->currentvbflags |= CRT2_LCD;
63268c2ecf20Sopenharmony_ci				} else if(ivideo->sisfb_crt2type != CRT2_LCD) {
63278c2ecf20Sopenharmony_ci					ivideo->currentvbflags |= ivideo->sisfb_crt2type;
63288c2ecf20Sopenharmony_ci				}
63298c2ecf20Sopenharmony_ci			} else {
63308c2ecf20Sopenharmony_ci				/* Chrontel 700x TV detection often unreliable, therefore
63318c2ecf20Sopenharmony_ci				 * use a different default order on such machines
63328c2ecf20Sopenharmony_ci				 */
63338c2ecf20Sopenharmony_ci				if((ivideo->sisvga_engine == SIS_300_VGA) &&
63348c2ecf20Sopenharmony_ci				   (ivideo->vbflags2 & VB2_CHRONTEL)) {
63358c2ecf20Sopenharmony_ci					if(ivideo->vbflags & CRT2_LCD)
63368c2ecf20Sopenharmony_ci						ivideo->currentvbflags |= CRT2_LCD;
63378c2ecf20Sopenharmony_ci					else if(ivideo->vbflags & CRT2_TV)
63388c2ecf20Sopenharmony_ci						ivideo->currentvbflags |= CRT2_TV;
63398c2ecf20Sopenharmony_ci					else if(ivideo->vbflags & CRT2_VGA)
63408c2ecf20Sopenharmony_ci						ivideo->currentvbflags |= CRT2_VGA;
63418c2ecf20Sopenharmony_ci				} else {
63428c2ecf20Sopenharmony_ci					if(ivideo->vbflags & CRT2_TV)
63438c2ecf20Sopenharmony_ci						ivideo->currentvbflags |= CRT2_TV;
63448c2ecf20Sopenharmony_ci					else if(ivideo->vbflags & CRT2_LCD)
63458c2ecf20Sopenharmony_ci						ivideo->currentvbflags |= CRT2_LCD;
63468c2ecf20Sopenharmony_ci					else if(ivideo->vbflags & CRT2_VGA)
63478c2ecf20Sopenharmony_ci						ivideo->currentvbflags |= CRT2_VGA;
63488c2ecf20Sopenharmony_ci				}
63498c2ecf20Sopenharmony_ci			}
63508c2ecf20Sopenharmony_ci		}
63518c2ecf20Sopenharmony_ci
63528c2ecf20Sopenharmony_ci		if(ivideo->vbflags & CRT2_LCD) {
63538c2ecf20Sopenharmony_ci			sisfb_detect_lcd_type(ivideo);
63548c2ecf20Sopenharmony_ci		}
63558c2ecf20Sopenharmony_ci
63568c2ecf20Sopenharmony_ci		sisfb_save_pdc_emi(ivideo);
63578c2ecf20Sopenharmony_ci
63588c2ecf20Sopenharmony_ci		if(!ivideo->sisfb_crt1off) {
63598c2ecf20Sopenharmony_ci			sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
63608c2ecf20Sopenharmony_ci		} else {
63618c2ecf20Sopenharmony_ci			if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
63628c2ecf20Sopenharmony_ci			   (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
63638c2ecf20Sopenharmony_ci				sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
63648c2ecf20Sopenharmony_ci			}
63658c2ecf20Sopenharmony_ci		}
63668c2ecf20Sopenharmony_ci
63678c2ecf20Sopenharmony_ci		if(ivideo->sisfb_mode_idx >= 0) {
63688c2ecf20Sopenharmony_ci			int bu = ivideo->sisfb_mode_idx;
63698c2ecf20Sopenharmony_ci			ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
63708c2ecf20Sopenharmony_ci					ivideo->sisfb_mode_idx, ivideo->currentvbflags);
63718c2ecf20Sopenharmony_ci			if(bu != ivideo->sisfb_mode_idx) {
63728c2ecf20Sopenharmony_ci				printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
63738c2ecf20Sopenharmony_ci					sisbios_mode[bu].xres,
63748c2ecf20Sopenharmony_ci					sisbios_mode[bu].yres,
63758c2ecf20Sopenharmony_ci					sisbios_mode[bu].bpp);
63768c2ecf20Sopenharmony_ci			}
63778c2ecf20Sopenharmony_ci		}
63788c2ecf20Sopenharmony_ci
63798c2ecf20Sopenharmony_ci		if(ivideo->sisfb_mode_idx < 0) {
63808c2ecf20Sopenharmony_ci			switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
63818c2ecf20Sopenharmony_ci			   case CRT2_LCD:
63828c2ecf20Sopenharmony_ci				ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
63838c2ecf20Sopenharmony_ci				break;
63848c2ecf20Sopenharmony_ci			   case CRT2_TV:
63858c2ecf20Sopenharmony_ci				ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
63868c2ecf20Sopenharmony_ci				break;
63878c2ecf20Sopenharmony_ci			   default:
63888c2ecf20Sopenharmony_ci				ivideo->sisfb_mode_idx = ivideo->defmodeidx;
63898c2ecf20Sopenharmony_ci				break;
63908c2ecf20Sopenharmony_ci			}
63918c2ecf20Sopenharmony_ci		}
63928c2ecf20Sopenharmony_ci
63938c2ecf20Sopenharmony_ci		ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
63948c2ecf20Sopenharmony_ci
63958c2ecf20Sopenharmony_ci		if(ivideo->refresh_rate != 0) {
63968c2ecf20Sopenharmony_ci			sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
63978c2ecf20Sopenharmony_ci						ivideo->sisfb_mode_idx);
63988c2ecf20Sopenharmony_ci		}
63998c2ecf20Sopenharmony_ci
64008c2ecf20Sopenharmony_ci		if(ivideo->rate_idx == 0) {
64018c2ecf20Sopenharmony_ci			ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
64028c2ecf20Sopenharmony_ci			ivideo->refresh_rate = 60;
64038c2ecf20Sopenharmony_ci		}
64048c2ecf20Sopenharmony_ci
64058c2ecf20Sopenharmony_ci		if(ivideo->sisfb_thismonitor.datavalid) {
64068c2ecf20Sopenharmony_ci			if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
64078c2ecf20Sopenharmony_ci						ivideo->sisfb_mode_idx,
64088c2ecf20Sopenharmony_ci						ivideo->rate_idx,
64098c2ecf20Sopenharmony_ci						ivideo->refresh_rate)) {
64108c2ecf20Sopenharmony_ci				printk(KERN_INFO "sisfb: WARNING: Refresh rate "
64118c2ecf20Sopenharmony_ci							"exceeds monitor specs!\n");
64128c2ecf20Sopenharmony_ci			}
64138c2ecf20Sopenharmony_ci		}
64148c2ecf20Sopenharmony_ci
64158c2ecf20Sopenharmony_ci		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
64168c2ecf20Sopenharmony_ci		ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
64178c2ecf20Sopenharmony_ci		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
64188c2ecf20Sopenharmony_ci
64198c2ecf20Sopenharmony_ci		sisfb_set_vparms(ivideo);
64208c2ecf20Sopenharmony_ci
64218c2ecf20Sopenharmony_ci		printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
64228c2ecf20Sopenharmony_ci			ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
64238c2ecf20Sopenharmony_ci			ivideo->refresh_rate);
64248c2ecf20Sopenharmony_ci
64258c2ecf20Sopenharmony_ci		/* Set up the default var according to chosen default display mode */
64268c2ecf20Sopenharmony_ci		ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
64278c2ecf20Sopenharmony_ci		ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
64288c2ecf20Sopenharmony_ci		ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
64298c2ecf20Sopenharmony_ci
64308c2ecf20Sopenharmony_ci		sisfb_bpp_to_var(ivideo, &ivideo->default_var);
64318c2ecf20Sopenharmony_ci
64328c2ecf20Sopenharmony_ci		ivideo->default_var.pixclock = (u32) (1000000000 /
64338c2ecf20Sopenharmony_ci			sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
64348c2ecf20Sopenharmony_ci
64358c2ecf20Sopenharmony_ci		if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
64368c2ecf20Sopenharmony_ci						ivideo->rate_idx, &ivideo->default_var)) {
64378c2ecf20Sopenharmony_ci			if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
64388c2ecf20Sopenharmony_ci				ivideo->default_var.pixclock <<= 1;
64398c2ecf20Sopenharmony_ci			}
64408c2ecf20Sopenharmony_ci		}
64418c2ecf20Sopenharmony_ci
64428c2ecf20Sopenharmony_ci		if(ivideo->sisfb_ypan) {
64438c2ecf20Sopenharmony_ci			/* Maximize regardless of sisfb_max at startup */
64448c2ecf20Sopenharmony_ci			ivideo->default_var.yres_virtual =
64458c2ecf20Sopenharmony_ci				sisfb_calc_maxyres(ivideo, &ivideo->default_var);
64468c2ecf20Sopenharmony_ci			if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
64478c2ecf20Sopenharmony_ci				ivideo->default_var.yres_virtual = ivideo->default_var.yres;
64488c2ecf20Sopenharmony_ci			}
64498c2ecf20Sopenharmony_ci		}
64508c2ecf20Sopenharmony_ci
64518c2ecf20Sopenharmony_ci		sisfb_calc_pitch(ivideo, &ivideo->default_var);
64528c2ecf20Sopenharmony_ci
64538c2ecf20Sopenharmony_ci		ivideo->accel = 0;
64548c2ecf20Sopenharmony_ci		if(ivideo->sisfb_accel) {
64558c2ecf20Sopenharmony_ci			ivideo->accel = -1;
64568c2ecf20Sopenharmony_ci#ifdef STUPID_ACCELF_TEXT_SHIT
64578c2ecf20Sopenharmony_ci			ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
64588c2ecf20Sopenharmony_ci#endif
64598c2ecf20Sopenharmony_ci		}
64608c2ecf20Sopenharmony_ci		sisfb_initaccel(ivideo);
64618c2ecf20Sopenharmony_ci
64628c2ecf20Sopenharmony_ci#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
64638c2ecf20Sopenharmony_ci		sis_fb_info->flags = FBINFO_DEFAULT 		|
64648c2ecf20Sopenharmony_ci				     FBINFO_HWACCEL_YPAN 	|
64658c2ecf20Sopenharmony_ci				     FBINFO_HWACCEL_XPAN 	|
64668c2ecf20Sopenharmony_ci				     FBINFO_HWACCEL_COPYAREA 	|
64678c2ecf20Sopenharmony_ci				     FBINFO_HWACCEL_FILLRECT 	|
64688c2ecf20Sopenharmony_ci				     ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
64698c2ecf20Sopenharmony_ci#else
64708c2ecf20Sopenharmony_ci		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
64718c2ecf20Sopenharmony_ci#endif
64728c2ecf20Sopenharmony_ci		sis_fb_info->var = ivideo->default_var;
64738c2ecf20Sopenharmony_ci		sis_fb_info->fix = ivideo->sisfb_fix;
64748c2ecf20Sopenharmony_ci		sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
64758c2ecf20Sopenharmony_ci		sis_fb_info->fbops = &sisfb_ops;
64768c2ecf20Sopenharmony_ci		sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
64778c2ecf20Sopenharmony_ci
64788c2ecf20Sopenharmony_ci		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
64798c2ecf20Sopenharmony_ci
64808c2ecf20Sopenharmony_ci		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
64818c2ecf20Sopenharmony_ci
64828c2ecf20Sopenharmony_ci		ivideo->wc_cookie = arch_phys_wc_add(ivideo->video_base,
64838c2ecf20Sopenharmony_ci						     ivideo->video_size);
64848c2ecf20Sopenharmony_ci		if(register_framebuffer(sis_fb_info) < 0) {
64858c2ecf20Sopenharmony_ci			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
64868c2ecf20Sopenharmony_ci			ret = -EINVAL;
64878c2ecf20Sopenharmony_ci			iounmap(ivideo->mmio_vbase);
64888c2ecf20Sopenharmony_ci			goto error_0;
64898c2ecf20Sopenharmony_ci		}
64908c2ecf20Sopenharmony_ci
64918c2ecf20Sopenharmony_ci		ivideo->registered = 1;
64928c2ecf20Sopenharmony_ci
64938c2ecf20Sopenharmony_ci		/* Enlist us */
64948c2ecf20Sopenharmony_ci		ivideo->next = card_list;
64958c2ecf20Sopenharmony_ci		card_list = ivideo;
64968c2ecf20Sopenharmony_ci
64978c2ecf20Sopenharmony_ci		printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
64988c2ecf20Sopenharmony_ci			ivideo->sisfb_accel ? "enabled" : "disabled",
64998c2ecf20Sopenharmony_ci			ivideo->sisfb_ypan  ?
65008c2ecf20Sopenharmony_ci				(ivideo->sisfb_max ? "enabled (auto-max)" :
65018c2ecf20Sopenharmony_ci						"enabled (no auto-max)") :
65028c2ecf20Sopenharmony_ci									"disabled");
65038c2ecf20Sopenharmony_ci
65048c2ecf20Sopenharmony_ci
65058c2ecf20Sopenharmony_ci		fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
65068c2ecf20Sopenharmony_ci			ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
65078c2ecf20Sopenharmony_ci
65088c2ecf20Sopenharmony_ci		printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
65098c2ecf20Sopenharmony_ci
65108c2ecf20Sopenharmony_ci	}	/* if mode = "none" */
65118c2ecf20Sopenharmony_ci
65128c2ecf20Sopenharmony_ci	return 0;
65138c2ecf20Sopenharmony_ci}
65148c2ecf20Sopenharmony_ci
65158c2ecf20Sopenharmony_ci/*****************************************************/
65168c2ecf20Sopenharmony_ci/*                PCI DEVICE HANDLING                */
65178c2ecf20Sopenharmony_ci/*****************************************************/
65188c2ecf20Sopenharmony_ci
65198c2ecf20Sopenharmony_cistatic void sisfb_remove(struct pci_dev *pdev)
65208c2ecf20Sopenharmony_ci{
65218c2ecf20Sopenharmony_ci	struct sis_video_info	*ivideo = pci_get_drvdata(pdev);
65228c2ecf20Sopenharmony_ci	struct fb_info		*sis_fb_info = ivideo->memyselfandi;
65238c2ecf20Sopenharmony_ci	int			registered = ivideo->registered;
65248c2ecf20Sopenharmony_ci	int			modechanged = ivideo->modechanged;
65258c2ecf20Sopenharmony_ci
65268c2ecf20Sopenharmony_ci	/* Unmap */
65278c2ecf20Sopenharmony_ci	iounmap(ivideo->mmio_vbase);
65288c2ecf20Sopenharmony_ci	iounmap(ivideo->video_vbase);
65298c2ecf20Sopenharmony_ci
65308c2ecf20Sopenharmony_ci	/* Release mem regions */
65318c2ecf20Sopenharmony_ci	release_mem_region(ivideo->video_base, ivideo->video_size);
65328c2ecf20Sopenharmony_ci	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
65338c2ecf20Sopenharmony_ci
65348c2ecf20Sopenharmony_ci	vfree(ivideo->bios_abase);
65358c2ecf20Sopenharmony_ci
65368c2ecf20Sopenharmony_ci	pci_dev_put(ivideo->lpcdev);
65378c2ecf20Sopenharmony_ci
65388c2ecf20Sopenharmony_ci	pci_dev_put(ivideo->nbridge);
65398c2ecf20Sopenharmony_ci
65408c2ecf20Sopenharmony_ci	arch_phys_wc_del(ivideo->wc_cookie);
65418c2ecf20Sopenharmony_ci
65428c2ecf20Sopenharmony_ci	/* If device was disabled when starting, disable
65438c2ecf20Sopenharmony_ci	 * it when quitting.
65448c2ecf20Sopenharmony_ci	 */
65458c2ecf20Sopenharmony_ci	if(!ivideo->sisvga_enabled)
65468c2ecf20Sopenharmony_ci		pci_disable_device(pdev);
65478c2ecf20Sopenharmony_ci
65488c2ecf20Sopenharmony_ci	/* Unregister the framebuffer */
65498c2ecf20Sopenharmony_ci	if(ivideo->registered) {
65508c2ecf20Sopenharmony_ci		unregister_framebuffer(sis_fb_info);
65518c2ecf20Sopenharmony_ci		framebuffer_release(sis_fb_info);
65528c2ecf20Sopenharmony_ci	}
65538c2ecf20Sopenharmony_ci
65548c2ecf20Sopenharmony_ci	/* OK, our ivideo is gone for good from here. */
65558c2ecf20Sopenharmony_ci
65568c2ecf20Sopenharmony_ci	/* TODO: Restore the initial mode
65578c2ecf20Sopenharmony_ci	 * This sounds easy but is as good as impossible
65588c2ecf20Sopenharmony_ci	 * on many machines with SiS chip and video bridge
65598c2ecf20Sopenharmony_ci	 * since text modes are always set up differently
65608c2ecf20Sopenharmony_ci	 * from machine to machine. Depends on the type
65618c2ecf20Sopenharmony_ci	 * of integration between chipset and bridge.
65628c2ecf20Sopenharmony_ci	 */
65638c2ecf20Sopenharmony_ci	if(registered && modechanged)
65648c2ecf20Sopenharmony_ci		printk(KERN_INFO
65658c2ecf20Sopenharmony_ci			"sisfb: Restoring of text mode not supported yet\n");
65668c2ecf20Sopenharmony_ci};
65678c2ecf20Sopenharmony_ci
65688c2ecf20Sopenharmony_cistatic struct pci_driver sisfb_driver = {
65698c2ecf20Sopenharmony_ci	.name		= "sisfb",
65708c2ecf20Sopenharmony_ci	.id_table 	= sisfb_pci_table,
65718c2ecf20Sopenharmony_ci	.probe		= sisfb_probe,
65728c2ecf20Sopenharmony_ci	.remove 	= sisfb_remove,
65738c2ecf20Sopenharmony_ci};
65748c2ecf20Sopenharmony_ci
65758c2ecf20Sopenharmony_cistatic int __init sisfb_init(void)
65768c2ecf20Sopenharmony_ci{
65778c2ecf20Sopenharmony_ci#ifndef MODULE
65788c2ecf20Sopenharmony_ci	char *options = NULL;
65798c2ecf20Sopenharmony_ci
65808c2ecf20Sopenharmony_ci	if(fb_get_options("sisfb", &options))
65818c2ecf20Sopenharmony_ci		return -ENODEV;
65828c2ecf20Sopenharmony_ci
65838c2ecf20Sopenharmony_ci	sisfb_setup(options);
65848c2ecf20Sopenharmony_ci#endif
65858c2ecf20Sopenharmony_ci	return pci_register_driver(&sisfb_driver);
65868c2ecf20Sopenharmony_ci}
65878c2ecf20Sopenharmony_ci
65888c2ecf20Sopenharmony_ci#ifndef MODULE
65898c2ecf20Sopenharmony_cimodule_init(sisfb_init);
65908c2ecf20Sopenharmony_ci#endif
65918c2ecf20Sopenharmony_ci
65928c2ecf20Sopenharmony_ci/*****************************************************/
65938c2ecf20Sopenharmony_ci/*                      MODULE                       */
65948c2ecf20Sopenharmony_ci/*****************************************************/
65958c2ecf20Sopenharmony_ci
65968c2ecf20Sopenharmony_ci#ifdef MODULE
65978c2ecf20Sopenharmony_ci
65988c2ecf20Sopenharmony_cistatic char		*mode = NULL;
65998c2ecf20Sopenharmony_cistatic int		vesa = -1;
66008c2ecf20Sopenharmony_cistatic unsigned int	rate = 0;
66018c2ecf20Sopenharmony_cistatic unsigned int	crt1off = 1;
66028c2ecf20Sopenharmony_cistatic unsigned int	mem = 0;
66038c2ecf20Sopenharmony_cistatic char		*forcecrt2type = NULL;
66048c2ecf20Sopenharmony_cistatic int		forcecrt1 = -1;
66058c2ecf20Sopenharmony_cistatic int		pdc = -1;
66068c2ecf20Sopenharmony_cistatic int		pdc1 = -1;
66078c2ecf20Sopenharmony_cistatic int		noaccel = -1;
66088c2ecf20Sopenharmony_cistatic int		noypan  = -1;
66098c2ecf20Sopenharmony_cistatic int		nomax = -1;
66108c2ecf20Sopenharmony_cistatic int		userom = -1;
66118c2ecf20Sopenharmony_cistatic int		useoem = -1;
66128c2ecf20Sopenharmony_cistatic char		*tvstandard = NULL;
66138c2ecf20Sopenharmony_cistatic int		nocrt2rate = 0;
66148c2ecf20Sopenharmony_cistatic int		scalelcd = -1;
66158c2ecf20Sopenharmony_cistatic char		*specialtiming = NULL;
66168c2ecf20Sopenharmony_cistatic int		lvdshl = -1;
66178c2ecf20Sopenharmony_cistatic int		tvxposoffset = 0, tvyposoffset = 0;
66188c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
66198c2ecf20Sopenharmony_cistatic int		resetcard = 0;
66208c2ecf20Sopenharmony_cistatic int		videoram = 0;
66218c2ecf20Sopenharmony_ci#endif
66228c2ecf20Sopenharmony_ci
66238c2ecf20Sopenharmony_cistatic int __init sisfb_init_module(void)
66248c2ecf20Sopenharmony_ci{
66258c2ecf20Sopenharmony_ci	sisfb_setdefaultparms();
66268c2ecf20Sopenharmony_ci
66278c2ecf20Sopenharmony_ci	if(rate)
66288c2ecf20Sopenharmony_ci		sisfb_parm_rate = rate;
66298c2ecf20Sopenharmony_ci
66308c2ecf20Sopenharmony_ci	if((scalelcd == 0) || (scalelcd == 1))
66318c2ecf20Sopenharmony_ci		sisfb_scalelcd = scalelcd ^ 1;
66328c2ecf20Sopenharmony_ci
66338c2ecf20Sopenharmony_ci	/* Need to check crt2 type first for fstn/dstn */
66348c2ecf20Sopenharmony_ci
66358c2ecf20Sopenharmony_ci	if(forcecrt2type)
66368c2ecf20Sopenharmony_ci		sisfb_search_crt2type(forcecrt2type);
66378c2ecf20Sopenharmony_ci
66388c2ecf20Sopenharmony_ci	if(tvstandard)
66398c2ecf20Sopenharmony_ci		sisfb_search_tvstd(tvstandard);
66408c2ecf20Sopenharmony_ci
66418c2ecf20Sopenharmony_ci	if(mode)
66428c2ecf20Sopenharmony_ci		sisfb_search_mode(mode, false);
66438c2ecf20Sopenharmony_ci	else if(vesa != -1)
66448c2ecf20Sopenharmony_ci		sisfb_search_vesamode(vesa, false);
66458c2ecf20Sopenharmony_ci
66468c2ecf20Sopenharmony_ci	sisfb_crt1off = (crt1off == 0) ? 1 : 0;
66478c2ecf20Sopenharmony_ci
66488c2ecf20Sopenharmony_ci	sisfb_forcecrt1 = forcecrt1;
66498c2ecf20Sopenharmony_ci	if(forcecrt1 == 1)
66508c2ecf20Sopenharmony_ci		sisfb_crt1off = 0;
66518c2ecf20Sopenharmony_ci	else if(forcecrt1 == 0)
66528c2ecf20Sopenharmony_ci		sisfb_crt1off = 1;
66538c2ecf20Sopenharmony_ci
66548c2ecf20Sopenharmony_ci	if(noaccel == 1)
66558c2ecf20Sopenharmony_ci		sisfb_accel = 0;
66568c2ecf20Sopenharmony_ci	else if(noaccel == 0)
66578c2ecf20Sopenharmony_ci		sisfb_accel = 1;
66588c2ecf20Sopenharmony_ci
66598c2ecf20Sopenharmony_ci	if(noypan == 1)
66608c2ecf20Sopenharmony_ci		sisfb_ypan = 0;
66618c2ecf20Sopenharmony_ci	else if(noypan == 0)
66628c2ecf20Sopenharmony_ci		sisfb_ypan = 1;
66638c2ecf20Sopenharmony_ci
66648c2ecf20Sopenharmony_ci	if(nomax == 1)
66658c2ecf20Sopenharmony_ci		sisfb_max = 0;
66668c2ecf20Sopenharmony_ci	else if(nomax == 0)
66678c2ecf20Sopenharmony_ci		sisfb_max = 1;
66688c2ecf20Sopenharmony_ci
66698c2ecf20Sopenharmony_ci	if(mem)
66708c2ecf20Sopenharmony_ci		sisfb_parm_mem = mem;
66718c2ecf20Sopenharmony_ci
66728c2ecf20Sopenharmony_ci	if(userom != -1)
66738c2ecf20Sopenharmony_ci		sisfb_userom = userom;
66748c2ecf20Sopenharmony_ci
66758c2ecf20Sopenharmony_ci	if(useoem != -1)
66768c2ecf20Sopenharmony_ci		sisfb_useoem = useoem;
66778c2ecf20Sopenharmony_ci
66788c2ecf20Sopenharmony_ci        if(pdc != -1)
66798c2ecf20Sopenharmony_ci		sisfb_pdc  = (pdc  & 0x7f);
66808c2ecf20Sopenharmony_ci
66818c2ecf20Sopenharmony_ci	if(pdc1 != -1)
66828c2ecf20Sopenharmony_ci		sisfb_pdca = (pdc1 & 0x1f);
66838c2ecf20Sopenharmony_ci
66848c2ecf20Sopenharmony_ci	sisfb_nocrt2rate = nocrt2rate;
66858c2ecf20Sopenharmony_ci
66868c2ecf20Sopenharmony_ci	if(specialtiming)
66878c2ecf20Sopenharmony_ci		sisfb_search_specialtiming(specialtiming);
66888c2ecf20Sopenharmony_ci
66898c2ecf20Sopenharmony_ci	if((lvdshl >= 0) && (lvdshl <= 3))
66908c2ecf20Sopenharmony_ci		sisfb_lvdshl = lvdshl;
66918c2ecf20Sopenharmony_ci
66928c2ecf20Sopenharmony_ci	sisfb_tvxposoffset = tvxposoffset;
66938c2ecf20Sopenharmony_ci	sisfb_tvyposoffset = tvyposoffset;
66948c2ecf20Sopenharmony_ci
66958c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
66968c2ecf20Sopenharmony_ci	sisfb_resetcard = (resetcard) ? 1 : 0;
66978c2ecf20Sopenharmony_ci	if(videoram)
66988c2ecf20Sopenharmony_ci		sisfb_videoram = videoram;
66998c2ecf20Sopenharmony_ci#endif
67008c2ecf20Sopenharmony_ci
67018c2ecf20Sopenharmony_ci	return sisfb_init();
67028c2ecf20Sopenharmony_ci}
67038c2ecf20Sopenharmony_ci
67048c2ecf20Sopenharmony_cistatic void __exit sisfb_remove_module(void)
67058c2ecf20Sopenharmony_ci{
67068c2ecf20Sopenharmony_ci	pci_unregister_driver(&sisfb_driver);
67078c2ecf20Sopenharmony_ci	printk(KERN_DEBUG "sisfb: Module unloaded\n");
67088c2ecf20Sopenharmony_ci}
67098c2ecf20Sopenharmony_ci
67108c2ecf20Sopenharmony_cimodule_init(sisfb_init_module);
67118c2ecf20Sopenharmony_cimodule_exit(sisfb_remove_module);
67128c2ecf20Sopenharmony_ci
67138c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
67148c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
67158c2ecf20Sopenharmony_ciMODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
67168c2ecf20Sopenharmony_ci
67178c2ecf20Sopenharmony_cimodule_param(mem, int, 0);
67188c2ecf20Sopenharmony_cimodule_param(noaccel, int, 0);
67198c2ecf20Sopenharmony_cimodule_param(noypan, int, 0);
67208c2ecf20Sopenharmony_cimodule_param(nomax, int, 0);
67218c2ecf20Sopenharmony_cimodule_param(userom, int, 0);
67228c2ecf20Sopenharmony_cimodule_param(useoem, int, 0);
67238c2ecf20Sopenharmony_cimodule_param(mode, charp, 0);
67248c2ecf20Sopenharmony_cimodule_param(vesa, int, 0);
67258c2ecf20Sopenharmony_cimodule_param(rate, int, 0);
67268c2ecf20Sopenharmony_cimodule_param(forcecrt1, int, 0);
67278c2ecf20Sopenharmony_cimodule_param(forcecrt2type, charp, 0);
67288c2ecf20Sopenharmony_cimodule_param(scalelcd, int, 0);
67298c2ecf20Sopenharmony_cimodule_param(pdc, int, 0);
67308c2ecf20Sopenharmony_cimodule_param(pdc1, int, 0);
67318c2ecf20Sopenharmony_cimodule_param(specialtiming, charp, 0);
67328c2ecf20Sopenharmony_cimodule_param(lvdshl, int, 0);
67338c2ecf20Sopenharmony_cimodule_param(tvstandard, charp, 0);
67348c2ecf20Sopenharmony_cimodule_param(tvxposoffset, int, 0);
67358c2ecf20Sopenharmony_cimodule_param(tvyposoffset, int, 0);
67368c2ecf20Sopenharmony_cimodule_param(nocrt2rate, int, 0);
67378c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
67388c2ecf20Sopenharmony_cimodule_param(resetcard, int, 0);
67398c2ecf20Sopenharmony_cimodule_param(videoram, int, 0);
67408c2ecf20Sopenharmony_ci#endif
67418c2ecf20Sopenharmony_ci
67428c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mem,
67438c2ecf20Sopenharmony_ci	"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
67448c2ecf20Sopenharmony_ci	  "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
67458c2ecf20Sopenharmony_ci	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
67468c2ecf20Sopenharmony_ci	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
67478c2ecf20Sopenharmony_ci	  "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
67488c2ecf20Sopenharmony_ci	  "The value is to be specified without 'KB'.\n");
67498c2ecf20Sopenharmony_ci
67508c2ecf20Sopenharmony_ciMODULE_PARM_DESC(noaccel,
67518c2ecf20Sopenharmony_ci	"\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
67528c2ecf20Sopenharmony_ci	  "(default: 0)\n");
67538c2ecf20Sopenharmony_ci
67548c2ecf20Sopenharmony_ciMODULE_PARM_DESC(noypan,
67558c2ecf20Sopenharmony_ci	"\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
67568c2ecf20Sopenharmony_ci	  "will be performed by redrawing the screen. (default: 0)\n");
67578c2ecf20Sopenharmony_ci
67588c2ecf20Sopenharmony_ciMODULE_PARM_DESC(nomax,
67598c2ecf20Sopenharmony_ci	"\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
67608c2ecf20Sopenharmony_ci	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
67618c2ecf20Sopenharmony_ci	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
67628c2ecf20Sopenharmony_ci	  "enable the user to positively specify a virtual Y size of the screen using\n"
67638c2ecf20Sopenharmony_ci	  "fbset. (default: 0)\n");
67648c2ecf20Sopenharmony_ci
67658c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mode,
67668c2ecf20Sopenharmony_ci	"\nSelects the desired default display mode in the format XxYxDepth,\n"
67678c2ecf20Sopenharmony_ci	 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
67688c2ecf20Sopenharmony_ci	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
67698c2ecf20Sopenharmony_ci	 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
67708c2ecf20Sopenharmony_ci
67718c2ecf20Sopenharmony_ciMODULE_PARM_DESC(vesa,
67728c2ecf20Sopenharmony_ci	"\nSelects the desired default display mode by VESA defined mode number, eg.\n"
67738c2ecf20Sopenharmony_ci	 "0x117 (default: 0x0103)\n");
67748c2ecf20Sopenharmony_ci
67758c2ecf20Sopenharmony_ciMODULE_PARM_DESC(rate,
67768c2ecf20Sopenharmony_ci	"\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
67778c2ecf20Sopenharmony_ci	  "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
67788c2ecf20Sopenharmony_ci	  "will be ignored (default: 60)\n");
67798c2ecf20Sopenharmony_ci
67808c2ecf20Sopenharmony_ciMODULE_PARM_DESC(forcecrt1,
67818c2ecf20Sopenharmony_ci	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
67828c2ecf20Sopenharmony_ci	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
67838c2ecf20Sopenharmony_ci	  "0=CRT1 OFF) (default: [autodetected])\n");
67848c2ecf20Sopenharmony_ci
67858c2ecf20Sopenharmony_ciMODULE_PARM_DESC(forcecrt2type,
67868c2ecf20Sopenharmony_ci	"\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
67878c2ecf20Sopenharmony_ci	  "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
67888c2ecf20Sopenharmony_ci	  "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
67898c2ecf20Sopenharmony_ci	  "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
67908c2ecf20Sopenharmony_ci	  "be used instead of TV to override the TV detection. Furthermore, on systems\n"
67918c2ecf20Sopenharmony_ci	  "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
67928c2ecf20Sopenharmony_ci	  "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
67938c2ecf20Sopenharmony_ci	  "depends on the very hardware in use. (default: [autodetected])\n");
67948c2ecf20Sopenharmony_ci
67958c2ecf20Sopenharmony_ciMODULE_PARM_DESC(scalelcd,
67968c2ecf20Sopenharmony_ci	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
67978c2ecf20Sopenharmony_ci	  "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
67988c2ecf20Sopenharmony_ci	  "show black bars around the image, TMDS panels will probably do the scaling\n"
67998c2ecf20Sopenharmony_ci	  "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
68008c2ecf20Sopenharmony_ci
68018c2ecf20Sopenharmony_ciMODULE_PARM_DESC(pdc,
68028c2ecf20Sopenharmony_ci	"\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
68038c2ecf20Sopenharmony_ci	  "should detect this correctly in most cases; however, sometimes this is not\n"
68048c2ecf20Sopenharmony_ci	  "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
68058c2ecf20Sopenharmony_ci	  "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
68068c2ecf20Sopenharmony_ci	  "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
68078c2ecf20Sopenharmony_ci	  "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
68088c2ecf20Sopenharmony_ci
68098c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_315
68108c2ecf20Sopenharmony_ciMODULE_PARM_DESC(pdc1,
68118c2ecf20Sopenharmony_ci	"\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
68128c2ecf20Sopenharmony_ci	  "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
68138c2ecf20Sopenharmony_ci	  "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
68148c2ecf20Sopenharmony_ci	  "implemented yet.\n");
68158c2ecf20Sopenharmony_ci#endif
68168c2ecf20Sopenharmony_ci
68178c2ecf20Sopenharmony_ciMODULE_PARM_DESC(specialtiming,
68188c2ecf20Sopenharmony_ci	"\nPlease refer to documentation for more information on this option.\n");
68198c2ecf20Sopenharmony_ci
68208c2ecf20Sopenharmony_ciMODULE_PARM_DESC(lvdshl,
68218c2ecf20Sopenharmony_ci	"\nPlease refer to documentation for more information on this option.\n");
68228c2ecf20Sopenharmony_ci
68238c2ecf20Sopenharmony_ciMODULE_PARM_DESC(tvstandard,
68248c2ecf20Sopenharmony_ci	"\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
68258c2ecf20Sopenharmony_ci	  "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
68268c2ecf20Sopenharmony_ci
68278c2ecf20Sopenharmony_ciMODULE_PARM_DESC(tvxposoffset,
68288c2ecf20Sopenharmony_ci	"\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
68298c2ecf20Sopenharmony_ci	  "Default: 0\n");
68308c2ecf20Sopenharmony_ci
68318c2ecf20Sopenharmony_ciMODULE_PARM_DESC(tvyposoffset,
68328c2ecf20Sopenharmony_ci	"\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
68338c2ecf20Sopenharmony_ci	  "Default: 0\n");
68348c2ecf20Sopenharmony_ci
68358c2ecf20Sopenharmony_ciMODULE_PARM_DESC(nocrt2rate,
68368c2ecf20Sopenharmony_ci	"\nSetting this to 1 will force the driver to use the default refresh rate for\n"
68378c2ecf20Sopenharmony_ci	  "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
68388c2ecf20Sopenharmony_ci
68398c2ecf20Sopenharmony_ci#if !defined(__i386__) && !defined(__x86_64__)
68408c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_SIS_300
68418c2ecf20Sopenharmony_ciMODULE_PARM_DESC(resetcard,
68428c2ecf20Sopenharmony_ci	"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
68438c2ecf20Sopenharmony_ci	  "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
68448c2ecf20Sopenharmony_ci	  "currently). Default: 0\n");
68458c2ecf20Sopenharmony_ci
68468c2ecf20Sopenharmony_ciMODULE_PARM_DESC(videoram,
68478c2ecf20Sopenharmony_ci	"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
68488c2ecf20Sopenharmony_ci	  "some non-x86 architectures where the memory auto detection fails. Only\n"
68498c2ecf20Sopenharmony_ci	  "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
68508c2ecf20Sopenharmony_ci#endif
68518c2ecf20Sopenharmony_ci#endif
68528c2ecf20Sopenharmony_ci
68538c2ecf20Sopenharmony_ci#endif 	   /*  /MODULE  */
68548c2ecf20Sopenharmony_ci
68558c2ecf20Sopenharmony_ci/* _GPL only for new symbols. */
68568c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sis_malloc);
68578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sis_free);
68588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sis_malloc_new);
68598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(sis_free_new);
68608c2ecf20Sopenharmony_ci
68618c2ecf20Sopenharmony_ci
68628c2ecf20Sopenharmony_ci
6863