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, ®); 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, ®d); 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, ®d); 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, ®16); 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