patch-2.4.25 linux-2.4.25/drivers/video/sis/sis_main.c
Next file: linux-2.4.25/drivers/video/sis/sis_main.h
Previous file: linux-2.4.25/drivers/video/sis/sis_accel.h
Back to the patch index
Back to the overall index
- Lines: 2208
- Date:
2004-02-18 05:36:31.000000000 -0800
- Orig file:
linux-2.4.24/drivers/video/sis/sis_main.c
- Orig date:
2003-11-28 10:26:21.000000000 -0800
diff -urN linux-2.4.24/drivers/video/sis/sis_main.c linux-2.4.25/drivers/video/sis/sis_main.c
@@ -1,14 +1,28 @@
/*
- * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/330
+ * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/M741/330/760
* frame buffer driver for Linux kernels 2.4.x and 2.5.x
*
- * (C) 1999 Silicon Integrated Systems, Inc.
- * (C) 2001-2003 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the named License,
+ * or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*
* Author: Thomas Winischhofer <thomas@winischhofer.net>
*
* Author of code base:
* SiS (www.sis.com.tw)
+ * Copyright (C) 1999 Silicon Integrated Systems, Inc.
*
* See http://www.winischhofer.net/ for more information and updates
*
@@ -73,8 +87,8 @@
#include "sis.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)
-#error "This version of sisfb requires at least 2.5.69"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#error "This version of sisfb requires at least 2.6.0"
#endif
#endif
@@ -120,7 +134,7 @@
/* ------------ Interface for init & mode switching code ------------- */
BOOLEAN
-sisfb_query_VGA_config_space(PSIS_HW_DEVICE_INFO psishw_ext,
+sisfb_query_VGA_config_space(PSIS_HW_INFO psishw_ext,
unsigned long offset, unsigned long set, unsigned long *value)
{
static struct pci_dev *pdev = NULL;
@@ -162,7 +176,7 @@
return TRUE;
}
-BOOLEAN sisfb_query_north_bridge_space(PSIS_HW_DEVICE_INFO psishw_ext,
+BOOLEAN sisfb_query_north_bridge_space(PSIS_HW_INFO psishw_ext,
unsigned long offset, unsigned long set, unsigned long *value)
{
static struct pci_dev *pdev = NULL;
@@ -193,6 +207,12 @@
case SIS_740:
nbridge_id = PCI_DEVICE_ID_SI_740;
break;
+ case SIS_661:
+ nbridge_id = PCI_DEVICE_ID_SI_660;
+ break;
+ case SIS_741:
+ nbridge_id = PCI_DEVICE_ID_SI_741;
+ break;
case SIS_660:
nbridge_id = PCI_DEVICE_ID_SI_660;
break;
@@ -524,16 +544,12 @@
#ifdef CONFIG_FB_SIS_300
if(sisvga_engine == SIS_300_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS300)) {
- return(-1);
- }
+ if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1);
}
#endif
#ifdef CONFIG_FB_SIS_315
if(sisvga_engine == SIS_315_VGA) {
- if(!(sisbios_mode[myindex].chipset & MD_SIS315)) {
- return(-1);
- }
+ if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
}
#endif
@@ -542,230 +558,71 @@
switch (vbflags & VB_DISPTYPE_DISP2) {
case CRT2_LCD:
switch (sishw_ext.ulCRT2LCDType) {
- case LCD_640x480:
- xres = 640; yres = 480; break;
- case LCD_800x600:
- xres = 800; yres = 600; break;
- case LCD_1024x600:
- xres = 1024; yres = 600; break;
- case LCD_1024x768:
- xres = 1024; yres = 768; break;
- case LCD_1152x768:
- xres = 1152; yres = 768; break;
- case LCD_1280x960:
- xres = 1280; yres = 960; break;
- case LCD_1280x768:
- xres = 1280; yres = 768; break;
- case LCD_1280x1024:
- xres = 1280; yres = 1024; break;
- case LCD_1400x1050:
- xres = 1400; yres = 1050; break;
- case LCD_1600x1200:
- xres = 1600; yres = 1200; break;
- case LCD_320x480: /* FSTN (old) */
- xres = 320; yres = 480; break;
- case LCD_640x480_2: /* FSTN (new) */
- case LCD_640x480_3:
- xres = 640; yres = 480; break;
- default:
- xres = 0; yres = 0; break;
+ case LCD_640x480: xres = 640; yres = 480; break;
+ case LCD_800x600: xres = 800; yres = 600; break;
+ case LCD_1024x600: xres = 1024; yres = 600; break;
+ case LCD_1024x768: xres = 1024; yres = 768; break;
+ case LCD_1152x768: xres = 1152; yres = 768; break;
+ case LCD_1280x960: xres = 1280; yres = 960; break;
+ case LCD_1280x768: xres = 1280; yres = 768; break;
+ case LCD_1280x1024:xres = 1280; yres = 1024; break;
+ case LCD_1400x1050:xres = 1400; yres = 1050; break;
+ case LCD_1600x1200:xres = 1600; yres = 1200; break;
+ case LCD_320x480: xres = 320; yres = 480; break; /* FSTN (old) */
+ case LCD_640x480_2:
+ case LCD_640x480_3:xres = 640; yres = 480; break; /* FSTN (new) */
+ default: xres = 0; yres = 0; break;
}
if(SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
- xres = 1360; yres = 1024;
+ xres = 1360; yres = 1024;
}
if(SiS_Pr.SiS_CustomT == CUT_PANEL848) {
- xres = 848; yres = 480;
+ xres = 848; yres = 480;
} else {
- if(sisbios_mode[myindex].xres > xres) {
- return(-1);
- }
- if(myres > yres) {
- return(-1);
- }
+ if(sisbios_mode[myindex].xres > xres) return(-1);
+ if(myres > yres) return(-1);
}
if(vbflags & (VB_LVDS | VB_30xBDH)) {
- switch (sisbios_mode[myindex].xres) {
- case 320:
- if((myres != 200) && (myres != 240))
- return(-1);
- if((myres == 240) || (myres == 480)) {
- if(!sisfb_fstn) {
- if(sisbios_mode[myindex].mode_no == 0x5a ||
- sisbios_mode[myindex].mode_no == 0x5b)
- return(-1);
- } else {
- if(sisbios_mode[myindex].mode_no == 0x50 ||
- sisbios_mode[myindex].mode_no == 0x56 ||
- sisbios_mode[myindex].mode_no == 0x53)
- return(-1);
- }
- }
- if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
- break;
- case 400:
- if(myres != 300) return(-1);
- if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
- break;
- case 512:
- if(myres != 384) return(-1);
- if(sishw_ext.ulCRT2LCDType == LCD_1024x600) return(-1);
- if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
- break;
- case 640:
- if((myres != 400) && (myres != 480))
- return -1;
- if(SiS_Pr.SiS_CustomT == CUT_PANEL848) {
- if(myres == 400)
- return(-1);
- }
- break;
- case 800:
- if(myres != 600) return(-1);
- break;
- case 848:
- if(SiS_Pr.SiS_CustomT != CUT_PANEL848) return(-1);
- if(myres != 480) return(-1);
- break;
- case 1024:
- if((myres != 600) && (myres != 768))
- return(-1);
- if((myres == 600) &&
- (sishw_ext.ulCRT2LCDType != LCD_1024x600))
- return(-1);
- break;
- case 1152:
- if(myres != 768) return(-1);
- if(sishw_ext.ulCRT2LCDType != LCD_1152x768) return(-1);
- break;
- case 1280:
- if((myres != 768) && (myres != 1024))
- return(-1);
- if((myres == 768) &&
- (sishw_ext.ulCRT2LCDType != LCD_1280x768))
- return(-1);
- if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
- break;
- case 1360:
- if(SiS_Pr.SiS_CustomT != CUT_BARCO1366) return(-1);
- if(myres != 1024) return(-1);
- break;
- case 1400:
- if(myres != 1050) return(-1);
- if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
- break;
- case 1600:
- if(myres != 1200) return(-1);
- if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
- break;
- default:
- return(-1);
- }
- } else {
- switch (sisbios_mode[myindex].xres) {
- case 320:
- if((myres != 200) && (myres != 240))
- return -1;
- break;
- case 400:
- if(myres != 300) return(-1);
- break;
- case 512:
- if(myres != 384) return(-1);
- break;
- case 640:
- if((myres != 400) && (myres != 480))
- return(-1);
- break;
- case 800:
- if(myres != 600) return(-1);
- break;
- case 1024:
- if(myres != 768) return(-1);
- break;
- case 1280:
- if((myres != 960) && (myres != 768) && (myres != 1024))
- return(-1);
- if((myres == 768) || (myres == 960)) {
- if(sishw_ext.ulCRT2LCDType == LCD_1400x1050)
- return(-1);
- }
- if(myres == 768) {
- if(sishw_ext.ulCRT2LCDType == LCD_1280x960)
- return(-1);
- }
- break;
- case 1400:
- if(myres != 1050) return(-1);
- break;
- case 1600:
- if(myres != 1200) return(-1);
- break;
- default:
- return(-1);
+ if(sisbios_mode[myindex].xres == 320) {
+ if((myres == 240) || (myres == 480)) {
+ if(!sisfb_fstn) {
+ if(sisbios_mode[myindex].mode_no == 0x5a ||
+ sisbios_mode[myindex].mode_no == 0x5b)
+ return(-1);
+ } else {
+ if(sisbios_mode[myindex].mode_no == 0x50 ||
+ sisbios_mode[myindex].mode_no == 0x56 ||
+ sisbios_mode[myindex].mode_no == 0x53)
+ return(-1);
+ }
+ }
}
}
+
+ if(SiS_GetModeID_LCD(sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres,
+ 0, sisfb_fstn, SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
+ return(-1);
+ }
break;
case CRT2_TV:
- switch (sisbios_mode[myindex].xres) {
- case 320:
- if(vbflags & VB_CHRONTEL) return(-1);
- if((myres != 200) && (myres != 240))
- return(-1);
- break;
- case 400:
- if(vbflags & VB_CHRONTEL) return(-1);
- if(myres != 300) return(-1);
- break;
- case 512:
- if((vbflags & VB_CHRONTEL) && (ivideo.chip < SIS_315H))
- return(-1);
- if((vbflags & VB_SISBRIDGE) && (vbflags & TV_NTSC))
- return(-1);
- if(myres != 384) return(-1);
- break;
- case 640:
- if((myres != 400) && (myres != 480))
- return(-1);
- break;
- case 720:
- if(vbflags & VB_CHRONTEL) return(-1);
- if((vbflags & TV_NTSC) && (myres != 480))
- return(-1);
- if((vbflags & TV_PAL) && (myres != 576))
- return(-1);
- break;
- case 768:
- if(vbflags & VB_CHRONTEL) return(-1);
- if(!(vbflags & TV_PAL)) return(-1);
- if(myres != 576) return(-1);
- break;
- case 800:
- if(myres != 600) return(-1);
- break;
- case 1024:
- if(vbflags & VB_301) return(-1);
- if(vbflags & VB_CHRONTEL) {
- if(ivideo.chip < SIS_315H) {
- return(-1);
- }
- }
- break;
- default:
- return(-1);
+ if(SiS_GetModeID_TV(sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+ sisbios_mode[myindex].yres, 0) < 0x14) {
+ return(-1);
}
break;
case CRT2_VGA:
- if(sisbios_mode[myindex].xres > 1600) return(-1);
- if(!(vbflags & (VB_301B|VB_301C|VB_302B))) {
- if(sisbios_mode[myindex].xres > 1400) return(-1);
+ if(SiS_GetModeID_VGA2(sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+ sisbios_mode[myindex].yres, 0) < 0x14) {
+ return(-1);
}
- break;
+ break;
}
+
return(myindex);
}
@@ -889,8 +746,9 @@
if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
found = TRUE;
- printk(KERN_INFO "sisfb: Special timing for %s %s forced\n",
- mycustomttable[i].vendorName, mycustomttable[i].cardName);
+ printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
+ mycustomttable[i].vendorName, mycustomttable[i].cardName,
+ mycustomttable[i].optionName);
break;
}
i++;
@@ -925,22 +783,40 @@
}
}
-static BOOLEAN sisfbcheckvretracecrt1(void)
+static BOOLEAN sisfballowretracecrt1(void)
{
unsigned char temp;
inSISIDXREG(SISCR,0x17,temp);
if(!(temp & 0x80)) return FALSE;
-
- if(sisvga_engine == SIS_315_VGA) {
- inSISIDXREG(SISSR,0x1f,temp);
- if(temp & 0xc0) return FALSE;
- }
+
+ inSISIDXREG(SISSR,0x1f,temp);
+ if(temp & 0xc0) return FALSE;
+
+ return TRUE;
+}
+
+static BOOLEAN sisfbcheckvretracecrt1(void)
+{
+
+ if(!sisfballowretracecrt1()) return FALSE;
if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
else return FALSE;
}
+static void sisfbwaitretracecrt1(void)
+{
+ int watchdog;
+
+ if(!sisfballowretracecrt1()) return;
+
+ watchdog = 65536;
+ while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
+ watchdog = 65536;
+ while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
+}
+
static BOOLEAN sisfbcheckvretracecrt2(void)
{
unsigned char temp, reg;
@@ -961,7 +837,7 @@
else return TRUE;
}
-static BOOLEAN sisfb_CheckVBRetrace(void)
+static BOOLEAN sisfb_CheckVBRetrace(void)
{
if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
if(sisfb_bridgeisslave()) {
@@ -1047,7 +923,7 @@
if(ivideo.currentvbflags & CRT2_LCD) {
- if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
+ if(ivideo.vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
if(backlight) {
SiS_SiS30xBLOn(&SiS_Pr, &sishw_ext);
} else {
@@ -1125,7 +1001,7 @@
struct fb_info *info)
{
unsigned int htotal = 0, vtotal = 0;
- double drate = 0, hrate = 0;
+ unsigned int drate = 0, hrate = 0;
int found_mode = 0;
int old_mode;
u32 pixclock;
@@ -1153,9 +1029,9 @@
}
if(pixclock && htotal && vtotal) {
- drate = 1E12 / pixclock;
- hrate = drate / htotal;
- ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+ drate = 1000000000 / pixclock;
+ hrate = (drate * 1000) / htotal;
+ ivideo.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
} else ivideo.refresh_rate = 60;
#if 0
@@ -1358,14 +1234,14 @@
u16 HRE, HBE, HRS, HBS, HDE, HT;
u8 sr_data, cr_data, cr_data2, cr_data3, mr_data;
int A, B, C, D, E, F, temp;
- double hrate, drate;
+ unsigned int hrate, drate, maxyres;
inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data);
- if (sr_data & SIS_INTERLACED_MODE)
- var->vmode = FB_VMODE_INTERLACED;
+ if(sr_data & SIS_INTERLACED_MODE)
+ var->vmode = FB_VMODE_INTERLACED;
else
- var->vmode = FB_VMODE_NONINTERLACED;
+ var->vmode = FB_VMODE_NONINTERLACED;
switch ((sr_data & 0x1C) >> 2) {
case SIS_8BPP_COLOR_MODE:
@@ -1431,16 +1307,16 @@
var->lower_margin = F;
var->vsync_len = C;
- if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- var->yres <<= 1;
- var->upper_margin <<= 1;
- var->lower_margin <<= 1;
- var->vsync_len <<= 1;
- } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- var->yres >>= 1;
- var->upper_margin >>= 1;
- var->lower_margin >>= 1;
- var->vsync_len >>= 1;
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+ var->yres <<= 1;
+ var->upper_margin <<= 1;
+ var->lower_margin <<= 1;
+ var->vsync_len <<= 1;
+ } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ var->yres >>= 1;
+ var->upper_margin >>= 1;
+ var->lower_margin >>= 1;
+ var->vsync_len >>= 1;
}
inSISIDXREG(SISSR, 0x0b, sr_data);
@@ -1502,34 +1378,42 @@
var->sync = 0;
mr_data = inSISREG(SISMISCR);
- if (mr_data & 0x80)
- var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+ if(mr_data & 0x80)
+ var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
else
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
- if (mr_data & 0x40)
- var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+ if(mr_data & 0x40)
+ var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
else
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
VT += 2;
VT <<= 1;
HT = (HT + 5) * 8;
- if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- VT <<= 1;
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+ VT <<= 1;
}
- hrate = (double) ivideo.refresh_rate * (double) VT / 2;
- drate = hrate * HT;
- var->pixclock = (u32) (1E12 / drate);
+ hrate = ivideo.refresh_rate * VT / 2;
+ drate = (hrate * HT) / 1000;
+ var->pixclock = (u32) (1000000000 / drate);
if(sisfb_ypan) {
- var->yres_virtual = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
- if(var->yres_virtual <= var->yres) {
- var->yres_virtual = var->yres;
- }
+ maxyres = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+ if(maxyres > 32767) maxyres = 32767;
+ if(sisfb_max) {
+ var->yres_virtual = maxyres;
+ } else {
+ if(var->yres_virtual > maxyres) {
+ var->yres_virtual = maxyres;
+ }
+ }
+ if(var->yres_virtual <= var->yres) {
+ var->yres_virtual = var->yres;
+ }
} else
- var->yres_virtual = var->yres;
+ var->yres_virtual = var->yres;
}
@@ -1963,7 +1847,7 @@
red >>= 8;
green >>= 8;
blue >>= 8;
- ((u32 *) (info->pseudo_palette))[regno] =
+ ((u32 *) (info->pseudo_palette))[regno] =
(red << 16) | (green << 8) | (blue);
break;
}
@@ -1986,7 +1870,7 @@
struct fb_info *info)
{
unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
- double drate = 0, hrate = 0;
+ unsigned int drate = 0, hrate = 0, maxyres;
int found_mode = 0;
int refresh_rate, search_idx;
BOOLEAN recalc_clock = FALSE;
@@ -2066,9 +1950,9 @@
} else if( (ivideo.current_htotal == htotal) && /* x=x & y=y & c=c -> assume depth change */
(ivideo.current_vtotal == vtotal) &&
(ivideo.current_pixclock == pixclock) ) {
- drate = 1E12 / pixclock;
- hrate = drate / htotal;
- refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+ drate = 1000000000 / pixclock;
+ hrate = (drate * 1000) / htotal;
+ refresh_rate = (unsigned int) (hrate * 2 / vtotal);
} else if( ( (ivideo.current_htotal != htotal) || /* x!=x | y!=y & c=c -> invalid pixclock */
(ivideo.current_vtotal != vtotal) ) &&
(ivideo.current_pixclock == var->pixclock) ) {
@@ -2081,9 +1965,9 @@
}
recalc_clock = TRUE;
} else if((pixclock) && (htotal) && (vtotal)) {
- drate = 1E12 / pixclock;
- hrate = drate / htotal;
- refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+ drate = 1000000000 / pixclock;
+ hrate = (drate * 1000) / htotal;
+ refresh_rate = (unsigned int) (hrate * 2 / vtotal);
} else if(ivideo.current_refresh_rate) {
refresh_rate = ivideo.current_refresh_rate;
recalc_clock = TRUE;
@@ -2097,7 +1981,7 @@
/* Eventually recalculate timing and clock */
if(recalc_clock) {
if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
- var->pixclock = (u32) (1E12 / sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
+ var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
sisbios_mode[search_idx].mode_no, myrateindex));
sisfb_mode_rate_to_ddata(&SiS_Pr, &sishw_ext,
sisbios_mode[search_idx].mode_no, myrateindex,
@@ -2131,25 +2015,31 @@
var->xres_virtual = var->xres;
if(sisfb_ypan) {
- /* TW: Now patch yres_virtual if we use panning */
- /* *** May I do this? *** */
- var->yres_virtual = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+ maxyres = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+ if(maxyres > 32767) maxyres = 32767;
+ if(sisfb_max) {
+ var->yres_virtual = maxyres;
+ } else {
+ if(var->yres_virtual > maxyres) {
+ var->yres_virtual = maxyres;
+ }
+ }
if(var->yres_virtual <= var->yres) {
- /* TW: Paranoia check */
- var->yres_virtual = var->yres;
+ var->yres_virtual = var->yres;
}
} else {
- if(var->yres != var->yres_virtual)
- var->yres_virtual = var->yres;
+ if(var->yres != var->yres_virtual) {
+ var->yres_virtual = var->yres;
+ }
var->xoffset = 0;
var->yoffset = 0;
}
/* Truncate offsets to maximum if too high */
- if (var->xoffset > var->xres_virtual - var->xres)
+ if(var->xoffset > var->xres_virtual - var->xres)
var->xoffset = var->xres_virtual - var->xres - 1;
- if (var->yoffset > var->yres_virtual - var->yres)
+ if(var->yoffset > var->yres_virtual - var->yres)
var->yoffset = var->yres_virtual - var->yres - 1;
/* Set everything else to 0 */
@@ -2353,6 +2243,12 @@
x.sisfb_currentvbflags = ivideo.currentvbflags;
x.sisfb_scalelcd = SiS_Pr.UsePanelScaler;
x.sisfb_specialtiming = SiS_Pr.SiS_CustomT;
+ x.sisfb_haveemi = SiS_Pr.HaveEMI ? 1 : 0;
+ x.sisfb_haveemilcd = SiS_Pr.HaveEMILCD ? 1 : 0;
+ x.sisfb_emi30 = SiS_Pr.EMI_30;
+ x.sisfb_emi31 = SiS_Pr.EMI_31;
+ x.sisfb_emi32 = SiS_Pr.EMI_32;
+ x.sisfb_emi33 = SiS_Pr.EMI_33;
if(copy_to_user((void *)arg, &x, sizeof(x)))
return -EFAULT;
break;
@@ -2365,6 +2261,25 @@
return put_user(0UL, (unsigned long *) arg);
break;
}
+ case SISFB_GET_AUTOMAXIMIZE:
+ {
+ if(sisfb_max)
+ return put_user(1UL, (unsigned long *) arg);
+ else
+ return put_user(0UL, (unsigned long *) arg);
+ break;
+ }
+ case SISFB_SET_AUTOMAXIMIZE:
+ {
+ unsigned long newmax;
+
+ if(copy_from_user(&newmax, (unsigned long *)arg, sizeof(newmax)))
+ return -EFAULT;
+
+ if(newmax) sisfb_max = 1;
+ else sisfb_max = 0;
+ break;
+ }
default:
return -EINVAL;
}
@@ -2378,7 +2293,7 @@
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- strcpy(fix->id, sis_fb_info.modename);
+ strcpy(fix->id, sis_fb_info->modename);
#else
strcpy(fix->id, myid);
#endif
@@ -2402,9 +2317,9 @@
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
if(ivideo.video_bpp == 8)
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
else
- fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->visual = FB_VISUAL_TRUECOLOR;
fix->xpanstep = 0;
if(sisfb_ypan) fix->ypanstep = 1;
@@ -2415,7 +2330,7 @@
fix->mmio_len = sisfb_mmio_size;
if(sisvga_engine == SIS_300_VGA)
fix->accel = FB_ACCEL_SIS_GLAMOUR;
- else if((ivideo.chip == SIS_330) || (ivideo.chip == SIS_660) || (ivideo.chip == SIS_760))
+ else if((ivideo.chip == SIS_330) || (ivideo.chip == SIS_760))
fix->accel = FB_ACCEL_SIS_XABRE;
else
fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
@@ -2547,179 +2462,42 @@
#endif /* CONFIG_FB_SIS_300 */
-#ifdef CONFIG_FB_SIS_315 /* for SiS 315/550/650/740/330/660/760 */
+#ifdef CONFIG_FB_SIS_315 /* for SiS 315/550/650/740/330/661/741/760 */
static int sisfb_get_dram_size_315(void)
{
- struct pci_dev *pdev = NULL;
- int pdev_valid = 0;
- u8 pci_data;
u8 reg = 0;
- if (ivideo.chip == SIS_550 ||
- ivideo.chip == SIS_650 ||
- ivideo.chip == SIS_740 ||
- ivideo.chip == SIS_660 ||
- ivideo.chip == SIS_760) {
-
-#ifdef LINUXBIOS
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
- pci_for_each_dev(pdev) {
-#else
- while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-
- if ( (pdev->vendor == PCI_VENDOR_ID_SI)
- && ( (pdev->device == PCI_DEVICE_ID_SI_550) ||
- (pdev->device == PCI_DEVICE_ID_SI_650) ||
- (pdev->device == PCI_DEVICE_ID_SI_740) ||
- (pdev->device == PCI_DEVICE_ID_SI_660) ||
- (pdev->device == PCI_DEVICE_ID_SI_760))) {
- pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS,
- &pci_data);
- pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
- ivideo.video_size = (unsigned int)(1 << (pci_data + 21));
- pdev_valid = 1;
-
- /* Initialize SR14 "by hand" */
- inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
- reg &= 0xC0;
- switch (pci_data) {
- case BRI_DRAM_SIZE_4MB:
- reg |= SIS550_DRAM_SIZE_4MB;
- break;
- case BRI_DRAM_SIZE_8MB:
- reg |= SIS550_DRAM_SIZE_8MB;
- break;
- case BRI_DRAM_SIZE_16MB:
- reg |= SIS550_DRAM_SIZE_16MB;
- break;
- case BRI_DRAM_SIZE_32MB:
- reg |= SIS550_DRAM_SIZE_32MB;
- break;
- case BRI_DRAM_SIZE_64MB:
- reg |= SIS550_DRAM_SIZE_64MB;
- break;
- }
-
- /* TODO: set Dual channel and bus width bits here */
-
- outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
- break;
- }
- }
-
- if (!pdev_valid) return -1;
-
-#else
+ if(ivideo.chip == SIS_550 ||
+ ivideo.chip == SIS_650 ||
+ ivideo.chip == SIS_740) {
inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
- switch (reg & SIS550_DRAM_SIZE_MASK) {
- case SIS550_DRAM_SIZE_4MB:
- ivideo.video_size = 0x400000; break;
- case SIS550_DRAM_SIZE_8MB:
- ivideo.video_size = 0x800000; break;
- case SIS550_DRAM_SIZE_16MB:
- ivideo.video_size = 0x1000000; break;
- case SIS550_DRAM_SIZE_24MB:
- ivideo.video_size = 0x1800000; break;
- case SIS550_DRAM_SIZE_32MB:
- ivideo.video_size = 0x2000000; break;
- case SIS550_DRAM_SIZE_64MB:
- ivideo.video_size = 0x4000000; break;
- case SIS550_DRAM_SIZE_96MB:
- ivideo.video_size = 0x6000000; break;
- case SIS550_DRAM_SIZE_128MB:
- ivideo.video_size = 0x8000000; break;
- case SIS550_DRAM_SIZE_256MB:
- ivideo.video_size = 0x10000000; break;
- default:
- /* TW: Some 550 BIOSes don't seem to initialize SR14 correctly (if at all),
- * do it the hard way ourselves in this case. Unfortunately, we don't
- * support 24, 48, 96 and other "odd" amounts here.
- */
- printk(KERN_INFO
- "sisfb: Warning: Could not determine memory size, "
- "now reading from PCI config\n");
- pdev_valid = 0;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
- pci_for_each_dev(pdev) {
-#else
- while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-
- if ( (pdev->vendor == PCI_VENDOR_ID_SI)
- && (pdev->device == PCI_DEVICE_ID_SI_550) ) {
+ reg &= 0x3f;
+ reg++;
+ reg <<= 2;
+ ivideo.video_size = reg << 20;
+ return 0;
- pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS,
- &pci_data);
- pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
- ivideo.video_size = (unsigned int)(1 << (pci_data+21));
- pdev_valid = 1;
- /* TW: Initialize SR14=IND_SIS_DRAM_SIZE */
- inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
- reg &= 0xC0;
- switch (pci_data) {
- case BRI_DRAM_SIZE_4MB:
- reg |= SIS550_DRAM_SIZE_4MB; break;
- case BRI_DRAM_SIZE_8MB:
- reg |= SIS550_DRAM_SIZE_8MB; break;
- case BRI_DRAM_SIZE_16MB:
- reg |= SIS550_DRAM_SIZE_16MB; break;
- case BRI_DRAM_SIZE_32MB:
- reg |= SIS550_DRAM_SIZE_32MB; break;
- case BRI_DRAM_SIZE_64MB:
- reg |= SIS550_DRAM_SIZE_64MB; break;
- default:
- printk(KERN_INFO "sisfb: Unable to determine memory size, giving up.\n");
- return -1;
- }
- outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
- }
- }
- if (!pdev_valid) {
- printk(KERN_INFO "sisfb: Total confusion - No SiS PCI VGA device found?!\n");
- return -1;
- }
- return 0;
- }
-#endif
+ } else if(ivideo.chip == SIS_661 ||
+ ivideo.chip == SIS_741 ||
+ ivideo.chip == SIS_660 ||
+ ivideo.chip == SIS_760) {
+
+ inSISIDXREG(SISCR, 0x79, reg);
+ reg &= 0xf0;
+ reg >>= 4;
+ ivideo.video_size = (1 << reg) << 20;
return 0;
} else { /* 315, 330 */
inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
- switch ((reg & SIS315_DRAM_SIZE_MASK) >> 4) {
- case SIS315_DRAM_SIZE_2MB:
- ivideo.video_size = 0x200000;
- break;
- case SIS315_DRAM_SIZE_4MB:
- ivideo.video_size = 0x400000;
- break;
- case SIS315_DRAM_SIZE_8MB:
- ivideo.video_size = 0x800000;
- break;
- case SIS315_DRAM_SIZE_16MB:
- ivideo.video_size = 0x1000000;
- break;
- case SIS315_DRAM_SIZE_32MB:
- ivideo.video_size = 0x2000000;
- break;
- case SIS315_DRAM_SIZE_64MB:
- ivideo.video_size = 0x4000000;
- break;
- case SIS315_DRAM_SIZE_128MB:
- ivideo.video_size = 0x8000000;
- break;
- default:
- return -1;
- }
-
+ ivideo.video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+
reg &= SIS315_DUAL_CHANNEL_MASK;
reg >>= 2;
-
+
if(ivideo.chip == SIS_330) {
if(reg) ivideo.video_size <<= 1;
@@ -2757,7 +2535,7 @@
if(sisvga_engine == SIS_300_VGA) {
- inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
+ inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
@@ -2817,9 +2595,8 @@
/* TW: Detect/set TV plug & type */
if(sisfb_tvplug != -1)
ivideo.vbflags |= sisfb_tvplug;
- if (cr32 & SIS_VB_HIVISION)
- ivideo.vbflags |= (TV_HIVISION | TV_SVIDEO);
- else if (cr32 & SIS_VB_SVIDEO)
+
+ if (cr32 & SIS_VB_SVIDEO)
ivideo.vbflags |= TV_SVIDEO;
else if (cr32 & SIS_VB_COMPOSITE)
ivideo.vbflags |= TV_AVIDEO;
@@ -2833,10 +2610,10 @@
ivideo.vbflags |= TV_PAL;
else
ivideo.vbflags |= TV_NTSC;
- } else if((ivideo.chip <= SIS_315PRO) || (ivideo.chip == SIS_330)) {
+ } else if((ivideo.chip <= SIS_315PRO) || (ivideo.chip >= SIS_330)) {
- inSISIDXREG(SISCR, 0x38, temp);
- if(temp & 0x10)
+ inSISIDXREG(SISSR, 0x38, temp);
+ if(temp & 0x01)
ivideo.vbflags |= TV_PAL;
else
ivideo.vbflags |= TV_NTSC;
@@ -2878,14 +2655,21 @@
case 0x01:
ivideo.hasVB = HASVB_301;
inSISIDXREG(SISPART4, 0x01, reg);
- if(reg < 0xb0) {
+ if(reg < 0xb0) {
ivideo.vbflags |= VB_301;
sishw_ext.ujVBChipID = VB_CHIP_301;
printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
} else if(reg < 0xc0) {
ivideo.vbflags |= VB_301B;
sishw_ext.ujVBChipID = VB_CHIP_301B;
- printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
+ inSISIDXREG(SISPART4,0x23,reg);
+ if(!(reg & 0x02)) {
+ sishw_ext.Is301BDH = TRUE;
+ ivideo.vbflags |= VB_30xBDH;
+ printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
+ } else {
+ printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
+ }
} else if(reg < 0xd0) {
ivideo.vbflags |= VB_301C;
sishw_ext.ujVBChipID = VB_CHIP_301C;
@@ -2895,9 +2679,16 @@
sishw_ext.ujVBChipID = VB_CHIP_301LV;
printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
} else if(reg <= 0xe1) {
- ivideo.vbflags |= VB_302LV;
- sishw_ext.ujVBChipID = VB_CHIP_302LV;
- printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
+ inSISIDXREG(SISPART4,0x39,reg);
+ if(reg == 0xff) {
+ ivideo.vbflags |= VB_302LV;
+ sishw_ext.ujVBChipID = VB_CHIP_302LV;
+ printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
+ } else {
+ ivideo.vbflags |= VB_302ELV;
+ sishw_ext.ujVBChipID = VB_CHIP_302ELV;
+ printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
+ }
}
break;
case 0x02:
@@ -2906,7 +2697,14 @@
if(reg < 0xd0) {
ivideo.vbflags |= VB_302B;
sishw_ext.ujVBChipID = VB_CHIP_302B;
- printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
+ inSISIDXREG(SISPART4,0x23,reg);
+ if(!(reg & 0x02)) {
+ sishw_ext.Is301BDH = TRUE;
+ ivideo.vbflags |= VB_30xBDH;
+ printk(KERN_INFO "%s SiS302B-DH %s\n", stdstr, bridgestr);
+ } else {
+ printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
+ }
} else if(reg < 0xe0) {
ivideo.vbflags |= VB_301LV;
sishw_ext.ujVBChipID = VB_CHIP_301LV;
@@ -2918,16 +2716,7 @@
}
break;
}
-
- if(ivideo.vbflags & (VB_301B | VB_302B)) {
- inSISIDXREG(SISPART4,0x23,reg);
- if(!(reg & 0x02)) {
- sishw_ext.Is301BDH = TRUE;
- ivideo.vbflags |= VB_30xBDH;
- printk(KERN_INFO "This %s does not support LCD output\n", bridgestr);
- }
- }
-
+
if((!(ivideo.vbflags & VB_VIDEOBRIDGE)) && (ivideo.chip != SIS_300)) {
inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
reg &= SIS_EXTERNAL_CHIP_MASK;
@@ -2958,7 +2747,7 @@
printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
break;
}
- } else {
+ } else if(ivideo.chip < SIS_661) {
switch (reg) {
case SIS310_EXTERNAL_CHIP_LVDS:
ivideo.hasVB = HASVB_LVDS;
@@ -2982,21 +2771,88 @@
} else if(ivideo.vbflags & VB_CHRONTEL) {
SiS_SenseCh();
}
-
+
}
/* ------------------ Sensing routines ------------------ */
-/* TW: Determine and detect attached devices on SiS30x */
+static BOOLEAN
+sisfb_test_DDC1(void)
+{
+ unsigned short old;
+ int count = 48;
+
+ old = SiS_ReadDDC1Bit(&SiS_Pr);
+ do {
+ if(old != SiS_ReadDDC1Bit(&SiS_Pr)) break;
+ } while(count--);
+ return (count == -1) ? FALSE : TRUE;
+}
+
+static void
+sisfb_sense_crt1(void)
+{
+ unsigned char SR1F, CR63=0, CR17;
+ unsigned short temp = 0xffff;
+ int i;
+ BOOLEAN mustwait = FALSE;
+
+ inSISIDXREG(SISSR,0x1F,SR1F);
+ orSISIDXREG(SISSR,0x1F,0x04);
+ andSISIDXREG(SISSR,0x1F,0x3F);
+ if(SR1F & 0xc0) mustwait = TRUE;
+
+ if(sisvga_engine == SIS_315_VGA) {
+ inSISIDXREG(SISCR,0x63,CR63);
+ CR63 &= 0x40;
+ andSISIDXREG(SISCR,0x63,0xBF);
+ }
+
+ inSISIDXREG(SISCR,0x17,CR17);
+ CR17 &= 0x80;
+ if(!CR17) {
+ orSISIDXREG(SISCR,0x17,0x80);
+ mustwait = TRUE;
+ outSISIDXREG(SISSR, 0x00, 0x01);
+ outSISIDXREG(SISSR, 0x00, 0x03);
+ }
+
+ if(mustwait) {
+ for(i=0; i < 10; i++) sisfbwaitretracecrt1();
+ }
+
+ i = 3;
+ do {
+ temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine, 0, 0, NULL);
+ } while(((temp == 0) || (temp == 0xffff)) && i--);
+
+ if((temp == 0) || (temp == 0xffff)) {
+ if(sisfb_test_DDC1()) temp = 1;
+ }
+
+ if((temp) && (temp != 0xffff)) {
+ orSISIDXREG(SISCR,0x32,0x20);
+ }
+
+ if(sisvga_engine == SIS_315_VGA) {
+ setSISIDXREG(SISCR,0x63,0xBF,CR63);
+ }
+
+ setSISIDXREG(SISCR,0x17,0x7F,CR17);
+
+ outSISIDXREG(SISSR,0x1F,SR1F);
+}
+
+/* Determine and detect attached devices on SiS30x */
int
SISDoSense(int tempbl, int tempbh, int tempcl, int tempch)
{
- int temp,i;
+ int temp;
outSISIDXREG(SISPART4,0x11,tempbl);
temp = tempbh | tempcl;
setSISIDXREG(SISPART4,0x10,0xe0,temp);
- for(i=0; i<10; i++) SiS_LongWait(&SiS_Pr);
+ SiS_DDC2Delay(&SiS_Pr, 0x1000);
tempch &= 0x7f;
inSISIDXREG(SISPART4,0x03,temp);
temp ^= 0x0e;
@@ -3008,12 +2864,12 @@
SiS_Sense30x(void)
{
u8 backupP4_0d,backupP2_00;
- u8 testsvhs_tempbl, testsvhs_tempbh;
- u8 testsvhs_tempcl, testsvhs_tempch;
- u8 testcvbs_tempbl, testcvbs_tempbh;
- u8 testcvbs_tempcl, testcvbs_tempch;
- u8 testvga2_tempbl, testvga2_tempbh;
- u8 testvga2_tempcl, testvga2_tempch;
+ u8 svhs_bl, svhs_bh;
+ u8 svhs_cl, svhs_ch;
+ u8 cvbs_bl, cvbs_bh;
+ u8 cvbs_cl, cvbs_ch;
+ u8 vga2_bl, vga2_bh;
+ u8 vga2_cl, vga2_ch;
int myflag, result, haveresult, i, j;
char stdstr[] = "sisfb: Detected";
char tvstr[] = "TV connected to";
@@ -3027,77 +2883,79 @@
if(sisvga_engine == SIS_300_VGA) {
if(ivideo.vbflags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV)) {
- testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
- testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
+ vga2_bh = 0x01; vga2_bl = 0x90;
+ svhs_bh = 0x01; svhs_bl = 0x6b;
+ cvbs_bh = 0x01; cvbs_bl = 0x74;
} else {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
+ vga2_bh = 0x00; vga2_bl = 0xd1;
+ svhs_bh = 0x00; svhs_bl = 0xb9;
+ cvbs_bh = 0x00; cvbs_bl = 0xb3;
}
inSISIDXREG(SISPART4,0x01,myflag);
if(myflag & 0x04) {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
- }
- testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
- testsvhs_tempch = 0x04; testsvhs_tempcl = 0x04;
- testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
+ vga2_bh = 0x00; vga2_bl = 0xfd;
+ svhs_bh = 0x00; svhs_bl = 0xdd;
+ cvbs_bh = 0x00; cvbs_bl = 0xee;
+ }
+ vga2_ch = 0x0e; vga2_cl = 0x08;
+ svhs_ch = 0x04; svhs_cl = 0x04;
+ cvbs_ch = 0x08; cvbs_cl = 0x04;
if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
- testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
+ vga2_bh = 0x00; vga2_bl = 0x00;
+ vga2_ch = 0x00; vga2_cl = 0x00;
}
if(ivideo.chip == SIS_300) {
inSISIDXREG(SISSR,0x3b,myflag);
if(!(myflag & 0x01)) {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
- testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
+ vga2_bh = 0x00; vga2_bl = 0x00;
+ vga2_ch = 0x00; vga2_cl = 0x00;
}
}
} else {
- if(ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) {
- testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
- testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
+ if(ivideo.vbflags & (VB_301B|VB_302B)) {
+ vga2_bh = 0x01; vga2_bl = 0x90;
+ svhs_bh = 0x01; svhs_bl = 0x6b;
+ cvbs_bh = 0x01; cvbs_bl = 0x74;
+ } else if(ivideo.vbflags & (VB_301C|VB_302ELV)) {
+ vga2_bh = 0x01; vga2_bl = 0x90;
+ svhs_bh = 0x01; svhs_bl = 0x6b;
+ cvbs_bh = 0x01; cvbs_bl = 0x10;
} else if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
- testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
+ vga2_bh = 0x00; vga2_bl = 0x00;
+ svhs_bh = 0x02; svhs_bl = 0x00;
+ cvbs_bh = 0x01; cvbs_bl = 0x00;
} else {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
- }
- if(ivideo.vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) {
- inSISIDXREG(SISPART4,0x01,myflag);
- if(myflag & 0x04) {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
- }
+ vga2_bh = 0x00; vga2_bl = 0xd1;
+ svhs_bh = 0x00; svhs_bl = 0xb9;
+ cvbs_bh = 0x00; cvbs_bl = 0xb3;
+ inSISIDXREG(SISPART4,0x01,myflag);
+ if(myflag & 0x04) {
+ vga2_bh = 0x00; vga2_bl = 0xfd;
+ svhs_bh = 0x00; svhs_bl = 0xdd;
+ cvbs_bh = 0x00; cvbs_bl = 0xee;
+ }
}
- if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
- testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
- testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
- testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
- testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
+
+ if(ivideo.vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+ vga2_bh = 0x00; vga2_bl = 0x00;
+ vga2_ch = 0x00; vga2_cl = 0x00;
+ svhs_ch = 0x04; svhs_cl = 0x08;
+ cvbs_ch = 0x08; cvbs_cl = 0x08;
} else {
- testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
- testsvhs_tempch = 0x04; testsvhs_tempcl = 0x04;
- testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
+ vga2_ch = 0x0e; vga2_cl = 0x08;
+ svhs_ch = 0x04; svhs_cl = 0x04;
+ cvbs_ch = 0x08; cvbs_cl = 0x04;
}
}
- if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
+ if(vga2_ch || vga2_cl || vga2_bh || vga2_bl) {
haveresult = 0;
for(j = 0; j < 10; j++) {
result = 0;
for(i = 0; i < 3; i++) {
- if(SISDoSense(testvga2_tempbl, testvga2_tempbh,
- testvga2_tempcl, testvga2_tempch))
+ if(SISDoSense(vga2_bl, vga2_bh, vga2_cl, vga2_ch))
result++;
}
if((result == 0) || (result >= 2)) break;
@@ -3110,12 +2968,15 @@
}
}
+ if(ivideo.vbflags & (VB_301C|VB_302ELV)) {
+ orSISIDXREG(SISPART4,0x0d,0x04);
+ }
+
haveresult = 0;
for(j = 0; j < 10; j++) {
result = 0;
for(i = 0; i < 3; i++) {
- if(SISDoSense(testsvhs_tempbl, testsvhs_tempbh,
- testsvhs_tempcl, testsvhs_tempch))
+ if(SISDoSense(svhs_bl, svhs_bh, svhs_cl, svhs_ch))
result++;
}
if((result == 0) || (result >= 2)) break;
@@ -3133,8 +2994,7 @@
for(j = 0; j < 10; j++) {
result = 0;
for(i = 0; i < 3; i++) {
- if(SISDoSense(testcvbs_tempbl, testcvbs_tempbh,
- testcvbs_tempcl, testcvbs_tempch))
+ if(SISDoSense(cvbs_bl, cvbs_bh, cvbs_cl, cvbs_ch))
result++;
}
if((result == 0) || (result >= 2)) break;
@@ -3173,7 +3033,7 @@
SiS_SetChrontelGPIO(&SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
SiS_DDC2Delay(&SiS_Pr, 1000);
temp1 = SiS_GetCH700x(&SiS_Pr, 0x25);
- /* TW: See Chrontel TB31 for explanation */
+ /* See Chrontel TB31 for explanation */
temp2 = SiS_GetCH700x(&SiS_Pr, 0x0e);
if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
SiS_SetCH700x(&SiS_Pr, 0x0b0e);
@@ -3270,7 +3130,7 @@
case 0x04:
printk(KERN_INFO "%s SCART output\n", stdstr);
orSISIDXREG(SISCR, 0x32, 0x04);
- andSISIDXREG(SISCR, 0x32, ~0x03);
+ andSISIDXREG(SISCR, 0x32, ~0x03);
break;
default:
andSISIDXREG(SISCR, 0x32, ~0x07);
@@ -3305,7 +3165,7 @@
u32 agp_phys;
#endif
#endif
-/* TW: The heap start is either set manually using the "mem" parameter, or
+/* The heap start is either set manually using the "mem" parameter, or
* defaults as follows:
* -) If more than 16MB videoRAM available, let our heap start at 12MB.
* -) If more than 8MB videoRAM available, let our heap start at 8MB.
@@ -3344,7 +3204,7 @@
#ifdef CONFIG_FB_SIS_315
if (sisvga_engine == SIS_315_VGA) {
- /* TW: Now initialize the 310 series' command queue mode.
+ /* Now initialize the 310 series' command queue mode.
* On 315, there are three queue modes available which
* are chosen by setting bits 7:5 in SR26:
* 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
@@ -3814,7 +3674,7 @@
static void sisfb_pre_setmode(void)
{
- u8 cr30 = 0, cr31 = 0, cr33 = 0;
+ u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0;
ivideo.currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
@@ -3830,12 +3690,7 @@
switch (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
case CRT2_TV:
ivideo.disp_state = DISPTYPE_TV;
- if (ivideo.vbflags & TV_HIVISION) {
- cr30 = (SIS_VB_OUTPUT_HIVISION | SIS_SIMULTANEOUS_VIEW_ENABLE);
- ivideo.currentvbflags |= (TV_HIVISION | TV_SVIDEO);
- ivideo.TV_type = TVMODE_HIVISION;
- ivideo.TV_plug = TVPLUG_SVIDEO;
- } else if (ivideo.vbflags & TV_SVIDEO) {
+ if (ivideo.vbflags & TV_SVIDEO) {
cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
ivideo.currentvbflags |= TV_SVIDEO;
ivideo.TV_plug = TVPLUG_SVIDEO;
@@ -3853,10 +3708,12 @@
if(!(ivideo.vbflags & TV_HIVISION)) {
if (ivideo.vbflags & TV_PAL) {
cr31 |= 0x01;
+ cr35 |= 0x01;
ivideo.currentvbflags |= TV_PAL;
ivideo.TV_type = TVMODE_PAL;
} else {
cr31 &= ~0x01;
+ cr35 &= ~0x01;
ivideo.currentvbflags |= TV_NTSC;
ivideo.TV_type = TVMODE_NTSC;
}
@@ -3884,6 +3741,11 @@
cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
}
+ if(ivideo.chip >= SIS_661) {
+ cr31 &= ~0x01;
+ /* Leave overscan bit alone */
+ setSISIDXREG(SISCR, 0x35, ~0x10, cr35);
+ }
outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR30, cr30);
outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR31, cr31);
outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR33, cr33);
@@ -3891,7 +3753,10 @@
#ifdef CONFIG_FB_SIS_315
if(sisvga_engine == SIS_315_VGA) {
/* Clear LCDA and PAL-N/M bits */
- andSISIDXREG(SISCR,0x38,~0xc3);
+ andSISIDXREG(SISCR,0x38,~0x03);
+ if(ivideo.chip < SIS_661) {
+ andSISIDXREG(SISCR,0x38,~0xc0);
+ }
}
#endif
@@ -3910,7 +3775,7 @@
#ifdef CONFIG_FB_SIS_300
BOOLEAN doit = TRUE;
#endif
- /* TW: We can't switch off CRT1 if bridge is in slave mode */
+ /* We can't switch off CRT1 if bridge is in slave mode */
if(ivideo.vbflags & VB_VIDEOBRIDGE) {
#ifdef CONFIG_FB_SIS_300
if(sisvga_engine == SIS_300_VGA) {
@@ -4089,7 +3954,7 @@
char *this_opt;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- sis_fb_info.fontname[0] = '\0';
+ sisfb_fontname[0] = '\0';
#endif
ivideo.refresh_rate = 0;
@@ -4115,7 +3980,8 @@
sisfb_inverse = 1;
/* fb_invert_cmaps(); */
} else if (!strnicmp(this_opt, "font:", 5)) {
- strcpy(sis_fb_info.fontname, this_opt + 5);
+ strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
+ sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
#endif
} else if (!strnicmp(this_opt, "vrate:", 6)) {
ivideo.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
@@ -4147,6 +4013,8 @@
sisfb_accel = 0;
} else if (!strnicmp(this_opt, "noypan", 6)) {
sisfb_ypan = 0;
+ } else if (!strnicmp(this_opt, "nomax", 5)) {
+ sisfb_max = 0;
} else if (!strnicmp(this_opt, "userom:", 7)) {
sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
} else if (!strnicmp(this_opt, "useoem:", 7)) {
@@ -4195,14 +4063,16 @@
char *sis_sig_300[4] = {
"300", "540", "630", "730"
};
- char *sis_sig_310[9] = {
- "315", "315", "315", "5315", "6325", "6325", "Xabre", "6330", "6330"
+ char *sis_sig_310[11] = {
+ "315", "315", "315", "5315", "6325", "6325",
+ "Xabre", "6330", "6330", "6330", "6330"
};
ushort sis_nums_300[4] = {
SIS_300, SIS_540, SIS_630, SIS_730
};
- unsigned short sis_nums_310[9] = {
- SIS_315PRO, SIS_315H, SIS_315, SIS_550, SIS_650, SIS_740, SIS_330, SIS_660, SIS_760
+ unsigned short sis_nums_310[11] = {
+ SIS_315PRO, SIS_315H, SIS_315, SIS_550, SIS_650, SIS_740,
+ SIS_330, SIS_661, SIS_741, SIS_660, SIS_760
};
for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
@@ -4239,7 +4109,7 @@
}
}
if(stage != 4) {
- for(i = 0;(i < 9) && (stage != 4); i++) {
+ for(i = 0;(i < 11) && (stage != 4); i++) {
if(strncmp(sis_sig_310[i], rom, strlen(sis_sig_310[i])) == 0) {
if(sis_nums_310[i] == ivideo.chip) {
stage = 4;
@@ -4271,9 +4141,7 @@
u16 reg16;
u8 reg;
- /* outb(0x77, 0x80); */ /* What is this? */
-
-#if 0
+#if 0
/* for DOC VB */
sisfb_set_reg4(0xcf8,0x800000e0);
reg32 = sisfb_get_reg3(0xcfc);
@@ -4288,7 +4156,7 @@
sisfb_registered = 0;
sisfb_thismonitor.datavalid = FALSE;
- memset(&sis_fb_info, 0, sizeof(sis_fb_info));
+ memset(&sishw_ext, 0, sizeof(sishw_ext));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
memset(&sisfb_lastrates[0], 0, 128);
@@ -4296,7 +4164,7 @@
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
memset(&sis_disp, 0, sizeof(sis_disp));
-#endif
+#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
pci_for_each_dev(pdev) {
@@ -4307,8 +4175,17 @@
if ((b->vendor == pdev->vendor)
&& (b->device == pdev->device)) {
pdev_valid = 1;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
- strcpy(sis_fb_info.modename, b->name);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ sis_fb_info = framebuffer_alloc(0, &pdev->dev);
+#else
+ sis_fb_info = kmalloc(sizeof(*sis_fb_info), GFP_KERNEL);
+#endif
+ if(!sis_fb_info) return -ENOMEM;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ memset(sis_fb_info, 0, sizeof(*sis_fb_info));
+#endif
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+ strcpy(sis_fb_info->modename, b->name);
#else
strcpy(myid, b->name);
#endif
@@ -4350,7 +4227,7 @@
if(reg32 == 0x07301039) {
ivideo.chip = SIS_730;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
- strcpy(sis_fb_info.modename, "SIS 730");
+ strcpy(sis_fb_info->modename, "SIS 730");
#else
strcpy(myid, "SIS 730");
#endif
@@ -4400,7 +4277,7 @@
if(reg32 == 0x07401039) {
ivideo.chip = SIS_740;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
- strcpy(sis_fb_info.modename, "SIS 740");
+ strcpy(sis_fb_info->modename, "SIS 740");
#else
strcpy(myid, "SIS 740");
#endif
@@ -4418,16 +4295,36 @@
break;
case PCI_DEVICE_ID_SI_660_VGA:
{
- ivideo.chip = SIS_660;
sisfb_set_reg4(0xCF8, 0x80000000);
reg32 = sisfb_get_reg3(0xCFC);
if(reg32 == 0x07601039) {
ivideo.chip = SIS_760;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
- strcpy(sis_fb_info.modename, "SIS 760");
+ strcpy(sis_fb_info->modename, "SIS 760");
#else
strcpy(myid, "SIS 760");
#endif
+ } else if(reg32 == 0x06601039) {
+ ivideo.chip = SIS_660;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+ strcpy(sis_fb_info->modename, "SIS 660");
+#else
+ strcpy(myid, "SIS 660");
+#endif
+ } else if(reg32 == 0x07411039) {
+ ivideo.chip = SIS_741;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+ strcpy(sis_fb_info->modename, "SIS 741");
+#else
+ strcpy(myid, "SIS 741");
+#endif
+ } else {
+ ivideo.chip = SIS_661;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+ strcpy(sis_fb_info->modename, "SIS 661");
+#else
+ strcpy(myid, "SIS 661");
+#endif
}
sisvga_engine = SIS_315_VGA;
sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
@@ -4436,6 +4333,7 @@
}
#endif
default:
+ kfree(sis_fb_info);
return -ENODEV;
}
sishw_ext.jChipType = ivideo.chip;
@@ -4447,20 +4345,26 @@
ivideo.video_base = pci_resource_start(pdev, 0);
ivideo.mmio_base = pci_resource_start(pdev, 1);
- sishw_ext.ulIOAddress = (unsigned short) ivideo.vga_base =
- (unsigned short) SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
+ sishw_ext.ulIOAddress = SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
+ ivideo.vga_base = (unsigned short) sishw_ext.ulIOAddress;
sisfb_mmio_size = pci_resource_len(pdev, 1);
if(!sisvga_enabled) {
- if (pci_enable_device(pdev)) return -EIO;
+ if(pci_enable_device(pdev)) {
+ kfree(sis_fb_info);
+ return -EIO;
+ }
}
SiS_Pr.SiS_Backup70xx = 0xff;
SiS_Pr.SiS_CHOverScan = -1;
SiS_Pr.SiS_ChSW = FALSE;
SiS_Pr.SiS_UseLCDA = FALSE;
- SiSRegInit(&SiS_Pr, (USHORT)sishw_ext.ulIOAddress);
+ SiS_Pr.HaveEMI = FALSE;
+ SiS_Pr.HaveEMILCD = FALSE;
+ SiS_Pr.OverruleEMI = FALSE;
+ SiSRegInit(&SiS_Pr, sishw_ext.ulIOAddress);
#ifdef CONFIG_FB_SIS_300
/* TW: Find PCI systems for Chrontel/GPIO communication setup */
@@ -4487,37 +4391,13 @@
if((reg & 0x80) && (reg != 0xff)) {
if((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {
printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
+ kfree(sis_fb_info);
return -EBUSY;
}
}
#endif
#endif
-#ifdef LINUXBIOS /* -------------------------------- */
-
-#ifdef CONFIG_FB_SIS_300
- if (sisvga_engine == SIS_300_VGA) {
- outSISIDXREG(SISSR, 0x28, 0x37); /* Reset memory clock */
-
- outSISIDXREG(SISSR, 0x29, 0x61);
-
- orSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_1A, SIS_SCRATCH_REG_1A_MASK);
- }
-#endif
-#ifdef CONFIG_FB_SIS_315
- if (ivideo.chip == SIS_550 || ivideo.chip == SIS_650 ||
- ivideo.chip == SIS_740 || ivideo.chip == SIS_660 ||
- ivideo.chip == SIS_760) {
- outSISIDXREG(SISSR, 0x28, 0x5a);
-
- outSISIDXREG(SISSR, 0x29, 0x64);
-
- outSISIDXREG(SISCR, 0x3a, 0x00);
- }
-#endif
-
-#endif /* LinuxBIOS -------------------------------- */
-
if (sisvga_engine == SIS_315_VGA) {
switch (ivideo.chip) {
case SIS_315H:
@@ -4528,6 +4408,8 @@
case SIS_550:
case SIS_650:
case SIS_740:
+ case SIS_661:
+ case SIS_741:
case SIS_660:
case SIS_760:
sishw_ext.bIntegratedMMEnabled = TRUE;
@@ -4547,7 +4429,6 @@
}
}
- sishw_ext.pDevice = NULL;
if(sisfb_userom) {
sishw_ext.pjVirtualRomBase = sis_find_rom();
if(sishw_ext.pjVirtualRomBase) {
@@ -4563,11 +4444,9 @@
sishw_ext.UseROM = FALSE;
printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
}
- sishw_ext.pjCustomizedROMImage = NULL;
sishw_ext.bSkipDramSizing = 0;
sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;
sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
- strcpy(sishw_ext.szVBIOSVer, "0.84");
/* Find systems for special custom timing */
if(SiS_Pr.SiS_CustomT == CUT_NONE) {
@@ -4598,13 +4477,13 @@
(mycustomttable[i].pcisubsysvendor == ivideo.subsysvendor) &&
(mycustomttable[i].pcisubsyscard == ivideo.subsysdevice) ) {
footprint = TRUE;
- if(sishw_ext.UseROM) {
- for(j=0; j<5; j++) {
- if(mycustomttable[i].biosFootprintAddr[j]) {
+ for(j=0; j<5; j++) {
+ if(mycustomttable[i].biosFootprintAddr[j]) {
+ if(sishw_ext.UseROM) {
if(sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
mycustomttable[i].biosFootprintData[j])
footprint = FALSE;
- }
+ } else footprint = FALSE;
}
}
if(footprint) {
@@ -4612,6 +4491,8 @@
printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
mycustomttable[i].vendorName,
mycustomttable[i].cardName);
+ printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
+ mycustomttable[i].optionName);
break;
}
}
@@ -4632,6 +4513,7 @@
sishw_ext.pSR = vmalloc(sizeof(SIS_DSReg) * SR_BUFFER_SIZE);
if (sishw_ext.pSR == NULL) {
printk(KERN_ERR "sisfb: Fatal error: Allocating SRReg space failed.\n");
+ kfree(sis_fb_info);
return -ENODEV;
}
sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
@@ -4640,6 +4522,7 @@
if (sishw_ext.pCR == NULL) {
vfree(sishw_ext.pSR);
printk(KERN_ERR "sisfb: Fatal error: Allocating CRReg space failed.\n");
+ kfree(sis_fb_info);
return -ENODEV;
}
sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;
@@ -4651,29 +4534,14 @@
sishw_ext.pjVideoMemoryAddress
= ioremap(ivideo.video_base, 0x4000000);
if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
-#ifdef LINUXBIOS /* TW: SiSInit now for LinuxBIOS only */
- SiSInit(&SiS_Pr, &sishw_ext);
-#endif
outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
}
}
-#ifdef LINUXBIOS
- else {
- sishw_ext.pjVideoMemoryAddress
- = ioremap(ivideo.video_base, 0x4000000);
- if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
- SiSInit(&SiS_Pr, &sishw_ext);
- outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
- }
- }
- if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
- orSISIDXREG(SISSR, 0x07, 0x10);
- }
-#endif
if(sisfb_get_dram_size_300()) {
vfree(sishw_ext.pSR);
vfree(sishw_ext.pCR);
printk(KERN_ERR "sisfb: Fatal error: Unable to determine RAM size\n");
+ kfree(sis_fb_info);
return -ENODEV;
}
}
@@ -4686,32 +4554,7 @@
sishw_ext.pjVideoMemoryAddress
= ioremap(ivideo.video_base, 0x8000000);
if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
-#ifdef LINUXBIOS
- /* TW: SISInit is now for LINUXBIOS only */
- SiSInit(&SiS_Pr, &sishw_ext);
-#endif
-
- outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-
- sishw_ext.bSkipDramSizing = TRUE;
- sishw_ext.pSR[0].jIdx = 0x13;
- sishw_ext.pSR[1].jIdx = 0x14;
- sishw_ext.pSR[2].jIdx = 0xFF;
- inSISIDXREG(SISSR, 0x13, sishw_ext.pSR[0].jVal);
- inSISIDXREG(SISSR, 0x14, sishw_ext.pSR[1].jVal);
- sishw_ext.pSR[2].jVal = 0xFF;
- }
- }
-#ifdef LINUXBIOS
- else {
- sishw_ext.pjVideoMemoryAddress
- = ioremap(ivideo.video_base, 0x8000000);
- if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
-
- SiSInit(&SiS_Pr, &sishw_ext);
-
outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-
sishw_ext.bSkipDramSizing = TRUE;
sishw_ext.pSR[0].jIdx = 0x13;
sishw_ext.pSR[1].jIdx = 0x14;
@@ -4721,11 +4564,11 @@
sishw_ext.pSR[2].jVal = 0xFF;
}
}
-#endif
- if (sisfb_get_dram_size_315()) {
+ if(sisfb_get_dram_size_315()) {
vfree(sishw_ext.pSR);
vfree(sishw_ext.pCR);
printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
+ kfree(sis_fb_info);
return -ENODEV;
}
}
@@ -4745,9 +4588,9 @@
if(sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
if(sisfb_pdc) {
- sishw_ext.pdc = sisfb_pdc;
+ SiS_Pr.PDC = sisfb_pdc;
} else {
- sishw_ext.pdc = 0;
+ SiS_Pr.PDC = 0;
}
if (!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) {
@@ -4755,6 +4598,7 @@
printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
vfree(sishw_ext.pSR);
vfree(sishw_ext.pCR);
+ kfree(sis_fb_info);
return -ENODEV;
}
@@ -4763,6 +4607,7 @@
release_mem_region(ivideo.video_base, ivideo.video_size);
vfree(sishw_ext.pSR);
vfree(sishw_ext.pCR);
+ kfree(sis_fb_info);
return -ENODEV;
}
@@ -4791,6 +4636,8 @@
sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
sishw_ext.Is301BDH = FALSE;
sishw_ext.usExternalChip = 0;
+
+ sisfb_sense_crt1();
sisfb_get_VB_type();
@@ -4834,63 +4681,72 @@
}
sisfb_detectedpdc = 0;
-#ifndef LINUXBIOS
+
#ifdef CONFIG_FB_SIS_300
- /* TW: Save the current PanelDelayCompensation if the LCD is currently used */
+ /* Save the current PanelDelayCompensation if the LCD is currently used */
if(sisvga_engine == SIS_300_VGA) {
- if(ivideo.vbflags & (VB_LVDS | VB_30xBDH)) {
+ if(ivideo.vbflags & (VB_LVDS | VB_30xBDH)) {
int tmp;
inSISIDXREG(SISCR,0x30,tmp);
if(tmp & 0x20) {
/* Currently on LCD? If yes, read current pdc */
inSISIDXREG(SISPART1,0x13,sisfb_detectedpdc);
sisfb_detectedpdc &= 0x3c;
- if(sishw_ext.pdc == 0) {
+ if(SiS_Pr.PDC == 0) {
/* Let option override detection */
- sishw_ext.pdc = sisfb_detectedpdc;
+ SiS_Pr.PDC = sisfb_detectedpdc;
}
printk(KERN_INFO
"sisfb: Detected LCD PanelDelayCompensation %d\n",
sisfb_detectedpdc);
}
- if((sishw_ext.pdc) && (sishw_ext.pdc != sisfb_detectedpdc)) {
+ if((SiS_Pr.PDC) && (SiS_Pr.PDC != sisfb_detectedpdc)) {
printk(KERN_INFO
"sisfb: Using LCD PanelDelayCompensation %d\n",
- sishw_ext.pdc);
+ SiS_Pr.PDC);
}
- }
+ }
}
#endif
-#endif
+
sisfb_detectedlcda = 0xff;
-#ifndef LINUXBIOS
+
#ifdef CONFIG_FB_SIS_315
if(sisvga_engine == SIS_315_VGA) {
/* Save PDC */
- if(ivideo.vbflags & (VB_301LV | VB_302LV)) {
+ if(ivideo.vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
int tmp;
inSISIDXREG(SISCR,0x30,tmp);
if(tmp & 0x20) {
/* Currently on LCD? If yes, read current pdc */
inSISIDXREG(SISPART1,0x2D,sisfb_detectedpdc);
- if(sishw_ext.pdc == 0) {
+ if(SiS_Pr.PDC == 0) {
/* Let option override detection */
- sishw_ext.pdc = sisfb_detectedpdc;
+ SiS_Pr.PDC = sisfb_detectedpdc;
}
printk(KERN_INFO
"sisfb: Detected LCD PanelDelayCompensation %d\n",
sisfb_detectedpdc);
}
- if((sishw_ext.pdc) && (sishw_ext.pdc != sisfb_detectedpdc)) {
+ if((SiS_Pr.PDC) && (SiS_Pr.PDC != sisfb_detectedpdc)) {
printk(KERN_INFO
"sisfb: Using LCD PanelDelayCompensation %d\n",
- sishw_ext.pdc);
+ SiS_Pr.PDC);
+ }
+ /* Save EMI */
+ if(ivideo.vbflags & (VB_302LV | VB_302ELV)) {
+ inSISIDXREG(SISPART4,0x30,SiS_Pr.EMI_30);
+ inSISIDXREG(SISPART4,0x31,SiS_Pr.EMI_31);
+ inSISIDXREG(SISPART4,0x32,SiS_Pr.EMI_32);
+ inSISIDXREG(SISPART4,0x33,SiS_Pr.EMI_33);
+ SiS_Pr.HaveEMI = TRUE;
+ if(tmp & 0x20) SiS_Pr.HaveEMILCD = TRUE;
}
}
/* Try to find about LCDA */
- if(ivideo.vbflags & (VB_302B | VB_301LV | VB_302LV)) {
+ if(ivideo.vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
int tmp;
inSISIDXREG(SISCR,0x34,tmp);
if((tmp <= 0x13) || (tmp == 0xff)) {
@@ -4921,7 +4777,6 @@
}
}
#endif
-#endif
if (!sisfb_crt1off) {
sisfb_handle_ddc(&sisfb_thismonitor, 0);
@@ -4991,6 +4846,7 @@
vfree(sishw_ext.pCR);
release_mem_region(ivideo.video_base, ivideo.video_size);
release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
+ kfree(sis_fb_info);
return -EINVAL;
}
@@ -5005,18 +4861,21 @@
sisfb_initaccel();
}
+ /* Maximize regardless of sisfb_max at startup */
+ default_var.yres_virtual = 32767;
sisfb_crtc_to_var(&default_var);
- sis_fb_info.node = -1;
- sis_fb_info.flags = FBINFO_FLAG_DEFAULT;
- sis_fb_info.blank = &sisfb_blank;
- sis_fb_info.fbops = &sisfb_ops;
- sis_fb_info.switch_con = &sisfb_switch;
- sis_fb_info.updatevar = &sisfb_update_var;
- sis_fb_info.changevar = NULL;
- sis_fb_info.disp = &sis_disp;
+ sis_fb_info->node = -1;
+ sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
+ sis_fb_info->blank = &sisfb_blank;
+ sis_fb_info->fbops = &sisfb_ops;
+ sis_fb_info->switch_con = &sisfb_switch;
+ sis_fb_info->updatevar = &sisfb_update_var;
+ sis_fb_info->changevar = NULL;
+ sis_fb_info->disp = &sis_disp;
+ strcpy(sis_fb_info->fontname, sisfb_fontname);
- sisfb_set_disp(-1, &default_var, &sis_fb_info);
+ sisfb_set_disp(-1, &default_var, sis_fb_info);
#else /* --------- For 2.5: Setup a somewhat sane default var ------------ */
@@ -5030,7 +4889,7 @@
sisfb_bpp_to_var(&default_var);
- default_var.pixclock = (u32) (1E12 /
+ default_var.pixclock = (u32) (1000000000 /
sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
sisfb_mode_no, sisfb_rate_idx));
@@ -5040,9 +4899,9 @@
&default_var.upper_margin, &default_var.lower_margin,
&default_var.hsync_len, &default_var.vsync_len,
&default_var.sync, &default_var.vmode)) {
- if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
- default_var.pixclock <<= 1;
- }
+ if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ default_var.pixclock <<= 1;
+ }
}
ivideo.accel = 0;
@@ -5053,26 +4912,26 @@
}
if(sisfb_ypan) {
- default_var.yres_virtual =
+ /* Maximize regardless of sisfb_max at startup */
+ default_var.yres_virtual =
ivideo.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
- if(default_var.yres_virtual <= default_var.yres) {
- default_var.yres_virtual = default_var.yres;
- }
- }
-
- sis_fb_info.flags = FBINFO_FLAG_DEFAULT;
- sis_fb_info.var = default_var;
- sis_fb_info.fix = sisfb_fix;
- sis_fb_info.par = &ivideo;
- sis_fb_info.screen_base = ivideo.video_vbase;
- sis_fb_info.fbops = &sisfb_ops;
-#if 0 /* Waits for class patch to go in */
- sis_fb_info.dev = &pdev->dev;
-#endif
- sisfb_get_fix(&sis_fb_info.fix, -1, &sis_fb_info);
- sis_fb_info.pseudo_palette = pseudo_palette;
+ if(default_var.yres_virtual > 32767) default_var.yres_virtual = 32767;
+ if(default_var.yres_virtual <= default_var.yres) {
+ default_var.yres_virtual = default_var.yres;
+ }
+ }
+
+ sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
+ sis_fb_info->var = default_var;
+ sis_fb_info->fix = sisfb_fix;
+ sis_fb_info->par = &ivideo;
+ sis_fb_info->screen_base = ivideo.video_vbase;
+ sis_fb_info->fbops = &sisfb_ops;
+ sis_fb_info->class_dev.dev = &pdev->dev;
+ sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
+ sis_fb_info->pseudo_palette = pseudo_palette;
- fb_alloc_cmap(&sis_fb_info.cmap, 256 , 0);
+ fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
#endif
printk(KERN_INFO "sisfb: Initial vbflags 0x%lx\n", ivideo.vbflags);
@@ -5091,7 +4950,7 @@
vc_resize_con(1, 1, 0);
#endif
- if(register_framebuffer(&sis_fb_info) < 0) {
+ if(register_framebuffer(sis_fb_info) < 0) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
vfree(sishw_ext.pSR);
vfree(sishw_ext.pCR);
@@ -5099,32 +4958,31 @@
release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
#endif
printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
+ kfree(sis_fb_info);
return -EINVAL;
}
sisfb_registered = 1;
- printk(KERN_INFO "sisfb: Installed SISFB_GET_INFO ioctl (%x)\n", SISFB_GET_INFO);
- printk(KERN_INFO "sisfb: Installed SISFB_GET_VBRSTATUS ioctl (%x)\n", SISFB_GET_VBRSTATUS);
+ printk(KERN_DEBUG "sisfb: Installed SISFB_GET_INFO ioctl (%x)\n", SISFB_GET_INFO);
+ printk(KERN_DEBUG "sisfb: Installed SISFB_GET_VBRSTATUS ioctl (%x)\n", SISFB_GET_VBRSTATUS);
printk(KERN_INFO "sisfb: 2D acceleration is %s, scrolling mode %s\n",
sisfb_accel ? "enabled" : "disabled",
- sisfb_ypan ? "ypan" : "redraw");
+ sisfb_ypan ? (sisfb_max ? "ypan (auto-max)" : "ypan (no auto-max)") : "redraw");
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
- GET_FB_IDX(sis_fb_info.node), sis_fb_info.modename, VER_MAJOR, VER_MINOR,
+ GET_FB_IDX(sis_fb_info->node), sis_fb_info->modename, VER_MAJOR, VER_MINOR,
VER_LEVEL);
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#else
printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
- sis_fb_info.node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
+ sis_fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
#endif
- printk(KERN_INFO "sisfb: (C) 2001-2003 Thomas Winischhofer. All rights reserved.\n");
+ printk(KERN_INFO "sisfb: (C) 2001-2003 Thomas Winischhofer.\n");
- } /* TW: if mode = "none" */
+ } /* if mode = "none" */
return 0;
}
@@ -5142,6 +5000,7 @@
static int pdc = 0;
static int noaccel = -1;
static int noypan = -1;
+static int nomax = -1;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
static int inverse = 0;
#endif
@@ -5153,7 +5012,7 @@
static char *specialtiming = NULL;
static int lvdshl = -1;
-MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/650/651/661/740/741/330 framebuffer driver");
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/650/651/661/740/741/330/760 framebuffer driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>; SiS; Various others");
@@ -5209,7 +5068,7 @@
MODULE_PARM(queuemode, "s");
MODULE_PARM_DESC(queuemode,
- "\nSelects the queue mode on 315/550/650/740/330/660. Possible choices are AGP, VRAM,\n"
+ "\nSelects the queue mode on 315/550/65x/74x/330/760. Possible choices are AGP, VRAM,\n"
"MMIO. AGP is only available if the kernel has AGP support. The queue mode is\n"
"important to programs using the 2D/3D accelerator of the SiS chip. The modes\n"
"require a totally different way of programming the engines. If any mode than\n"
@@ -5252,14 +5111,21 @@
MODULE_PARM(noaccel, "i");
MODULE_PARM_DESC(noaccel,
- "\nIf set to anything other than 0, 2D acceleration and y-panning will be\n"
- "disabled. (default: 0)");
+ "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+ "(default: 0)");
MODULE_PARM(noypan, "i");
MODULE_PARM_DESC(noypan,
"\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
"will be performed by redrawing the screen. (default: 0)");
+MODULE_PARM(nomax, "i");
+MODULE_PARM_DESC(nomax,
+ "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
+ "memory for the virtual screen in order to optimize scrolling performance. If this\n"
+ "is set to anything other than 0, sisfb will not do this and thereby enable the user\n"
+ "to positively specify a virtual Y size of the screen using fbset. (default: 0)\n");
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
MODULE_PARM(inverse, "i");
MODULE_PARM_DESC(inverse,
@@ -5349,9 +5215,13 @@
if(noypan == 1) sisfb_ypan = 0;
else if(noypan == 0) sisfb_ypan = 1;
+
+ if(nomax == 1) sisfb_max = 0;
+ else if(nomax == 0) sisfb_max = 1;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
if(inverse) sisfb_inverse = 1;
+ sisfb_fontname[0] = '\0';
#endif
if(mem) sisfb_mem = mem;
@@ -5362,7 +5232,7 @@
if (queuemode) sisfb_search_queuemode(queuemode);
- /* TW: If other queuemode than MMIO, disable 2D accel and ypan */
+ /* If other queuemode than MMIO, disable 2D accel and ypan */
if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
sisfb_accel = 0;
}
@@ -5383,7 +5253,7 @@
void cleanup_module(void)
{
- /* TW: Release mem regions */
+ /* Release mem regions */
release_mem_region(ivideo.video_base, ivideo.video_size);
release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
@@ -5398,7 +5268,12 @@
/* Unregister the framebuffer */
if(sisfb_registered) {
- unregister_framebuffer(&sis_fb_info);
+ unregister_framebuffer(sis_fb_info);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ framebuffer_release(sis_fb_info);
+#else
+ kfree(sis_fb_info);
+#endif
}
if(sishw_ext.pSR) vfree(sishw_ext.pSR);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)