diff --git a/src/kernel_patches/linux-2.4.6-sis.patch b/src/kernel_patches/linux-2.4.6-sis.patch index 9e3ef58f28..1d7456d414 100644 --- a/src/kernel_patches/linux-2.4.6-sis.patch +++ b/src/kernel_patches/linux-2.4.6-sis.patch @@ -1,6 +1,17 @@ -diff -ur linux-2.4.6/arch/i386/config.in linux-2.4.6-sis/arch/i386/config.in ---- linux-2.4.6/arch/i386/config.in Wed Jun 20 18:47:39 2001 -+++ linux-2.4.6-sis/arch/i386/config.in Thu Jul 19 10:18:35 2001 +diff -urN linux-2.4.6-official/arch/i386/Linuxbios.in linux-2.4.6-linuxbios/arch/i386/Linuxbios.in +--- linux-2.4.6-official/arch/i386/Linuxbios.in Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/arch/i386/Linuxbios.in Mon Jul 23 12:16:04 2001 +@@ -0,0 +1,7 @@ ++mainmenu_option next_comment ++comment 'Linuxbios Options' ++bool 'Force IDE Controllers on?' CONFIG_LINUXBIOS_FORCE_IDE_CONTROLLER_ON ++bool 'Wait for HDA to spin up?' CONFIG_LINUXBIOS_WAIT_HDA_SPINUP ++bool 'Do not touch debug registers?' CONFIG_LINUXBIOS_DONT_TOUCH_DR ++bool 'LOBOS (Linux Os Boots OS)?' CONFIG_LINUXBIOS_LOBOS ++endmenu +diff -urN linux-2.4.6-official/arch/i386/config.in linux-2.4.6-linuxbios/arch/i386/config.in +--- linux-2.4.6-official/arch/i386/config.in Thu Jun 21 08:47:39 2001 ++++ linux-2.4.6-linuxbios/arch/i386/config.in Mon Jul 23 12:13:13 2001 @@ -389,3 +389,13 @@ #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ @@ -15,9 +26,9 @@ diff -ur linux-2.4.6/arch/i386/config.in linux-2.4.6-sis/arch/i386/config.in +fi + +endmenu -diff -ur linux-2.4.6/arch/i386/kernel/process.c linux-2.4.6-sis/arch/i386/kernel/process.c ---- linux-2.4.6/arch/i386/kernel/process.c Fri Feb 9 12:29:44 2001 -+++ linux-2.4.6-sis/arch/i386/kernel/process.c Thu Jul 19 10:18:35 2001 +diff -urN linux-2.4.6-official/arch/i386/kernel/process.c linux-2.4.6-linuxbios/arch/i386/kernel/process.c +--- linux-2.4.6-official/arch/i386/kernel/process.c Sat Feb 10 03:29:44 2001 ++++ linux-2.4.6-linuxbios/arch/i386/kernel/process.c Mon Jul 23 12:13:13 2001 @@ -49,6 +49,131 @@ #include @@ -172,9 +183,9 @@ diff -ur linux-2.4.6/arch/i386/kernel/process.c linux-2.4.6-sis/arch/i386/kernel if (pm_power_off) pm_power_off(); } -diff -ur linux-2.4.6/drivers/ide/ide-pci.c linux-2.4.6-sis/drivers/ide/ide-pci.c ---- linux-2.4.6/drivers/ide/ide-pci.c Wed Jun 27 15:12:04 2001 -+++ linux-2.4.6-sis/drivers/ide/ide-pci.c Thu Jul 19 10:18:36 2001 +diff -urN linux-2.4.6-official/drivers/ide/ide-pci.c linux-2.4.6-linuxbios/drivers/ide/ide-pci.c +--- linux-2.4.6-official/drivers/ide/ide-pci.c Thu Jun 28 05:12:04 2001 ++++ linux-2.4.6-linuxbios/drivers/ide/ide-pci.c Mon Jul 23 12:13:13 2001 @@ -628,8 +628,19 @@ for (port = 0; port <= 1; ++port) { unsigned long base = 0, ctl = 0; @@ -195,9 +206,9 @@ diff -ur linux-2.4.6/drivers/ide/ide-pci.c linux-2.4.6-sis/drivers/ide/ide-pci.c if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03)) return; if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { -diff -ur linux-2.4.6/drivers/ide/ide-probe.c linux-2.4.6-sis/drivers/ide/ide-probe.c ---- linux-2.4.6/drivers/ide/ide-probe.c Sun Mar 18 10:25:02 2001 -+++ linux-2.4.6-sis/drivers/ide/ide-probe.c Thu Jul 19 10:18:36 2001 +diff -urN linux-2.4.6-official/drivers/ide/ide-probe.c linux-2.4.6-linuxbios/drivers/ide/ide-probe.c +--- linux-2.4.6-official/drivers/ide/ide-probe.c Mon Mar 19 01:25:02 2001 ++++ linux-2.4.6-linuxbios/drivers/ide/ide-probe.c Mon Jul 23 12:13:13 2001 @@ -310,6 +310,13 @@ if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY)) return 4; @@ -212,9 +223,9 @@ diff -ur linux-2.4.6/drivers/ide/ide-probe.c linux-2.4.6-sis/drivers/ide/ide-pro #ifdef DEBUG printk("probing for %s: present=%d, media=%d, probetype=%s\n", drive->name, drive->present, drive->media, -diff -ur linux-2.4.6/drivers/mtd/devices/docprobe.c linux-2.4.6-sis/drivers/mtd/devices/docprobe.c ---- linux-2.4.6/drivers/mtd/devices/docprobe.c Tue Jun 12 11:30:27 2001 -+++ linux-2.4.6-sis/drivers/mtd/devices/docprobe.c Thu Jul 19 16:54:34 2001 +diff -urN linux-2.4.6-official/drivers/mtd/devices/docprobe.c linux-2.4.6-linuxbios/drivers/mtd/devices/docprobe.c +--- linux-2.4.6-official/drivers/mtd/devices/docprobe.c Wed Jun 13 01:30:27 2001 ++++ linux-2.4.6-linuxbios/drivers/mtd/devices/docprobe.c Mon Jul 23 12:13:13 2001 @@ -39,7 +39,7 @@ a Millennium enough that they go through and work out what the difference is :) @@ -224,42 +235,1789 @@ diff -ur linux-2.4.6/drivers/mtd/devices/docprobe.c linux-2.4.6-sis/drivers/mtd/ #include #include -diff -ur linux-2.4.6/drivers/video/sis/Makefile linux-2.4.6-sis/drivers/video/sis/Makefile ---- linux-2.4.6/drivers/video/sis/Makefile Fri Dec 29 15:07:23 2000 -+++ linux-2.4.6-sis/drivers/video/sis/Makefile Thu Jul 19 10:19:08 2001 -@@ -4,9 +4,7 @@ +diff -urN linux-2.4.6-official/drivers/video/sis/Makefile linux-2.4.6-linuxbios/drivers/video/sis/Makefile +--- linux-2.4.6-official/drivers/video/sis/Makefile Sat Dec 30 06:07:23 2000 ++++ linux-2.4.6-linuxbios/drivers/video/sis/Makefile Thu Jul 5 15:28:11 2001 +@@ -4,9 +4,21 @@ O_TARGET := sisfb.o -obj-y := sis_main.o sis_300.o sis_301.o -+obj-y := sisfb_lite.o sisfb_accel.o - obj-m := $(O_TARGET) +-obj-m := $(O_TARGET) ++# SiS 530/620 ++#obj-y := sisfb_lite.o sisfb_legacy_init.o sisfb_530_init.o sisfb_530_core.o sisfb_530_accel.o ++ ++# SiS 540/630 ++#obj-y := sisfb_lite.o sisfb_accel.o sisfb_legacy_init.o sisfb_300_init.o \ ++# sisfb_300_core.o sisfb_530_accel.o -include $(TOPDIR)/Rules.make -- -- -+include $(TOPDIR)/Rules.make -diff -urN linux-2.4.3-official/drivers/video/sis/Makefile linux-2.4.3-linuxbios/drivers/video/sis/Makefile ---- linux-2.4.3-official/drivers/video/sis/Makefile Sat Dec 30 06:07:23 2000 -+++ linux-2.4.3-linuxbios/drivers/video/sis/Makefile Tue Apr 10 10:33:36 2001 -@@ -4,9 +4,7 @@ ++# SiS 550 ++#obj-y := sisfb_lite.o sisfb_accel.o sisfb_legacy_init.o sisfb_315_init.o \ ++# sisfb_300_core.o sisfb_315_accel.o - O_TARGET := sisfb.o ++obj-y := sisfb_lite.o sisfb_accel.o sisfb_legacy_init.o sisfb_300_init.o \ ++ sisfb_300_core.o sisfb_530_accel.o \ ++ sisfb_315_init.o sisfb_315_accel.o ++ ++obj-m := $(O_TARGET) --obj-y := sis_main.o sis_300.o sis_301.o -+obj-y := sisfb_lite.o sisfb_accel.o - obj-m := $(O_TARGET) - --include $(TOPDIR)/Rules.make -- -- +include $(TOPDIR)/Rules.make \ No newline at end of file -diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linuxbios/drivers/video/sis/sisfb_accel.c ---- linux-2.4.3-official/drivers/video/sis/sisfb_accel.c Thu Jan 1 08:00:00 1970 -+++ linux-2.4.3-linuxbios/drivers/video/sis/sisfb_accel.c Tue Apr 10 10:33:36 2001 -@@ -0,0 +1,777 @@ -+/* sisfb_accel.c: 2D Hardware Acceleration for SiS 300/540/630/730 +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_300_core.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_300_core.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_300_core.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_300_core.c Mon Jul 23 11:58:33 2001 +@@ -0,0 +1,579 @@ ++/* sisfb_300_core.c: Setting Video Mode for SiS 540/550/630/730 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * 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 License, or ++ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. Glamour Design Guideline V0.8 ++ * 2. Programmer's Guide to the EGA, VGA, and Super VGA Card. Third Edition, ++ * Richard F. Ferraro, Addison-Welsey, Aug. 1994 ++ * 3. sis86c201.c in XFree86 3.3.6 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_300_core.h" ++ ++static void sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); ++static void sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); ++static void sisfb_set_memory_clocks(struct sisfb_info * sisfb); ++static int sisfb_get_memory_size(struct sisfb_info * sisfb); ++static void sisfb_set_crt1_crtc_regs(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_mode_regs(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_pitch(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_offset(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_vclk(struct sisfb_info * sisfb, struct sisfb_par * par); ++static int sisfb_set_fifo_thresholds(struct sisfb_info * sisfb, struct sisfb_par * par); ++ ++/** ++ * sisfb_get_clock: - Read the clock generator parameters ++ * @sisfb: SiS Frame Buffer structure ++ * @clock: Paramters of the clock generator (return) ++ * @which: Which clock generator to be read. ++ * ++ * Read the clock generator parameters to @clock form the hardware. The desired ++ * clock generator is specified by @which. Valid values are MCLK for memory clock, ++ * VCLK for video dot clock and ECLK for 3D engine. ++ */ ++static void ++sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) ++{ ++ u8 data; ++ ++ /* get divider and numerator */ ++ data = sisfb_get_seq_reg(sisfb, which); ++ clock->divider = ((data & 0x80) >> 7) + 1; ++ clock->numerator = (data & ~0x80) + 1; ++ ++ /* get denumerator and post scalar */ ++ data = sisfb_get_seq_reg(sisfb, which + 1); ++ clock->denumerator = (data & 0x1F) + 1; ++ clock->post_scalar = ((data & 0xE0) >> 5) + 1; ++ ++ /* get VCO gain */ ++ data = sisfb_get_seq_reg(sisfb, which + 2); ++ clock->vco_gain = (data >> 7); ++} ++ ++/** ++ * sisfb_set_clock: - Set the clock generator parameters ++ * @sisfb: SiS Frame Buffer structure ++ * @clock: Paramters of the clock generator ++ * @which: Which clock generator to be read. ++ * ++ * Set the clock generator parameters @clock to the hardware. The desired clock ++ * generator is specified by @which. Valid values are MCLK for memory clock, ++ * VCLK for video dot clock and ECLK for 3D engine. ++ */ ++static void ++sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) ++{ ++ u8 data; ++ ++ /* set divider and numerator */ ++ data = (clock->numerator - 1) & 0x7F; ++ data |= (clock->divider - 1) ? 0x80 : 0x00; ++ sisfb_set_seq_reg(sisfb, which, data); ++ ++ /* set denumerator and post scalar */ ++ data = (clock->denumerator - 1) & 0x1F; ++ data |= (clock->post_scalar - 1) << 5; ++ sisfb_set_seq_reg(sisfb, which + 1, data); ++ ++ /* set VCO gain */ ++ data = clock->vco_gain ? 0x80 : 0x00; ++ sisfb_set_seq_reg(sisfb, which + 2, data); ++} ++ ++/** ++ * sisfb_set_memory_clocks: - Set memory bus clock rate ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Set the memory clocks for VGA core. Form SiS 300 and up, the VGA core has ++ * 2 independent clocks for 2D and 3D engines. We can set them to different ++ * rates seperatly. ++ */ ++extern unsigned long mclk, eclk; ++static void __devinit ++sisfb_set_memory_clocks(struct sisfb_info * sisfb) ++{ ++ struct sisfb_clock_param clock; ++ ++ /* set the clock rate according to the option */ ++ sisfb_calc_clock_param(&clock, mclk); ++ sisfb_set_clock(sisfb, &clock, SIS300_MCLK); ++ ++ sisfb_calc_clock_param(&clock, eclk); ++ sisfb_set_clock(sisfb, &clock, SIS300_ECLK); ++ ++ /* read the clock rate back and show to user */ ++ sisfb_get_clock(sisfb, &clock, SIS300_MCLK); ++ printk(KERN_INFO "sisfb_lite: 2D Memory Clock = %6ld KHz\n", ++ sisfb_calc_clock_freq(&clock)); ++ ++ sisfb_get_clock(sisfb, &clock, SIS300_ECLK); ++ printk(KERN_INFO "sisfb_lite: 3D Memory Clock = %6ld KHz\n", ++ sisfb_calc_clock_freq(&clock)); ++} ++ ++/** ++ * sisfb_get_memory_size: - Get framebuffer memory size ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV if SMA is incorrectly/not configured ++ * ++ * Get the framebuffer memory size from host controller. For SiS 530/620 and ++ * SiS 540/630/730 Families, the Shared Memory Area (SMA) is enabled in Bit 7, ++ * size is stored in Bit 4..6 of Register 0x63, Host Bridge (i.e. PCI 0:0.0). ++ * The register is set by DRAM initialzation code during boot process and can ++ * not be re-configured once the DRAM has been turned on. ++ */ ++#define SIS630_BANKENABLE 0x63 ++static int __devinit ++sisfb_get_memory_size(struct sisfb_info * sisfb) ++{ ++ struct pci_dev * host = NULL; ++ u8 dram_status, sma_size, sma_size_bits; ++ ++ if ((host = pci_find_slot(0, 0)) == NULL) { ++ printk(KERN_EMERG "sisfb_lite: Can not find Host Controller !!!\n"); ++ return -ENODEV; ++ } ++ ++ /* get SMA configuration from register 0x63 */ ++ pci_read_config_byte(host, SIS630_BANKENABLE, &dram_status); ++ ++ /* SMA not enabled */ ++ if ((dram_status & 0x80) != 0x80) ++ return -ENODEV; ++ ++ /* compute Shared Menory Area (SMA) size in Mega Bytes */ ++ sma_size_bits = (dram_status >> 4) & 0x7; ++ if (sma_size_bits > 5) { ++ // this is invalid! ++ printk(KERN_EMERG "sisfb_lite: Invalid Shared Memory Area Configuration !!!\n"); ++ return -ENODEV; ++ } ++ sma_size = (2 << sma_size_bits); ++ sisfb->video_size_virt = sma_size * 1024 * 1024; ++ ++ return 0; ++} ++ ++static void ++sisfb_set_crt1_crtc_regs(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u16 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend; ++ u16 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend; ++ u16 overflow, overflow_h1, overflow_h2, overflow_v; ++ ++ /* first convert 'par' to "screen" unit */ ++ htotal = (par->htotal >> 3) - 5; ++ hdispend = (par->hdispend >> 3) - 1; ++ hblankstart = (par->hsyncstart >> 3) - 1; ++ hblankend = (par->hsyncend >> 3); ++ hsyncstart = (par->hsyncstart >> 3); ++ hsyncend = (par->hsyncend >> 3); ++ ++ vtotal = par->vtotal - 2; ++ vdispend = par->vdispend - 1; ++ vsyncstart = par->vsyncstart; ++ vsyncend = par->vsyncend; ++ vblankstart = par->vsyncstart; ++ vblankend = par->vsyncend + 1; ++ ++ /* the "overlow" bits (8:15) of the screen parameters are spread all over ++ * various registers */ ++ overflow = ++ ((vsyncstart & 0x200) >> 2) | /* Bit 7, Vertical Retrace Start Bit 9 */ ++ ((vdispend & 0x200) >> 3) | /* Bit 6, Vertical Display End Bit 9 */ ++ ((vtotal & 0x200) >> 4) | /* Bit 5, Vertical Total Bit 9 */ ++ 0x10 | /* Bit 4, line compare Bit 8 */ ++ ((vblankstart & 0x100) >> 5) | /* Bit 3, Vertical Blank Start Bit 8 */ ++ ((vsyncstart & 0x100) >> 6) | /* Bit 2, Vertical Retrace Start Bit 8 */ ++ ((vdispend & 0x100) >> 7) | /* Bit 1, Vertical Display End Bit 8 */ ++ ((vtotal & 0x100) >> 8); /* Bit 0, Vertical Total Bit 8 */ ++ ++ overflow_v = ++ ((vsyncend & 0x010) << 1) | /* Bit 5, Vertical Retrace End Bit 4 */ ++ ((vblankend & 0x100) >> 4) | /* Bit 4, Vertical Blank End Bit 8 */ ++ ((vsyncstart & 0x400) >> 7) | /* Bit 3, Vertical Retrace Start Bit 10 */ ++ ((vblankstart & 0x400) >> 8) | /* Bit 2, Vertical Blank Start Bit 10 */ ++ ((vdispend & 0x400) >> 9) | /* Bit 1, Vertical Display End Bit 10 */ ++ ((vtotal & 0x400) >> 10); /* Bit 0, Vertical Total Bit 10 */ ++ ++ overflow_h1 = ++ ((hsyncstart & 0x300) >> 2) | /* Bit 6,7 Horizontal Retrace Start Bit 8,9 */ ++ ((hblankstart & 0x300) >> 4) | /* Bit 4,5 Horizontal Blank Start Bit 8,9 */ ++ ((hdispend & 0x300) >> 6) | /* Bit 2,3 Horizontal Display End Bit 8,9 */ ++ ((htotal & 0x300) >> 8); /* Bit 0,1 Horizontal Total Bit 8,9 */ ++ ++ overflow_h2 = ++ ((hsyncend & 0x020) >> 3) | /* Bit 2 Horizontal Retrace End Bit 5 */ ++ ((hblankend & 0x0C0) >> 6); /* Bit 0,1 Horizontal Blank End Bit 6,7 */ ++ ++ /* write 'par' to hardware registers, Standard VGA part, low order bits */ ++ sisfb_set_crtc_reg(sisfb, 0x00, htotal); ++ sisfb_set_crtc_reg(sisfb, 0x01, hdispend); ++ sisfb_set_crtc_reg(sisfb, 0x02, hblankstart); ++ sisfb_set_crtc_reg(sisfb, 0x03, ++ 0x80 | /* Bit 7, Enable Vertical Retrace Start/End */ ++ (hblankend & 0x1f)); /* Bit 0:4, Horizontal Blank End Bit 0:4 */ ++ sisfb_set_crtc_reg(sisfb, 0x04, hsyncstart); ++ sisfb_set_crtc_reg(sisfb, 0x05, ++ (hblankend & 0x20) << 2 | /* Bit 7, Horizontal Blank End Bit 5 */ ++ (hsyncend & 0x1f)); /* Bit 0:4, Horizontal Retrace End Bit 0:4 */ ++ sisfb_set_crtc_reg(sisfb, 0x06, vtotal); ++ sisfb_set_crtc_reg(sisfb, 0x09, ++ 0x40 | /* Bit 6, line compare Bit 9 */ ++ (vblankstart & 0x200) >> 4); /* Bit 5, Vertical Blank Start Bit 9 */ ++ sisfb_set_crtc_reg(sisfb, 0x10, vsyncstart); ++ sisfb_set_crtc_reg(sisfb, 0x11, (vsyncend & 0x0F) | 0x20); ++ sisfb_set_crtc_reg(sisfb, 0x12, vdispend); ++ sisfb_set_crtc_reg(sisfb, 0x15, vblankstart); ++ sisfb_set_crtc_reg(sisfb, 0x16, vblankend); ++ ++ /* Standard VGA part, overflow bits */ ++ sisfb_set_crtc_reg(sisfb, 0x07, overflow); ++ ++ /* Extended Registers, overflow bits */ ++ sisfb_set_seq_reg(sisfb, 0x0A, overflow_v); ++ sisfb_set_seq_reg(sisfb, 0x0B, overflow_h1); ++ sisfb_set_seq_reg(sisfb, 0x0C, overflow_h2); ++} ++ ++/** ++ * sisfb_set_crt1_mode_regs: - Set misc video mode registers ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Set color depth and enable 2D engine. The display line width register SR 0x10 ++ * is also enabled. ++ */ ++static void ++sisfb_set_crt1_mode_regs(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u8 tmp; ++ ++ /* enable Enhanced Graphics Mode and Auto Line Width Counter */ ++ tmp = 0x03; ++ switch (par->bits_per_pixel) { ++ case 32: ++ tmp |= 0x10; ++ break; ++ case 16: ++ tmp |= 0x08; ++ break; ++ case 8: ++ default: ++ break; ++ } ++ sisfb_set_seq_reg(sisfb, 0x06, tmp); ++ ++ /* enable 2D engine */ ++ sisfb_set_seq_reg(sisfb, 0x1E, 0x40); ++} ++ ++/** ++ * sisfb_set_crt1_pitch: - Set screen pitch registers for CRT1 ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Set the screen pitch registers for CRT1. Screen pitch refers to the memory address ++ * difference between two dots of the same col on two vertically neighboring scan lines. ++ * The CRTC 0x13 is called "offset register" in VGA literatures. SiS VGA also defines ++ * its own screen line width register SR 0x10 which is enabled by Bit 0 of SR 0x06. ++ */ ++static void ++sisfb_set_crt1_pitch(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u16 pitch = par->line_length >> 3; ++ u8 line_length = ((par->line_length + 63) >> 6) + 1; ++ ++ /* disable line compare */ ++ sisfb_set_seq_reg(sisfb, 0x0F, 0x08); ++ ++ /* screen pitch, in units of double word */ ++ sisfb_set_crtc_reg(sisfb, 0x13, pitch & 0xFF); ++ sisfb_set_seq_reg(sisfb, 0x0E, (pitch >> 8) & 0x0F); ++ ++ /* display line length, in units of 64 bytes */ ++ sisfb_set_seq_reg(sisfb, 0x10, line_length); ++} ++ ++/** ++ * sisfb_set_crt1_offset: - Set screen start offset register for CRT1 ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Set the screen start offset registers for CRT1. Screen start offset refers to the ++ * memory address of the pixel (0, 0) on the current vitrual screen. This address ++ * is calculated when the virtual screen is panned by pan_display() or when the var ++ * is changed and deoced by decode_var(). This value is stored in the ++ * par->screen_offset member of the current display. par->screen_offset is in the ++ * unit of byte while the VGA hardware uses Double Word. ++ */ ++static void ++sisfb_set_crt1_offset(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u32 offset; ++ ++ /* convert offset address from units of byte to double word */ ++ offset = par->screen_offset >> 2; ++ ++ /* set screen start memory address in units of double word, ++ bit 23:16 in SR0D, bit 15:8 in CR0C, bit 7:0 in CR0D */ ++ sisfb_set_crtc_reg(sisfb, 0x0C, offset >> 8); ++ sisfb_set_crtc_reg(sisfb, 0x0D, offset); ++ sisfb_set_seq_reg(sisfb, 0x0D, offset >> 16); ++} ++ ++/** ++ * sisfb_set_crt1_vclk: - Set video dot clock frequence for CRT1 ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Select normal clock generator as DCLK source. Set the clock frequence as ++ * specified in @par->dot_clock. Also set the DAC slew rate according to DCLK ++ * frequence. ++ */ ++static void ++sisfb_set_crt1_vclk(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ /* FixME: Use clock_param for par->dot_clock */ ++ u32 vclk = par->dot_clock / 1000; ++ u8 tmp = 0x10, tmp1; ++ struct sisfb_clock_param clock; ++ ++ /* Select normal DCLK clock generator */ ++ sisfb_set_seq_reg(sisfb, 0x31, 0x00); ++ ++ /* set vclk frequence, FixME: do error check */ ++ sisfb_calc_clock_param(&clock, vclk); ++ sisfb_set_clock(sisfb, &clock, SIS300_DCLK); ++ ++ sisfb_get_clock(sisfb, &clock, SIS300_DCLK); ++ printk(KERN_INFO "sisfb_lite: Video Dot Clock = %6ld KHz\n", ++ sisfb_calc_clock_freq(&clock)); ++ ++ /* set DAC slew rate, the statesment in Glamour Design Guideline V.08 ++ * is totally contracted to the true hardware implementation */ ++ if (vclk < 100000) ++ tmp |= 0x03; ++ else if (vclk < 200000) ++ tmp |= 0x02; ++ else if (vclk < 250000) ++ tmp |= 0x01; ++ ++ /* FixME: Set half DCLK if VCLK is too high, ++ * need to be updated for SiS 315 */ ++ if (vclk > 150000) { ++ tmp |= 0x80; ++ tmp1 = 0x08; ++ } else { ++ tmp &= 0x7F; ++ tmp1 = 0x00; ++ } ++ ++ sisfb_set_seq_reg(sisfb, 0x07, tmp); ++ sisfb_set_seq_reg(sisfb, 0x32, tmp1); ++} ++ ++static u8 latency_factor[] = { ++ 97, 88, 86, 79, 77, 0, ++ 0, 87, 85, 78, 76, 54, ++ 80, 72, 69, 63, 61, 0, ++ 0, 70, 68, 62, 59, 37, ++}; ++ ++static int ++sisfb_set_fifo_thresholds(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u32 vclk = par->dot_clock / 1000; ++ unsigned int i = 0, threshold; ++ int grant_timer, fg_queue, bg_queue; ++ struct pci_dev * host = NULL; ++ u8 queue, srf; ++ ++ if ((host = pci_find_slot(0, 0)) == NULL) { ++ printk(KERN_EMERG "sisfb_lite: Can not find Host Controller !!!\n"); ++ return -ENODEV; ++ } ++ ++ pci_read_config_byte(host, 0x53, &queue); ++ queue &= 0xF0; ++ ++ for (grant_timer = 1; grant_timer >= 0; grant_timer--) { ++ for (fg_queue = 0; fg_queue <= 5; fg_queue++) { ++ for (bg_queue = 0; bg_queue <= 1; bg_queue++) { ++ threshold = latency_factor[i++] * vclk; ++ threshold *= (par->bits_per_pixel >> 3); ++ threshold /= (mclk * 16); ++ if (threshold > 0x13 || threshold == 0x00) ++ ; ++ else ++ goto set_threshold; ++ } ++ } ++ } ++ ++ return -EINVAL; ++ ++ set_threshold: ++ /* write froeground and backgroudn queue, GUI grant timer */ ++ queue |= ((fg_queue << 1) | bg_queue); ++ pci_write_config_byte(host, 0x53, queue); ++ pci_write_config_byte(host, 0xA3, grant_timer); ++ ++ /* Write CRT/CPU threshold low, CRT/Engine threshold high */ ++ threshold += 1; ++ srf = sisfb_get_seq_reg(sisfb, 0x0F); ++ sisfb_set_seq_reg(sisfb, 0x08, ((threshold & 0x0F) << 4 | 0x0F)); ++ sisfb_set_seq_reg(sisfb, 0x0F, ((threshold & 0x10) << 1 | srf )); ++ ++ /* Write CRT/CPU threshold high */ ++ threshold += 3; ++ if (threshold > 0x0F) ++ threshold = 0x0F; ++ sisfb_set_seq_reg(sisfb, 0x09, (threshold & 0x0F)); ++ ++ return 0; ++} ++ ++/** ++ * sisfb_config_memory: - Configure Framebuffer Memory ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV on Failure ++ * ++ * Configure the frame buffer memory. ++ * If Memory Type Range Registers (MTRR) is configured in the kernel. We set the ++ * Frame Buffer area as "Write Combine" to boost the perfromance. ++ */ ++int __devinit ++sisfb_config_memory(struct sisfb_info * sisfb) ++{ ++ int ret; ++ u8 data = 0; ++ ++ /* Check if we have SMA configured correctly and HOW MUCH */ ++ if ((ret = sisfb_get_memory_size(sisfb)) < 0) ++ return ret; ++ ++ /* Enable PCI Relocated IO, Memory Mapped IO and Linear Framebuffer Addressing */ ++ data = SIS300_PCI_VGA_MEM_DISABLE | SIS300_PCI_VGA_IO_DISABLE; ++ data |= SIS300_PCI_PCI_IO_ENABLE | SIS300_PCI_PCI_MMIO_ENABLE; ++ data |= SIS300_PCI_LINEAR_ENABLE; ++ sisfb_set_seq_reg(sisfb, SIS300_PCI_ADDR_SET, data); ++ ++ /* ioremap MMIO and Framebuffer Area */ ++ sisfb->video_base_virt = ++ ioremap(sisfb->video_base_phy, sisfb->video_size_virt); ++ sisfb->mmio_base_virt = ++ ioremap(sisfb->mmio_base_phy, sisfb->mmio_size_phy); ++ ++ printk(KERN_INFO "sisfb_lite: framebuffer at 0x%lx, mapped to 0x%p, size %lu KB\n", ++ sisfb->video_base_phy, (char *) sisfb->video_base_virt, ++ sisfb->video_size_virt / 1024); ++ ++ sisfb_set_memory_clocks(sisfb); ++ ++#ifdef CONFIG_MTRR ++ /* Use MTRR to boost performance */ ++ sisfb->mtrr = mtrr_add(sisfb->video_base_phy, sisfb->video_size_virt, ++ MTRR_TYPE_WRCOMB, 1); ++ if (sisfb->mtrr >= 0) { ++ printk(KERN_INFO "sisfb_lite: Turned on MTRR Write Combine for framebuffer\n"); ++ } ++#endif /* CONFIG_MTRR */ ++ ++ return 0; ++} ++ ++/** ++ * sisfb_pan_var: - Set screen start offset ++ * @var: Frame Buffer changable part ++ * @info: Frame Buffer structure ++ * ++ * Set the screen start offset accroding to xoffset, yoffset, xres_virtual ++ * ++ * Virtual Screen: ++ * ++ * -------------------------------------------> xres_vitrual ++ * | O ++ * | ----------------------------------------- ++ * | | O' | ++ * | | ------------------------ | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | ------------------------ | ++ * | | D' | ++ * | | | ++ * | | | ++ * v ----------------------------------------- D ++ * yres_virtual ++ */ ++int ++sisfb_pan_display_300(struct fb_var_screeninfo * var, struct sisfb_info * sisfb) ++{ ++ u32 offset; ++ ++ /* offset address in units of "pixels" */ ++ offset = var->yoffset * var->xres_virtual + var->xoffset; ++ /* offset address in units of byte */ ++ offset = offset * (var->bits_per_pixel >> 3); ++ ++ /* update screen_offset member of current par structure */ ++ sisfb->current_par.screen_offset = offset; ++ ++ sisfb_set_crt1_offset(sisfb, &sisfb->current_par); ++ ++ return 0; ++} ++ ++/* ++ * Set the hardware according to 'par'. ++ */ ++void ++sisfb_set_par_300(struct sisfb_par *par, struct sisfb_info * sisfb) ++{ ++ sisfb_display_off(sisfb); ++ ++ /* Standard VGA CRTC Registers */ ++ sisfb_set_crt1_crtc_regs(sisfb, par); ++ ++ /* Extended Registers, other stuff */ ++ sisfb_set_crt1_pitch(sisfb, par); ++ sisfb_set_crt1_offset(sisfb, par); ++ sisfb_set_crt1_vclk(sisfb, par); ++ sisfb_set_crt1_mode_regs(sisfb, par); ++ sisfb_set_fifo_thresholds(sisfb, par); ++ ++ /* makes 'par' values as the current_par of this framebuffer */ ++ sisfb->current_par = *par; ++ ++ sisfb_display_on(sisfb); ++} +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_300_core.h linux-2.4.6-linuxbios/drivers/video/sis/sisfb_300_core.h +--- linux-2.4.6-official/drivers/video/sis/sisfb_300_core.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_300_core.h Thu Jul 5 17:14:20 2001 +@@ -0,0 +1,24 @@ ++#ifndef __SISFB_300_CORE__ ++#define __SISFB_300_CORE__ ++ ++#define SIS300_PCI_ADDR_SET 0x20 ++#define SIS300_PCI_PCI_MMIO_ENABLE 0x01 ++#define SIS300_PCI_VGA_MEM_DISABLE 0x04 ++#define SIS300_PCI_VGA_IO_DISABLE 0x10 ++#define SIS300_PCI_PCI_IO_ENABLE 0x20 ++#define SIS300_PCI_LINEAR_ENABLE 0x80 ++ ++#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */ ++#define HW_CURSOR_AREA_SIZE 0x1000 /* 4K */ ++ ++enum clock_gen_base { ++ SIS300_MCLK = 0x28, ++ SIS300_DCLK = 0x2B, ++ SIS300_ECLK = 0x2E ++}; ++ ++extern int sisfb_config_memory(struct sisfb_info * sisfb); ++extern int sisfb_pan_display_300(struct fb_var_screeninfo * var, struct sisfb_info * sisfb); ++extern void sisfb_set_par_300(struct sisfb_par *par, struct sisfb_info * sisfb); ++ ++#endif /* __SISFB_300_CORE__ */ +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_300_init.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_300_init.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_300_init.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_300_init.c Mon Jul 16 16:57:50 2001 +@@ -0,0 +1,203 @@ ++/* sisfb_300_init.c: Initialization Code for SiS 540/630/730 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * 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 License, or ++ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. Glamour Design Guideline V0.8 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_300_core.h" ++#include "sisfb_530_accel.h" ++ ++static void sisfb_set_pci_agp_timming(struct sisfb_info * sisfb); ++static void sisfb_enable_turbo_queue(struct sisfb_info * sisfb); ++static void sisfb_fake_vgabios(struct sisfb_info * sisfb); ++ ++/* Default values for PCI/AGP Timming control registers: SR21-SR25, SR32 */ ++static u8 pci_timming[] __initdata = { ++ 0xB6, 0xBA, 0xF6, 0x0D, 0x00, 0x11 ++}; ++ ++/** ++ * sisfb_set_pci_agp_timming: - Set AGP/PCI timming control registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Initialize PCI and AGP timming control registers. Most of them are ++ * dumped form normal BIOS setting. ++ */ ++static void __devinit ++sisfb_set_pci_agp_timming(struct sisfb_info * sisfb) ++{ ++ u8 AGP, tmp; ++ ++ /* SR3A, Hardware Trap III */ ++ tmp = sisfb_get_seq_reg(sisfb, 0x3A); ++ if ((tmp & 0x30) == 0x30) ++ // PCI Mode ++ AGP = 0; ++ else ++ // AGP Mode; ++ AGP = 1; ++ ++ tmp = pci_timming[0]; ++ if (AGP == 0) ++ // Disable AGP Request High Priority ++ tmp &= ~0x10; ++ sisfb_set_seq_reg(sisfb, 0x21, tmp); ++ ++ tmp = pci_timming[1]; ++ if (AGP == 1) ++ // Enable PCI Burst memory write ++ tmp |= 0x20; ++ sisfb_set_seq_reg(sisfb, 0x22, tmp); ++ ++ sisfb_set_seq_reg(sisfb, 0x23, pci_timming[2]); ++ sisfb_set_seq_reg(sisfb, 0x24, pci_timming[3]); ++ sisfb_set_seq_reg(sisfb, 0x25, pci_timming[4]); ++ sisfb_set_seq_reg(sisfb, 0x32, pci_timming[5]); ++} ++ ++/** ++ * sisfb_enable_turbo_queue: - Set Turbo Queue size and enable it ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Commands to the Graphics Engine (2D, 3D, etc) are buffered in ++ * the Video Memory which is called Turbo Queue in SiS VGA Specs. ++ * Usually this buffer area takes the last few KBs in the Video RAM. ++ */ ++/* default turbo queue size == 64KB */ ++static int tqueue_size = 0x10000; ++static void __devinit ++sisfb_enable_turbo_queue(struct sisfb_info * sisfb) ++{ ++ u32 tqueue_pos; ++ u8 tqueue_status; ++ ++ /* turbo queue position, in units of 64KB */ ++ tqueue_pos = sisfb->video_size_virt - tqueue_size; ++ tqueue_pos /= 0x10000; ++ ++ /* enable Turbo Tueue */ ++ tqueue_status = 0x80 | (tqueue_pos >> 8); ++ ++ sisfb_set_seq_reg(sisfb, 0x26, tqueue_pos); ++ sisfb_set_seq_reg(sisfb, 0x27, tqueue_status); ++ ++ printk(KERN_INFO "sisfb_lite: Use %dKB off-screen memory for Turbo Queue\n", ++ tqueue_size / 1024); ++} ++ ++/** ++ * sisfb_fake_vgabios: - Pretend we still have VGA BIOS ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Many of the Extended Sequencer Registers and Externded CRT Controller Registers ++ * are used by traditional System/VGA BIOS and Drivers to pass information back and ++ * forth. We have to fake some resonable values for these registers in order to let ++ * some stupid applications like XFree 3.3.6 work properly. ++ */ ++static void __devinit ++sisfb_fake_vgabios(struct sisfb_info * sisfb) ++{ ++ int i; ++ u8 data, sma_size; ++ u8 fake_bios[] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F}; ++ ++ /* SR 14 is used as "protocol" by VGA BIOS and XFree86 for passing SMA size ++ and bus width, we have to fake them :~-( */ ++ sma_size = sisfb->video_size_virt >> 21; ++ data = fake_bios[ffs(sma_size) - 1]; ++ data |= 0x40; // 64-bit bus ++ sisfb_set_seq_reg(sisfb, 0x14, data); ++ ++ /* SR16-SR19 are used as "protocol" by VGA BIOS and System BIOS for passing ++ information about TV-out, we have to clear them :~-( */ ++ for (i = 0x16; i <= 0x19; i++) { ++ sisfb_set_seq_reg(sisfb, i, 0x00); ++ } ++ ++ /* SR1A are used as "protocol" by VGA BIOS and System BIOS for passing ++ information about M/B frequence, we have to fake them :~-( */ ++ sisfb_set_seq_reg(sisfb, 0x1A, 0x12); ++ ++ /* set MD out enable to 1T (what the hell ??) */ ++ sisfb_set_seq_reg(sisfb, 0x15, 0x01); ++ ++ /* SR1B, SR1C are not used by SiS 630 (used by SiS 300 ??), ++ clear them. */ ++ sisfb_set_seq_reg(sisfb, 0x1B, 0x00); ++ sisfb_set_seq_reg(sisfb, 0x1C, 0x00); ++ ++ /* CR30-CR37 are used by VGA BIOS to pass information ++ about SiS 301, clean them */ ++ for (i = 0x30; i <= 0x37; i++) { ++ sisfb_set_crtc_reg(sisfb, i, 0x00); ++ } ++} ++ ++/** ++ * sisfb_init_300: - Initialize the SiS300 VGA Core in SiS300, SiS630,540,730 ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV if SMA is incorrectly/not configured ++ * ++ * SiS 300 VGA core is used in SiS540/630/730 chipsets. This routine inits ++ * the very SiS300 specific stuff. ++ */ ++int __devinit ++sisfb_init_300(struct sisfb_info * sisfb) ++{ ++ int ret; ++ ++ if ((ret = sisfb_config_memory(sisfb)) < 0) ++ return ret; ++ ++ sisfb_init_legacy_vga(sisfb); ++ ++ /* set to High Speed DAC by default */ ++ sisfb_set_seq_reg(sisfb, 0x07, 0x13); ++ ++ /* Disable DAC pedestal */ ++ sisfb_set_seq_reg(sisfb, 0x1F, 0x00); ++ ++ sisfb_set_pci_agp_timming(sisfb); ++ ++ /* disable power management mode */ ++ sisfb_set_seq_reg(sisfb, 0x11, 0x0F); ++ ++ /* set screen start memory address bit 23:16 to 0, bit 15:0 are in CR0C, CR0D */ ++ sisfb_set_seq_reg(sisfb, 0x0D, 0x00); ++ ++ sisfb_enable_turbo_queue(sisfb); ++ ++ sisfb_fake_vgabios(sisfb); ++ ++ /* set hardware specific functions */ ++ sisfb->accelerator = &sis530_accelerator; ++ sisfb->set_par = sisfb_set_par_300; ++ sisfb->pan_display = sisfb_pan_display_300; ++ sisfb->set_disp = sisfb_set_dispsw_accel; ++ ++ return 0; ++} +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_300_video.h linux-2.4.6-linuxbios/drivers/video/sis/sisfb_300_video.h +--- linux-2.4.6-official/drivers/video/sis/sisfb_300_video.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_300_video.h Thu May 31 03:07:11 2001 +@@ -0,0 +1,146 @@ ++#ifndef __SISFB_300_VIDEO__ ++#define __SISFB_300_VIDEO__ ++ ++#ifdef __KERNEL__ ++#include "sisfb_lite.h" ++#endif __KERNEL__ ++ ++enum sis300_video_registers { ++ SIS300_VIDEO_PASSWORD = 0x00, ++ ++ /* Video Window Horizonal Start/End */ ++ SIS300_VIDEO_WIN_HOR_DISP_START_LOW = 0x01, ++ SIS300_VIDEO_WIN_HOR_DISP_END_LOW = 0x02, ++ SIS300_VODEO_WIN_HOR_OVERFLOW = 0x03, ++ ++ /* Video Window Horizonal Start/End */ ++ SIS300_VIDEO_WIN_VER_DISP_START_LOW = 0x04, ++ SIS300_VIDEO_WIN_VER_DISP_END_LOW = 0x05, ++ SIS300_VODEO_WIN_VER_OVERFLOW = 0x06, ++ ++ /* Y Plane (4:2:0) or YUV (4:2:2) buffer start address */ ++ SIS300_VIDEO_Y_BUF_START_LOW = 0x07, ++ SIS300_VIDEO_Y_BUF_START_MIDDLE = 0x08, ++ SIS300_VIDEO_Y_HOR_START_HIGH = 0x09, ++ ++ /* U Plane (4:2:0) buffer start address */ ++ SIS300_VIDEO_U_BUF_START_LOW = 0x0A, ++ SIS300_VIDEO_U_BUF_START_MIDDLE = 0x0B, ++ SIS300_VIDEO_U_HOR_START_HIGH = 0x0C, ++ ++ /* U Plane (4:2:0) buffer start address */ ++ SIS300_VIDEO_V_BUF_START_LOW = 0x0D, ++ SIS300_VIDEO_V_BUF_START_MIDDLE = 0x0E, ++ SIS300_VIDEO_V_HOR_START_HIGH = 0x0F, ++ ++ /* Ptich for Y, UV Planes */ ++ SIS300_VIDEO_Y_BUF_PITCH_LOW = 0x10, ++ SIS300_VIDEO_UV_BUF_PITCH_LOW = 0x11, ++ SIS300_VIDEO_Y_UV_BUF_PITCH_HIGH = 0x12, ++ ++ /* FixMe: No idea what this is */ ++ SIS300_VIDEO_Y_BUF_PRESET_LOW = 0x13, ++ SIS300_VIDEO_Y_BUF_PRESET_MIDDLE = 0x14, ++ ++ SIS300_VIDEO_UV_BUF_PRESET_LOW = 0x15, ++ SIS300_VIDEO_UV_BUF_PRESET_MIDDLE = 0x16, ++ ++ SIS300_VIDEO_Y_UV_BUF_PRESET_HIGH = 0x17, ++ ++ /* Image Sacling control registers */ ++ SIS300_VIDEO_HOR_POST_UP_SCALE_LOW = 0x18, ++ SIS300_VIDEO_HOR_POST_UP_SCALE_HIGH = 0x19, ++ ++ SIS300_VIDEO_VER_UP_SCALE_LOW = 0x1A, ++ SIS300_VIDEO_VER_UP_SCALE_HIGH = 0x1B, ++ ++ SIS300_VIDEO_SCALE_CONTROL = 0x1C, ++ ++ /* Playback line buffer control */ ++ SIS300_VIDEO_PLAYBACK_THRESHOLD_LOW = 0x1C, ++ SIS300_VIDEO_PLAYBACK_THRESHOLD_HIGH = 0x1C, ++ SIS300_VIDEO_PLAYBACK_LINE_BUF_SIZE = 0x1C, ++ ++ /* Destination color key, RGB color space*/ ++ SIS300_VIDEO_OVERLAY_COLORKEY_RED_MIN = 0x20, ++ SIS300_VIDEO_OVERLAY_COLORKEY_GREEN_MIN = 0x21, ++ SIS300_VIDEO_OVERLAY_COLORKEY_BLUE_MIN = 0x22, ++ SIS300_VIDEO_OVERLAY_COLORKEY_RED_MAX = 0x23, ++ SIS300_VIDEO_OVERLAY_COLORKEY_GREEN_MAX = 0x24, ++ SIS300_VIDEO_OVERLAY_COLORKEY_BLUE_MAX = 0x25, ++ ++ /* Source color key, YUV color space */ ++ SIS300_VIDEO_OVERLAY_CHROMAKEY_Y_MIN = 0x26, ++ SIS300_VIDEO_OVERLAY_CHROMAKEY_U_MIN = 0x27, ++ SIS300_VIDEO_OVERLAY_CHROMAKEY_V_MIN = 0x28, ++ SIS300_VIDEO_OVERLAY_CHROMAKEY_Y_MAX = 0x29, ++ SIS300_VIDEO_OVERLAY_CHROMAKEY_U_MAX = 0x2A, ++ SIS300_VIDEO_OVERLAY_CHROMAKEY_V_MAX = 0x2B, ++ ++ /* Contrast Enhancement and Brightness control */ ++ SIS300_VIDEO_CONTRAST_FACTOR = 0x2C, ++ SIS300_VIDEO_BRIGHTNESS = 0x2D, ++ SIS300_VIDEO_CONTRAST_ENHANCE_CONTROL = 0x2E, ++ ++ SIS300_VIDEO_KEY_OVERLAY_MODE = 0x2F, ++ ++ /* Misc Control, inclue YUV 422, YUV 420 selectrion */ ++ SIS300_VIDEO_MISC_CONTROL_0 = 0x2F, ++ SIS300_VIDEO_MISC_CONTROL_1 = 0x2F, ++ SIS300_VIDEO_MISC_CONTROL_2 = 0x2F ++}; ++ ++#define SIS300_VIDEO_ADDR 0x01 ++#define SIS300_VIDEO_DATA 0x02 ++ ++static inline void ++sisfb_set_video_reg(struct sisfb_info * sisfb, u8 index, u8 data) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + SIS300_VIDEO_ADDR); ++ outb(data, port + SIS300_VIDEO_DATA); ++} ++ ++static inline u8 ++sisfb_get_video_reg(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + SIS00_VIDEO_ADDR); ++ return inb(port + SIS300_VIDEO_DATA); ++} ++ ++/** ++ * sisfb_lock_regs: - Lock the Video Acclerator Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Lock Video Acclerator Registers by writing 0x21 (%SIS_PASSWD_LOCK) to ++ * SIS300_VIDEO_PASSWORD register ++ */ ++static inline void ++sisfb_lock_regs(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ /* lock the access to Video Accelerator Registers */ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_PASSWORD, SIS_PASSWD_LOCK); ++} ++ ++/** ++ * sisfb_unlock_regs: - Unlock the Video Acclerator Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Unlock Video Acclerator Registers by writing 0x86 (%SIS_PASSWD_UNLOCK) to ++ * SIS300_VIDEO_PASSWD register ++ */ ++static inline void ++sisfb_unlock_regs(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ /* unlock the access to Video Accelerator Registers */ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_PASSWORD, SIS_PASSWD_UNLOCK); ++} ++ ++#endif /* __SISFB_300_VIDEO__ */ +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_301_lcd.h linux-2.4.6-linuxbios/drivers/video/sis/sisfb_301_lcd.h +--- linux-2.4.6-official/drivers/video/sis/sisfb_301_lcd.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_301_lcd.h Tue Jul 17 19:05:52 2001 +@@ -0,0 +1,33 @@ ++#ifndef __SISFB_301_LCD__ ++#define __SISFB_301_LCD__ ++ ++enum sisfb_301_lcd_registers { ++ SIS301_LCD_FUNCTION_CONTROL, SIS301_LCD_FIFO_HIGH, ++ SIS301_LCD_FIFO_LOW, SIS301_LCD_FIFO_STOP, ++ SIS301_LCD_BASE_ADDR_HIGH, SIS301_LCD_BASE_ADDR_MED, ++ SIS301_LCD_BASE_ADDR_LOW, SIS301_LCD_LINE_OFFSET, ++ SIS301_LCD_HR_TOTAL, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ ++ SIS301_LCD_FUNCTION_CONTROL, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ ++ SIS301_LCD_FUNCTION_CONTROL, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++ SIS301_LCD_, SIS301_LCD_, ++}; ++ ++#endif /* __SISFB_301_LCD__ */ +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_315_accel.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_315_accel.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_315_accel.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_315_accel.c Thu Jul 12 10:48:23 2001 +@@ -0,0 +1,399 @@ ++/* sisfb_315_accel.c: 2D Hardware Acceleration for SiS 550 ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * 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 License, or ++ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 315 2D Engine Register, Version 0.30, Jun. 12, 2000 ++ * 2. sis315_accel.c in XFree86 4.0.2 ++ */ ++ ++#include "sisfb_315_accel.h" ++ ++/** ++ * sisfb_wait_idle: - Wait for 2D and 3D engine being idle ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Polling the Connamd Queue Status register until all the following condition is ++ * meat. ++ * bit 31 2D/3D engine, Hardware/Software Queue: 1 is idle and empty ++ * bit 30 Hardware Command Queue: 1 is empty, ++ * bit 29 2D Engine: 1 idle ++ * bit 28 3D Engine: 1 idle ++ */ ++static inline void ++sisfb_wait_idle(struct sisfb_info *sisfb) ++{ ++ int count = 0x10; ++ volatile u32 dummy = 0x00000000; ++ ++ while (dummy != 0x80000000 && --count) { ++ dummy = sisfb_readl(sisfb, SIS315_2D_CMD_QUEUE_STATUS) & 0x80000000; ++ } ++} ++ ++static inline void ++sisfb_set_agp_base(struct sisfb_info *sisfb) ++{ ++ u16 base; ++ ++ switch (sisfb->current_par.bits_per_pixel) { ++ case 8: ++ case 24: ++ default: ++ base = 0x0000; ++ break; ++ case 16: ++ base = 0x8000; ++ break; ++ case 32: ++ base = 0xC000; ++ break; ++ } ++ sisfb_writew(sisfb, SIS315_2D_AGP_BASE, base); ++} ++ ++static inline u32 ++sisfb_command_bpp(struct sisfb_info *sisfb) ++{ ++ switch (sisfb->current_par.bits_per_pixel) { ++ case 8: ++ default: ++ return SIS315_2D_CMD_CFB_8; ++ case 16: ++ return SIS315_2D_CMD_CFB_16; ++ case 32: ++ return SIS315_2D_CMD_CFB_32; ++ } ++} ++ ++/** ++ * sisfb_fillrect: - Fill a rectangle area on framebuffer ++ * @sisfb: SiS Frame Buffer structure ++ * @x: X origin ++ * @y: Y origin ++ * @width: width ++ * @height: height ++ * @color: color to fill ++ * @rop: Raster Operation for the fill ++ * ++ * Fille a rectangle area on(off ??) the screen starting from (@x, @y) to ++ * (@x + @width, @y + @height) with @color. ++ * The raster operation @rop is used for solid fill or invert (vai ROP_XOR). ++ * ++ * Note: ++ * 1. The Source Pitch is dummy in this case. ++ * 2. We have to use Pattern ROPs with color in Pattern FG/BG Color Register. ++ */ ++static void ++sisfb_fillrect(struct sisfb_info *sisfb, u32 x, u32 y, ++ u32 width, u32 height, u32 color, u8 rop) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, 0 /* dummy*/); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (0, 0) */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS315_2D_SRC_Y, 0); ++ ++ /* setup Destination X and Y origin == (x, y) */ ++ sisfb_writew(sisfb, SIS315_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS315_2D_DST_Y, y); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS315_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS315_2D_RECT_HEIGHT, height); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_FG_COLOR, color); ++ ++ /* Command = BitBlt, X++, Y++, pattern = Pattern Foreground Color Register, ROP = rop */ ++ cmd = SIS315_2D_CMD_BITBLT | SIS315_2D_CMD_PAT_FG_REG | ++ sisfb_command_bpp(sisfb) | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++/** ++ * sisfb_copyrect: - Copy a rectangle area ++ * @sisfb: SiS Frame Buffer structure ++ * @srcx: X origin of source rectangle ++ * @srcy: Y origin of source rectangle ++ * @sdst: X origin of destination rectangle ++ * @sdst: Y origin of destination rectangle ++ * @width: width ++ * @height: height ++ * ++ * Copy a rectangle area on(off ??) the screen starting from (@xsrc, @ysrc) to ++ * (@xsrc + @width, @ysrc + @height) to (@xdst, @ydst). ++ * ++ * FixMe: Do we need to set up x,y direction ?? ++ */ ++static void ++sisfb_copyrect(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, u8 rop) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++#ifdef FIXME ++ u32 x_dir = SIS315_2D_CMD_DIR_X_INC, y_dir = SIS315_2D_CMD_DIR_X_INC; ++ /* If the direction is "decreasing", the chip wants the addresses ++ * to be at the other end, so we must be aware of that in our ++ * calculations. */ ++ if (srcx <= dstx) { ++ x_dir = SIS315_2D_CMD_DIR_X_DEC; ++ srcx += width - 1; ++ dstx += width - 1; ++ } ++ ++ if (srcy <= dsty) { ++ y_dir = SIS315_2D_CMD_DIR_Y_DEC; ++ srcy += height - 1; ++ dsty += height - 1; ++ } ++#endif ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, pitch); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (screen_offset, screen_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, base); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_X, srcx); ++ sisfb_writew(sisfb, SIS315_2D_SRC_Y, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS315_2D_DST_X, dstx); ++ sisfb_writew(sisfb, SIS315_2D_DST_Y, dsty); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS315_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS315_2D_RECT_HEIGHT, height); ++ ++ /* Command = BitBlt, X Dir, Y Dir, bitblt from video memory (ScrenToScreen), ROP = rop */ ++ cmd = SIS315_2D_CMD_BITBLT | SIS315_2D_CMD_SRC_VIDEO | ++ sisfb_command_bpp(sisfb) | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++/** ++ * sisfb_8x8_color_expand: - Color expand with 8x8 monochrome bit mask ++ * @sisfb: SiS Frame Buffer structure ++ * @x: X origin ++ * @y: Y origin ++ * @width: width ++ * @height: height ++ * @fg: foreground color to expand ++ * @bg: background color to expand ++ * @rop: Raster Operation for the expand ++ * @bitmap: 8x8 monochrom bitmap (64 bits) ++ * ++ * Color expand the 8x8 bitmap @bitmap by setting bits with value 1 to @fg while bits ++ * with value 0 to @bg. If @bg == -1 then background pixels are not expanded. Also fill ++ * the rectangle (@x, @y) - (@x + @width, @y + @height) with the expanded pattern. ++ * ++ * Note: ++ * 1. The Source Pitch is width/8 then rounded up. ++ * 2. We have to use Pattern ROPs with color in Pattern FG/BG Color Register. ++ */ ++static void ++sisfb_8x8_color_expand(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, ++ u32 height, u32 fg, u32 bg, u8 rop, u8 * bitmap) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, (width + 7) >> 3); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (0, 0) */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS315_2D_SRC_Y, 0); ++ ++ /* setup Destination X and Y origin == (x, y) */ ++ sisfb_writew(sisfb, SIS315_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS315_2D_DST_Y, y); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS315_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS315_2D_RECT_HEIGHT, height); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_FG_COLOR, fg); ++ ++ /* setup the foreground color in Pattern Background Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_BG_COLOR, bg); ++ ++ /* store 8x8 mono bitmap to Mono Mask Register */ ++ sisfb_writel(sisfb, SIS315_2D_MONO_MASK, *(u32 *) bitmap); ++ sisfb_writel(sisfb, SIS315_2D_MONO_MASK + 4, *(u32 *) (bitmap + 4)); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Register, ROP = rop */ ++ cmd = SIS315_2D_CMD_COLOREXP | SIS315_2D_CMD_PAT_MONO_MASK | ++ sisfb_command_bpp(sisfb) | (rop << 8); ++ ++ /* if background color == -1 then don't expand background pixels */ ++ if (bg == -1) ++ cmd |= SIS315_2D_CMD_TRANSPARENT; ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++/** ++ * sisfb_color_expand: - Color expand with Pattern Register ++ * @sisfb: SiS Frame Buffer structure ++ * @x: X origin ++ * @y: Y origin ++ * @width: width ++ * @height: height ++ * @fg: foreground color to expand ++ * @bg: background color to expand ++ * @rop: Raster Operation for the expand ++ * @bitmap: monochrom bitmap (384 bytes max) ++ * @size: size of @bitmap ++ * ++ * Color expand the bitmap @bitmap by setting bits with value 1 to @fg while bits ++ * with value 0 to @bg. If @bg == -1 then background pixels are not expanded. The ++ * bitmap is transfered to hardware Pattern Register and can be as large as 384 bytes, ++ * effectively expanding 3072 pixels in a single operation. ++ * ++ * The rectangle (@x, @y) - (@x + @width, @y + @height) is filled with the expanded pattern. ++ * If the size of @bitmap is samller then 384 bytes and the size of the rectangle is larger ++ * then 3072 pixels, some pixels in the rectangle are filled with "garbage". ++ * ++ * Note: ++ * 1. The Source Pitch is width/8 then rounded up (i.e. in units of byte). ++ * 2. We have to use Normal ROPs with color in Source FG/BG Color Register. ++ */ ++static void ++sisfb_color_expand(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, ++ u32 height, u32 fg, u32 bg, u8 rop, u8 * bitmap, u32 size) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, (width + 7) >> 3); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screem_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (0, 0) */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS315_2D_SRC_Y, 0); ++ ++ /* setup Destination X and Y origin == (x, y) */ ++ sisfb_writew(sisfb, SIS315_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS315_2D_DST_Y, y); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS315_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS315_2D_RECT_HEIGHT, height); ++ ++ /* setup the foreground color in Source Foreground Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_FG_COLOR, fg); ++ ++ /* setup the foreground color in Source Background Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_BG_COLOR, bg); ++ ++ /* transfer bitmap pattern to pattern register */ ++ memcpy_toio(sisfb->mmio_base_virt + SIS315_2D_PATTERN_REG, ++ bitmap, size); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Register, ROP = rop */ ++ cmd = SIS315_2D_CMD_COLOREXP | SIS315_2D_CMD_PAT_PAT_REG | ++ sisfb_command_bpp(sisfb) | (rop << 8); ++ ++ /* if background color == -1 then don't expand background pixels */ ++ if (bg == -1) ++ cmd |= SIS315_2D_CMD_TRANSPARENT; ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++struct sisfb_accelerator sis315_accelerator = { ++ fillrect: sisfb_fillrect, ++ copyrect: sisfb_copyrect, ++ copyrect_transparent: NULL, //sisfb_copyrect_transparent, ++ ++ color_expand_8x8: sisfb_8x8_color_expand, ++ color_expand: sisfb_color_expand, ++ ++ drawline: NULL, //sisfb_drawline, ++ drawline_style: NULL, //sisfb_drawline_style ++}; +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_315_accel.h linux-2.4.6-linuxbios/drivers/video/sis/sisfb_315_accel.h +--- linux-2.4.6-official/drivers/video/sis/sisfb_315_accel.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_315_accel.h Mon Jul 23 12:24:41 2001 +@@ -0,0 +1,95 @@ ++#ifndef __SISFB_315_ACCEL__ ++#define __SISFB_315_ACCEL__ ++ ++#ifdef __KERNEL__ ++#include "sisfb_lite.h" ++#endif __KERNEL__ ++ ++#include "sisfb_accel.h" ++ ++enum sis315_2d_registers { ++ SIS315_2D_SRC_ADDR = 0x8200, ++ SIS315_2D_SRC_PITCH = 0x8204, SIS315_2D_AGP_BASE = 0x8206, ++ SIS315_2D_SRC_Y = 0x8208, SIS315_2D_SRC_X = 0x820A, ++ SIS315_2D_DST_Y = 0x820C, SIS315_2D_DST_X = 0x820E, ++ SIS315_2D_DST_ADDR = 0x8210, ++ SIS315_2D_DST_PITCH = 0x8214, SIS315_2D_DST_HEIGHT = 0x8216, ++ SIS315_2D_RECT_WIDTH = 0x8218, SIS315_2D_RECT_HEIGHT = 0x821A, ++ SIS315_2D_PAT_FG_COLOR = 0x821C, ++ SIS315_2D_PAT_BG_COLOR = 0x8220, ++ SIS315_2D_SRC_FG_COLOR = 0x8224, ++ SIS315_2D_SRC_BG_COLOR = 0x8228, ++ SIS315_2D_MONO_MASK = 0x822C, ++ SIS315_2D_LEFT_CLIP = 0x8234, SIS315_2D_TOP_CLIP = 0x8236, ++ SIS315_2D_RIGHT_CLIP = 0x8238, SIS315_2D_BOT_CLIP = 0x823A, ++ SIS315_2D_CMD = 0x823C, ++ SIS315_2D_PATTERN_REG = 0x8300 ++}; ++ ++enum sis315_2d_registers_drawline { ++ SIS315_2D_LINE_X0 = 0x8208, SIS315_2D_LINE_Y0 = 0x820A, ++ SIS315_2D_LINE_X1 = 0x820C, SIS315_2D_LINE_Y1 = 0x820E, ++ SIS315_2D_LINE_COUNT = 0x8218, SIS315_2D_LINE_STYLE_PERIOD = 0x821A, ++ SIS315_2D_LINE_STYLE_0 = 0x822C, ++ SIS315_2D_LINE_STYLE_1 = 0x8230, ++ SIS315_2D_LINE_Xn = 0x8300, SIS315_2D_LINE_Yn = 0x8302, ++}; ++ ++enum sis315_2d_register_transparent_bitblt { ++ SIS315_2D_TRANS_DEST_KEY_HIGH = 0x821C, ++ SIS315_2D_TRANS_DEST_KEY_LOW = 0x8220, ++ SIS315_2D_TRANS_SRC_KEY_HIGH = 0x8224, ++ SIS315_2D_TRANS_SRC_KEY_LOW = 0x8228, ++}; ++ ++enum sis315_2d_cmd_type { ++ SIS315_2D_CMD_BITBLT = 0x00, SIS315_2D_CMD_COLOREXP = 0x01, ++ SIS315_2D_CMD_ENCOLOREXP = 0x02, SIS315_2D_CMD_MULTIPLE_SCANLINE = 0x03, ++ SIS315_2D_CMD_LINE_DRAW = 0x04, SIS315_2D_CMD_TRAPEZOID_FILL = 0x05, ++ SIS315_2D_CMD_TRANSPARENT_BITBLT = 0x06, SIS315_2D_CMD_ALPHA_BLENDING = 0x07, ++ SIS315_2D_CMD_3D_FUNCTION = 0x08, SIS315_2D_CMD_CLEAR_Z_BUFFER = 0x09, ++ SIS315_2D_CMD_GRADIENT_FILL = 0x0A, SIS315_2D_CMD_STRETCH_BITBLT = 0x0B ++}; ++ ++enum sis315_2d_cmd_control { ++ SIS315_2D_CMD_SRC_VIDEO = 0x00, ++ SIS315_2D_CMD_SRC_SYSTEM = 0x10, ++ SIS315_2D_CMD_SRC_AGP = 0x20, ++ ++ SIS315_2D_CMD_PAT_FG_REG = 0x00, ++ SIS315_2D_CMD_PAT_PAT_REG = 0x40, ++ SIS315_2D_CMD_PAT_MONO_MASK = 0x80, ++ ++ SIS315_2D_CMD_CFB_8 = 0x00000000, ++ SIS315_2D_CMD_CFB_16 = 0x00010000, ++ SIS315_2D_CMD_CFB_32 = 0x00020000, ++ ++ SIS315_2D_CMD_RECT_CLIP_EN = 0x00040000, ++ SIS315_2D_CMD_TRANSPARENT = 0x00100000, ++ ++ /* Subfunction for Color/Enhanced Color Expansion */ ++ SIS315_2D_CMD_COLOR_TO_MONO = 0x00100000, ++ SIS315_2D_CMD_AA_TEXT = 0x00200000, ++ ++ SIS315_2D_CMD_MERGE_CLIP_DIS = 0x04000000, ++ ++ SIS315_2D_CMD_LINE_STLYE_ENABLE = 0x00800000 ++ ++#if 0 ++ SIS315_2D_CMD_DIR_X_INC = 0x00010000, ++ SIS315_2D_CMD_DIR_X_DEC = 0x00000000, ++ SIS315_2D_CMD_DIR_Y_INC = 0x00020000, ++ SIS315_2D_CMD_DIR_Y_DEC = 0x00000000, ++#endif ++}; ++ ++enum sis315_command_queue_registers { ++ SIS315_2D_CMD_QUEUE_BASE_ADDRESS = 0x85C0, ++ SIS315_2D_CMD_QUEUE_WRITE_POINTER = 0x85C4, ++ SIS315_2D_CMD_QUEUE_READ_POINTER = 0x85C8, ++ SIS315_2D_CMD_QUEUE_STATUS = 0x85CC ++}; ++ ++extern struct sisfb_accelerator sis315_accelerator; ++ ++#endif /* __SISFB_315_ACCEL__ */ +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_315_init.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_315_init.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_315_init.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_315_init.c Fri Jul 6 15:14:05 2001 +@@ -0,0 +1,238 @@ ++/* sisfb_315_init.c: Initialization Code for SiS 550 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * 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 License, or ++ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. Glamour II Design Guideline V.12 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_300_core.h" ++#include "sisfb_315_accel.h" ++ ++static void sisfb_set_pci_agp_timming(struct sisfb_info * sisfb); ++static void sisfb_set_dram_config(struct sisfb_info * sisfb); ++static void sisfb_enable_turbo_queue(struct sisfb_info * sisfb); ++static void sisfb_fake_vgabios(struct sisfb_info * sisfb); ++ ++/* Default values for PCI/AGP Timming control registers: SR21-SR25, SR32 */ ++static u8 pci_timming[] __initdata = { ++ /* SR 0x21 - 0x25, 0x31 - 0x33 */ ++ 0xB6, 0xB2, 0xF6, 0x0D, 0x30, 0x00, 0x01, 0x10 ++}; ++ ++/** ++ * sisfb_set_pci_agp_timming: - Set AGP/PCI timming control registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Initialize PCI and AGP timming control registers. Most of them are ++ * dumped form normal BIOS setting. ++ */ ++static void __devinit ++sisfb_set_pci_agp_timming(struct sisfb_info * sisfb) ++{ ++ u8 AGP, tmp; ++ ++ /* SR3A, Hardware Trap III */ ++ tmp = sisfb_get_seq_reg(sisfb, 0x3A); ++ if ((tmp & 0x30) == 0x30) ++ // PCI Mode ++ AGP = 0; ++ else ++ // AGP Mode; ++ AGP = 1; ++ ++ tmp = pci_timming[0]; ++ if (AGP == 0) ++ // Disable AGP Request High Priority ++ tmp &= ~0x10; ++ sisfb_set_seq_reg(sisfb, 0x21, tmp); ++ ++ tmp = pci_timming[1]; ++ if (AGP == 1) ++ // Enable PCI Burst memory write ++ tmp |= 0x20; ++ sisfb_set_seq_reg(sisfb, 0x22, tmp); ++ ++ sisfb_set_seq_reg(sisfb, 0x23, pci_timming[2]); ++ sisfb_set_seq_reg(sisfb, 0x24, pci_timming[3]); ++ sisfb_set_seq_reg(sisfb, 0x25, pci_timming[4]); ++ sisfb_set_seq_reg(sisfb, 0x31, pci_timming[5]); ++ sisfb_set_seq_reg(sisfb, 0x32, pci_timming[6]); ++ sisfb_set_seq_reg(sisfb, 0x33, pci_timming[7]); ++ ++ /* command queue threshold, max = 11111b */ ++ sisfb_set_seq_reg(sisfb, 0x27, 0x1F); ++} ++ ++static u8 dram_config1[] __initdata = { ++ /* SR 0x15-0x1B */ ++ 0x00, 0x0F, 0x5E, 0xA9, 0xA0, 0x00, 0x30 ++}; ++ ++static u8 dram_config2[] __initdata = { ++ /* CR 0x40-0x44 */ ++ 0x33, 0x33, 0x00, 0x03, 0x00 ++}; ++ ++static void __devinit ++sisfb_set_dram_config(struct sisfb_info * sisfb) ++{ ++ int i; ++ ++ for (i = 0x15; i <= 0x1B; i++) ++ sisfb_set_seq_reg(sisfb, i, dram_config1[i - 0x15]); ++ ++ for (i = 0x40; i <= 0x44; i++) ++ sisfb_set_crtc_reg(sisfb, i, dram_config2[i - 0x40]); ++} ++ ++/** ++ * sisfb_enable_turbo_queue: - Set Turbo Queue size and enable it ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Commands to the Graphics Engine (2D, 3D, etc) are buffered in ++ * the Video Memory which is called Turbo Queue in SiS VGA Specs. ++ * Usually this buffer area takes the last few KBs in the Video RAM. ++ */ ++/* default turbo queue size == 512KB */ ++static int tqueue_size = 0x80000; ++static void __devinit ++sisfb_enable_turbo_queue(struct sisfb_info * sisfb) ++{ ++ u32 tqueue_pos; ++ volatile u8 dummy; ++ ++ tqueue_pos = sisfb->video_size_virt - tqueue_size; ++ ++ /* set Command Queue threshold to max value 11111b */ ++ sisfb_set_seq_reg(sisfb, 0x27, 0x1F); ++ /* synchronous reset for Connamd Queue */ ++ sisfb_set_seq_reg(sisfb, 0x26, 0x01); ++ ++ /* FixMe: What does this mean ?? */ ++ dummy = sisfb_readb(sisfb, 0x85C8); ++ sisfb_writeb(sisfb, 0x85C4, dummy); ++ ++ /* enable Command Queue (on Video RAM) , MMIO Commands */ ++ sisfb_set_seq_reg(sisfb, 0x26, 0x22); ++ ++ /* set Command Queue Base Address */ ++ sisfb_writeb(sisfb, 0x85C0, tqueue_pos); ++ ++ printk(KERN_INFO "sisfb_lite: Use %dKB off-screen memory for Turbo Queue\n", ++ tqueue_size / 1024); ++} ++ ++/** ++ * sisfb_fake_vgabios: - Pretend we still have VGA BIOS ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Many of the Extended Sequencer Registers and Externded CRT Controller Registers ++ * are used by traditional System/VGA BIOS and Drivers to pass information back and ++ * forth. We have to fake some resonable values for these registers in order to let ++ * some stupid applications like XFree 3.3.6 work properly. ++ */ ++static void __devinit ++sisfb_fake_vgabios(struct sisfb_info * sisfb) ++{ ++ int i; ++ u8 data, sma_size; ++ u8 fake_bios[] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F}; ++ ++ /* SR 14 is used as "protocol" by VGA BIOS and XFree86 for passing SMA size ++ and bus width, we have to fake them :~-( */ ++ sma_size = sisfb->video_size_virt >> 21; ++ data = fake_bios[ffs(sma_size) - 1]; ++ data |= 0x40; // 64-bit bus ++ sisfb_set_seq_reg(sisfb, 0x14, data); ++ ++ /* SR16-SR19 are used as "protocol" by VGA BIOS and System BIOS for passing ++ information about TV-out, we have to clear them :~-( */ ++ for (i = 0x16; i <= 0x19; i++) { ++ sisfb_set_seq_reg(sisfb, i, 0x00); ++ } ++ ++ /* SR1A are used as "protocol" by VGA BIOS and System BIOS for passing ++ information about M/B frequence, we have to fake them :~-( */ ++ sisfb_set_seq_reg(sisfb, 0x1A, 0x12); ++ ++ /* set MD out enable to 1T (what the hell ??) */ ++ sisfb_set_seq_reg(sisfb, 0x15, 0x01); ++ ++ /* SR1B, SR1C are not used by SiS 630 (used by SiS 300 ??), ++ clear them. */ ++ sisfb_set_seq_reg(sisfb, 0x1B, 0x00); ++ sisfb_set_seq_reg(sisfb, 0x1C, 0x00); ++ ++ /* CR30-CR37 are used by VGA BIOS to pass information ++ about SiS 301, clean them */ ++ for (i = 0x30; i <= 0x3F; i++) { ++ sisfb_set_crtc_reg(sisfb, i, 0x00); ++ } ++} ++ ++/** ++ * sisfb_init_315: - Initialize the SiS315 VGA Core in SiS550 ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV if SMA is incorrectly/not configured ++ * ++ * SiS 315 VGA core is used in SiS550 chipsets. This routine inits ++ * the very SiS315 specific stuff. ++ */ ++int __devinit ++sisfb_init_315(struct sisfb_info * sisfb) ++{ ++ int ret; ++ ++ if ((ret = sisfb_config_memory(sisfb)) < 0) ++ return ret; ++ ++ sisfb_init_legacy_vga(sisfb); ++ ++ /* set to High Speed DAC by default */ ++ sisfb_set_seq_reg(sisfb, 0x07, 0x10); ++ ++ /* Disable DAC pedestal */ ++ sisfb_set_seq_reg(sisfb, 0x1F, 0x00); ++ ++ sisfb_set_pci_agp_timming(sisfb); ++ ++ sisfb_set_dram_config(sisfb); ++ ++ /* disable power management mode */ ++ sisfb_set_seq_reg(sisfb, 0x11, 0x0F); ++ ++ sisfb_enable_turbo_queue(sisfb); ++ ++ sisfb_fake_vgabios(sisfb); ++ ++ /* set hardware specific functions */ ++ sisfb->accelerator = &sis315_accelerator; ++ sisfb->set_par = sisfb_set_par_300; ++ sisfb->pan_display = sisfb_pan_display_300; ++ sisfb->set_disp = sisfb_set_dispsw_fbcon; ++ ++ return 0; ++} +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_530_accel.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_accel.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_530_accel.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_accel.c Thu Jul 12 10:48:13 2001 +@@ -0,0 +1,572 @@ ++/* sisfb_530_accel.c: 2D Hardware Acceleration for SiS 530/620/540/630/730 + * + * Copyright 2001 Ollie Lho + * @@ -291,43 +2049,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + * 4. sis300_accel.c in XFree86 4.0.2 + */ + -+#include "sisfb_accel.h" -+ -+static inline void -+sisfb_writeb(struct sisfb_info *sisfb, u32 offset, u8 val) -+{ -+ writeb(val, sisfb->mmio_base_virt + offset); -+} -+ -+static inline void -+sisfb_writew(struct sisfb_info *sisfb, u32 offset, u16 val) -+{ -+ writew(val, sisfb->mmio_base_virt + offset); -+} -+ -+static inline void -+sisfb_writel(struct sisfb_info *sisfb, u32 offset, u32 val) -+{ -+ writel(val, sisfb->mmio_base_virt + offset); -+} -+ -+static inline u8 -+sisfb_readb(struct sisfb_info *sisfb, u32 offset) -+{ -+ return readb(sisfb->mmio_base_virt + offset); -+} -+ -+static inline u16 -+sisfb_readw(struct sisfb_info *sisfb, u32 offset) -+{ -+ return readw(sisfb->mmio_base_virt + offset); -+} -+ -+static inline u32 -+sisfb_readl(struct sisfb_info *sisfb, u32 offset) -+{ -+ return readl(sisfb->mmio_base_virt + offset); -+} ++#include "sisfb_530_accel.h" + +/** + * sisfb_wait_idle: - Wait for 2D and 3D engine being idle @@ -343,10 +2065,10 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux +sisfb_wait_idle(struct sisfb_info *sisfb) +{ + int count = 0x10; -+ volatile u32 dummy = 0xe0000000; ++ volatile u32 dummy = 0x00000000; + + while (dummy != 0xe0000000 && --count) { -+ dummy = sisfb_readl(sisfb, SIS300_2D_CMD_STATUS) & 0xe000000; ++ dummy = sisfb_readl(sisfb, SIS530_2D_CMD_STATUS) & 0xe0000000; + } +} + @@ -363,7 +2085,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux +{ + do { + /* nothing */ -+ } while ((sisfb_readl(sisfb, SIS300_2D_CMD_STATUS) & 0x1FFF) < (length)); ++ } while ((sisfb_readl(sisfb, SIS530_2D_CMD_STATUS) & 0x1FFF) < (length)); +} + +static inline void @@ -384,7 +2106,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + base = 0xC000; + break; + } -+ sisfb_writew(sisfb, SIS300_2D_AGP_BASE, base); ++ sisfb_writew(sisfb, SIS530_2D_AGP_BASE, base); +} + +/** @@ -411,43 +2133,44 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux +{ + u32 cmd; + u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; + + /* FixMe: What the hell is this ?? */ + sisfb_set_agp_base(sisfb); + + /* setup Source & Desination Pitch */ -+ sisfb_writew(sisfb, SIS300_2D_SRC_PITCH, 0 /* dummy*/); -+ sisfb_writew(sisfb, SIS300_2D_DST_PITCH, pitch); ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, 0 /* dummy*/); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); + + /* disable merge clipping */ -+ sisfb_writew(sisfb, SIS300_2D_DST_HEIGHT, -1); ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); + -+ /* setup Source & Destination Base Address == (0, 0) */ -+ sisfb_writel(sisfb, SIS300_2D_SRC_ADDR, 0); -+ sisfb_writel(sisfb, SIS300_2D_DST_ADDR, 0); ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); + + /* setup Source X and Y origin == (0, 0) */ -+ sisfb_writew(sisfb, SIS300_2D_SRC_X, 0); -+ sisfb_writew(sisfb, SIS300_2D_SRC_Y, 0); ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, 0); + + /* setup Destination X and Y origin == (x, y) */ -+ sisfb_writew(sisfb, SIS300_2D_DST_X, x); -+ sisfb_writew(sisfb, SIS300_2D_DST_Y, y); ++ sisfb_writew(sisfb, SIS530_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, y); + + /* setup Rectangle Width and Height */ -+ sisfb_writew(sisfb, SIS300_2D_RECT_WIDTH, width); -+ sisfb_writew(sisfb, SIS300_2D_RECT_HEIGHT, height); ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); + + /* setup the foreground color in Pattern Foreground Color Register */ -+ sisfb_writel(sisfb, SIS300_2D_PAT_FG_COLOR, color); ++ sisfb_writel(sisfb, SIS530_2D_PAT_FG_COLOR, color); + + /* Command = BitBlt, X++, Y++, pattern = Pattern Foreground Color Register, ROP = rop */ -+ cmd = SIS300_2D_CMD_BITBLT | SIS300_2D_CMD_PAT_FG_REG | -+ SIS300_2D_CMD_DIR_X_INC | SIS300_2D_CMD_DIR_Y_INC | (rop << 8); ++ cmd = SIS530_2D_CMD_BITBLT | SIS530_2D_CMD_PAT_FG_REG | ++ SIS530_2D_CMD_DIR_X_INC | SIS530_2D_CMD_DIR_Y_INC | (rop << 8); + + /* Fire The Command !! */ -+ sisfb_writel(sisfb, SIS300_2D_CMD, cmd); -+ sisfb_writel(sisfb, SIS300_2D_CMD_STATUS, 0); ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); +} + +/** @@ -468,20 +2191,21 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + u32 dstx, u32 dsty, u32 width, u32 height, u8 rop) +{ + u32 cmd; -+ u32 x_dir = SIS300_2D_CMD_DIR_X_INC, y_dir = SIS300_2D_CMD_DIR_X_INC; ++ u32 x_dir = SIS530_2D_CMD_DIR_X_INC, y_dir = SIS530_2D_CMD_DIR_X_INC; + u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; + + /* If the direction is "decreasing", the chip wants the addresses + * to be at the other end, so we must be aware of that in our + * calculations. */ + if (srcx <= dstx) { -+ x_dir = SIS300_2D_CMD_DIR_X_DEC; ++ x_dir = SIS530_2D_CMD_DIR_X_DEC; + srcx += width - 1; + dstx += width - 1; + } + + if (srcy <= dsty) { -+ y_dir = SIS300_2D_CMD_DIR_Y_DEC; ++ y_dir = SIS530_2D_CMD_DIR_Y_DEC; + srcy += height - 1; + dsty += height - 1; + } @@ -490,35 +2214,105 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + sisfb_set_agp_base(sisfb); + + /* setup Source & Desination Pitch */ -+ sisfb_writew(sisfb, SIS300_2D_SRC_PITCH, pitch); -+ sisfb_writew(sisfb, SIS300_2D_DST_PITCH, pitch); ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, pitch); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); + + /* disable merge clipping */ -+ sisfb_writew(sisfb, SIS300_2D_DST_HEIGHT, -1); ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); + -+ /* setup Source & Destination Base Address == (0, 0) */ -+ sisfb_writel(sisfb, SIS300_2D_SRC_ADDR, 0); -+ sisfb_writel(sisfb, SIS300_2D_DST_ADDR, 0); ++ /* setup Source & Destination Base Address == (screen_offset, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, base); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); + + /* setup Source X and Y origin == (srcx, srcy) */ -+ sisfb_writew(sisfb, SIS300_2D_SRC_X, srcx); -+ sisfb_writew(sisfb, SIS300_2D_SRC_Y, srcy); ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, srcx); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, srcy); + + /* setup Destination X and Y origin == (dstx, dsty) */ -+ sisfb_writew(sisfb, SIS300_2D_DST_X, dstx); -+ sisfb_writew(sisfb, SIS300_2D_DST_Y, dsty); ++ sisfb_writew(sisfb, SIS530_2D_DST_X, dstx); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, dsty); + + /* setup Rectangle Width and Height */ -+ sisfb_writew(sisfb, SIS300_2D_RECT_WIDTH, width); -+ sisfb_writew(sisfb, SIS300_2D_RECT_HEIGHT, height); ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); + + /* Command = BitBlt, X Dir, Y Dir, bitblt from video memory (ScrenToScreen), ROP = rop */ -+ cmd = SIS300_2D_CMD_BITBLT | SIS300_2D_CMD_SRC_VIDEO | ++ cmd = SIS530_2D_CMD_BITBLT | SIS530_2D_CMD_SRC_VIDEO | + x_dir | y_dir | (rop << 8); + + /* Fire The Command !! */ -+ sisfb_writel(sisfb, SIS300_2D_CMD, cmd); -+ sisfb_writel(sisfb, SIS300_2D_CMD_STATUS, 0); ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++static void ++sisfb_copyrect_transparent(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, ++ u32 src_hi, u32 src_low, ++ u32 dst_hi, u32 dst_low, ++ u8 rop) ++{ ++ u32 cmd; ++ u32 x_dir = SIS530_2D_CMD_DIR_X_INC, y_dir = SIS530_2D_CMD_DIR_X_INC; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* If the direction is "decreasing", the chip wants the addresses ++ * to be at the other end, so we must be aware of that in our ++ * calculations. */ ++ if (srcx <= dstx) { ++ x_dir = SIS530_2D_CMD_DIR_X_DEC; ++ srcx += width - 1; ++ dstx += width - 1; ++ } ++ ++ if (srcy <= dsty) { ++ y_dir = SIS530_2D_CMD_DIR_Y_DEC; ++ srcy += height - 1; ++ dsty += height - 1; ++ } ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, pitch); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (screen_offset, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, base); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, srcx); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS530_2D_DST_X, dstx); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, dsty); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); ++ ++ /* setup Source Color Key */ ++ sisfb_writew(sisfb, SIS530_2D_TRANS_SRC_KEY_HIGH, src_hi); ++ sisfb_writew(sisfb, SIS530_2D_TRANS_SRC_KEY_LOW, src_low); ++ ++ /* setup Destination Color Key */ ++ sisfb_writew(sisfb, SIS530_2D_TRANS_DEST_KEY_HIGH, dst_hi); ++ sisfb_writew(sisfb, SIS530_2D_TRANS_DEST_KEY_LOW, dst_low); ++ ++ /* Command = BitBlt, X Dir, Y Dir, bitblt from video memory (ScrenToScreen), ROP = rop */ ++ cmd = SIS530_2D_CMD_TRANSPARENT_BITBLT | SIS530_2D_CMD_SRC_VIDEO | ++ x_dir | y_dir | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); +} + +/** @@ -533,9 +2327,9 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + * @rop: Raster Operation for the expand + * @bitmap: 8x8 monochrom bitmap (64 bits) + * -+ * Color expand the 8x8 bitmap @bitmap by setting the bit with value 1 to @fg while bit -+ * with value 0 to @bg. Also fill the rectangle (@x, @y) - (@x + @width, @y + @height) -+ * with the expanded pattern. ++ * Color expand the 8x8 bitmap @bitmap by setting bits with value 1 to @fg while bits ++ * with value 0 to @bg. If @bg == -1 then background pixels are not expanded. Also fill ++ * the rectangle (@x, @y) - (@x + @width, @y + @height) with the expanded pattern. + * + * Note: + * 1. The Source Pitch is dummy in this case. @@ -547,50 +2341,55 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux +{ + u32 cmd; + u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; + + /* FixMe: What the hell is this ?? */ + sisfb_set_agp_base(sisfb); + + /* setup Source & Desination Pitch */ -+ sisfb_writew(sisfb, SIS300_2D_SRC_PITCH, 0 /*dummy*/); -+ sisfb_writew(sisfb, SIS300_2D_DST_PITCH, pitch); ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, 0 /*dummy*/); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); + + /* disable merge clipping */ -+ sisfb_writew(sisfb, SIS300_2D_DST_HEIGHT, -1); ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); + -+ /* setup Source & Destination Base Address == (0, 0) */ -+ sisfb_writel(sisfb, SIS300_2D_SRC_ADDR, 0); -+ sisfb_writel(sisfb, SIS300_2D_DST_ADDR, 0); ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); + + /* setup Source X and Y origin == (0, 0) */ -+ sisfb_writew(sisfb, SIS300_2D_SRC_X, 0); -+ sisfb_writew(sisfb, SIS300_2D_SRC_Y, 0); ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, 0); + + /* setup Destination X and Y origin == (x, y) */ -+ sisfb_writew(sisfb, SIS300_2D_DST_X, x); -+ sisfb_writew(sisfb, SIS300_2D_DST_Y, y); ++ sisfb_writew(sisfb, SIS530_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, y); + + /* setup Rectangle Width and Height */ -+ sisfb_writew(sisfb, SIS300_2D_RECT_WIDTH, width); -+ sisfb_writew(sisfb, SIS300_2D_RECT_HEIGHT, height); ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); + + /* setup the foreground color in Pattern Foreground Color Register */ -+ sisfb_writel(sisfb, SIS300_2D_PAT_FG_COLOR, fg); ++ sisfb_writel(sisfb, SIS530_2D_PAT_FG_COLOR, fg); + + /* setup the foreground color in Pattern Background Color Register */ -+ sisfb_writel(sisfb, SIS300_2D_PAT_BG_COLOR, bg); ++ sisfb_writel(sisfb, SIS530_2D_PAT_BG_COLOR, bg); + + /* store 8x8 mono bitmap to Mono Mask Register */ -+ sisfb_writel(sisfb, SIS300_2D_MONO_MASK, *(u32 *) bitmap); -+ sisfb_writel(sisfb, SIS300_2D_MONO_MASK + 4, *(u32 *) (bitmap + 4)); ++ sisfb_writel(sisfb, SIS530_2D_MONO_MASK, *(u32 *) bitmap); ++ sisfb_writel(sisfb, SIS530_2D_MONO_MASK + 4, *(u32 *) (bitmap + 4)); + + /* Command = Color Expand, X++, Y++, color = Mono Mask, ROP = rop */ -+ cmd = SIS300_2D_CMD_COLOREXP | SIS300_2D_CMD_PAT_MONO_MASK | -+ SIS300_2D_CMD_DIR_X_INC | SIS300_2D_CMD_DIR_Y_INC | (rop << 8); ++ cmd = SIS530_2D_CMD_COLOREXP | SIS530_2D_CMD_PAT_MONO_MASK | ++ SIS530_2D_CMD_DIR_X_INC | SIS530_2D_CMD_DIR_Y_INC | (rop << 8); ++ ++ /* if background color == -1 then don't expand background pixels */ ++ if (bg == -1) ++ cmd |= SIS530_2D_CMD_TRANSPARENT; + + /* Fire The Command !! */ -+ sisfb_writel(sisfb, SIS300_2D_CMD, cmd); -+ sisfb_writel(sisfb, SIS300_2D_CMD_STATUS, 0); ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); +} + +/** @@ -606,9 +2405,10 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + * @bitmap: monochrom bitmap (384 bytes max) + * @size: size of @bitmap + * -+ * Color expand the bitmap @bitmap by setting the bit with value 1 to @fg while bit -+ * with value 0 to @bg. The bitmap is transfered to hardware Pattern Register and -+ * can be as large as 384 bytes, effectively expanding 3072 pixels in a single operation. ++ * Color expand the bitmap @bitmap by setting bits with value 1 to @fg while bits ++ * with value 0 to @bg. If @bg == -1 then background pixels are not expanded. The ++ * bitmap is transfered to hardware Pattern Register and can be as large as 384 bytes, ++ * effectively expanding 3072 pixels in a single operation. + * + * The rectangle (@x, @y) - (@x + @width, @y + @height) is filled with the expanded + * pattern. If the size of @bitmap is samller then 384 bytes and the size of the @@ -616,10 +2416,8 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + * with "garbage". + * + * Note: -+ * 1. The Source Pitch is dummy in this case. ++ * 1. The Source Pitch is width/8 then rounded up (i.e. in units of byte). + * 2. We have to use Normal ROPs with color in Source FG/BG Color Register. -+ * 3. The width of the pattern has to be larger than 16. If the width is less -+ * 16, @bitmap should be padded. + */ +static void +sisfb_color_expand(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, @@ -627,57 +2425,535 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux +{ + u32 cmd; + u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; + + /* FixMe: What the hell is this ?? */ + sisfb_set_agp_base(sisfb); + + /* setup Source & Desination Pitch */ -+ sisfb_writew(sisfb, SIS300_2D_SRC_PITCH, 0 /*dummy*/); -+ sisfb_writew(sisfb, SIS300_2D_DST_PITCH, pitch); ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, (width + 7) >> 3); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); + + /* disable merge clipping */ -+ sisfb_writew(sisfb, SIS300_2D_DST_HEIGHT, -1); ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); + -+ /* setup Source & Destination Base Address == (0, 0) */ -+ sisfb_writel(sisfb, SIS300_2D_SRC_ADDR, 0); -+ sisfb_writel(sisfb, SIS300_2D_DST_ADDR, 0); ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); + + /* setup Source X and Y origin == (0, 0) */ -+ sisfb_writew(sisfb, SIS300_2D_SRC_X, 0); -+ sisfb_writew(sisfb, SIS300_2D_SRC_Y, 0); ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, 0); + + /* setup Destination X and Y origin == (x, y) */ -+ sisfb_writew(sisfb, SIS300_2D_DST_X, x); -+ sisfb_writew(sisfb, SIS300_2D_DST_Y, y); ++ sisfb_writew(sisfb, SIS530_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, y); + + /* setup Rectangle Width and Height */ -+ sisfb_writew(sisfb, SIS300_2D_RECT_WIDTH, width); -+ sisfb_writew(sisfb, SIS300_2D_RECT_HEIGHT, height); ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); + + /* setup the foreground color in Source Foreground Color Register */ -+ sisfb_writel(sisfb, SIS300_2D_SRC_FG_COLOR, fg); ++ sisfb_writel(sisfb, SIS530_2D_SRC_FG_COLOR, fg); + + /* setup the foreground color in Source Background Color Register */ -+ sisfb_writel(sisfb, SIS300_2D_SRC_BG_COLOR, bg); ++ sisfb_writel(sisfb, SIS530_2D_SRC_BG_COLOR, bg); + + /* transfer bitmap pattern to pattern register */ -+ memcpy_toio(sisfb->mmio_base_virt + SIS300_2D_PATTERN_REG, ++ memcpy_toio(sisfb->mmio_base_virt + SIS530_2D_PATTERN_REG, + bitmap, size); + + /* Command = Color Expand, X++, Y++, color = Pattern Register, ROP = rop */ -+ cmd = SIS300_2D_CMD_COLOREXP |SIS300_2D_CMD_PAT_PAT_REG | -+ SIS300_2D_CMD_DIR_X_INC | SIS300_2D_CMD_DIR_Y_INC | (rop << 8); ++ cmd = SIS530_2D_CMD_COLOREXP |SIS530_2D_CMD_PAT_PAT_REG | ++ SIS530_2D_CMD_DIR_X_INC | SIS530_2D_CMD_DIR_Y_INC | (rop << 8); ++ ++ /* if background color == -1 then don't expand background pixels */ ++ if (bg == -1) ++ cmd |= SIS530_2D_CMD_TRANSPARENT; + + /* Fire The Command !! */ -+ sisfb_writel(sisfb, SIS300_2D_CMD, cmd); -+ sisfb_writel(sisfb, SIS300_2D_CMD_STATUS, 0); ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); +} + +static void ++sisfb_drawline(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, 1); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_X0, srcx); ++ sisfb_writew(sisfb, SIS530_2D_LINE_Y0, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_X1, dstx); ++ sisfb_writew(sisfb, SIS530_2D_LINE_Y1, dsty); ++ ++ /* setup Line Segement Count == 1 */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_COUNT, 1); ++ sisfb_writew(sisfb, SIS530_2D_LINE_STYLE_PERIOD, 0); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_FG_COLOR, fg); ++ ++ /* setup the foreground color in Pattern Background Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_BG_COLOR, bg); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Foreground Register, ROP = rop */ ++ cmd = SIS530_2D_CMD_LINE_DRAW | SIS530_2D_CMD_PAT_FG_REG | ++ (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++static void ++sisfb_drawline_style(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop, u8 * bitmap) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, 1); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, 0) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_X0, srcx); ++ sisfb_writew(sisfb, SIS530_2D_LINE_Y0, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_X1, dstx); ++ sisfb_writew(sisfb, SIS530_2D_LINE_Y1, dsty); ++ ++ /* setup Line Segment Count == 1 */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_COUNT, 1); ++ sisfb_writew(sisfb, SIS530_2D_LINE_STYLE_PERIOD, 0); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_FG_COLOR, fg); ++ ++ /* setup the foreground color in Pattern Background Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_BG_COLOR, bg); ++ ++ /* transfer bitmap pattern to Line Style register */ ++ sisfb_writel(sisfb, SIS530_2D_LINE_STYLE_0, * bitmap); ++ sisfb_writel(sisfb, SIS530_2D_LINE_STYLE_1, *(bitmap + 1)); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Register, ROP = rop */ ++ cmd = SIS530_2D_CMD_LINE_DRAW | SIS530_2D_CMD_PAT_FG_REG | ++ SIS530_2D_CMD_LINE_STLYE_ENABLE | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++struct sisfb_accelerator sis530_accelerator = { ++ fillrect: sisfb_fillrect, ++ copyrect: sisfb_copyrect, ++ copyrect_transparent: sisfb_copyrect_transparent, ++ ++ color_expand_8x8: sisfb_8x8_color_expand, ++ color_expand: sisfb_color_expand, ++ ++ drawline: sisfb_drawline, ++ drawline_style: sisfb_drawline_style, ++}; +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_530_accel.h linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_accel.h +--- linux-2.4.6-official/drivers/video/sis/sisfb_530_accel.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_accel.h Mon Jul 23 12:24:37 2001 +@@ -0,0 +1,76 @@ ++#ifndef __SISFB_530_ACCEL__ ++#define __SISFB_530_ACCEL__ ++ ++#ifdef __KERNEL__ ++#include "sisfb_lite.h" ++#endif __KERNEL__ ++ ++#include "sisfb_accel.h" ++ ++enum sis530_2d_registers { ++ SIS530_2D_SRC_ADDR = 0x8200, ++ SIS530_2D_SRC_PITCH = 0x8204, SIS530_2D_AGP_BASE = 0x8206, ++ SIS530_2D_SRC_Y = 0x8208, SIS530_2D_SRC_X = 0x820A, ++ SIS530_2D_DST_Y = 0x820C, SIS530_2D_DST_X = 0x820E, ++ SIS530_2D_DST_ADDR = 0x8210, ++ SIS530_2D_DST_PITCH = 0x8214, SIS530_2D_DST_HEIGHT = 0x8216, ++ SIS530_2D_RECT_WIDTH = 0x8218, SIS530_2D_RECT_HEIGHT = 0x821A, ++ SIS530_2D_PAT_FG_COLOR = 0x821C, ++ SIS530_2D_PAT_BG_COLOR = 0x8220, ++ SIS530_2D_SRC_FG_COLOR = 0x8224, ++ SIS530_2D_SRC_BG_COLOR = 0x8228, ++ SIS530_2D_MONO_MASK = 0x822C, ++ SIS530_2D_LEFT_CLIP = 0x8234, SIS530_2D_TOP_CLIP = 0x8236, ++ SIS530_2D_RIGHT_CLIP = 0x8238, SIS530_2D_BOT_CLIP = 0x823A, ++ SIS530_2D_CMD = 0x823C, ++ SIS530_2D_CMD_STATUS = 0x8240, ++ SIS530_2D_PATTERN_REG = 0x8300 ++}; ++ ++enum sis530_2d_registers_drawline { ++ SIS530_2D_LINE_X0 = 0x8208, SIS530_2D_LINE_Y0 = 0x820A, ++ SIS530_2D_LINE_X1 = 0x820C, SIS530_2D_LINE_Y1 = 0x820E, ++ SIS530_2D_LINE_COUNT = 0x8218, SIS530_2D_LINE_STYLE_PERIOD = 0x821A, ++ SIS530_2D_LINE_STYLE_0 = 0x822C, ++ SIS530_2D_LINE_STYLE_1 = 0x8230, ++ SIS530_2D_LINE_Xn = 0x8300, SIS530_2D_LINE_Yn = 0x8302, ++}; ++ ++enum sis530_2d_register_transparent_bitblt { ++ SIS530_2D_TRANS_DEST_KEY_HIGH = 0x821C, ++ SIS530_2D_TRANS_DEST_KEY_LOW = 0x8220, ++ SIS530_2D_TRANS_SRC_KEY_HIGH = 0x8224, ++ SIS530_2D_TRANS_SRC_KEY_LOW = 0x8228, ++}; ++ ++enum sis530_2d_cmd_type { ++ SIS530_2D_CMD_BITBLT = 0x00, SIS530_2D_CMD_COLOREXP = 0x01, ++ SIS530_2D_CMD_ENCOLOREXP = 0x02, SIS530_2D_CMD_MULTIPLE_SCANLINE = 0x03, ++ SIS530_2D_CMD_LINE_DRAW = 0x04, SIS530_2D_CMD_TRAPEZOID_FILL = 0x05, ++ SIS530_2D_CMD_TRANSPARENT_BITBLT = 0x06 ++}; ++ ++enum sis530_2d_cmd_control { ++ SIS530_2D_CMD_SRC_VIDEO = 0x00, ++ SIS530_2D_CMD_SRC_SYSTEM = 0x10, ++ SIS530_2D_CMD_SRC_AGP = 0x20, ++ ++ SIS530_2D_CMD_PAT_FG_REG = 0x00, ++ SIS530_2D_CMD_PAT_PAT_REG = 0x40, ++ SIS530_2D_CMD_PAT_MONO_MASK = 0x80, ++ ++ SIS530_2D_CMD_DIR_X_INC = 0x00010000, ++ SIS530_2D_CMD_DIR_X_DEC = 0x00000000, ++ SIS530_2D_CMD_DIR_Y_INC = 0x00020000, ++ SIS530_2D_CMD_DIR_Y_DEC = 0x00000000, ++ ++ SIS530_2D_CMD_RECT_CLIP_EN = 0x00040000, ++ SIS530_2D_CMD_MERGE_CLIP_DIS = 0x04000000, ++ SIS530_2D_CMD_TRANSPARENT = 0x00100000, ++ ++ SIS530_2D_CMD_LINE_STLYE_ENABLE = 0x00800000 ++}; ++ ++extern struct sisfb_accelerator sis530_accelerator; ++ ++#endif /* __SISFB_530_ACCEL__ */ +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_530_core.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_core.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_530_core.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_core.c Thu Jul 19 11:45:37 2001 +@@ -0,0 +1,102 @@ ++/* sisfb_530_core.c: Setting Video Mode for SiS 530/620 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * 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 License, or ++ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 530 Host, PCI, 3D Graphics & Memory Controller Datasheet, ++ * Preliminary v1.0 Nov. 10, 1998 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_530_core.h" ++ ++static void sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); ++static void sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); ++static void sisfb_set_memory_clocks(struct sisfb_info * sisfb); ++static int sisfb_get_memory_size(struct sisfb_info * sisfb); ++static void sisfb_set_crt1_crtc_regs(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_mode_regs(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_pitch(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_offset(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_vclk(struct sisfb_info * sisfb, struct sisfb_par * par); ++static int sisfb_set_fifo_thresholds(struct sisfb_info * sisfb, struct sisfb_par * par); ++ ++/** ++ * sisfb_get_clock: - Read the clock generator parameters ++ * @sisfb: SiS Frame Buffer structure ++ * @clock: Paramters of the clock generator (return) ++ * @which: Which clock generator to be read. ++ * ++ * Read the clock generator parameters to @clock form the hardware. The desired ++ * clock generator is specified by @which. Valid values are MCLK for memory clock, ++ * VCLK for video dot clock and ECLK for 3D engine. ++ */ ++static void ++sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) ++{ ++ u8 data; ++ ++ /* get divider and numerator */ ++ data = sisfb_get_seq_reg(sisfb, which); ++ clock->divider = ((data & 0x80) >> 7) + 1; ++ clock->numerator = (data & ~0x80) + 1; ++ ++ /* get denumerator and post scalar */ ++ data = sisfb_get_seq_reg(sisfb, which + 1); ++ clock->denumerator = (data & 0x1F) + 1; ++ clock->post_scalar = ((data & 0xE0) >> 5) + 1; ++ ++ /* get VCO gain */ ++ data = sisfb_get_seq_reg(sisfb, which + 2); ++ clock->vco_gain = (data >> 7); ++} ++ ++/** ++ * sisfb_set_clock: - Set the clock generator parameters ++ * @sisfb: SiS Frame Buffer structure ++ * @clock: Paramters of the clock generator ++ * @which: Which clock generator to be read. ++ * ++ * Set the clock generator parameters @clock to the hardware. The desired clock ++ * generator is specified by @which. Valid values are MCLK for memory clock, ++ * VCLK for video dot clock and ECLK for 3D engine. ++ */ ++static void ++sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) ++{ ++ u8 data; ++ ++ /* set divider and numerator */ ++ data = (clock->numerator - 1) & 0x7F; ++ data |= (clock->divider - 1) ? 0x80 : 0x00; ++ sisfb_set_seq_reg(sisfb, which, data); ++ ++ /* set denumerator and post scalar */ ++ data = (clock->denumerator - 1) & 0x1F; ++ data |= (clock->post_scalar - 1) << 5; ++ sisfb_set_seq_reg(sisfb, which + 1, data); ++ ++ /* set VCO gain */ ++ data = clock->vco_gain ? 0x80 : 0x00; ++ sisfb_set_seq_reg(sisfb, which + 2, data); ++} +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_530_core.h linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_core.h +--- linux-2.4.6-official/drivers/video/sis/sisfb_530_core.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_core.h Thu Jul 19 12:04:49 2001 +@@ -0,0 +1,17 @@ ++#ifndef __SISFB_530_CORE__ ++#define __SISFB_530_CORE__ ++ ++#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */ ++#define HW_CURSOR_AREA_SIZE 0x1000 /* 4K */ ++ ++enum clock_gen_base { ++ SIS530_CLK = 0x13, ++ SIS530_MCLK = 0x28, ++ SIS530_DCLK = 0x2A, ++}; ++ ++extern int sisfb_config_memory(struct sisfb_info * sisfb); ++extern int sisfb_pan_display_300(struct fb_var_screeninfo * var, struct sisfb_info * sisfb); ++extern void sisfb_set_par_300(struct sisfb_par *par, struct sisfb_info * sisfb); ++ ++#endif /* __SISFB_300_CORE__ */ +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_530_init.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_init.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_530_init.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_530_init.c Mon Jul 16 17:15:26 2001 +@@ -0,0 +1,113 @@ ++/* sisfb_530_init.c: Initialization code for SiS 530/620 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * 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 License, or ++ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 6326 AGP/PCI Graphics & Video Acclerator. Rev 1.0, May 12, 1997 ++ * 2. SiS 530 Host, PCI, 3D Graphics & Memory Controller Datasheet, ++ * Preliminary v1.0 Nov. 10, 1998 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_530_core.h" ++#include "sisfb_530_accel.h" ++ ++/** ++ * sisfb_enable_turbo_queue: - Set Turbo Queue size and enable it ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Commands to the Graphics Engine (2D, 3D, etc) are buffered in ++ * the Video Memory which is called Turbo Queue in SiS VGA Specs. ++ * Usually this buffer area takes the last few KBs in the Video RAM. ++ */ ++/* default turbo queue size == 32KB */ ++static int tqueue_size = 0x8000; ++static void __devinit ++sisfb_enable_turbo_queue(struct sisfb_info * sisfb) ++{ ++ u32 tqueue_pos; ++ u8 tqueue_status; ++ ++ /* turbo queue position, in units of 32KB */ ++ tqueue_pos = sisfb->video_size_virt - tqueue_size; ++ tqueue_pos /= 0x8000; ++ ++ /* enable Turbo Tueue and Graphics Engine Programming */ ++ tqueue_Status = sisfb_get_seq_reg(sisfb, 0x27); ++ tqueue_status |= 0xC0; ++ ++ sisfb_set_seq_reg(sisfb, 0x27, tqueue_status); ++ sisfb_set_seq_reg(sisfb, 0x2C, tqueue_pos); ++ ++ printk(KERN_INFO "sisfb_lite: Use %dKB off-screen memory for Turbo Queue\n", ++ tqueue_size / 1024); ++ ++} ++ ++/** ++ * sisfb_init_530: - Initialize the SiS530 VGA Core in SiS 530/620 ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV if SMA is incorrectly/not configured ++ * ++ * SiS 300 VGA core is used in SiS 530/620 chipsets. This routine inits ++ * the very SiS300 specific stuff. ++ */ ++int __devinit ++sisfb_init_530(struct sisfb_info * sisfb) ++{ ++ int ret; ++ ++ if ((ret = sisfb_config_memory(sisfb)) < 0) ++ return ret; ++ ++ sisfb_init_legacy_vga(sisfb); ++ ++#if 0 ++ /* set to High Speed DAC by default */ ++ sisfb_set_seq_reg(sisfb, 0x07, 0x13); ++ ++ /* Disable DAC pedestal */ ++ sisfb_set_seq_reg(sisfb, 0x1F, 0x00); ++ ++ sisfb_set_pci_agp_timming(sisfb); ++ ++ /* disable power management mode */ ++ sisfb_set_seq_reg(sisfb, 0x11, 0x0F); ++ ++ /* set screen start memory address bit 23:16 to 0, bit 15:0 are in CR0C, CR0D */ ++ sisfb_set_seq_reg(sisfb, 0x0D, 0x00); ++ ++ sisfb_enable_turbo_queue(sisfb); ++ ++ sisfb_fake_vgabios(sisfb); ++#endif ++ ++ /* set hardware specific functions */ ++ sisfb->accelerator = &sis530_accelerator; ++ sisfb->set_par = sisfb_set_par_530; ++ sisfb->pan_display = sisfb_pan_display_53; ++ sisfb->set_disp = sisfb_set_dispsw_accel; ++ ++ return 0; ++} +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_accel.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_accel.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_accel.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_accel.c Thu Jul 12 10:40:14 2001 +@@ -0,0 +1,360 @@ ++/* sisfb_accel.c: Generic 2D Hardware Acceleration Layer for Text Mode Console ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * 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 License, or ++ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_accel.h" ++ ++static void +sisfb_cfbX_bmove(struct display *disp, int sy, int sx, int dy, int dx, + int height, int width) +{ + struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); + + sx *= fontwidth(disp); + sy *= fontheight(disp); @@ -686,7 +2962,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + width *= fontwidth(disp); + height *= fontheight(disp); + -+ sisfb_copyrect(sisfb, sx, sy, dx, dy, width, height, ROP_COPY); ++ accel->copyrect(sisfb, sx, sy, dx, dy, width, height, ROP_COPY); +} + +static void @@ -694,19 +2970,23 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + int width, u32 color) +{ + struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); + + sx *= fontwidth(disp); + sy *= fontheight(disp); + width *= fontwidth(disp); + height *= fontheight(disp); + -+ sisfb_fillrect(sisfb, sx, sy, width, height, color, ROP_COPY_PAT); ++ accel->fillrect(sisfb, sx, sy, width, height, color, ROP_COPY_PAT); +} + +static void +sisfb_cfbX_putc(struct display *disp, int c, int sy, int sx, u32 fg, u32 bg) +{ + struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); + int width = fontwidth(disp); + int height = fontheight(disp); + int width_b = (width + 7) >> 3; @@ -715,20 +2995,8 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + sx *= fontwidth(disp); + sy *= fontheight(disp); + -+ if (width_b == 1) { -+ int i; -+ u16 padded[PAT_REG_SIZE]; -+ -+ /* FixMe: It seems that the engine only accept 16 bit padded data */ -+ for (i = 0; i < width_b * height; i++) -+ padded[i] = (u16) bitmap[i]; -+ -+ sisfb_color_expand(sisfb, sx, sy, width, height, fg, bg, -+ ROP_COPY, (u8 *) padded, width_b * height * 2); -+ } else { -+ sisfb_color_expand(sisfb, sx, sy, width, height, fg, bg, -+ ROP_COPY, bitmap, width_b * height); -+ } ++ accel->color_expand(sisfb, sx, sy, width, height, fg, bg, ++ ROP_COPY, bitmap, width_b * height); +} + +static void @@ -736,6 +3004,8 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + int sy, int sx, u32 fg, u32 bg) +{ + struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); + int width = fontwidth(disp); + int height = fontheight(disp); + int width_b = (width + 7) >> 3; @@ -750,20 +3020,8 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + c = scr_readw(s++) & disp->charmask; + bitmap = disp->fontdata + c * height * width_b; + -+ if (width_b == 1) { -+ int i; -+ u16 padded[PAT_REG_SIZE]; -+ -+ /* FixMe: It seems that the engine only accept 16 bit padded data */ -+ for (i = 0; i < width_b * height; i++) -+ padded[i] = (u16) bitmap[i]; -+ -+ sisfb_color_expand(sisfb, sx, sy, width, height, fg, bg, -+ ROP_COPY, (u8 *) padded, width_b * height * 2); -+ } else { -+ sisfb_color_expand(sisfb, sx, sy, width, height, fg, bg, -+ ROP_COPY, bitmap, width_b * height); -+ } ++ accel->color_expand(sisfb, sx, sy, width, height, fg, bg, ++ ROP_COPY, bitmap, width_b * height); + + sx += fontwidth(disp); + } @@ -773,11 +3031,13 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux +sisfb_cfbX_revc(struct display *disp, int sx, int sy) +{ + struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); + int width = fontwidth(disp); + int height = fontheight(disp); + int bpp = sisfb->current_par.bits_per_pixel; + -+ sisfb_fillrect(sisfb, sx * width, sy * height, width, height, ++ accel->fillrect(sisfb, sx * width, sy * height, width, height, + (bpp == 8) ? 0x0f : 0xffffffff, ROP_XOR_PAT); +} + @@ -917,6 +3177,8 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + int bottom_only) +{ + struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); + unsigned int cell_w = fontwidth(disp); + unsigned int cell_h = fontheight(disp); + unsigned int right_width = disp->var.xres % cell_w; @@ -926,22 +3188,22 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + + if (!bottom_only && right_width) { + /* clear whole right margin, not only visible portion */ -+ sisfb_fillrect(sisfb, -+ disp->var.xoffset + right_start, 0, -+ right_width, disp->var.yres_virtual, -+ 0x0000, ROP_COPY_PAT); ++ accel->fillrect(sisfb, ++ disp->var.xoffset + right_start, 0, ++ right_width, disp->var.yres_virtual, ++ 0x0000, ROP_COPY_PAT); + } + + if (bottom_height) { -+ sisfb_fillrect(sisfb, -+ disp->var.xoffset, disp->var.yoffset + bottom_start, -+ right_start, bottom_height, -+ 0x0000, ROP_COPY_PAT); ++ accel->fillrect(sisfb, ++ disp->var.xoffset, disp->var.yoffset + bottom_start, ++ right_start, bottom_height, ++ 0x0000, ROP_COPY_PAT); + } +} + +#ifdef FBCON_HAS_CFB8 -+struct display_switch sisfb_cfb8 = { ++static struct display_switch sisfb_cfb8 = { + setup: fbcon_cfb8_setup, + bmove: sisfb_cfbX_bmove, + clear: sisfb_cfb8_clear, @@ -955,7 +3217,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux +#endif + +#ifdef FBCON_HAS_CFB16 -+struct display_switch sisfb_cfb16 = { ++static struct display_switch sisfb_cfb16 = { + setup: fbcon_cfb16_setup, + bmove: sisfb_cfbX_bmove, + clear: sisfb_cfb16_clear, @@ -968,22 +3230,8 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux +}; +#endif + -+#ifdef FBCON_HAS_CFB24 -+struct display_switch sisfb_cfb24 = { -+ setup: fbcon_cfb24_setup, -+ bmove: fbcon_cfb24_bmove, -+ clear: fbcon_cfb24_clear, -+ putc: fbcon_cfb24_putc, -+ putcs: fbcon_cfb24_putcs, -+ revc: fbcon_cfb24_revc, -+ cursor: NULL, -+ clear_margins: fbcon_cfb24_clear_margins, -+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) -+}; -+#endif -+ +#ifdef FBCON_HAS_CFB32 -+struct display_switch sisfb_cfb32 = { ++static struct display_switch sisfb_cfb32 = { + setup: fbcon_cfb32_setup, + bmove: sisfb_cfbX_bmove, + clear: sisfb_cfb32_clear, @@ -997,7 +3245,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux +#endif + +void -+sisfb_set_dispsw_sis300(struct display *disp, struct sisfb_info *sisfb, ++sisfb_set_dispsw_accel(struct display *disp, struct sisfb_info *sisfb, + int bpp, int accel) +{ + switch (bpp) { @@ -1015,13 +3263,6 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + break; +#endif + -+#ifdef FBCON_HAS_CFB24 -+ case 24: -+ disp->dispsw = &sisfb_cfb24; -+ disp->dispsw_data = sisfb->fbcon_cmap.cfb24; -+ break; -+#endif -+ +#ifdef FBCON_HAS_CFB32 + case 32: + disp->dispsw = &sisfb_cfb32; @@ -1036,101 +3277,118 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.c linux-2.4.3-linux + + disp->scrollmode = SCROLL_YREDRAW; +} -diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_accel.h linux-2.4.3-linuxbios/drivers/video/sis/sisfb_accel.h ---- linux-2.4.3-official/drivers/video/sis/sisfb_accel.h Thu Jan 1 08:00:00 1970 -+++ linux-2.4.3-linuxbios/drivers/video/sis/sisfb_accel.h Tue Apr 10 14:06:05 2001 -@@ -0,0 +1,78 @@ -+#ifndef __SISFB_LITE_ACCEL__ -+#define __SISFB_LITE_ACCEL__ -+ -+#ifdef __KERNEL__ -+#include "sisfb_lite.h" -+#endif __KERNEL__ -+ -+enum sis300_2d_registers { -+ SIS300_2D_SRC_ADDR = 0x8200, -+ SIS300_2D_SRC_PITCH = 0x8204, SIS300_2D_AGP_BASE = 0x8206, -+ SIS300_2D_SRC_Y = 0x8208, SIS300_2D_SRC_X = 0x820A, -+ SIS300_2D_DST_Y = 0x820C, SIS300_2D_DST_X = 0x820E, -+ SIS300_2D_DST_ADDR = 0x8210, -+ SIS300_2D_DST_PITCH = 0x8214, SIS300_2D_DST_HEIGHT = 0x8216, -+ SIS300_2D_RECT_WIDTH = 0x8218, SIS300_2D_RECT_HEIGHT = 0x821A, -+ SIS300_2D_PAT_FG_COLOR = 0x821C, -+ SIS300_2D_PAT_BG_COLOR = 0x8220, -+ SIS300_2D_SRC_FG_COLOR = 0x8224, -+ SIS300_2D_SRC_BG_COLOR = 0x8228, -+ SIS300_2D_MONO_MASK = 0x822C, -+ SIS300_2D_LEFT_CLIP = 0x8234, SIS300_2D_TOP_CLIP = 0x8236, -+ SIS300_2D_RIGHT_CLIP = 0x8238, SIS300_2D_BOT_CLIP = 0x823A, -+ SIS300_2D_CMD = 0x823C, -+ SIS300_2D_CMD_STATUS = 0x8240, -+ SIS300_2D_PATTERN_REG = 0x8300 -+}; +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_accel.h linux-2.4.6-linuxbios/drivers/video/sis/sisfb_accel.h +--- linux-2.4.6-official/drivers/video/sis/sisfb_accel.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_accel.h Fri Jul 6 10:26:41 2001 +@@ -0,0 +1,86 @@ ++#ifndef __SISFB_ACCEL__ ++#define __SISFB_ACCEL__ + +#define PAT_REG_SIZE 384 + -+enum sis300_2d_registers_drawline { -+ SIS300_2D_LINE_X0 = 0x8208, SIS300_2D_LINE_Y0 = 0x820A, -+ SIS300_2D_LINE_X1 = 0x820C, SIS300_2D_LINE_Y1 = 0x820E, -+ SIS300_2D_LINE_COUNT = 0x8218, SIS300_2D_LINE_STYLE_PERIOD = 0x821A, -+ SIS300_2D_LINE_STYLE_0 = 0x822C, -+ SIS300_2D_LINE_STYLE_1 = 0x8230, -+ SIS300_2D_LINE_Xn = 0x8300, SIS300_2D_LINE_Yn = 0x8302, ++enum sisfb_raster_op_bitblt { ++ ROP_CLEAR = 0x00, /* dst = 0, 0 */ ++ ROP_AND = 0x88, /* dst = dst & src, DSa */ ++ RON_AND_REVERSE = 0x44, /* dst = ~dst & src, SDna */ ++ ROP_COPY = 0xCC, /* dst = src, S */ ++ ROP_AND_INVERTED = 0x22, /* dst = dst & ~src, DSna */ ++ ROP_NOOP = 0xAA, /* dst = dst, D */ ++ ROP_XOR = 0x66, /* dst = dst ^ src, DSx */ ++ ROP_OR = 0xEE, /* dst = dst | src, DSo */ ++ ROP_NOR = 0x11, /* dst = ~(dst | src), DSon */ ++ ROP_EQUIV = 0x99, /* dst = dst ^ ~src, DSxn */ ++ ROP_INVERT = 0x55, /* dst = ~dst, Dn */ ++ ROP_OR_INVERSE = 0xDD, /* dst = ~dst | src, SDno */ ++ ROP_COPY_INVERTED = 0x33, /* dst = ~src, Sn */ ++ ROP_OR_INVERTED = 0xBB, /* dst = ~src | dst, DSno */ ++ ROP_NAND = 0x77, /* dst = ~(dst & src), DSan */ ++ ROP_SET = 0xFF, /* dst = 1, 1 */ ++ ++ /* same as above, but with pattern as source */ ++ ROP_CLEAR_PAT = 0x00, /* dst = 0, 0 */ ++ ROP_AND_PAT = 0xA0, /* dst = dst & src, DSa */ ++ RON_AND_REVERSE_PAT = 0x50, /* dst = ~dst & src, SDna */ ++ ROP_COPY_PAT = 0xF0, /* dst = src, S */ ++ ROP_AND_INVERTED_PAT = 0x0A, /* dst = dst & ~src, DSna */ ++ ROP_NOOP_PAT = 0xAA, /* dst = dst, D */ ++ ROP_XOR_PAT = 0x5A, /* dst = dst ^ src, DSx */ ++ ROP_OR_PAT = 0xFA, /* dst = dst | src, DSo */ ++ ROP_NOR_PAT = 0x05, /* dst = ~(dst | src), DSon */ ++ ROP_EQUIV_PAT = 0xA5, /* dst = dst ^ ~src, DSxn */ ++ ROP_INVERT_PAT = 0x55, /* dst = ~dst, Dn */ ++ ROP_OR_REVERSE_PAT = 0xDD, /* dst = ~dst | src, SDno */ ++ ROP_COPY_INVERTED_PAT = 0x0F, /* dst = ~src, Sn */ ++ ROP_OR_INVERTED_PAT = 0xAF, /* dst = ~src | dst, DSno */ ++ ROP_NAND_PAT = 0x5F, /* dst = ~(dst & src), DSan */ ++ ROP_SET_PAT = 0xFF, /* dst = 1, 1 */ +}; + -+enum sis300_2d_cmd_type { -+ SIS300_2D_CMD_BITBLT = 0x00, SIS300_2D_CMD_COLOREXP = 0x01, -+ SIS300_2D_CMD_ENCOLOREXP = 0x02, SIS300_2D_CMD_MULTIPLE_SCANLINE = 0x03, -+ SIS300_2D_CMD_LINE_DRAW = 0x04, SIS300_2D_CMD_TRAPEZOID_FILL = 0x05, -+ SIS300_2D_CMD_TRANSPARENT_BITBLT = 0x06 ++enum sisfb_raster_op_transparent_bitblt { ++ ROP_BLACK, ++ ROP_NOT_MERGE_PEN, +}; + -+enum sis300_2d_cmd_control { -+ SIS300_2D_CMD_SRC_VIDEO = 0x00, -+ SIS300_2D_CMD_SRC_SYSTEM = 0x10, -+ SIS300_2D_CMD_SRC_AGP = 0x20, ++#ifdef __KERNEL__ ++struct sisfb_accelerator { ++ void (*fillrect)(struct sisfb_info *sisfb, u32 x, u32 y, ++ u32 width, u32 height, u32 color, u8 rop); ++ void (*copyrect)(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, u8 rop); ++ void (*copyrect_transparent)(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, ++ u32 src_hi, u32 src_low, ++ u32 dst_hi, u32 dst_low, ++ u8 rop); + -+ SIS300_2D_CMD_PAT_FG_REG = 0x00, -+ SIS300_2D_CMD_PAT_PAT_REG = 0x40, -+ SIS300_2D_CMD_PAT_MONO_MASK = 0x80, ++ void (*color_expand_8x8)(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, ++ u32 height, u32 fg, u32 bg, u8 rop, u8 * bitmap); ++ void (*color_expand)(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, ++ u32 height, u32 fg, u32 bg, u8 rop, u8 * bitmap, u32 size); + -+ SIS300_2D_CMD_DIR_X_INC = 0x00010000, -+ SIS300_2D_CMD_DIR_X_DEC = 0x00000000, -+ SIS300_2D_CMD_DIR_Y_INC = 0x00020000, -+ SIS300_2D_CMD_DIR_Y_DEC = 0x00000000, ++ void (*drawline)(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop); ++ void (*drawline_style)(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop, ++ u8 * bitmap); + -+ SIS300_2D_CMD_RECT_CLIP_EN = 0x00040000, -+ SIS300_2D_CMD_MERGE_CLIP_DIS = 0x04000000, -+ SIS300_2D_CMD_TRANSPARENT = 0x00100000, ++#if 0 ++ /* not implemented yet */ ++ void (*span_fill)(struct sisfb_info * sisfb, u32 srcy, u32 fg, u32 bg, ++ u32 *span, u8 rop, u8 * bitmap); + -+ SIS300_2D_CMD_LINE_STLYE_ENABLE = 0x00800000 ++ void (*trapezoid_fill)(struct sisfb_info * sisfb, ...); ++#endif +}; + -+enum sis300_raster_op { -+ ROP_COPY = 0xCC, // src -+ ROP_INVERT = 0x55, // NOT dst -+ ROP_XOR = 0x66, // src XOR dst ++void ++sisfb_set_dispsw_accel(struct display *disp, struct sisfb_info *sisfb, ++ int bpp, int accel); + -+ /* same as above, but with pattern fill */ -+ ROP_COPY_PAT = 0xF0, // src -+ ROP_INVERT_PAT = 0x55, // NOT dst -+ ROP_XOR_PAT = 0x5A // src XOR dst -+}; ++#endif /* __KERNEL_ */ + -+#endif /* __SISFB_LITE_ACCEL__ */ -diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxbios/drivers/video/sis/sisfb_lite.c ---- linux-2.4.3-official/drivers/video/sis/sisfb_lite.c Thu Jan 1 08:00:00 1970 -+++ linux-2.4.3-linuxbios/drivers/video/sis/sisfb_lite.c Tue Apr 10 16:35:27 2001 -@@ -0,0 +1,2274 @@ -+/* sisfb_lite.c: SiSFB Lite, Frame Buffer Device Driver for SiS 540/630/730 requires no VGA BIOS ++#endif /* __SISFB_ACCEL__ */ +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_legacy_init.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_legacy_init.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_legacy_init.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_legacy_init.c Fri Jul 6 16:55:12 2001 +@@ -0,0 +1,313 @@ ++/* sisfb_legacy_init.c: Initialization code for Legacy VGA Registers + * -+ * Copyright 2000 Ollie Lho ++ * Copyright 2001 Ollie Lho ++ * ++ * 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 License, or ++ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * -+ * This driver is derived form an eraly version of sisfb.c which is: -+ * This driver is partly based on the VBE 2.0 compliant graphic -+ * boards framebuffer driver, which is -+ * -+ * (c) 1998 Gerd Knorr + * + * This driver is implemented by the Author for his own personal interests and is NOT a + * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct @@ -1139,80 +3397,22 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + * + * Reference: + * 1. SiS 6326 AGP/PCI Graphics & Video Acclerator. Rev 1.0, May 12, 1997 -+ * 2. Programmer's Guide to the EGA, VGA, and Super VGA Card. Thrid Edition, ++ * 2. SiS 530 Host, PCI, 3D Graphics & Memory Controller Datasheet, ++ * Preliminary v1.0 Nov. 10, 1998 ++ * 3. Programmer's Guide to the EGA, VGA, and Super VGA Card. Third Edition, + * Richard F. Ferraro, Addison-Welsey, Aug. 1994 -+ * 3. Glamour Design Guideline V0.8 -+ * 4. Graphics Hardware by Geert Uytterhoeven -+ * 5. sis86c201.c in XFree86 3.3.6 -+ * -+ * ToDo: -+ * 0. more document -+ * 1. figure out if we need both default_par and current_par + */ + -+/* make checkconfig does not check included files... */ -+#include +#include "sisfb_lite.h" + -+static struct pci_device_id sisfb_pci_tbl [] __devinitdata = { -+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, -+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SIS_GLAMOUR}, -+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, -+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SIS_GLAMOUR}, -+ {0,} -+}; -+MODULE_DEVICE_TABLE (pci, sisfb_pci_tbl); -+ -+static char fontname[40] __initdata; -+static const char * mode_option __initdata; -+ -+static struct fb_var_screeninfo default_var __initdata = { -+ /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ -+ xres: 640, -+ yres: 480, -+ xres_virtual: 640, -+ yres_virtual: 480, -+ xoffset: 0, -+ yoffset: 0, -+ bits_per_pixel: 8, -+ grayscale: 0, -+ red: {0, 8, 0}, -+ green: {0, 8, 0}, -+ blue: {0, 8, 0}, -+ transp: {0, 0, 0}, -+ nonstd: 0, -+ activate: FB_ACTIVATE_NOW, -+ height: -1, -+ width: -1, -+ accel_flags: 0, -+ -+ /* timming, virtually the same as sisfb_default_mode */ -+ pixclock: 39722, -+ left_margin: 48, -+ right_margin: 16, -+ upper_margin: 33, -+ lower_margin: 10, -+ hsync_len: 96, -+ vsync_len: 2, -+ sync: 0, -+ vmode: FB_VMODE_NONINTERLACED -+}; -+ -+static struct fb_videomode sisfb_default_mode __initdata = { -+ name: "640x480-8@60", -+ refresh: 60, -+ xres: 640, -+ yres: 480, -+ pixclock: 39722, -+ left_margin: 48, -+ right_margin: 16, -+ upper_margin: 33, -+ lower_margin: 10, -+ hsync_len: 96, -+ vsync_len: 2, -+ sync: 0, -+ vmode: FB_VMODE_NONINTERLACED -+}; ++static void sisfb_set_default_misc_reg(struct sisfb_info * sisfb); ++static void sisfb_set_default_seq_regs(struct sisfb_info * sisfb); ++static void sisfb_set_default_crtc_regs(struct sisfb_info * sisfb); ++static void sisfb_set_default_grc_regs(struct sisfb_info * sisfb); ++static void sisfb_set_default_attr_regs(struct sisfb_info * sisfb); ++static void sisfb_permute_dac_rgb(struct sisfb_info * sisfb, u8 * colors); ++static void sisfb_load_default_palette(struct sisfb_info * sisfb); ++void sisfb_init_legacy_vga(struct sisfb_info * sisfb); + +static u8 default_vga_palette[] __initdata = { + /* Palette 0-15, original EGA 16 colors stored as 00bbggrr where @@ -1237,373 +3437,6 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + 0x0B, 0x0C, 0x0D, 0x0F, 0x10 +}; + -+/* Default values for PCI/AGP Timming control registers: SR21-SR25, SR32 */ -+static u8 pci_timming[] __initdata = { -+ 0xB6, 0xBA, 0xF6, 0x0D, 0x00, 0x11 -+}; -+ -+/* The Programmable Clock Generator: -+ * -+ * The programmable clock generator is based on Phase Lock Loop (PLL) technology -+ * which requires only one external clock source to generate clock signals with -+ * various frequences. Conceptially, the PLL is just like an OP Amp and is consisted -+ * of a Phase Detector, a Voltage Controlled Oscillator and some frequence dividers. -+ * The clock source Fref is feed to the frequence divider /DeNumerator, then passed -+ * to the Phase Detector (PD). The output of the Phase Detector is used to drive the -+ * Voltage Controlled Oscillator (VCO). The clock signal output of the VCO, called Fvco, -+ * is then feedback to the Pahse Detector after divided by /Divider and /Numerator. -+ * When the PLL is in a stationary state, the 2 inputs of the Phase Detector is the -+ * same. Thus we have equation (1). -+ * -+ * The VCO can only generate a certain range of Fvco, for most case 135 MHz < Fvco < 250 MHz. -+ * If we would like to generate clock frequence Fout that is lower then the lower -+ * bound of Fvco, another frequnce divider called Post Scalar is needed. Then we -+ * have equation (2). By solving equatiuon (1) and (2) we can find the relationship -+ * between clock source Fref and generated clock Fout as in equation (3). -+ * -+ * Note: -+ * 1. From dumping the VGA BIOS data, it seems that the VCO in SiS 630 can generate -+ * frequence in the range of 90 MHZ - 400 MHz. But for the sake of safety, we just -+ * assume that 150 MHz < Fvco < 300 MHz in this implementation. -+ * -+ * 2. The /Divider is in Bit 7 of clock generator I, /Numerator is in Bit 0..6 of -+ * clock generator I and /DeNumerator is in Bit 0..4 of clock generator II. Their -+ * actual values are the values stored in the corresponding register plus 1. -+ * -+ * 3. The /Post Scalar is in Bit 5..7 of clock generator II. The actual meaning of -+ * the values in the register is not clear from the document. We assume that: -+ * 000 => 1, 001 => 2, 010 => 3, 011 => 4 -+ * 110 => 6, 111 => 8, others are reserved. -+ * -+ * 4. The document (6326 Spec and Glamour Design Guideline) only states the VCO Gain, -+ * Bit 7 of clock generator register III should be set for "high frequence operation" -+ * but without specifying the definition of "high frequence". From XFree86 3.3.6, -+ * sisfb.c and BIOS dumping, they are always set. -+ * -+ * -------------- -+ * -------| /Numerator |<------ -+ * | -------------- | -+ * | ------------ -+ * | | /Divider | -+ * | ------------ -+ * | | -+ * ---------------- V ------ ------- | ---------------- -+ * Fref ----> | /DeNumerator |---+--->| CP |----->| VCO |------->| /Post Scalar | ----> Fout -+ * ---------------- PD ------ ------- Fvco ---------------- -+ * ^ -+ * | -+ * Gain -+ * -+ * For -+ * Fref Fvco Fvco -+ * ----------- = ------------------- (1) and Fout = ----------- (2) -+ * DeNumerator Divider * Numerator Post Scalar -+ * -+ * We have -+ * Divider * Numerator -+ * Fout = ------------------------- Fref (14.318 MHz) (3) -+ * Denumerator * Post Scalar -+ * -+ * Reference: -+ * 1. SiS 6326 AGP/PCI Graphics & Video Acclerator. Rev 1.0, May 12, 1997 -+ * 2. Graphics Hardware by Geert Uytterhoeven -+ * 3. sis86c201.c in XFree86 3.3.6 -+ * 4. Glamour Design Guideline V0.8 -+ */ -+ -+/* Clock generator source, 14.318 MHz */ -+#define CLOCK_SOURCE 14318 -+/* Minimium Fvco 150 MHz */ -+#define MIN_F_VCO 150000 -+/* Maximium Fvco 300 MHz */ -+#define MAX_F_VCO 300000 -+ -+struct sisfb_clock_param { -+ /* parameters for setting clock generator for SiS VGA core */ -+ u8 divider; -+ u8 numerator; -+ u8 denumerator; -+ u8 post_scalar; -+ u8 vco_gain; -+}; -+ -+enum clock_gen_base { -+ SIS300_MCLK = 0x28, -+ SIS300_DCLK = 0x2B, -+ SIS300_ECLK = 0x2E -+}; -+ -+static int inverse; -+ -+/* Interface used by the world */ -+int sisfb_setup(char *options); -+int sisfb_init(void); -+ -+/* Internal routines */ -+static void do_install_cmap(struct display * disp, struct fb_info *info); -+static void sisfb_set_dispsw_fbcon(struct display * disp, struct sisfb_info * sisfb, int bpp, int accel); -+static void sisfb_set_dispsw(struct display * disp, struct sisfb_info * sisfb, int bpp, int accel); -+/* ---------------------------------------------------------------------------------- */ -+static void sisfb_lock_regs(struct sisfb_info * sisfb); -+static void sisfb_unlock_regs(struct sisfb_info * sisfb); -+static void sisfb_display_on(struct sisfb_info * sisfb); -+static void sisfb_display_off(struct sisfb_info * sisfb); -+/* ---------------------------------------------------------------------------------- */ -+static void sisfb_set_default_misc_reg(struct sisfb_info * sisfb); -+static void sisfb_set_default_seq_regs(struct sisfb_info * sisfb); -+static void sisfb_set_default_crtc_regs(struct sisfb_info * sisfb); -+static void sisfb_set_default_grc_regs(struct sisfb_info * sisfb); -+static void sisfb_set_default_attr_regs(struct sisfb_info * sisfb); -+static void sisfb_permute_dac_rgb(struct sisfb_info * sisfb, u8 * colors); -+static void sisfb_load_default_palette(struct sisfb_info * sisfb); -+static void sisfb_init_legacy_vga(struct sisfb_info * sisfb); -+/* ---------------------------------------------------------------------------------- */ -+static unsigned long sisfb_calc_clock_freq(struct sisfb_clock_param * clock); -+static int sisfb_calc_clock_param(struct sisfb_clock_param * clock, unsigned long freq); -+static void sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); -+static void sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); -+/* ---------------------------------------------------------------------------------- */ -+static int sisfb_get_memory_size(struct sisfb_info * sisfb); -+static void sisfb_set_memory_clocks(struct sisfb_info * sisfb); -+static int sisfb_config_memory(struct sisfb_info * sisfb); -+static void sisfb_fake_vgabios(struct sisfb_info * sisfb); -+static void sisfb_set_pci_agp_timming(struct sisfb_info * sisfb); -+static void sisfb_init_300(struct sisfb_info * sisfb); -+/* ---------------------------------------------------------------------------------- */ -+static int sisfb_encode_fix(struct fb_fix_screeninfo * fix, struct sisfb_par * par, -+ struct sisfb_info * sisfb); -+static int sisfb_decode_var(struct fb_var_screeninfo * var, struct sisfb_par * par, -+ const struct sisfb_info * sisfb); -+static int sisfb_encode_var(struct fb_var_screeninfo * var, const struct sisfb_par * par, -+ const struct sisfb_info * sisfb); -+static void sisfb_set_par(struct sisfb_par *par, struct sisfb_info * sisfb); -+static int sisfb_getcolreg(unsigned regno, unsigned * red, unsigned * green, unsigned * blue, -+ unsigned * transp, struct fb_info * info); -+static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, -+ unsigned transp, struct fb_info * info); -+/* ---------------------------------------------------------------------------------- */ -+static int sisfb_switch_con(int con, struct fb_info * info); -+static void sisfb_blank(int blank, struct fb_info * info); -+/* ----------------------------------------- fb_ops --------------------------------- */ -+static int sisfb_get_fix(struct fb_fix_screeninfo * fix, int con, struct fb_info * info); -+static int sisfb_get_var(struct fb_var_screeninfo * var, int con, struct fb_info * info); -+static int sisfb_set_var(struct fb_var_screeninfo * var, int con, struct fb_info * info); -+static int sisfb_get_cmap(struct fb_cmap * cmap, int kspc, int con, struct fb_info * info); -+static int sisfb_set_cmap(struct fb_cmap * cmap, int kspc, int con, struct fb_info * info); -+static int sisfb_ioctl(struct inode * inode, struct file * file, unsigned int cmd, -+ unsigned long arg, int con, struct fb_info * info); -+ -+static inline void -+sisfb_set_gen_reg(struct sisfb_info * sisfb, u16 port, u8 data) -+{ -+ u16 base = sisfb->vga_io_base; -+ -+ outb(data, port + base - 0x380); -+} -+ -+static inline u8 -+sisfb_get_gen_reg(struct sisfb_info * sisfb, u16 port) -+{ -+ u16 base = sisfb->vga_io_base; -+ -+ return inb(port + base - 0x380); -+} -+ -+static inline void -+sisfb_set_seq_reg(struct sisfb_info * sisfb, u8 index, u8 data) -+{ -+ u16 port = sisfb->vga_io_base; -+ -+ outb(index, port + SEQ_ADDR); -+ outb(data, port + SEQ_DATA); -+} -+ -+static inline u8 -+sisfb_get_seq_reg(struct sisfb_info * sisfb, u8 index) -+{ -+ u16 port = sisfb->vga_io_base; -+ -+ outb(index, port + SEQ_ADDR); -+ return inb(port + SEQ_DATA); -+} -+ -+static inline void -+sisfb_set_crtc_reg(struct sisfb_info * sisfb, u8 index, u8 data) -+{ -+ u16 port = sisfb->vga_io_base; -+ -+ outb(index, port + CRTC_ADDR); -+ outb(data, port + CRTC_DATA); -+} -+ -+static inline u8 -+sisfb_get_crtc_reg(struct sisfb_info * sisfb, u8 index) -+{ -+ u16 port = sisfb->vga_io_base; -+ -+ outb(index, port + CRTC_ADDR); -+ return inb(port + CRTC_DATA); -+} -+ -+static inline void -+sisfb_set_grc_reg(struct sisfb_info * sisfb, u8 index, u8 data) -+{ -+ u16 port = sisfb->vga_io_base; -+ -+ outb(index, port + GRC_ADDR); -+ outb(data, port + GRC_DATA); -+} -+ -+static inline u8 -+sisfb_get_grc_reg(struct sisfb_info * sisfb, u8 index) -+{ -+ u16 port = sisfb->vga_io_base; -+ -+ outb(index, port + GRC_ADDR); -+ return inb(port + GRC_DATA); -+} -+ -+static inline void -+sisfb_set_attr_reg(struct sisfb_info * sisfb, u8 index, u8 data) -+{ -+ u16 port = sisfb->vga_io_base; -+ volatile u8 dummy; -+ -+ /* Read port 0x3DA, to set the Adderss flip-flop */ -+ dummy = sisfb_get_gen_reg(sisfb, 0x3DA); -+ outb(index, port + ATTR_WRITE); -+ outb(data, port + ATTR_WRITE); -+} -+ -+static inline u8 -+sisfb_get_attr_reg(struct sisfb_info * sisfb, u8 index) -+{ -+ u16 port = sisfb->vga_io_base; -+ volatile u8 dummy; -+ -+ /* Read port 0x3DA, to set the Adderss flip-flop */ -+ dummy = sisfb_get_gen_reg(sisfb, 0x3DA); -+ outb(index, port + ATTR_READ); -+ return inb(port + ATTR_READ); -+} -+ -+/** -+ * sisfb_set_dac_index: - Select DAC color register to be loaded -+ * @sisfb: SiS Frame Buffer structure -+ * @index: Index of the DAC color Register to be loaded -+ * -+ * Select the DAC color register to be loaded by programming the -+ * DAC Write Address Register. -+ */ -+static inline void -+sisfb_set_dac_index(struct sisfb_info * sisfb, u8 index) -+{ -+ u16 port = sisfb->vga_io_base; -+ -+ outb(index, port + DACW_ADDR); -+} -+ -+/** -+ * sisfb_set_dac_rgb: - Load the DAC color register -+ * @sisfb: SiS Frame Buffer structure -+ * @red: Red component -+ * @green: Green component -+ * @blue: Blue compoenet -+ * -+ * Load the DAC color register with (@red, @green, @blue) by writing to the DAC Data -+ * Register. The color register to be loaded is implicitely selected by the DAC Write -+ * Address Register. -+ */ -+static inline void -+sisfb_set_dac_rgb(struct sisfb_info * sisfb, u8 red, u8 green, u8 blue) -+{ -+ u16 port = sisfb->vga_io_base; -+ -+ outb(red, port + DAC_DATA); -+ outb(green, port + DAC_DATA); -+ outb(blue, port + DAC_DATA); -+} -+ -+/** -+ * sisfb_lock_regs: - Lock the CRTC Registers 0-7 and Extended Sequencer Registers -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * Lock CRTC 0-7 by setting Bit 7 of CRTC 0x11. -+ * Lock Extended Registers by writing 0x21 (%SIS_PASSWD_LOCK) to -+ * SR 0x05 (%SIS_PASSWD) -+ */ -+static void -+sisfb_lock_regs(struct sisfb_info * sisfb) -+{ -+ u8 data; -+ -+ /* Set Bit 7 to enable Write Protect for CR0 to CR7 */ -+ data = sisfb_get_crtc_reg(sisfb, 0x11); -+ data = data | 0x80; -+ sisfb_set_crtc_reg(sisfb, 0x11, data); -+ -+ /* lock the access to Extended Registers SR5-SR3C and/or CR30-CR37 ?? */ -+ sisfb_set_seq_reg(sisfb, SIS_PASSWD, SIS_PASSWD_LOCK); -+} -+ -+/** -+ * sisfb_unlock_regs: - Unlock the CRTC Registers 0-7 and Extended Sequencer Registers -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * Unlock CRTC 0-7 by clearing Bit 7 of CRTC 0x11. -+ * Unlock Extended Registers by writing 0x86 (%SIS_PASSWD_UNLOCK) to -+ * SR 0x05 (%SIS_PASSWD) -+ */ -+static void -+sisfb_unlock_regs(struct sisfb_info * sisfb) -+{ -+ u8 data; -+ -+ /* clear Bit 7 to disable Write Protect for CR0 to CR7 */ -+ data = sisfb_get_crtc_reg(sisfb, 0x11); -+ data = data & 0x7f; -+ sisfb_set_crtc_reg(sisfb, 0x11, data); -+ -+ /* unlock the access to Extended Registers SR5-SR3C and/or CR30-CR37 ?? */ -+ sisfb_set_seq_reg(sisfb, SIS_PASSWD, SIS_PASSWD_UNLOCK); -+} -+ -+/** -+ * sisfb_display_on: - Turn the monitor on. -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * Turn on the monitor by clearing Bit 5 of Seqencer Register 0x01 -+ */ -+static void -+sisfb_display_on(struct sisfb_info * sisfb) -+{ -+ u8 data; -+ -+ data = sisfb_get_seq_reg(sisfb, 0x01); -+ -+ /* clear SR1 Bit 5: Screen Off ==> Screen On */ -+ data &= ~0x20; -+ sisfb_set_seq_reg(sisfb, 0x01, data); -+} -+ -+/** -+ * sisfb_display_off: - Turn the monitor off. -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * Turn off the monitor by settng Bit 5 of Seqencer Register 0x01 -+ */ -+static void -+sisfb_display_off(struct sisfb_info * sisfb) -+{ -+ u8 data; -+ -+ data = sisfb_get_seq_reg(sisfb, 0x01); -+ -+ /* set SR1 Bit5: Screen Off */ -+ data |= 0x20; -+ sisfb_set_seq_reg(sisfb, 0x01, data); -+} -+ +/** + * sisfb_set_default_misc_reg: - Set default value for standard VGA Miscellaneouse + * Output Register @@ -1834,11 +3667,11 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + +/** + * sisfb_init_legacy_vga: - Initialize the Standard VGA Registers -+ * @clock: paramters of the clock generator. ++ * @sisfb: SiS Frame Buffer structure + * + * Call other help functions to initialize the standard/legacy VGA registers. + */ -+static void __devinit ++void __devinit +sisfb_init_legacy_vga(struct sisfb_info * sisfb) +{ + sisfb_set_default_seq_regs(sisfb); @@ -1851,6 +3684,421 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + will not work. I have no idea why */ + sisfb_set_default_crtc_regs(sisfb); +} +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_legacy_vga.h linux-2.4.6-linuxbios/drivers/video/sis/sisfb_legacy_vga.h +--- linux-2.4.6-official/drivers/video/sis/sisfb_legacy_vga.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_legacy_vga.h Tue May 29 15:44:10 2001 +@@ -0,0 +1,276 @@ ++#ifndef __SISFB_LEGACY_VGA__ ++#define __SISFB_LEGACY_VGA__ ++ ++/* VGA register Offsets */ ++#define ATTR_WRITE 0x40 ++#define ATTR_READ 0x41 ++#define MISC_OUT_W 0x42 ++#define SEQ_ADDR 0x44 ++#define SEQ_DATA 0x45 ++#define PEL_MASK 0x46 ++#define DACR_ADDR 0x47 ++#define DACW_ADDR 0x48 ++#define DAC_DATA 0x49 ++#define MISC_OUT_R 0x4C ++#define GRC_ADDR 0x4E ++#define GRC_DATA 0x4F ++#define CRTC_ADDR 0x54 ++#define CRTC_DATA 0x55 ++ ++#define FEATURE_READ 0x4A ++#define FEATURE_WRITE 0x5A ++ ++#define SIS_PASSWD 0x05 ++#define SIS_PASSWD_LOCK 0x21 ++#define SIS_PASSWD_UNLOCK 0x86 ++ ++static inline void ++sisfb_writeb(struct sisfb_info *sisfb, u32 offset, u8 val) ++{ ++ writeb(val, sisfb->mmio_base_virt + offset); ++} ++ ++static inline void ++sisfb_writew(struct sisfb_info *sisfb, u32 offset, u16 val) ++{ ++ writew(val, sisfb->mmio_base_virt + offset); ++} ++ ++static inline void ++sisfb_writel(struct sisfb_info *sisfb, u32 offset, u32 val) ++{ ++ writel(val, sisfb->mmio_base_virt + offset); ++} ++ ++static inline u8 ++sisfb_readb(struct sisfb_info *sisfb, u32 offset) ++{ ++ return readb(sisfb->mmio_base_virt + offset); ++} ++ ++static inline u16 ++sisfb_readw(struct sisfb_info *sisfb, u32 offset) ++{ ++ return readw(sisfb->mmio_base_virt + offset); ++} ++ ++static inline u32 ++sisfb_readl(struct sisfb_info *sisfb, u32 offset) ++{ ++ return readl(sisfb->mmio_base_virt + offset); ++} ++ ++static inline void ++sisfb_set_gen_reg(struct sisfb_info * sisfb, u16 port, u8 data) ++{ ++ u16 base = sisfb->vga_io_base; ++ ++ outb(data, port + base - 0x380); ++} ++ ++static inline u8 ++sisfb_get_gen_reg(struct sisfb_info * sisfb, u16 port) ++{ ++ u16 base = sisfb->vga_io_base; ++ ++ return inb(port + base - 0x380); ++} ++ ++static inline void ++sisfb_set_seq_reg(struct sisfb_info * sisfb, u8 index, u8 data) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + SEQ_ADDR); ++ outb(data, port + SEQ_DATA); ++} ++ ++static inline u8 ++sisfb_get_seq_reg(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + SEQ_ADDR); ++ return inb(port + SEQ_DATA); ++} ++ ++static inline void ++sisfb_set_crtc_reg(struct sisfb_info * sisfb, u8 index, u8 data) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + CRTC_ADDR); ++ outb(data, port + CRTC_DATA); ++} ++ ++static inline u8 ++sisfb_get_crtc_reg(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + CRTC_ADDR); ++ return inb(port + CRTC_DATA); ++} ++ ++static inline void ++sisfb_set_grc_reg(struct sisfb_info * sisfb, u8 index, u8 data) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + GRC_ADDR); ++ outb(data, port + GRC_DATA); ++} ++ ++static inline u8 ++sisfb_get_grc_reg(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + GRC_ADDR); ++ return inb(port + GRC_DATA); ++} ++ ++static inline void ++sisfb_set_attr_reg(struct sisfb_info * sisfb, u8 index, u8 data) ++{ ++ u16 port = sisfb->vga_io_base; ++ volatile u8 dummy; ++ ++ /* Read port 0x3DA, to set the Adderss flip-flop */ ++ dummy = sisfb_get_gen_reg(sisfb, 0x3DA); ++ outb(index, port + ATTR_WRITE); ++ outb(data, port + ATTR_WRITE); ++} ++ ++static inline u8 ++sisfb_get_attr_reg(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ volatile u8 dummy; ++ ++ /* Read port 0x3DA, to set the Adderss flip-flop */ ++ dummy = sisfb_get_gen_reg(sisfb, 0x3DA); ++ outb(index, port + ATTR_READ); ++ return inb(port + ATTR_READ); ++} ++ ++/** ++ * sisfb_set_dac_index: - Select DAC color register to be loaded ++ * @sisfb: SiS Frame Buffer structure ++ * @index: Index of the DAC color Register to be loaded ++ * ++ * Select the DAC color register to be loaded by programming the ++ * DAC Write Address Register. ++ */ ++static inline void ++sisfb_set_dac_index(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + DACW_ADDR); ++} ++ ++/** ++ * sisfb_set_dac_rgb: - Load the DAC color register ++ * @sisfb: SiS Frame Buffer structure ++ * @red: Red component ++ * @green: Green component ++ * @blue: Blue compoenet ++ * ++ * Load the DAC color register with (@red, @green, @blue) by writing to the DAC Data ++ * Register. The color register to be loaded is implicitely selected by the DAC Write ++ * Address Register. ++ */ ++static inline void ++sisfb_set_dac_rgb(struct sisfb_info * sisfb, u8 red, u8 green, u8 blue) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(red, port + DAC_DATA); ++ outb(green, port + DAC_DATA); ++ outb(blue, port + DAC_DATA); ++} ++ ++/** ++ * sisfb_lock_regs: - Lock the CRTC Registers 0-7 and Extended Sequencer Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Lock CRTC 0-7 by setting Bit 7 of CRTC 0x11. ++ * Lock Extended Registers by writing 0x21 (%SIS_PASSWD_LOCK) to ++ * SR 0x05 (%SIS_PASSWD) ++ */ ++static inline void ++sisfb_lock_regs(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ /* Set Bit 7 to enable Write Protect for CR0 to CR7 */ ++ data = sisfb_get_crtc_reg(sisfb, 0x11); ++ data = data | 0x80; ++ sisfb_set_crtc_reg(sisfb, 0x11, data); ++ ++ /* lock the access to Extended Registers SR5-SR3C and/or CR30-CR37 ?? */ ++ sisfb_set_seq_reg(sisfb, SIS_PASSWD, SIS_PASSWD_LOCK); ++} ++ ++/** ++ * sisfb_unlock_regs: - Unlock the CRTC Registers 0-7 and Extended Sequencer Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Unlock CRTC 0-7 by clearing Bit 7 of CRTC 0x11. ++ * Unlock Extended Registers by writing 0x86 (%SIS_PASSWD_UNLOCK) to ++ * SR 0x05 (%SIS_PASSWD) ++ */ ++static inline void ++sisfb_unlock_regs(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ /* clear Bit 7 to disable Write Protect for CR0 to CR7 */ ++ data = sisfb_get_crtc_reg(sisfb, 0x11); ++ data = data & 0x7f; ++ sisfb_set_crtc_reg(sisfb, 0x11, data); ++ ++ /* unlock the access to Extended Registers SR5-SR3C and/or CR30-CR37 ?? */ ++ sisfb_set_seq_reg(sisfb, SIS_PASSWD, SIS_PASSWD_UNLOCK); ++} ++ ++/** ++ * sisfb_display_on: - Turn the monitor on. ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Turn on the monitor by clearing Bit 5 of Seqencer Register 0x01 ++ */ ++static inline void ++sisfb_display_on(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ data = sisfb_get_seq_reg(sisfb, 0x01); ++ ++ /* clear SR1 Bit 5: Screen Off ==> Screen On */ ++ data &= ~0x20; ++ sisfb_set_seq_reg(sisfb, 0x01, data); ++} ++ ++/** ++ * sisfb_display_off: - Turn the monitor off. ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Turn off the monitor by settng Bit 5 of Seqencer Register 0x01 ++ */ ++static inline void ++sisfb_display_off(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ data = sisfb_get_seq_reg(sisfb, 0x01); ++ ++ /* set SR1 Bit5: Screen Off */ ++ data |= 0x20; ++ sisfb_set_seq_reg(sisfb, 0x01, data); ++} ++ ++extern void sisfb_init_legacy_vga(struct sisfb_info * sisfb); ++ ++#endif /* __SISFB_LEGACY_VGA__ */ +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_lite.c linux-2.4.6-linuxbios/drivers/video/sis/sisfb_lite.c +--- linux-2.4.6-official/drivers/video/sis/sisfb_lite.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_lite.c Mon Jul 9 10:04:38 2001 +@@ -0,0 +1,1132 @@ ++/* sisfb_lite.c: SiSFB Lite, Frame Buffer Device Driver for SiS 540/630/730 requires no VGA BIOS ++ * ++ * Copyright 2000 Ollie Lho ++ * ++ * This driver is derived form an eraly version of sisfb.c which is: ++ * This driver is partly based on the VBE 2.0 compliant graphic ++ * boards framebuffer driver, which is ++ * ++ * (c) 1998 Gerd Knorr ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 6326 AGP/PCI Graphics & Video Acclerator. Rev 1.0, May 12, 1997 ++ * 2. Programmer's Guide to the EGA, VGA, and Super VGA Card. Third Edition, ++ * Richard F. Ferraro, Addison-Welsey, Aug. 1994 ++ * 3. Glamour Design Guideline V0.8 ++ * 4. Graphics Hardware by Geert Uytterhoeven ++ * 5. sis86c201.c in XFree86 3.3.6 ++ * ++ * ToDo: ++ * 0. more document ++ * 1. figure out if we need both default_par and current_par ++ */ ++ ++/* make checkconfig does not check included files... */ ++#include ++#include "sisfb_lite.h" ++ ++#define PCI_DEVICE_ID_SI_550_VGA 0x5315 ++ ++static struct pci_device_id sisfb_pci_tbl [] __devinitdata = { ++ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, SISFB_LITE_300}, ++ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, SISFB_LITE_300}, ++ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, SISFB_LITE_315}, ++ {0,} ++}; ++MODULE_DEVICE_TABLE (pci, sisfb_pci_tbl); ++ ++static char fontname[40] __initdata; ++static const char * mode_option __initdata; ++ ++static struct fb_var_screeninfo default_var __initdata = { ++ /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ ++ xres: 640, ++ yres: 480, ++ xres_virtual: 640, ++ yres_virtual: 480, ++ xoffset: 0, ++ yoffset: 0, ++ bits_per_pixel: 8, ++ grayscale: 0, ++ red: {0, 8, 0}, ++ green: {0, 8, 0}, ++ blue: {0, 8, 0}, ++ transp: {0, 0, 0}, ++ nonstd: 0, ++ activate: FB_ACTIVATE_NOW, ++ height: -1, ++ width: -1, ++ accel_flags: 0, ++ ++ /* timming, virtually the same as sisfb_default_mode */ ++ pixclock: 39722, ++ left_margin: 48, ++ right_margin: 16, ++ upper_margin: 33, ++ lower_margin: 10, ++ hsync_len: 96, ++ vsync_len: 2, ++ sync: 0, ++ vmode: FB_VMODE_NONINTERLACED ++}; ++ ++static struct fb_videomode sisfb_default_mode __initdata = { ++ name: "640x480-8@60", ++ refresh: 60, ++ xres: 640, ++ yres: 480, ++ pixclock: 39722, ++ left_margin: 48, ++ right_margin: 16, ++ upper_margin: 33, ++ lower_margin: 10, ++ hsync_len: 96, ++ vsync_len: 2, ++ sync: 0, ++ vmode: FB_VMODE_NONINTERLACED ++}; ++ ++static int inverse; ++ ++unsigned long mclk = 100000, eclk = 100000; ++ ++extern int sisfb_init_300(struct sisfb_info * sisfb); ++extern int sisfb_init_315(struct sisfb_info * sisfb); ++ ++/* Interface used by the world */ ++int sisfb_setup(char *options); ++int sisfb_init(void); ++ ++/* Internal routines */ ++static void do_install_cmap(struct display * disp, struct fb_info *info); ++/* ---------------------------------------------------------------------------------- */ ++static int sisfb_encode_fix(struct fb_fix_screeninfo * fix, struct sisfb_par * par, ++ struct sisfb_info * sisfb); ++static int sisfb_decode_var(struct fb_var_screeninfo * var, struct sisfb_par * par, ++ const struct sisfb_info * sisfb); ++static int sisfb_encode_var(struct fb_var_screeninfo * var, const struct sisfb_par * par, ++ const struct sisfb_info * sisfb); ++static int sisfb_getcolreg(unsigned regno, unsigned * red, unsigned * green, unsigned * blue, ++ unsigned * transp, struct fb_info * info); ++static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, ++ unsigned transp, struct fb_info * info); ++/* ---------------------------------------------------------------------------------- */ ++static int sisfb_switch_con(int con, struct fb_info * info); ++static void sisfb_blank(int blank, struct fb_info * info); ++/* ----------------------------------------- fb_ops --------------------------------- */ ++static int sisfb_get_fix(struct fb_fix_screeninfo * fix, int con, struct fb_info * info); ++static int sisfb_get_var(struct fb_var_screeninfo * var, int con, struct fb_info * info); ++static int sisfb_set_var(struct fb_var_screeninfo * var, int con, struct fb_info * info); ++static int sisfb_get_cmap(struct fb_cmap * cmap, int kspc, int con, struct fb_info * info); ++static int sisfb_set_cmap(struct fb_cmap * cmap, int kspc, int con, struct fb_info * info); ++static int sisfb_ioctl(struct inode * inode, struct file * file, unsigned int cmd, ++ unsigned long arg, int con, struct fb_info * info); + +/** + * sisfb_calc_clock_freq: - Calculate the clock frequence generated by @clock @@ -1860,7 +4108,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + * generator given the paremters stated in @clock. The frequence is returned + * in the unit of KHz. + */ -+static unsigned long ++unsigned long +sisfb_calc_clock_freq(struct sisfb_clock_param * clock) +{ + unsigned long freq = CLOCK_SOURCE; @@ -1906,7 +4154,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + * pair such that the error between the generated frequence f_out and desirec + * frequence @freq is minimal. + */ -+static int ++int +sisfb_calc_clock_param(struct sisfb_clock_param * clock, unsigned long freq) +{ + int numerator, denumerator; @@ -1951,326 +4199,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb +} + +/** -+ * sisfb_get_clock: - Read the clock generator parameters -+ * @sisfb: SiS Frame Buffer structure -+ * @clock: Paramters of the clock generator (return) -+ * @which: Which clock generator to be read. -+ * -+ * Read the clock generator parameters to @clock form the hardware. The desired -+ * clock generator is specified by @which. Valid values are MCLK for memory clock, -+ * VCLK for video dot clock and ECLK for 3D engine. -+ */ -+static void -+sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) -+{ -+ u8 data; -+ -+ /* get divider and numerator */ -+ data = sisfb_get_seq_reg(sisfb, which); -+ clock->divider = ((data & 0x80) >> 7) + 1; -+ clock->numerator = (data & ~0x80) + 1; -+ -+ /* get denumerator and post scalar */ -+ data = sisfb_get_seq_reg(sisfb, which + 1); -+ clock->denumerator = (data & 0x1F) + 1; -+ clock->post_scalar = ((data & 0xE0) >> 5) + 1; -+ -+ /* get VCO gain */ -+ data = sisfb_get_seq_reg(sisfb, which + 2); -+ clock->vco_gain = (data >> 7); -+} -+ -+/** -+ * sisfb_set_clock: - Set the clock generator parameters -+ * @sisfb: SiS Frame Buffer structure -+ * @clock: Paramters of the clock generator -+ * @which: Which clock generator to be read. -+ * -+ * Set the clock generator parameters @clock to the hardware. The desired clock -+ * generator is specified by @which. Valid values are MCLK for memory clock, -+ * VCLK for video dot clock and ECLK for 3D engine. -+ */ -+static void -+sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) -+{ -+ u8 data; -+ -+ /* set divider and numerator */ -+ data = (clock->numerator - 1) & 0x7F; -+ data |= (clock->divider - 1) ? 0x80 : 0x00; -+ sisfb_set_seq_reg(sisfb, which, data); -+ -+ /* set denumerator and post scalar */ -+ data = (clock->denumerator - 1) & 0x1F; -+ data |= (clock->post_scalar - 1) << 5; -+ sisfb_set_seq_reg(sisfb, which + 1, data); -+ -+ /* set VCO gain */ -+ data = clock->vco_gain ? 0x80 : 0x00; -+ sisfb_set_seq_reg(sisfb, which + 2, data); -+} -+ -+/** -+ * sisfb_get_memory_size: - Get framebuffer memory size -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * Return 0 on Success, -ENODEV if SMA is incorrectly/not configured -+ * -+ * Get the framebuffer memory size from host controller. For SiS 530/620 and -+ * SiS 540/630/730 Families, the Shared Memory Area (SMA) is enabled in Bit 7, -+ * size is stored in Bit 4..6 of Register 0x63, Host Bridge (i.e. PCI 0:0.0). -+ * The register is set by DRAM initialzation code during boot process and can -+ * not be re-configured once the DRAM has been turned on. -+ */ -+#define SIS630_BANKENABLE 0x63 -+static int __devinit -+sisfb_get_memory_size(struct sisfb_info * sisfb) -+{ -+ struct pci_dev * host = NULL; -+ u8 dram_status, sma_size, sma_size_bits; -+ -+ if ((host = pci_find_slot(0, 0)) == NULL) { -+ printk(KERN_EMERG "sisfb_lite: Can not find Host Controller !!!\n"); -+ return -ENODEV; -+ } -+ -+ /* get SMA configuration from register 0x63 */ -+ pci_read_config_byte(host, SIS630_BANKENABLE, &dram_status); -+ -+ /* SMA not enabled */ -+ if ((dram_status & 0x80) != 0x80) -+ return -ENODEV; -+ -+ /* compute Shared Menory Area (SMA) size in Mega Bytes */ -+ sma_size_bits = (dram_status >> 4) & 0x7; -+ if (sma_size_bits > 5) { -+ // this is invalid! -+ printk(KERN_EMERG "sisfb_lite: Invalid Shared Memory Area Configuration !!!\n"); -+ return -ENODEV; -+ } -+ sma_size = (2 << sma_size_bits); -+ sisfb->video_size_virt = sma_size * 1024 * 1024; -+ -+ return 0; -+} -+ -+/** -+ * sisfb_set_memory_clocks: - Set memory bus clock rate -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * Set the memory clocks for VGA core. Form SiS 300 and up, the VGA core has -+ * 2 independent clocks for 2D and 3D engines. We can set them to different -+ * rates seperatly. -+ */ -+static unsigned long mclk = 100000, eclk = 100000; -+static void __devinit -+sisfb_set_memory_clocks(struct sisfb_info * sisfb) -+{ -+ struct sisfb_clock_param clock; -+ -+ /* set the clock rate according to the option */ -+ sisfb_calc_clock_param(&clock, mclk); -+ sisfb_set_clock(sisfb, &clock, SIS300_MCLK); -+ -+ sisfb_calc_clock_param(&clock, eclk); -+ sisfb_set_clock(sisfb, &clock, SIS300_ECLK); -+ -+ /* read the clock rate back and show to user */ -+ sisfb_get_clock(sisfb, &clock, SIS300_MCLK); -+ printk(KERN_INFO "sisfb_lite: 2D Memory Clock = %6ld KHz\n", -+ sisfb_calc_clock_freq(&clock)); -+ -+ sisfb_get_clock(sisfb, &clock, SIS300_ECLK); -+ printk(KERN_INFO "sisfb_lite: 3D Memory Clock = %6ld KHz\n", -+ sisfb_calc_clock_freq(&clock)); -+} -+ -+/** -+ * sisfb_config_memory: - Configure Framebuffer Memory -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * Return 0 on Success, -ENODEV on Failure -+ * -+ * Configure the frame buffer memory. -+ * If Memory Type Range Registers (MTRR) is configured in the kernel. We set the -+ * Frame Buffer area as "Write Combine" to boost the perfromance. -+ */ -+static int __devinit -+sisfb_config_memory(struct sisfb_info * sisfb) -+{ -+ int ret; -+ u8 data; -+ -+ /* Check if we have SMA configured correctly and HOW MUCH */ -+ if ((ret = sisfb_get_memory_size(sisfb)) < 0) -+ return ret; -+ -+ /* Enable PCI Relocated IO, Memory Mapped IO and Linear Framebuffer Addressing */ -+ data = SIS300_PCI_MMIO_ENABLE; -+ data |= SIS300_PCI_IO_ENABLE; -+ data |= SIS300_PCI_LINEAR_ENABLE; -+ sisfb_set_seq_reg(sisfb, SIS300_PCI_ADDR_SET, data); -+ -+ /* ioremap MMIO and Framebuffer Area */ -+ sisfb->video_base_virt = -+ ioremap(sisfb->video_base_phy, sisfb->video_size_virt); -+ sisfb->mmio_base_virt = -+ ioremap(sisfb->mmio_base_phy, sisfb->mmio_size_phy); -+ -+ printk(KERN_INFO "sisfb_lite: framebuffer at 0x%lx, mapped to 0x%p, size %lu KB\n", -+ sisfb->video_base_phy, (char *) sisfb->video_base_virt, -+ sisfb->video_size_virt / 1024); -+ -+ sisfb_set_memory_clocks(sisfb); -+ -+#ifdef CONFIG_MTRR -+ /* Use MTRR to boost performance */ -+ sisfb->mtrr = mtrr_add(sisfb->video_base_phy, sisfb->video_size_virt, -+ MTRR_TYPE_WRCOMB, 1); -+ if (sisfb->mtrr >= 0) { -+ printk(KERN_INFO "sisfb_lite: Turned on MTRR Write Combine for framebuffer\n"); -+ } -+#endif /* CONFIG_MTRR */ -+ -+ return 0; -+} -+ -+/** -+ * sisfb_fake_vgabios: - Pretend we still have VGA BIOS -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * Many of the Extended Sequencer Registers and Externded CRT Controller Registers -+ * are used by traditional System/VGA BIOS and Drivers to pass information back and -+ * forth. We have to fake some resonable values for these registers in order to let -+ * some stupid applications like XFree 3.3.6 work properly. -+ */ -+static void __devinit -+sisfb_fake_vgabios(struct sisfb_info * sisfb) -+{ -+ int i; -+ u8 data, sma_size; -+ u8 fake_bios[] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F}; -+ -+ /* SR 14 is used as "protocol" by VGA BIOS and XFree86 for passing SMA size -+ and bus width, we have to fake them :~-( */ -+ sma_size = sisfb->video_size_virt >> 21; -+ data = fake_bios[ffs(sma_size) - 1]; -+ data |= 0x40; // 64-bit bus -+ sisfb_set_seq_reg(sisfb, 0x14, data); -+ -+ /* SR16-SR19 are used as "protocol" by VGA BIOS and System BIOS for passing -+ information about TV-out, we have to clear them :~-( */ -+ for (i = 0x16; i <= 0x19; i++) { -+ sisfb_set_seq_reg(sisfb, i, 0x00); -+ } -+ -+ /* SR1A are used as "protocol" by VGA BIOS and System BIOS for passing -+ information about M/B frequence, we have to fake them :~-( */ -+ sisfb_set_seq_reg(sisfb, 0x1A, 0x12); -+ -+ /* set MD out enable to 1T (what the hell ??) */ -+ sisfb_set_seq_reg(sisfb, 0x15, 0x01); -+ -+ /* SR1B, SR1C are not used by SiS 630 (used by SiS 300 ??), -+ clear them. */ -+ sisfb_set_seq_reg(sisfb, 0x1B, 0x00); -+ sisfb_set_seq_reg(sisfb, 0x1C, 0x00); -+ -+ /* CR30-CR37 are used by VGA BIOS to pass information -+ about SiS 301, clean them */ -+ for (i = 0x30; i <= 0x37; i++) { -+ sisfb_set_crtc_reg(sisfb, i, 0x00); -+ } -+} -+ -+/** -+ * sisfb_set_pci_agp_timming: - Set AGP/PCI timming control registers -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * FixME: This function is not finished and is almost BOGUS. -+ */ -+static void __devinit -+sisfb_set_pci_agp_timming(struct sisfb_info * sisfb) -+{ -+ u8 AGP, tmp; -+ -+ /* SR3A, Hardware Trap III */ -+ tmp = sisfb_get_seq_reg(sisfb, 0x3A); -+ if ((tmp & 0x30) == 0x30) -+ // PCI Mode -+ AGP = 0; -+ else -+ // AGP Mode; -+ AGP = 1; -+ -+ tmp = pci_timming[0]; -+ if (AGP == 0) -+ // Disable AGP Request High Priority -+ tmp &= ~0x10; -+ sisfb_set_seq_reg(sisfb, 0x21, tmp); -+ -+ tmp = pci_timming[1]; -+ if (AGP == 1) -+ // Enable PCI Burst memory write -+ tmp |= 0x20; -+ sisfb_set_seq_reg(sisfb, 0x22, tmp); -+ -+ sisfb_set_seq_reg(sisfb, 0x23, pci_timming[2]); -+ sisfb_set_seq_reg(sisfb, 0x24, pci_timming[3]); -+ sisfb_set_seq_reg(sisfb, 0x25, pci_timming[4]); -+ sisfb_set_seq_reg(sisfb, 0x32, pci_timming[5]); -+} -+ -+ -+/* default turbo queue size == 64KB */ -+static int tqueue_size = 0x10000; -+static void __devinit -+sisfb_enable_turbo_queue(struct sisfb_info * sisfb) -+{ -+ u32 tqueue_pos; -+ u8 tqueue_status; -+ -+ tqueue_pos = sisfb->video_size_virt - tqueue_size; -+ tqueue_pos /= 0x10000; -+ -+ /* enable Turbo Tueue */ -+ tqueue_status = 0x80 | (tqueue_pos >> 8); -+ -+ sisfb_set_seq_reg(sisfb, 0x26, tqueue_pos); -+ sisfb_set_seq_reg(sisfb, 0x27, tqueue_status); -+ -+ printk(KERN_INFO "sisfb_lite: Use %dKB off-screen memory for Turbo Queue\n", -+ tqueue_size / 1024); -+} -+ -+/** -+ * sisfb_init_300: - Initialize the SiS300 VGA Core in SiS300, SiS630,540,730 -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * SiS 300 VGA core is used in SiS540/630/730 chipsets. This routine inits -+ * the very SiS300 specific stuff. -+ */ -+static void __devinit -+sisfb_init_300(struct sisfb_info * sisfb) -+{ -+ /* set to High Speed DAC by default */ -+ sisfb_set_seq_reg(sisfb, 0x07, 0x13); -+ -+ /* Disable DAC pedestal */ -+ sisfb_set_seq_reg(sisfb, 0x1F, 0x00); -+ -+ sisfb_set_pci_agp_timming(sisfb); -+ -+ /* disable power management mode */ -+ sisfb_set_seq_reg(sisfb, 0x11, 0x0F); -+ -+ sisfb_enable_turbo_queue(sisfb); -+ -+ sisfb_fake_vgabios(sisfb); -+} -+ -+/** -+ * sisfb_install_cmap: - Install colormap ++ * do_install_cmap: - Install colormap + * @disp: Display structure of current console + * @info: Frame Buffer structure + * @@ -2290,7 +4219,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + } +} + -+static void ++void +sisfb_set_dispsw_fbcon(struct display * disp, struct sisfb_info * sisfb, int bpp, int accel) +{ + switch (bpp) { @@ -2308,13 +4237,6 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + break; +#endif + -+#ifdef FBCON_HAS_CFB24 -+ case 24: -+ disp->dispsw = &fbcon_cfb24; -+ disp->dispsw_data = sisfb->fbcon_cmap.cfb24; -+ break; -+#endif -+ +#ifdef FBCON_HAS_CFB32 + case 32: + disp->dispsw = &fbcon_cfb32; @@ -2330,249 +4252,6 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + disp->scrollmode = SCROLL_YREDRAW; +} + -+extern void sisfb_set_dispsw_sis300(struct display * disp, struct sisfb_info * sisfb, -+ int bpp, int accel); -+ -+static void -+sisfb_set_dispsw(struct display * disp, struct sisfb_info * sisfb, int bpp, int accel) -+{ -+ sisfb_set_dispsw_sis300(disp, sisfb, bpp, accel); -+} -+ -+static void -+sisfb_set_crt1_crtc_regs(struct sisfb_info * sisfb, struct sisfb_par * par) -+{ -+ u16 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend; -+ u16 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend; -+ u16 overflow, overflow_h1, overflow_h2, overflow_v; -+ -+ /* first convert 'par' to "screen" unit */ -+ htotal = (par->htotal >> 3) - 5; -+ hdispend = (par->hdispend >> 3) - 1; -+ hblankstart = (par->hsyncstart >> 3) - 1; -+ hblankend = (par->hsyncend >> 3); -+ hsyncstart = (par->hsyncstart >> 3); -+ hsyncend = (par->hsyncend >> 3); -+ -+ vtotal = par->vtotal - 2; -+ vdispend = par->vdispend - 1; -+ vsyncstart = par->vsyncstart; -+ vsyncend = par->vsyncend; -+ vblankstart = par->vsyncstart; -+ vblankend = par->vsyncend + 1; -+ -+ overflow = -+ ((vsyncstart & 0x200) >> 2) | /* Bit 7, Vertical Retrace Start Bit 9 */ -+ ((vdispend & 0x200) >> 3) | /* Bit 6, Vertical Display End Bit 9 */ -+ ((vtotal & 0x200) >> 4) | /* Bit 5, Vertical Total Bit 9 */ -+ 0x10 | /* Bit 4, line compare Bit 8 */ -+ ((vblankstart & 0x100) >> 5) | /* Bit 3, Vertical Blank Start Bit 8 */ -+ ((vsyncstart & 0x100) >> 6) | /* Bit 2, Vertical Retrace Start Bit 8 */ -+ ((vdispend & 0x100) >> 7) | /* Bit 1, Vertical Display End Bit 8 */ -+ ((vtotal & 0x100) >> 8); /* Bit 0, Vertical Total Bit 8 */ -+ -+ overflow_v = -+ ((vsyncend & 0x010) << 1) | /* Bit 5, Vertical Retrace End Bit 4 */ -+ ((vblankend & 0x100) >> 4) | /* Bit 4, Vertical Blank End Bit 8 */ -+ ((vsyncstart & 0x400) >> 7) | /* Bit 3, Vertical Retrace Start Bit 10 */ -+ ((vblankstart & 0x400) >> 8) | /* Bit 2, Vertical Blank Start Bit 10 */ -+ ((vdispend & 0x400) >> 9) | /* Bit 1, Vertical Display End Bit 10 */ -+ ((vtotal & 0x400) >> 10); /* Bit 0, Vertical Total Bit 10 */ -+ -+ overflow_h1 = -+ ((hsyncstart & 0x300) >> 2) | /* Bit 6,7 Horizontal Retrace Start Bit 8,9 */ -+ ((hblankstart & 0x300) >> 4) | /* Bit 4,5 Horizontal Blank Start Bit 8,9 */ -+ ((hdispend & 0x300) >> 6) | /* Bit 2,3 Horizontal Display End Bit 8,9 */ -+ ((htotal & 0x300) >> 8); /* Bit 0,1 Horizontal Total Bit 8,9 */ -+ -+ overflow_h2 = -+ ((hsyncend & 0x020) >> 3) | /* Bit 2 Horizontal Retrace End Bit 5 */ -+ ((hblankend & 0x0C0) >> 6); /* Bit 0,1 Horizontal Blank End Bit 6,7 */ -+ -+ /* write 'par' to hardware registers, Standard VGA part, low order bits */ -+ sisfb_set_crtc_reg(sisfb, 0x00, htotal); -+ sisfb_set_crtc_reg(sisfb, 0x01, hdispend); -+ sisfb_set_crtc_reg(sisfb, 0x02, hblankstart); -+ sisfb_set_crtc_reg(sisfb, 0x03, -+ 0x80 | /* Bit 7, Enable Vertical Retrace Start/End */ -+ (hblankend & 0x1f)); /* Bit 0:4, Horizontal Blank End Bit 0:4 */ -+ sisfb_set_crtc_reg(sisfb, 0x04, hsyncstart); -+ sisfb_set_crtc_reg(sisfb, 0x05, -+ (hblankend & 0x20) << 2 | /* Bit 7, Horizontal Blank End Bit 5 */ -+ (hsyncend & 0x1f)); /* Bit 0:4, Horizontal Retrace End Bit 0:4 */ -+ sisfb_set_crtc_reg(sisfb, 0x06, vtotal); -+ sisfb_set_crtc_reg(sisfb, 0x09, -+ 0x40 | /* Bit 6, line compare Bit 9 */ -+ (vblankstart & 0x200) >> 4); /* Bit 5, Vertical Blank Start Bit 9 */ -+ sisfb_set_crtc_reg(sisfb, 0x10, vsyncstart); -+ sisfb_set_crtc_reg(sisfb, 0x11, (vsyncend & 0x0F) | 0x20); -+ sisfb_set_crtc_reg(sisfb, 0x12, vdispend); -+ sisfb_set_crtc_reg(sisfb, 0x15, vblankstart); -+ sisfb_set_crtc_reg(sisfb, 0x16, vblankend); -+ -+ /* Standard VGA part, overflow bits */ -+ sisfb_set_crtc_reg(sisfb, 0x07, overflow); -+ -+ /* Extended Registers, overflow bits */ -+ sisfb_set_seq_reg(sisfb, 0x0A, overflow_v); -+ sisfb_set_seq_reg(sisfb, 0x0B, overflow_h1); -+ sisfb_set_seq_reg(sisfb, 0x0C, overflow_h2); -+} -+ -+static void -+sisfb_set_crt1_mode_regs(struct sisfb_info * sisfb, struct sisfb_par * par) -+{ -+ u8 tmp; -+ -+ /* enable Enhanced Graphics Mode and Auto Line Width Counter */ -+ tmp = 0x03; -+ switch (par->bits_per_pixel) { -+ case 32: -+ tmp |= 0x10; -+ break; -+ case 24: -+ tmp |= 0x0C; -+ break; -+ case 16: -+ tmp |= 0x08; -+ break; -+ default: -+ break; -+ } -+ sisfb_set_seq_reg(sisfb, 0x06, tmp); -+ -+ /* enable 2D engine */ -+ sisfb_set_seq_reg(sisfb, 0x1E, 0x40); -+} -+ -+/** -+ * sisfb_set_crt1_pitch: - Set screen pitch registers for CRT1 -+ * @sisfb: SiS Frame Buffer structure -+ * -+ * Set the screen pitch registers for CRT1. Screen pitch refers to the memory address -+ * difference between two dots of the same col on two vertically neighboring scan lines. -+ * The CRTC 0x13 is called "offset register" in VGA literatures. SiS VGA also defines -+ * its own screen line width register SR 0x10. -+ */ -+static void -+sisfb_set_crt1_pitch(struct sisfb_info * sisfb, struct sisfb_par * par) -+{ -+ /* FixME: take interlance into account */ -+ u16 pitch = par->line_length >> 3; -+ u8 line_length = ((par->line_length + 63) >> 6) + 1; -+ -+ /* disable line compare */ -+ sisfb_set_seq_reg(sisfb, 0x0F, 0x08); -+ -+ /* screen pitch, FixME what is the exact unit of this ?? Byte, Double, Long ?? */ -+ sisfb_set_crtc_reg(sisfb, 0x13, pitch & 0xFF); -+ sisfb_set_seq_reg(sisfb, 0x0E, (pitch >> 8) & 0x0F); -+ -+ /* line length */ -+ sisfb_set_seq_reg(sisfb, 0x10, line_length); -+} -+ -+static void -+sisfb_set_crt1_vclk(struct sisfb_info * sisfb, struct sisfb_par * par) -+{ -+ /* FixME: Use clock_param for par->dot_clock */ -+ u32 vclk = par->dot_clock / 1000; -+ u8 tmp = 0x10, tmp1; -+ struct sisfb_clock_param clock; -+ -+ /* Select normal DCLK */ -+ sisfb_set_seq_reg(sisfb, 0x31, 0x00); -+ -+ /* set vclk frequence, FixME: do error check */ -+ sisfb_calc_clock_param(&clock, vclk); -+ sisfb_set_clock(sisfb, &clock, SIS300_DCLK); -+ -+ sisfb_get_clock(sisfb, &clock, SIS300_DCLK); -+ printk(KERN_INFO "sisfb_lite: Video Dot Clock = %6ld KHz\n", -+ sisfb_calc_clock_freq(&clock)); -+ -+ /* set vclk state, this is totally contradict to Glamour Design Guideline */ -+ if (vclk < 100000) -+ tmp |= 0x03; -+ else if (vclk < 200000) -+ tmp |= 0x02; -+ else if (vclk < 250000) -+ tmp |= 0x01; -+ -+ /* set half clock, why ?? */ -+ if (vclk > 150000) { -+ tmp |= 0x80; -+ tmp1 = 0x08; -+ } else { -+ tmp &= 0x7F; -+ tmp1 = 0x00; -+ } -+ -+ sisfb_set_seq_reg(sisfb, 0x07, tmp); -+ sisfb_set_seq_reg(sisfb, 0x32, tmp1); -+} -+ -+static u8 latency_factor[] = { -+ 97, 88, 86, 79, 77, 0, -+ 0, 87, 85, 78, 76, 54, -+ 80, 72, 69, 63, 61, 0, -+ 0, 70, 68, 62, 59, 37, -+}; -+ -+static int -+sisfb_set_fifo_thresholds(struct sisfb_info * sisfb, struct sisfb_par * par) -+{ -+ u32 vclk = par->dot_clock / 1000; -+ unsigned int i = 0, threshold; -+ int grant_timer, fg_queue, bg_queue; -+ struct pci_dev * host = NULL; -+ u8 queue, srf; -+ -+ if ((host = pci_find_slot(0, 0)) == NULL) { -+ printk(KERN_EMERG "sisfb_lite: Can not find Host Controller !!!\n"); -+ return -ENODEV; -+ } -+ -+ pci_read_config_byte(host, 0x53, &queue); -+ queue &= 0xF0; -+ -+ for (grant_timer = 1; grant_timer >= 0; grant_timer--) { -+ for (fg_queue = 0; fg_queue <= 5; fg_queue++) { -+ for (bg_queue = 0; bg_queue <= 1; bg_queue++) { -+ threshold = latency_factor[i++] * vclk; -+ threshold *= (par->bits_per_pixel >> 3); -+ threshold /= (mclk * 16); -+ if (threshold > 0x13 || threshold == 0x00) -+ ; -+ else -+ goto set_threshold; -+ } -+ } -+ } -+ -+ return -EINVAL; -+ -+ set_threshold: -+ /* write froeground and backgroudn queue, GUI grant timer */ -+ queue |= ((fg_queue << 1) | bg_queue); -+ pci_write_config_byte(host, 0x53, queue); -+ pci_write_config_byte(host, 0xA3, grant_timer); -+ -+ /* Write CRT/CPU threshold low, CRT/Engine threshold high */ -+ threshold += 1; -+ srf = sisfb_get_seq_reg(sisfb, 0x0F); -+ sisfb_set_seq_reg(sisfb, 0x08, ((threshold & 0x0F) << 4 | 0x0F)); -+ sisfb_set_seq_reg(sisfb, 0x0F, ((threshold & 0x10) << 1 | srf )); -+ -+ /* Write CRT/CPU threshold high */ -+ threshold += 3; -+ if (threshold > 0x0F) -+ threshold = 0x0F; -+ sisfb_set_seq_reg(sisfb, 0x09, (threshold & 0x0F)); -+ -+ return 0; -+} -+ +/** + * sisfb_encode_fix: - Encode the Fixed Part of the Display + * @fix: Fixed screen info (return) @@ -2594,18 +4273,9 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id, "SiSFB Lite"); + -+ /* fix->smem_start is used as a hack to reserve offsecren memory for -+ * Xserver and MPEG decoder library */ + fix->smem_start = sisfb->video_base_phy; + fix->smem_len = sisfb->video_size_virt; + -+#ifdef XFree86_BUG -+ if (sisfb->video_size_virt > 0x800000) -+ fix->smem_len = RESERVED_MEM_SIZE_8M; /* reserved for Xserver */ -+ else -+ fix->smem_len = RESERVED_MEM_SIZE_4M; /* reserved for Xserver */ -+#endif -+ + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; + @@ -2614,8 +4284,8 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + else + fix->visual = FB_VISUAL_TRUECOLOR; + -+ fix->xpanstep = 0; -+ fix->ypanstep = 0; ++ fix->xpanstep = 8; ++ fix->ypanstep = 1; + fix->ywrapstep = 0; + + fix->line_length = par->line_length; @@ -2625,14 +4295,6 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + + fix->accel = FB_ACCEL_SIS_GLAMOUR; + -+#ifdef XFree86_BUG -+ /* FixMe: Remove these lines, currently used for old sisfb.c and -+ * other graphics library */ -+ fix->reserved[0] = sisfb->video_size_virt & 0xFFFF; -+ fix->reserved[1] = (sisfb->video_size_virt >> 16) & 0xFFFF; -+ fix->reserved[2] = 0; /* capabilities, Trubo Queue and HW Cursor */ -+#endif -+ + return 0; +} + @@ -2654,30 +4316,31 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + struct sisfb_par * par, const struct sisfb_info * sisfb) +{ + if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && -+ var->bits_per_pixel != 24 && var->bits_per_pixel != 32) { ++ var->bits_per_pixel != 32) { + printk(KERN_ERR "sisfb_lite: depth not supported: %u\n", + var->bits_per_pixel); + return -EINVAL; + } + -+ if (var->xoffset) { -+ printk(KERN_ERR "sisfb_lite: xoffset not supported\n"); ++ /* make sure there is enough video ram for the mode */ ++ if ((u32)(var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8) > ++ sisfb->video_size_virt) { ++ printk(KERN_ERR "sisfb_lite: Not enough memory for mode\n"); + return -EINVAL; + } + -+ if (var->yoffset) { -+ printk(KERN_ERR "yoffset not supported\n"); -+ return -EINVAL; -+ } ++ /* FixMe: virtual resolution can only be 2^N for SiS530/620 */ + + memset(par, 0, sizeof(struct sisfb_par)); + + par->hdispend = var->xres; ++ par->xvirt = var->xres_virtual; + par->hsyncstart = par->hdispend + var->right_margin; + par->hsyncend = par->hsyncstart + var->hsync_len; + par->htotal = par->hsyncend + var->left_margin; + + par->vdispend = var->yres; ++ par->yvirt = var->yres_virtual; + par->vsyncstart = par->vdispend + var->lower_margin; + par->vsyncend = par->vsyncstart + var->vsync_len; + par->vtotal = par->vsyncend + var->upper_margin; @@ -2687,7 +4350,11 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + par->bits_per_pixel = var->bits_per_pixel; + par->cmap_len = (par->bits_per_pixel == 8) ? 256 : 16; + -+ par->line_length = var->xres * (par->bits_per_pixel >> 3); ++ par->line_length = var->xres_virtual * (var->bits_per_pixel >> 3); ++ ++ /* update screen_offset member of current par structure */ ++ par->screen_offset = (var->yoffset * var->xres_virtual + var->xoffset) * ++ (var->bits_per_pixel >> 3); + +#if 0 + if (var->sync & FB_SYNC_HOR_HIGH_ACT) @@ -2719,8 +4386,8 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + + var->xres = par->hdispend; + var->yres = par->vdispend; -+ var->xres_virtual = var->xres; -+ var->yres_virtual = var->yres; ++ var->xres_virtual = par->xvirt; ++ var->yres_virtual = par->yvirt; + var->right_margin = par->hsyncstart - par->hdispend; + var->hsync_len = par->hsyncend - par->hsyncstart; + var->left_margin = par->htotal - par->hsyncend; @@ -2732,11 +4399,14 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + var->width = -1; + + switch (par->bits_per_pixel) { ++#ifdef FBCON_HAS_CFB8 + case 8: + var->red.length = 6; + var->green.length = 6; + var->blue.length = 6; + break; ++#endif ++#ifdef FBCON_HAS_CFB16 + case 16: /* RGB 565 */ + var->red.offset = 11; + var->red.length = 5; @@ -2747,16 +4417,8 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + var->transp.offset = 0; + var->transp.length = 0; + break; -+ case 24: /* RGB 888 */ -+ var->red.offset = 16; -+ var->red.length = 8; -+ var->green.offset = 8; -+ var->green.length = 8; -+ var->blue.offset = 0; -+ var->blue.length = 8; -+ var->transp.offset = 0; -+ var->transp.length = 0; -+ break; ++#endif ++#ifdef FBCON_HAS_CFB32 + case 32: + var->red.offset = 16; + var->red.length = 8; @@ -2767,6 +4429,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + var->transp.offset = 24; + var->transp.length = 8; + break; ++#endif + } + + var->pixclock = (u32) (1E12 / par->dot_clock); @@ -2784,28 +4447,6 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + return 0; +} + -+/* -+ * Set the hardware according to 'par'. -+ */ -+static void -+sisfb_set_par(struct sisfb_par *par, struct sisfb_info * sisfb) -+{ -+ sisfb_display_off(sisfb); -+ -+ /* Standard VAG CRTC Registers */ -+ sisfb_set_crt1_crtc_regs(sisfb, par); -+ -+ /* Extended Registers, other stuff */ -+ sisfb_set_crt1_pitch(sisfb, par); -+ sisfb_set_crt1_vclk(sisfb, par); -+ sisfb_set_crt1_mode_regs(sisfb, par); -+ sisfb_set_fifo_thresholds(sisfb, par); -+ -+ sisfb->current_par = *par; -+ -+ sisfb_display_on(sisfb); -+} -+ +/** + * sisfb_getcolreg: - Read color register + * @regno: Color register number @@ -2891,11 +4532,6 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + ((blue & 0xF8) >> 3); + break; +#endif -+#ifdef FBCON_HAS_CFB24 -+ case 24: -+ sisfb->fbcon_cmap.cfb24[regno] = (red << 16) | (green << 8) | (blue); -+ break; -+#endif +#ifdef FBCON_HAS_CFB32 + case 32: + sisfb->fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue); @@ -2934,10 +4570,10 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + + /* convert var to par and set the hardware by set_par */ + sisfb_decode_var(&fb_display[con].var, &par, sisfb); -+ sisfb_set_par(&par, sisfb); ++ sisfb->set_par(&par, sisfb); + + /* set display switch for current bits_per_pixel */ -+ sisfb_set_dispsw(&fb_display[con], sisfb, fb_display[con].var.bits_per_pixel, 0); ++ sisfb->set_disp(&fb_display[con], sisfb, fb_display[con].var.bits_per_pixel, 0); + + /* Install new colormap for current console */ + do_install_cmap(&fb_display[con], info); @@ -2945,6 +4581,17 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + return 1; +} + ++static int ++sisfb_updatevar(int con, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ ++ if (con == sisfb->currcon) ++ sisfb->pan_display(&fb_display[con].var, sisfb); ++ ++ return 0; ++} ++ +/** + * sisfb_blank: - Blanking or Unblanking the CRT + * @blank: 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off @@ -3105,7 +4752,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + display->inverse = inverse; + display->var = *var; + -+ sisfb_set_dispsw(display, sisfb, var->bits_per_pixel, 0); ++ sisfb->set_disp(display, sisfb, var->bits_per_pixel, 0); + + if (info->changevar) + (*info->changevar) (con); @@ -3114,13 +4761,13 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + /* call sisfb_set_par if the console is visible (foreground) console + or during initialization */ + if (!sisfb->info.display_fg || sisfb->info.display_fg->vc_num == con || con < 0) -+ sisfb_set_par(&par, sisfb); ++ sisfb->set_par(&par, sisfb); + + /* clear OnScreen */ + memset((unsigned char *) sisfb->video_base_virt, 0, par.line_length * var->yres); + + /* if we have changed the color depth, install new colormap -+ FixME: We only alloc_cmap but never free one ?? */ ++ FixME: We only alloc_cmap but never free one ?? */ + if (oldbpp != var->bits_per_pixel || con < 0) { + if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) + return err; @@ -3206,6 +4853,56 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + return err; +} + ++/* ++ * Pan or Wrap the Display ++ * ++ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag ++ */ ++static int ++sisfb_pan_display(struct fb_var_screeninfo * var, int con, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ struct display *disp; ++ ++ if (con == -1) ++ disp = &sisfb->disp; ++ else ++ disp = &fb_display[con]; ++ ++ if (var->xoffset > (var->xres_virtual - var->xres)) ++ return -EINVAL; ++ if (var->yoffset > (var->yres_virtual - var->yres)) ++ return -EINVAL; ++ ++ if (var->vmode & FB_VMODE_YWRAP) { ++ if (var->yoffset < 0 || ++ var->yoffset >= disp->var.yres_virtual || ++ var->xoffset) ++ return -EINVAL; ++ } else { ++ if (var->xoffset + disp->var.xres > disp->var.xres_virtual || ++ var->yoffset + disp->var.yres > disp->var.yres_virtual) ++ return -EINVAL; ++ } ++ ++ if (con == sisfb->currcon) ++ sisfb->pan_display(var, sisfb); ++ ++ /* update xoffset, yoffset and vmode members of var structure for current ++ * console this is neceressary since this function is called by a seperate ++ * ioctl function than set_var (actually, set_var doesn't care about these ++ * members at all) */ ++ disp->var.xoffset = var->xoffset; ++ disp->var.yoffset = var->yoffset; ++ ++ if (var->vmode & FB_VMODE_YWRAP) ++ disp->var.vmode |= FB_VMODE_YWRAP; ++ else ++ disp->var.vmode &= ~FB_VMODE_YWRAP; ++ ++ return 0; ++} ++ +static int sisfb_ioctl(struct inode * inode, struct file * file, unsigned int cmd, + unsigned long arg, int con, struct fb_info * info) +{ @@ -3219,6 +4916,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + fb_set_var: sisfb_set_var, + fb_get_cmap: sisfb_get_cmap, + fb_set_cmap: sisfb_set_cmap, ++ fb_pan_display: sisfb_pan_display, + fb_ioctl: sisfb_ioctl, +}; + @@ -3249,13 +4947,9 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb +static int __devinit +sisfb_probe(struct pci_dev * pci_dev, const struct pci_device_id * pci_id) +{ -+ unsigned long tsc; + struct sisfb_info * sisfb; + struct fb_var_screeninfo var; + -+ rdtscl(tsc); -+ printk("sisfb init start TSC = %lu\n", tsc); -+ + if (pci_enable_device(pci_dev)) + return -ENODEV; + @@ -3290,9 +4984,19 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + } + + sisfb_unlock_regs(sisfb); -+ sisfb_config_memory(sisfb); -+ sisfb_init_legacy_vga(sisfb); -+ sisfb_init_300(sisfb); ++ ++ switch (pci_id->driver_data) { ++ case SISFB_LITE_300: ++ sisfb_init_300(sisfb); ++ break; ++ case SISFB_LITE_315: ++ sisfb_init_315(sisfb); ++ break; ++ case SISFB_LITE_530: ++ default: ++ printk(KERN_ERR "UnSupupported SiS VGA Core\n"); ++ goto failed; ++ } + + strcpy(sisfb->info.modename, "SiSFB Lite"); + @@ -3302,7 +5006,7 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + sisfb->info.disp = &sisfb->disp; + strcpy(sisfb->info.fontname, fontname); + sisfb->info.switch_con = &sisfb_switch_con; -+ sisfb->info.updatevar = NULL; ++ sisfb->info.updatevar = &sisfb_updatevar; + sisfb->info.blank = &sisfb_blank; + sisfb->info.flags = FBINFO_FLAG_DEFAULT; + @@ -3320,30 +5024,30 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb + sisfb->currcon = 0; + + if (register_framebuffer((struct fb_info *) sisfb) < 0) { -+ /* clean things up when failed to register frame buffer */ -+ pci_dev->driver_data = NULL; -+ release_mem_region(sisfb->video_base_phy, sisfb->video_size_phy); -+ release_mem_region(sisfb->mmio_base_phy, sisfb->mmio_size_phy); -+ release_region(sisfb->vga_io_base, sisfb->vga_io_size); -+ -+ iounmap(sisfb->video_base_virt); -+ iounmap(sisfb->mmio_base_virt); -+ -+#ifdef CONFIG_MTRR -+ mtrr_del(sisfb->mtrr, sisfb->video_base_phy, sisfb->video_size_virt); -+#endif /* CONFIG_MTRR */ -+ -+ kfree(sisfb); -+ return -EINVAL; ++ goto failed; + } + + /* make sisfb a driver_data of the PCI device */ + pci_set_drvdata(pci_dev, sisfb); + -+ rdtscl(tsc); -+ printk("sisfb init end TSC = %lu\n", tsc); -+ + return 0; ++ ++ failed: ++ /* clean things up when failed to register frame buffer */ ++ pci_dev->driver_data = NULL; ++ release_mem_region(sisfb->video_base_phy, sisfb->video_size_phy); ++ release_mem_region(sisfb->mmio_base_phy, sisfb->mmio_size_phy); ++ release_region(sisfb->vga_io_base, sisfb->vga_io_size); ++ ++ iounmap(sisfb->video_base_virt); ++ iounmap(sisfb->mmio_base_virt); ++ ++#ifdef CONFIG_MTRR ++ mtrr_del(sisfb->mtrr, sisfb->video_base_phy, sisfb->video_size_virt); ++#endif /* CONFIG_MTRR */ ++ ++ kfree(sisfb); ++ return -EINVAL; +} + +static void __devexit @@ -3396,10 +5100,10 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.c linux-2.4.3-linuxb +#endif /* MODULE */ + +module_exit(sisfb_cleanup); -diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.h linux-2.4.3-linuxbios/drivers/video/sis/sisfb_lite.h ---- linux-2.4.3-official/drivers/video/sis/sisfb_lite.h Thu Jan 1 08:00:00 1970 -+++ linux-2.4.3-linuxbios/drivers/video/sis/sisfb_lite.h Tue Apr 10 14:06:02 2001 -@@ -0,0 +1,146 @@ +diff -urN linux-2.4.6-official/drivers/video/sis/sisfb_lite.h linux-2.4.6-linuxbios/drivers/video/sis/sisfb_lite.h +--- linux-2.4.6-official/drivers/video/sis/sisfb_lite.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.6-linuxbios/drivers/video/sis/sisfb_lite.h Mon Jul 23 12:24:31 2001 +@@ -0,0 +1,211 @@ +#ifndef __SISFB_LITE__ +#define __SISFB_LITE__ + @@ -3418,8 +5122,6 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.h linux-2.4.3-linuxb +#include +#include +#include -+//#include -+//#include + +#include + @@ -3430,13 +5132,17 @@ diff -urN linux-2.4.3-official/drivers/video/sis/sisfb_lite.h linux-2.4.3-linuxb +#include