patch-2.4.15 linux/drivers/video/sis/sis_main.c
Next file: linux/drivers/video/sis/sis_main.h
Previous file: linux/drivers/video/sis/sis_301.h
Back to the patch index
Back to the overall index
- Lines: 4454
- Date:
Fri Nov 9 14:11:14 2001
- Orig file:
v2.4.14/linux/drivers/video/sis/sis_main.c
- Orig date:
Mon Nov 5 15:55:33 2001
diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/sis_main.c linux/drivers/video/sis/sis_main.c
@@ -1,5 +1,5 @@
/*
- * SiS 300/630/540 frame buffer device For Kernal 2.4.x
+ * SiS 300/630/540/315H/315 frame buffer device For Kernal 2.4.x
*
* This driver is partly based on the VBE 2.0 compliant graphic
* boards framebuffer driver, which is
@@ -8,7 +8,7 @@
*
*/
-#undef SISFBDEBUG
+//#undef SISFBDEBUG
#include <linux/config.h>
#include <linux/module.h>
@@ -27,10 +27,13 @@
#include <linux/pci.h>
#include <linux/vt_kern.h>
#include <linux/capability.h>
-#include <linux/sisfb.h>
#include <linux/fs.h>
+#include <linux/agp_backend.h>
+#include <linux/types.h>
+#include <linux/sisfb.h>
#include <asm/io.h>
+#include <asm/mtrr.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
@@ -38,568 +41,543 @@
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
-#include "sis.h"
-#ifdef NOBIOS
-#include "bios.h"
-#endif
-
-/* ------------------- Constant Definitions ------------------------- */
-
-/* capabilities */
-#define TURBO_QUEUE_CAP 0x80
-#define HW_CURSOR_CAP 0x40
+#include "osdef.h"
+#include "vgatypes.h"
+#include "sis_main.h"
-/* VGA register Offsets */
-#define SEQ_ADR (0x14)
-#define SEQ_DATA (0x15)
-#define DAC_ADR (0x18)
-#define DAC_DATA (0x19)
-#define CRTC_ADR (0x24)
-#define CRTC_DATA (0x25)
+/* -------------------- Macro definitions ---------------------------- */
-#define DAC2_ADR 0x16 - 0x30
-#define DAC2_DATA 0x17 - 0x30
-
-
-/* SiS indexed register indexes */
-#define IND_SIS_PASSWORD (0x05)
-#define IND_SIS_DRAM_SIZE (0x14)
-#define IND_SIS_MODULE_ENABLE (0x1E)
-#define IND_SIS_PCI_ADDRESS_SET (0x20)
-#define IND_SIS_TURBOQUEUE_ADR (0x26)
-#define IND_SIS_TURBOQUEUE_SET (0x27)
-
-/* Sis register value */
-#define SIS_PASSWORD (0x86)
-
-#define SIS_2D_ENABLE (0x40)
+#ifdef SISFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
-#define SIS_MEM_MAP_IO_ENABLE (0x01)
-#define SIS_PCI_ADDR_ENABLE (0x80)
+#define vgawb(reg,data) \
+ (outb(data, ivideo.vga_base+reg))
+#define vgaww(reg,data) \
+ (outw(data, ivideo.vga_base+reg))
+#define vgawl(reg,data) \
+ (outl(data, ivideo.vga_base+reg))
+#define vgarb(reg) \
+ (inb(ivideo.vga_base+reg))
-//#define MMIO_SIZE 0x10000 /* 64K MMIO capability */
-#define MAX_ROM_SCAN 0x10000
+/* --------------- Hardware Access Routines -------------------------- */
-#define RESERVED_MEM_SIZE_4M 0x400000 /* 4M */
-#define RESERVED_MEM_SIZE_8M 0x800000 /* 8M */
+void sisfb_set_reg1 (u16 port, u16 index, u16 data)
+{
+ outb ((u8) (index & 0xff), port);
+ port++;
+ outb ((u8) (data & 0xff), port);
+}
-/* Mode set stuff */
-#define DEFAULT_MODE 0 /* 640x480x8 */
-#define DEFAULT_LCDMODE 9 /* 800x600x8 */
-#define DEFAULT_TVMODE 9 /* 800x600x8 */
+void sisfb_set_reg3 (u16 port, u16 data)
+{
+ outb ((u8) (data & 0xff), port);
+}
-/* heap stuff */
-#define OH_ALLOC_SIZE 4000
-#define SENTINEL 0x7fffffff
+void sisfb_set_reg4 (u16 port, unsigned long data)
+{
+ outl ((u32) (data & 0xffffffff), port);
+}
-#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */
-#define HW_CURSOR_AREA_SIZE 0x1000 /* 4K */
+u8 sisfb_get_reg1 (u16 port, u16 index)
+{
+ u8 data;
-/* ------------------- Global Variables ----------------------------- */
+ outb ((u8) (index & 0xff), port);
+ port += 1;
+ data = inb (port);
+ return (data);
+}
-struct video_info ivideo;
-HW_DEVICE_EXTENSION HwExt={0,0,0,0,0,0};
+u8 sisfb_get_reg2 (u16 port)
+{
+ u8 data;
-struct GlyInfo {
- unsigned char ch;
- int fontwidth;
- int fontheight;
- u8 gmask[72];
- int ngmask;
-};
+ data = inb (port);
-/* Supported SiS Chips list */
-static struct board {
- u16 vendor, device;
- const char *name;
-} dev_list[] = {
- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"},
- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540"},
- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630"},
- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_730_VGA, "SIS 730"},
- {0, 0, NULL}
-};
+ return (data);
+}
-/* card parameters */
-unsigned long rom_base;
-unsigned long rom_vbase;
-
-/* mode */
-static int video_type = FB_TYPE_PACKED_PIXELS;
-static int video_linelength;
-static int video_cmap_len;
-static int sisfb_off = 0;
-static int crt1off = 0;
-
-static struct fb_var_screeninfo default_var = {
- 0, 0, 0, 0,
- 0, 0,
- 0,
- 0,
- {0, 8, 0},
- {0, 8, 0},
- {0, 8, 0},
- {0, 0, 0},
- 0,
- FB_ACTIVATE_NOW, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,
- FB_VMODE_NONINTERLACED,
- {0, 0, 0, 0, 0, 0}
-};
+u32 sisfb_get_reg3 (u16 port)
+{
+ u32 data;
-static struct display disp;
-static struct fb_info fb_info;
-static struct {
- u16 blue, green, red, pad;
-} palette[256];
-static union {
-#ifdef FBCON_HAS_CFB16
- u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB24
- u32 cfb24[16];
-#endif
-#ifdef FBCON_HAS_CFB32
- u32 cfb32[16];
-#endif
-} fbcon_cmap;
+ data = inl (port);
+ return (data);
+}
-static int inverse = 0;
-static int currcon = 0;
+/* --------------- Interface to BIOS code ---------------------------- */
-static struct display_switch sisfb_sw;
+BOOLEAN sisfb_query_VGA_config_space (PSIS_HW_DEVICE_INFO psishw_ext,
+ unsigned long offset, unsigned long set,
+ unsigned long *value)
+{
+ static struct pci_dev *pdev = NULL;
+ static unsigned char init = 0, valid_pdev = 0;
-static u8 caps = 0;
-static unsigned long MMIO_SIZE = 0;
-
-/* ModeSet stuff */
-unsigned char uDispType = 0;
-int mode_idx = -1;
-u8 mode_no = 0;
-u8 rate_idx = 0;
-
-static const struct _sisbios_mode {
- char name[15];
- u8 mode_no;
- u16 xres;
- u16 yres;
- u16 bpp;
- u16 rate_idx;
- u16 cols;
- u16 rows;
-} sisbios_mode[] = {
- {"640x480x8", 0x2E, 640, 480, 8, 1, 80, 30},
- {"640x480x16", 0x44, 640, 480, 16, 1, 80, 30},
- {"640x480x32", 0x62, 640, 480, 32, 1, 80, 30},
- {"720x480x8", 0x31, 720, 480, 8, 1, 90, 30}, /* NTSC TV */
- {"720x480x16", 0x33, 720, 480, 16, 1, 90, 30},
- {"720x480x32", 0x35, 720, 480, 32, 1, 90, 30},
- {"720x576x8", 0x32, 720, 576, 8, 1, 90, 36}, /* PAL TV */
- {"720x576x16", 0x34, 720, 576, 16, 1, 90, 36},
- {"720x576x32", 0x36, 720, 576, 32, 1, 90, 36},
- {"800x600x8", 0x30, 800, 600, 8, 2, 100, 37},
- {"800x600x16", 0x47, 800, 600, 16, 2, 100, 37},
- {"800x600x32", 0x63, 800, 600, 32, 2, 100, 37},
- {"1024x768x8", 0x38, 1024, 768, 8, 2, 128, 48},
- {"1024x768x16", 0x4A, 1024, 768, 16, 2, 128, 48},
- {"1024x768x32", 0x64, 1024, 768, 32, 2, 128, 48},
- {"1280x1024x8", 0x3A, 1280, 1024, 8, 2, 160, 64},
- {"1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64},
- {"1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64},
- {"1600x1200x8", 0x3C, 1600, 1200, 8, 1, 200, 75},
- {"1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75},
- {"1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75},
- {"1920x1440x8", 0x68, 1920, 1440, 8, 1, 240, 75},
- {"1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75},
- {"1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75},
- {"\0", 0x00, 0, 0, 0, 0, 0, 0}
-};
+ if (!set)
+ DPRINTK ("Get VGA offset 0x%lx\n", offset);
+ else
+ DPRINTK ("Set offset 0x%lx to 0x%lx\n", offset, *value);
-static struct _vrate {
- u16 idx;
- u16 xres;
- u16 yres;
- u16 refresh;
-} vrate[] = {
- {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85},
- {5, 640, 480, 100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200},
- {1, 720, 480, 60},
- {1, 720, 576, 50},
- {1, 800, 600, 56}, {2, 800, 600, 60}, {3, 800, 600, 72}, {4, 800, 600, 75},
- {5, 800, 600, 85}, {6, 800, 600, 100}, {7, 800, 600, 120}, {8, 800, 600, 160},
- {1, 1024, 768, 43}, {2, 1024, 768, 60}, {3, 1024, 768, 70}, {4, 1024, 768, 75},
- {5, 1024, 768, 85}, {6, 1024, 768, 100}, {7, 1024, 768, 120},
- {1, 1280, 1024, 43}, {2, 1280, 1024, 60}, {3, 1280, 1024, 75}, {4, 1280, 1024, 85},
- {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75},
- {5, 1600, 1200, 85},
- {1, 1920, 1440, 60},
- {0, 0, 0, 0}
-};
+ if (!init) {
+ init = TRUE;
+ pci_for_each_dev (pdev) {
+ DPRINTK ("Current: 0x%x, target: 0x%x\n", pdev->device,
+ ivideo.chip_id);
+ if ((pdev->vendor == PCI_VENDOR_ID_SI)
+ && (pdev->device == ivideo.chip_id)) {
+ valid_pdev = TRUE;
+ break;
+ }
+ }
+ }
+ if (!valid_pdev) {
+ printk (KERN_DEBUG "Can't find SiS %d VGA device.\n",
+ ivideo.chip_id);
+ return FALSE;
+ }
-/* HEAP stuff */
+ if (set == 0)
+ pci_read_config_dword (pdev, offset, (u32 *) value);
+ else
+ pci_write_config_dword (pdev, offset, (u32) (*value));
-struct OH {
- struct OH *pohNext;
- struct OH *pohPrev;
- unsigned long ulOffset;
- unsigned long ulSize;
-};
+ return TRUE;
+}
-struct OHALLOC {
- struct OHALLOC *pohaNext;
- struct OH aoh[1];
-};
+BOOLEAN sisfb_query_north_bridge_space (PSIS_HW_DEVICE_INFO psishw_ext,
+ unsigned long offset, unsigned long set,
+ unsigned long *value)
+{
+ static struct pci_dev *pdev = NULL;
+ static unsigned char init = 0, valid_pdev = 0;
+ u16 nbridge_id = 0;
-struct HEAP {
- struct OH ohFree;
- struct OH ohUsed;
- struct OH *pohFreeList;
- struct OHALLOC *pohaChain;
+ if (!init) {
+ init = TRUE;
+ switch (ivideo.chip) {
+ case SIS_540:
+ nbridge_id = PCI_DEVICE_ID_SI_540;
+ break;
+ case SIS_630:
+ nbridge_id = PCI_DEVICE_ID_SI_630;
+ break;
+ case SIS_730:
+ nbridge_id = PCI_DEVICE_ID_SI_730;
+ break;
+ case SIS_550:
+ nbridge_id = PCI_DEVICE_ID_SI_550;
+ break;
+ default:
+ nbridge_id = 0;
+ break;
+ }
- unsigned long ulMaxFreeSize;
-};
+ pci_for_each_dev (pdev) {
+ DPRINTK ("Current: 0x%x, target: 0x%x\n", pdev->device,
+ ivideo.chip_id);
+ if ((pdev->vendor == PCI_VENDOR_ID_SI)
+ && (pdev->device == nbridge_id)) {
+ valid_pdev = TRUE;
+ break;
+ }
+ }
+ }
-struct HEAP heap;
-unsigned long heap_start;
-unsigned long heap_end;
-unsigned long heap_size;
+ if (!valid_pdev) {
+ printk (KERN_DEBUG "Can't find SiS %d North Bridge device.\n",
+ nbridge_id);
+ return FALSE;
+ }
-unsigned int tqueue_pos;
-unsigned long hwcursor_vbase;
+ if (set == 0)
+ pci_read_config_dword (pdev, offset, (u32 *) value);
+ else
+ pci_write_config_dword (pdev, offset, (u32) (*value));
+ return TRUE;
+}
-/* -------------------- Macro definitions --------------------------- */
+/* -------------------- Export functions ----------------------------- */
-#ifdef SISFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
+static void sis_get_glyph (SIS_GLYINFO * gly)
+{
+ struct display *p = &fb_display[currcon];
+ u16 c;
+ u8 *cdat;
+ int widthb;
+ u8 *gbuf = gly->gmask;
+ int size;
-#define vgawb(reg,data) \
- (outb(data, ivideo.vga_base+reg))
-#define vgaww(reg,data) \
- (outw(data, ivideo.vga_base+reg))
-#define vgawl(reg,data) \
- (outl(data, ivideo.vga_base+reg))
-#define vgarb(reg) \
- (inb(ivideo.vga_base+reg))
+ gly->fontheight = fontheight (p);
+ gly->fontwidth = fontwidth (p);
+ widthb = (fontwidth (p) + 7) / 8;
-/* ---------------------- Routine Prototype ------------------------- */
+ c = gly->ch & p->charmask;
+ if (fontwidth (p) <= 8)
+ cdat = p->fontdata + c * fontheight (p);
+ else
+ cdat = p->fontdata + (c * fontheight (p) << 1);
-/* Interface used by the world */
-int sisfb_setup(char *options);
-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);
+ size = fontheight (p) * widthb;
+ memcpy (gbuf, cdat, size);
+ gly->ngmask = size;
+}
-/* Interface to the low level console driver */
-int sisfb_init(void);
-static int sisfb_update_var(int con, struct fb_info *info);
-static int sisfb_switch(int con, struct fb_info *info);
-static void sisfb_blank(int blank, struct fb_info *info);
+void sis_dispinfo (struct ap_data *rec)
+{
+ rec->minfo.bpp = ivideo.video_bpp;
+ rec->minfo.xres = ivideo.video_width;
+ rec->minfo.yres = ivideo.video_height;
+ rec->minfo.v_xres = ivideo.video_vwidth;
+ rec->minfo.v_yres = ivideo.video_vheight;
+ rec->minfo.org_x = ivideo.org_x;
+ rec->minfo.org_y = ivideo.org_y;
+ rec->minfo.vrate = ivideo.refresh_rate;
+ rec->iobase = ivideo.vga_base - 0x30;
+ rec->mem_size = ivideo.video_size;
+ rec->disp_state = ivideo.disp_state;
+ rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
+ rec->hasVB = ivideo.hasVB;
+ rec->TV_type = ivideo.TV_type;
+ rec->TV_plug = ivideo.TV_plug;
+ rec->chip = ivideo.chip;
+}
-/* Internal routines */
-static void crtc_to_var(struct fb_var_screeninfo *var);
-static void sisfb_set_disp(int con, struct fb_var_screeninfo *var);
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
- unsigned *blue, unsigned *transp,
- struct fb_info *fb_info);
-static int sis_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *fb_info);
-static void do_install_cmap(int con, struct fb_info *info);
-static int do_set_var(struct fb_var_screeninfo *var, int isactive,
- struct fb_info *info);
+/* ------------------ Internal Routines ------------------------------ */
-/* set-mode routines */
-void SetReg1(u16 port, u16 index, u16 data);
-void SetReg3(u16 port, u16 data);
-void SetReg4(u16 port, unsigned long data);
-u8 GetReg1(u16 port, u16 index);
-u8 GetReg2(u16 port);
-u32 GetReg3(u16 port);
-extern BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
- USHORT ModeNo);
-extern BOOLEAN SiSInit300(PHW_DEVICE_EXTENSION HwDeviceExtension);
-static void pre_setmode(void);
-static void post_setmode(void);
-static void search_mode(const char *name);
-static u8 search_refresh_rate(unsigned int rate);
+static void sisfb_search_mode (const char *name)
+{
+ int i = 0;
-/* heap routines */
-static int sisfb_heap_init(void);
-static struct OH *poh_new_node(void);
-static struct OH *poh_allocate(unsigned long size);
-static struct OH *poh_free(unsigned long base);
-static void delete_node(struct OH *poh);
-static void insert_node(struct OH *pohList, struct OH *poh);
-static void free_node(struct OH *poh);
+ if (name == NULL)
+ return;
-/* ---------------------- Internal Routines ------------------------- */
+ while (sisbios_mode[i].mode_no != 0) {
+ if (!strcmp (name, sisbios_mode[i].name)) {
+ sisfb_mode_idx = i;
+ break;
+ }
+ i++;
+ }
-inline static u32 RD32(unsigned char *base, s32 off)
-{
- return readl(base + off);
+ if (sisfb_mode_idx < 0)
+ DPRINTK ("Invalid user mode : %s\n", name);
}
-inline static void WR32(unsigned char *base, s32 off, u32 v)
+static void sisfb_validate_mode (void)
{
- writel(v, base + off);
-}
+ switch (ivideo.disp_state & DISPTYPE_DISP2) {
+ case DISPTYPE_LCD:
+// Eden Chen
+ switch (sishw_ext.ulCRT2LCDType) {
+ case LCD_1024x768:
+ if (sisbios_mode[sisfb_mode_idx].xres > 1024)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_1280x1024:
+ case LCD_1280x960:
+ if (sisbios_mode[sisfb_mode_idx].xres > 1280)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_2048x1536:
+ if (sisbios_mode[sisfb_mode_idx].xres > 2048)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_1920x1440:
+ if (sisbios_mode[sisfb_mode_idx].xres > 1920)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_1600x1200:
+ if (sisbios_mode[sisfb_mode_idx].xres > 1600)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_800x600:
+ if (sisbios_mode[sisfb_mode_idx].xres > 800)
+ sisfb_mode_idx = -1;
+ break;
+ case LCD_640x480:
+ if (sisbios_mode[sisfb_mode_idx].xres > 640)
+ sisfb_mode_idx = -1;
+ break;
+ default:
+ sisfb_mode_idx = -1;
+ }
+// ~Eden Chen
-inline static void WR16(unsigned char *base, s32 off, u16 v)
-{
- writew(v, base + off);
+ if (sisbios_mode[sisfb_mode_idx].xres == 720)
+ sisfb_mode_idx = -1;
+ break;
+ case DISPTYPE_TV:
+ switch (sisbios_mode[sisfb_mode_idx].xres) {
+ case 800:
+ case 640:
+ break;
+ case 720:
+ if (ivideo.TV_type == TVMODE_NTSC) {
+ if (sisbios_mode[sisfb_mode_idx].yres != 480)
+ sisfb_mode_idx = -1;
+ } else if (ivideo.TV_type == TVMODE_PAL) {
+ if (sisbios_mode[sisfb_mode_idx].yres != 576)
+ sisfb_mode_idx = -1;
+ }
+ break;
+ /*karl */
+ case 1024:
+ if (ivideo.TV_type == TVMODE_NTSC) {
+ if (sisbios_mode[sisfb_mode_idx].bpp == 32)
+ sisfb_mode_idx -= 1;
+ }
+ break;
+ default:
+ sisfb_mode_idx = -1;
+ }
+ break;
+ }
}
-inline static void WR8(unsigned char *base, s32 off, u8 v)
+static u8 sisfb_search_refresh_rate (unsigned int rate)
{
- writeb(v, base + off);
-}
+ u16 xres, yres;
+ int i = 0;
-inline static u32 regrl(s32 off)
-{
- return RD32(ivideo.mmio_vbase, off);
-}
+ xres = sisbios_mode[sisfb_mode_idx].xres;
+ yres = sisbios_mode[sisfb_mode_idx].yres;
-inline static void regwl(s32 off, u32 v)
-{
- WR32(ivideo.mmio_vbase, off, v);
-}
+ sisfb_rate_idx = 0;
+ while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
+ if ((sisfb_vrate[i].xres == xres)
+ && (sisfb_vrate[i].yres == yres)) {
+ if (sisfb_vrate[i].refresh == rate) {
+ sisfb_rate_idx = sisfb_vrate[i].idx;
+ break;
+ } else if (sisfb_vrate[i].refresh > rate) {
+ if ((sisfb_vrate[i].refresh - rate) <= 2) {
+ DPRINTK
+ ("Adjust rate from %d up to %d\n",
+ rate, sisfb_vrate[i].refresh);
+ sisfb_rate_idx = sisfb_vrate[i].idx;
+ ivideo.refresh_rate =
+ sisfb_vrate[i].refresh;
+ } else if (((rate - sisfb_vrate[i - 1].refresh) <= 2)
+ && (sisfb_vrate[i].idx != 1)) {
+ DPRINTK("Adjust rate from %d down to %d\n",
+ rate, sisfb_vrate[i - 1].refresh);
+ sisfb_rate_idx = sisfb_vrate[i - 1].idx;
+ ivideo.refresh_rate = sisfb_vrate[i - 1].refresh;
+ }
+ break;
+ }
+ }
+ i++;
+ }
+
+ if (sisfb_rate_idx > 0) {
+ return sisfb_rate_idx;
+ } else {
+ DPRINTK ("Unsupported rate %d for %dx%d mode\n", rate, xres,
+ yres);
+ return 0;
+ }
-inline static void regww(s32 off, u16 v)
-{
- WR16(ivideo.mmio_vbase, off, v);
}
-inline static void regwb(s32 off, u8 v)
+static int sis_getcolreg (unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
+ unsigned *transp, struct fb_info *fb_info)
{
- WR8(ivideo.mmio_vbase, off, v);
+ if (regno >= video_cmap_len)
+ return 1;
+
+ *red = palette[regno].red;
+ *green = palette[regno].green;
+ *blue = palette[regno].blue;
+ *transp = 0;
+ return 0;
}
-/*
- * Get CRTC registers to set var
- */
-static void crtc_to_var(struct fb_var_screeninfo *var)
+static int sis_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *fb_info)
{
- u16 VRE, VBE, VRS, VBS, VDE, VT;
- u16 HRE, HBE, HRS, HBS, HDE, HT;
- u8 uSRdata, uCRdata, uCRdata2, uCRdata3, uMRdata;
- int A, B, C, D, E, F, temp;
- double hrate, drate;
-
- vgawb(SEQ_ADR, 0x6);
- uSRdata = vgarb(SEQ_DATA);
- if (uSRdata & 0x20)
- var->vmode = FB_VMODE_INTERLACED;
- else
- var->vmode = FB_VMODE_NONINTERLACED;
+ if (regno >= video_cmap_len)
+ return 1;
- switch ((uSRdata & 0x1c) >> 2) {
- case 0:
- var->bits_per_pixel = 8;
- break;
- case 2:
- var->bits_per_pixel = 16;
- break;
- case 4:
- var->bits_per_pixel = 32;
- break;
- }
+ palette[regno].red = red;
+ palette[regno].green = green;
+ palette[regno].blue = blue;
- switch (var->bits_per_pixel) {
+ switch (ivideo.video_bpp) {
+#ifdef FBCON_HAS_CFB8
case 8:
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
- video_cmap_len = 256;
- break;
- case 16: /* RGB 565 */
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- video_cmap_len = 16;
+ vgawb (DAC_ADR, regno);
+ vgawb (DAC_DATA, red >> 10);
+ vgawb (DAC_DATA, green >> 10);
+ vgawb (DAC_DATA, blue >> 10);
+ if (ivideo.disp_state & DISPTYPE_DISP2) {
+ vgawb (DAC2_ADR, regno);
+ vgawb (DAC2_DATA, red >> 8);
+ vgawb (DAC2_DATA, green >> 8);
+ vgawb (DAC2_DATA, blue >> 8);
+ }
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;
- video_cmap_len = 16;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 15:
+ case 16:
+ fbcon_cmap.cfb16[regno] =
+ ((red & 0xf800)) |
+ ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ fbcon_cmap.cfb24[regno] = (red << 16) | (green << 8) | (blue);
break;
+#endif
+#ifdef FBCON_HAS_CFB32
case 32:
- 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 = 24;
- var->transp.length = 8;
- video_cmap_len = 16;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
break;
+#endif
}
+ return 0;
+}
- vgawb(SEQ_ADR, 0xa);
- uSRdata = vgarb(SEQ_DATA);
-
- vgawb(CRTC_ADR, 0x6);
- uCRdata = vgarb(CRTC_DATA);
- vgawb(CRTC_ADR, 0x7);
- uCRdata2 = vgarb(CRTC_DATA);
- VT =
- (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x01) << 8) |
- ((u16) (uCRdata2 & 0x20) << 4) | ((u16) (uSRdata & 0x01) <<
- 10);
- A = VT + 2;
-
- vgawb(CRTC_ADR, 0x12);
- uCRdata = vgarb(CRTC_DATA);
- VDE =
- (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x02) << 7) |
- ((u16) (uCRdata2 & 0x40) << 3) | ((u16) (uSRdata & 0x02) << 9);
- E = VDE + 1;
-
- vgawb(CRTC_ADR, 0x10);
- uCRdata = vgarb(CRTC_DATA);
- VRS =
- (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x04) << 6) |
- ((u16) (uCRdata2 & 0x80) << 2) | ((u16) (uSRdata & 0x08) << 7);
- F = VRS + 1 - E;
-
- vgawb(CRTC_ADR, 0x15);
- uCRdata = vgarb(CRTC_DATA);
- vgawb(CRTC_ADR, 0x9);
- uCRdata3 = vgarb(CRTC_DATA);
- VBS =
- (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x08) << 5) |
- ((u16) (uCRdata3 & 0x20) << 4) | ((u16) (uSRdata & 0x04) << 8);
-
- vgawb(CRTC_ADR, 0x16);
- uCRdata = vgarb(CRTC_DATA);
- VBE = (uCRdata & 0xff) | ((u16) (uSRdata & 0x10) << 4);
- temp = VBE - ((E - 1) & 511);
- B = (temp > 0) ? temp : (temp + 512);
-
- vgawb(CRTC_ADR, 0x11);
- uCRdata = vgarb(CRTC_DATA);
- VRE = (uCRdata & 0x0f) | ((uSRdata & 0x20) >> 1);
- temp = VRE - ((E + F - 1) & 31);
- C = (temp > 0) ? temp : (temp + 32);
-
- D = B - F - C;
-
- var->yres = var->yres_virtual = E;
- var->upper_margin = D;
- var->lower_margin = F;
- var->vsync_len = C;
-
- vgawb(SEQ_ADR, 0xb);
- uSRdata = vgarb(SEQ_DATA);
-
- vgawb(CRTC_ADR, 0x0);
- uCRdata = vgarb(CRTC_DATA);
- HT = (uCRdata & 0xff) | ((u16) (uSRdata & 0x03) << 8);
- A = HT + 5;
-
- vgawb(CRTC_ADR, 0x1);
- uCRdata = vgarb(CRTC_DATA);
- HDE = (uCRdata & 0xff) | ((u16) (uSRdata & 0x0C) << 6);
- E = HDE + 1;
+static int sisfb_do_set_var (struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info)
+{
+ unsigned int htotal =
+ var->left_margin + var->xres + var->right_margin + var->hsync_len;
+ unsigned int vtotal =
+ var->upper_margin + var->yres + var->lower_margin + var->vsync_len;
+ double drate = 0, hrate = 0;
+ int found_mode = 0;
+ int old_mode;
- vgawb(CRTC_ADR, 0x4);
- uCRdata = vgarb(CRTC_DATA);
- HRS = (uCRdata & 0xff) | ((u16) (uSRdata & 0xC0) << 2);
- F = HRS - E - 3;
+ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
+ vtotal <<= 1;
+ else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+ vtotal <<= 2;
+ else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+ var->yres <<= 1;
- vgawb(CRTC_ADR, 0x2);
- uCRdata = vgarb(CRTC_DATA);
- HBS = (uCRdata & 0xff) | ((u16) (uSRdata & 0x30) << 4);
-
- vgawb(SEQ_ADR, 0xc);
- uSRdata = vgarb(SEQ_DATA);
- vgawb(CRTC_ADR, 0x3);
- uCRdata = vgarb(CRTC_DATA);
- vgawb(CRTC_ADR, 0x5);
- uCRdata2 = vgarb(CRTC_DATA);
- HBE =
- (uCRdata & 0x1f) | ((u16) (uCRdata2 & 0x80) >> 2) |
- ((u16) (uSRdata & 0x03) << 6);
- HRE = (uCRdata2 & 0x1f) | ((uSRdata & 0x04) << 3);
+ if (!htotal || !vtotal) {
+ DPRINTK ("Invalid 'var' Information!\n");
+ return -EINVAL;
+ }
- temp = HBE - ((E - 1) & 255);
- B = (temp > 0) ? temp : (temp + 256);
+ drate = 1E12 / var->pixclock;
+ hrate = drate / htotal;
+ ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
- temp = HRE - ((E + F + 3) & 63);
- C = (temp > 0) ? temp : (temp + 64);
+ DPRINTK ("Chagne mode to %dx%dx%d-%dMHz\n",
+ var->xres, var->yres, var->bits_per_pixel,
+ ivideo.refresh_rate);
+
+ old_mode = sisfb_mode_idx;
+ sisfb_mode_idx = 0;
+
+ while ((sisbios_mode[sisfb_mode_idx].mode_no != 0)
+ && (sisbios_mode[sisfb_mode_idx].xres <= var->xres)) {
+ if ((sisbios_mode[sisfb_mode_idx].xres == var->xres)
+ && (sisbios_mode[sisfb_mode_idx].yres == var->yres)
+ && (sisbios_mode[sisfb_mode_idx].bpp ==
+ var->bits_per_pixel)) {
+ sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+ found_mode = 1;
+ break;
+ }
+ sisfb_mode_idx++;
+ }
- D = B - F - C;
+ if (found_mode)
+ sisfb_validate_mode ();
+ else
+ sisfb_mode_idx = -1;
- var->xres = var->xres_virtual = E * 8;
- var->left_margin = D * 8;
- var->right_margin = F * 8;
- var->hsync_len = C * 8;
+ if (sisfb_mode_idx < 0) {
+ DPRINTK ("sisfb does not support mode %dx%d-%d\n", var->xres,
+ var->yres, var->bits_per_pixel);
+ sisfb_mode_idx = old_mode;
+ return -EINVAL;
+ }
- var->activate = FB_ACTIVATE_NOW;
+ if (sisfb_search_refresh_rate (ivideo.refresh_rate) == 0) {
+ sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
+ ivideo.refresh_rate = 60;
+ }
- var->sync = 0;
+ if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
+ sisfb_pre_setmode ();
- uMRdata = vgarb(0x1C);
- if (uMRdata & 0x80)
- var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
- else
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
+// Eden Chen
+/*
+#ifdef CONFIG_FB_SIS_300
+ if (SiSSetMode(&sishw_ext, sisfb_mode_no)) {
+ DPRINTK("set mode[0x%x]: failed\n", sisfb_mode_no);
+ return -1;
+ }
+#endif
- if (uMRdata & 0x40)
- var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
- else
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
+#ifdef CONFIG_FB_SIS_315
+ if (SiSSetMode310(&sishw_ext, sisfb_mode_no)) {
+ DPRINTK("set mode[0x%x]: failed\n", sisfb_mode_no);
+ return -1;
+ }
- VT += 2;
- VT <<= 1;
- HT = (HT + 5) * 8;
+#endif
+*/
+ if (SiSSetMode (&sishw_ext, sisfb_mode_no) == 0) {
+ DPRINTK ("set mode[0x%x]: failed\n", sisfb_mode_no);
+ return -1;
+ }
+
+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
+// ~Eden Chen
+ sisfb_post_setmode ();
+
+ DPRINTK ("Set New Mode : %dx%dx%d-%d \n",
+ sisbios_mode[sisfb_mode_idx].xres,
+ sisbios_mode[sisfb_mode_idx].yres,
+ sisbios_mode[sisfb_mode_idx].bpp, ivideo.refresh_rate);
+
+ ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
+ ivideo.video_vwidth = ivideo.video_width =
+ sisbios_mode[sisfb_mode_idx].xres;
+ ivideo.video_vheight = ivideo.video_height =
+ sisbios_mode[sisfb_mode_idx].yres;
+ ivideo.org_x = ivideo.org_y = 0;
+ video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
- hrate = (double) ivideo.refresh_rate * (double) VT / 2;
- drate = hrate * HT;
- var->pixclock = (u32) (1E12 / drate);
+ }
+ return 0;
}
-static void sisfb_set_disp(int con, struct fb_var_screeninfo *var)
+static void sisfb_set_disp (int con, struct fb_var_screeninfo *var)
{
struct fb_fix_screeninfo fix;
struct display *display;
struct display_switch *sw;
- long flags;
+ u32 flags;
if (con >= 0)
display = &fb_display[con];
else
- display = &disp; /* used during initialization */
+ display = &disp;
- sisfb_get_fix(&fix, con, 0);
+ sisfb_get_fix (&fix, con, 0);
display->screen_base = ivideo.video_vbase;
display->visual = fix.visual;
@@ -609,12 +587,11 @@
display->ywrapstep = fix.ywrapstep;
display->line_length = fix.line_length;
display->next_line = fix.line_length;
- /*display->can_soft_blank = 1; */
display->can_soft_blank = 0;
- display->inverse = inverse;
+ display->inverse = sisfb_inverse;
display->var = *var;
- save_flags(flags);
+ save_flags (flags);
switch (ivideo.video_bpp) {
#ifdef FBCON_HAS_CFB8
case 8:
@@ -644,852 +621,1380 @@
sw = &fbcon_dummy;
return;
}
- memcpy(&sisfb_sw, sw, sizeof(*sw));
+ memcpy (&sisfb_sw, sw, sizeof (*sw));
display->dispsw = &sisfb_sw;
- restore_flags(flags);
+ restore_flags (flags);
display->scrollmode = SCROLL_YREDRAW;
sisfb_sw.bmove = fbcon_redraw_bmove;
-
}
-/*
- * Read a single color register and split it into colors/transparent.
- * Return != 0 for invalid regno.
- */
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
- unsigned *transp, struct fb_info *fb_info)
+static void sisfb_do_install_cmap (int con, struct fb_info *info)
{
- if (regno >= video_cmap_len)
- return 1;
+ if (con != currcon)
+ return;
- *red = palette[regno].red;
- *green = palette[regno].green;
- *blue = palette[regno].blue;
- *transp = 0;
- return 0;
+ if (fb_display[con].cmap.len)
+ fb_set_cmap (&fb_display[con].cmap, 1, sis_setcolreg, info);
+ else
+ fb_set_cmap (fb_default_cmap (video_cmap_len), 1,
+ sis_setcolreg, info);
}
-/*
- * Set a single color register. The values supplied are already
- * rounded down to the hardware's capabilities (according to the
- * entries in the var structure). Return != 0 for invalid regno.
- */
-static int sis_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *fb_info)
-{
-
- if (regno >= video_cmap_len)
- return 1;
-
- palette[regno].red = red;
- palette[regno].green = green;
- palette[regno].blue = blue;
+/* --------------- Chip-dependent Routines --------------------------- */
- switch (ivideo.video_bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- vgawb(DAC_ADR, regno);
- vgawb(DAC_DATA, red >> 10);
- vgawb(DAC_DATA, green >> 10);
- vgawb(DAC_DATA, blue >> 10);
- if(uDispType & MASK_DISPTYPE_DISP2)
- {
- /* VB connected */
- vgawb(DAC2_ADR, regno);
- vgawb(DAC2_DATA, red >> 8);
- vgawb(DAC2_DATA, green >> 8);
- vgawb(DAC2_DATA, blue >> 8);
- }
+#ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */
+static int sisfb_get_dram_size_300 (void)
+{
+ struct pci_dev *pdev = NULL;
+ int pdev_valid = 0;
+ u8 pci_data, reg;
+ u16 nbridge_id;
+ switch (ivideo.chip) {
+ case SIS_540:
+ nbridge_id = PCI_DEVICE_ID_SI_540;
break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 15:
- case 16:
- fbcon_cmap.cfb16[regno] =
- ((red & 0xf800)) |
- ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+ case SIS_630:
+ nbridge_id = PCI_DEVICE_ID_SI_630;
break;
-#endif
-#ifdef FBCON_HAS_CFB24
- case 24:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- fbcon_cmap.cfb24[regno] =
- (red << 16) | (green << 8) | (blue);
+ case SIS_730:
+ nbridge_id = PCI_DEVICE_ID_SI_730;
break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- fbcon_cmap.cfb32[regno] =
- (red << 16) | (green << 8) | (blue);
+ default:
+ nbridge_id = 0;
break;
-#endif
}
- return 0;
-}
-static void do_install_cmap(int con, struct fb_info *info)
-{
- if (con != currcon)
- return;
+ if (nbridge_id == 0) {
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+ ivideo.video_size =
+ ((unsigned
+ int) ((vgarb (SEQ_DATA) & SIS_DRAM_SIZE_MASK) + 1) << 20);
+ } else {
+ pci_for_each_dev (pdev) {
+ if ((pdev->vendor == PCI_VENDOR_ID_SI)
+ && (pdev->device == nbridge_id)) {
+ //&& (pdev->device == PCI_DEVICE_ID_SI_630)) {
+ pci_read_config_byte (pdev, IND_BRI_DRAM_STATUS,
+ &pci_data);
+ pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
+ ivideo.video_size =
+ (unsigned int) (1 << (pci_data + 21));
+ pdev_valid = 1;
- if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, 1, sis_setcolreg, info);
- else
- fb_set_cmap(fb_default_cmap(video_cmap_len), 1,
- sis_setcolreg, info);
+ reg = SIS_DATA_BUS_64 << 6;
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+ switch (pci_data) {
+ case BRI_DRAM_SIZE_2MB:
+ reg |= SIS_DRAM_SIZE_2MB;
+ break;
+ case BRI_DRAM_SIZE_4MB:
+ reg |= SIS_DRAM_SIZE_4MB;
+ break;
+ case BRI_DRAM_SIZE_8MB:
+ reg |= SIS_DRAM_SIZE_8MB;
+ break;
+ case BRI_DRAM_SIZE_16MB:
+ reg |= SIS_DRAM_SIZE_16MB;
+ break;
+ case BRI_DRAM_SIZE_32MB:
+ reg |= SIS_DRAM_SIZE_32MB;
+ break;
+ case BRI_DRAM_SIZE_64MB:
+ reg |= SIS_DRAM_SIZE_64MB;
+ break;
+ }
+ vgawb (SEQ_DATA, reg);
+ break;
+ }
+ }
+
+ if (!pdev_valid)
+ return -1;
+ }
+
+ return 0;
}
-static int do_set_var(struct fb_var_screeninfo *var, int isactive,
- struct fb_info *info)
+static void sisfb_detect_VB_connect_300(void)
{
- unsigned int htotal =
- var->left_margin + var->xres + var->right_margin +
- var->hsync_len;
- unsigned int vtotal =
- var->upper_margin + var->yres + var->lower_margin +
- var->vsync_len;
- double drate = 0, hrate = 0;
- int found_mode = 0;
- int old_mode;
+ u8 sr16, sr17, cr32, temp;
- if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
- vtotal <<= 1;
- else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
- vtotal <<= 2;
- else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
- var->yres <<= 1;
+ vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_17);
+ sr17 = vgarb (SEQ_DATA);
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR32);
+ cr32 = vgarb (CRTC_DATA);
+ ivideo.TV_plug = ivideo.TV_type = 0;
+ if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
+ if ((sr17 & 0x01) && !sisfb_crt1off)
+ sisfb_crt1off = 0;
+ else {
+ if (sr17 & 0x0E)
+ sisfb_crt1off = 1;
+ else
+ sisfb_crt1off = 0;
+ }
- if (!htotal || !vtotal) {
- DPRINTK("Invalid 'var' Information!\n");
- return 1;
- }
+ if (sr17 & 0x08)
+ ivideo.disp_state = DISPTYPE_CRT2;
+ else if (sr17 & 0x02)
+ ivideo.disp_state = DISPTYPE_LCD;
+ else if (sr17 & 0x04) {
+ ivideo.disp_state = DISPTYPE_TV;
+ if (sr17 & 0x20)
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ else if (sr17 & 0x10)
+ ivideo.TV_plug = TVPLUG_COMPOSITE;
- drate = 1E12 / var->pixclock;
- hrate = drate / htotal;
- ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+ vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_16);
+ sr16 = vgarb (SEQ_DATA);
+ if (sr16 & 0x20)
+ ivideo.TV_type = TVMODE_PAL;
+ else
+ ivideo.TV_type = TVMODE_NTSC;
+ } else
+ ivideo.disp_state = 0;
+ } else {
+ if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
+ sisfb_crt1off = 0;
+ else {
+ if (cr32 & 0x5F)
+ sisfb_crt1off = 1;
+ else
+ sisfb_crt1off = 0;
+ }
- old_mode = mode_idx;
- mode_idx = 0;
+ if (cr32 & SIS_VB_CRT2)
+ ivideo.disp_state = DISPTYPE_CRT2;
+ else if (cr32 & SIS_VB_LCD)
+ ivideo.disp_state = DISPTYPE_LCD;
+ else if (cr32 & SIS_VB_TV) {
+ ivideo.disp_state = DISPTYPE_TV;
+ if (cr32 & SIS_VB_HIVISION) {
+ ivideo.TV_type = TVMODE_HIVISION;
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ } else if (cr32 & SIS_VB_SVIDEO)
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ else if (cr32 & SIS_VB_COMPOSITE)
+ ivideo.TV_plug = TVPLUG_COMPOSITE;
+ else if (cr32 & SIS_VB_SCART)
+ ivideo.TV_plug = TVPLUG_SCART;
- while ((sisbios_mode[mode_idx].mode_no != 0)
- && (sisbios_mode[mode_idx].xres <= var->xres)) {
- if ((sisbios_mode[mode_idx].xres == var->xres)
- && (sisbios_mode[mode_idx].yres == var->yres)
- && (sisbios_mode[mode_idx].bpp == var->bits_per_pixel)) {
- mode_no = sisbios_mode[mode_idx].mode_no;
- found_mode = 1;
- break;
- }
- mode_idx++;
+ if (ivideo.TV_type == 0) {
+ // Eden Chen
+ //temp = *((u8 *)(sishw_ext.VirtualRomBase+0x52));
+ //if (temp&0x40) {
+ // temp=*((u8 *)(sishw_ext.VirtualRomBase+0x53));
+ //} else {
+ vgawb (SEQ_ADR, IND_SIS_POWER_ON_TRAP);
+ temp = vgarb (SEQ_DATA);
+ //}
+ // ~Eden Chen
+ if (temp & 0x01)
+ ivideo.TV_type = TVMODE_PAL;
+ else
+ ivideo.TV_type = TVMODE_NTSC;
+ }
+ } else
+ ivideo.disp_state = 0;
}
+}
- if(found_mode)
- {
- switch(uDispType & MASK_DISPTYPE_DISP2)
- {
- case MASK_DISPTYPE_LCD:
- switch(HwExt.usLCDType)
- {
- case LCD1024:
- if(var->xres > 1024)
- found_mode = 0;
- break;
- case LCD1280:
- if(var->xres > 1280)
- found_mode = 0;
- break;
- case LCD2048:
- if(var->xres > 2048)
- found_mode = 0;
+static void sisfb_get_VB_type_300 (void)
+{
+ u8 reg;
+
+ if (ivideo.chip != SIS_300) {
+ if (!sisfb_has_VB_300 ()) {
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR37);
+ reg = vgarb (CRTC_DATA);
+
+ switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
+ case SIS_EXTERNAL_CHIP_SIS301:
+ ivideo.hasVB = HASVB_301;
break;
- case LCD1920:
- if(var->xres > 1920)
- found_mode = 0;
+ case SIS_EXTERNAL_CHIP_LVDS:
+ ivideo.hasVB = HASVB_LVDS;
break;
- case LCD1600:
- if(var->xres > 1600)
- found_mode = 0;
+ case SIS_EXTERNAL_CHIP_TRUMPION:
+ ivideo.hasVB = HASVB_TRUMPION;
break;
- case LCD800:
- if(var->xres > 800)
- found_mode = 0;
+ case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
+ ivideo.hasVB = HASVB_LVDS_CHRONTEL;
break;
- case LCD640:
- if(var->xres > 640)
- found_mode = 0;
+ case SIS_EXTERNAL_CHIP_CHRONTEL:
+ ivideo.hasVB = HASVB_CHRONTEL;
break;
default:
- found_mode = 0;
- }
- if(var->xres == 720) /* mode only for TV */
- found_mode = 0;
- break;
- case MASK_DISPTYPE_TV:
- switch(var->xres)
- {
- case 800:
- case 640:
break;
- case 720:
- if(ivideo.TV_type == TVMODE_NTSC)
- {
- if(sisbios_mode[mode_idx].yres != 480)
- found_mode = 0;
- }
- else if(ivideo.TV_type == TVMODE_PAL)
- {
- if(sisbios_mode[mode_idx].yres != 576)
- found_mode = 0;
+ }
+ }
+ } else {
+ sisfb_has_VB_300 ();
+ }
+
+ //sishw_ext.hasVB = ivideo.hasVB;
+}
+
+static int sisfb_has_VB_300 (void)
+{
+ // Eden Chen
+ //u8 sr38, sr39, vb_chipid;
+ u8 vb_chipid;
+
+ //vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP);
+ //sr38 = vgarb(SEQ_DATA);
+ //vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP2);
+ //sr39 = vgarb(SEQ_DATA);
+ vgawb (VB_PART4_ADR, 0x0);
+ vb_chipid = vgarb (VB_PART4_DATA);
+
+ switch (vb_chipid) {
+ case 0x01:
+ ivideo.hasVB = HASVB_301;
+ break;
+ case 0x02:
+ ivideo.hasVB = HASVB_302;
+ break;
+ case 0x03:
+ ivideo.hasVB = HASVB_303;
+ break;
+ default:
+ ivideo.hasVB = HASVB_NONE;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#endif /* CONFIG_FB_SIS_300 */
+
+#ifdef CONFIG_FB_SIS_315 /* for SiS 315H/315 */
+static int sisfb_get_dram_size_315 (void)
+{
+#ifdef LINUXBIOS
+ struct pci_dev *pdev = NULL;
+ int pdev_valid = 0;
+ u8 pci_data;
+#endif
+ u8 reg = 0;
+
+ if (ivideo.chip == SIS_550) {
+#ifdef LINUXBIOS
+ pci_for_each_dev (pdev) {
+ if ((pdev->vendor == PCI_VENDOR_ID_SI)
+ && (pdev->device == PCI_DEVICE_ID_SI_550)) {
+ pci_read_config_byte (pdev, IND_BRI_DRAM_STATUS,
+ &pci_data);
+ pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
+ ivideo.video_size =
+ (unsigned int) (1 << (pci_data + 21));
+ pdev_valid = 1;
+
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+ reg = vgarb (SEQ_DATA) & 0xC0;
+
+ switch (pci_data) {
+ //case BRI_DRAM_SIZE_2MB:
+ // reg |= (SIS315_DRAM_SIZE_2MB << 4); break;
+ case BRI_DRAM_SIZE_4MB:
+ reg |= SIS550_DRAM_SIZE_4MB;
+ break;
+ case BRI_DRAM_SIZE_8MB:
+ reg |= SIS550_DRAM_SIZE_8MB;
+ break;
+ case BRI_DRAM_SIZE_16MB:
+ reg |= SIS550_DRAM_SIZE_16MB;
+ break;
+ case BRI_DRAM_SIZE_32MB:
+ reg |= SIS550_DRAM_SIZE_32MB;
+ break;
+ case BRI_DRAM_SIZE_64MB:
+ reg |= SIS550_DRAM_SIZE_64MB;
+ break;
+ /* case BRI_DRAM_SIZE_128MB:
+ reg |= (SIS315_DRAM_SIZE_128MB << 4); break; */
}
+
+ /* TODO : set Dual channel and bus width bits here */
+
+ vgawb (SEQ_DATA, reg);
break;
- default:
- /* illegal mode */
- found_mode = 0;
}
+ }
+
+ if (!pdev_valid)
+ return -1;
+#else
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+ reg = vgarb (SEQ_DATA);
+ switch (reg & SIS550_DRAM_SIZE_MASK) {
+ case SIS550_DRAM_SIZE_4MB:
+ ivideo.video_size = 0x400000;
+ break;
+ case SIS550_DRAM_SIZE_8MB:
+ ivideo.video_size = 0x800000;
+ break;
+ case SIS550_DRAM_SIZE_16MB:
+ ivideo.video_size = 0x1000000;
+ break;
+ case SIS550_DRAM_SIZE_24MB:
+ ivideo.video_size = 0x1800000;
+ break;
+ case SIS550_DRAM_SIZE_32MB:
+ ivideo.video_size = 0x2000000;
+ break;
+ case SIS550_DRAM_SIZE_64MB:
+ ivideo.video_size = 0x4000000;
+ break;
+ case SIS550_DRAM_SIZE_96MB:
+ ivideo.video_size = 0x6000000;
+ break;
+ case SIS550_DRAM_SIZE_128MB:
+ ivideo.video_size = 0x8000000;
+ break;
+ case SIS550_DRAM_SIZE_256MB:
+ ivideo.video_size = 0x10000000;
+ break;
+ default:
+ return -1;
+ }
+#endif
+ return 0;
+ } else {
+ vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+ reg = vgarb (SEQ_DATA);
+ switch ((reg & SIS315_DRAM_SIZE_MASK) >> 4) {
+ case SIS315_DRAM_SIZE_2MB:
+ ivideo.video_size = 0x200000;
+ break;
+ case SIS315_DRAM_SIZE_4MB:
+ ivideo.video_size = 0x400000;
+ break;
+ case SIS315_DRAM_SIZE_8MB:
+ ivideo.video_size = 0x800000;
+ break;
+ case SIS315_DRAM_SIZE_16MB:
+ ivideo.video_size = 0x1000000;
break;
+ case SIS315_DRAM_SIZE_32MB:
+ ivideo.video_size = 0x2000000;
+ break;
+ case SIS315_DRAM_SIZE_64MB:
+ ivideo.video_size = 0x4000000;
+ break;
+ case SIS315_DRAM_SIZE_128MB:
+ ivideo.video_size = 0x8000000;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ reg &= SIS315_DUAL_CHANNEL_MASK;
+ reg >>= 2;
+ switch (reg) {
+ case SIS315_SINGLE_CHANNEL_2_RANK:
+ ivideo.video_size <<= 1;
+ break;
+ case SIS315_DUAL_CHANNEL_1_RANK:
+ ivideo.video_size <<= 1;
+ break;
+ }
+
+ return 0;
+}
+
+static void sisfb_detect_VB_connect_315 (void)
+{
+ u8 cr32, temp;
+
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR32);
+ cr32 = vgarb (CRTC_DATA);
+
+ ivideo.TV_plug = ivideo.TV_type = 0;
+ if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
+ sisfb_crt1off = 0;
+ else {
+ if (cr32 & 0x5F)
+ sisfb_crt1off = 1;
+ else
+ sisfb_crt1off = 0;
+ }
+
+ if (cr32 & SIS_VB_CRT2)
+ ivideo.disp_state = DISPTYPE_CRT2;
+ else if (cr32 & SIS_VB_LCD)
+ ivideo.disp_state = DISPTYPE_LCD;
+ else if (cr32 & SIS_VB_TV) {
+ ivideo.disp_state = DISPTYPE_TV;
+
+ if (cr32 & SIS_VB_HIVISION) {
+ ivideo.TV_type = TVMODE_HIVISION;
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ } else if (cr32 & SIS_VB_SVIDEO)
+ ivideo.TV_plug = TVPLUG_SVIDEO;
+ else if (cr32 & SIS_VB_COMPOSITE)
+ ivideo.TV_plug = TVPLUG_COMPOSITE;
+ else if (cr32 & SIS_VB_SCART)
+ ivideo.TV_plug = TVPLUG_SCART;
+
+ if (ivideo.TV_type == 0) {
+ vgawb (SEQ_ADR, IND_SIS_POWER_ON_TRAP);
+ temp = vgarb (SEQ_DATA);
+
+ if (temp & 0x01)
+ ivideo.TV_type = TVMODE_PAL;
+ else
+ ivideo.TV_type = TVMODE_NTSC;
}
+ } else
+ ivideo.disp_state = 0;
+}
+
+static void sisfb_get_VB_type_315 (void)
+{
+ u8 vb_chipid;
+
+ vgawb (VB_PART4_ADR, 0x0);
+ vb_chipid = vgarb (VB_PART4_DATA);
+
+ switch (vb_chipid) {
+ case 0x01:
+ ivideo.hasVB = HASVB_301;
+ break;
+ case 0x02:
+ ivideo.hasVB = HASVB_302;
+ break;
+ case 0x03:
+ ivideo.hasVB = HASVB_303;
+ break;
+ default:
+ ivideo.hasVB = HASVB_NONE;
}
+ // Eden Chen
+ //sishw_ext.hasVB = ivideo.hasVB;
+ // ~Eden Chen
+}
+#endif /* CONFIG_FB_SIS_315 */
+
+/* --------------------- Heap Routines ------------------------------- */
+
+static int sisfb_heap_init (void)
+{
+ SIS_OH *poh;
+ u8 temp = 0;
+#ifdef CONFIG_FB_SIS_315
+ int agp_enabled = 1;
+ u32 agp_size;
+ unsigned long *cmdq_baseport = 0;
+ unsigned long *read_port = 0;
+ unsigned long *write_port = 0;
+ SIS_CMDTYPE cmd_type;
+#ifndef AGPOFF
+ agp_kern_info *agp_info;
+ agp_memory *agp;
+ u32 agp_phys;
+#endif
+#endif
+ /*karl:10/01/2001 */
+ if (!sisfb_mem) {
- if (!found_mode) {
- printk("sisfb does not support mode %dx%d-%d\n", var->xres,
- var->yres, var->bits_per_pixel);
- mode_idx = old_mode;
- return 1;
+ if (ivideo.video_size > 0x800000)
+ sisfb_heap_start =
+ (unsigned long) ivideo.video_vbase + 0x800000;
+ else
+ sisfb_heap_start =
+ (unsigned long) ivideo.video_vbase + 0x400000;
+ } else
+ sisfb_heap_start =
+ (unsigned long) (ivideo.video_vbase + sisfb_mem * 0x100000);
+
+ sisfb_heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
+ sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
+
+#ifdef CONFIG_FB_SIS_315
+
+ cmdq_baseport =
+ (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE);
+ write_port =
+ (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT);
+ read_port = (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_READPORT);
+
+ DPRINTK ("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport,
+ read_port, write_port);
+
+ agp_size = COMMAND_QUEUE_AREA_SIZE;
+
+#ifndef AGPOFF
+
+ agp_info = vmalloc (sizeof (agp_kern_info));
+ memset ((void *) agp_info, 0x00, sizeof (agp_kern_info));
+ agp_copy_info (agp_info);
+
+ agp_backend_acquire ();
+
+ agp =
+ agp_allocate_memory (COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
+ AGP_NORMAL_MEMORY);
+ if (agp == NULL) {
+ DPRINTK ("Allocate AGP buffer failed.\n");
+ agp_enabled = 0;
+ } else {
+ if (agp_bind_memory (agp, agp->pg_start) != 0) {
+ DPRINTK ("AGP : can not bind memory\n");
+ agp_enabled = 0;
+ } else {
+ agp_enable (0);
+ }
}
- if (search_refresh_rate(ivideo.refresh_rate) == 0) {
- /* not supported rate */
- rate_idx = sisbios_mode[mode_idx].rate_idx;
- ivideo.refresh_rate = 60;
- }
+#else
+ agp_enabled = 0;
+#endif
+ if (agp_enabled)
+ cmd_type = AGP_CMD_QUEUE;
+ else if (sisfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)
+ cmd_type = VM_CMD_QUEUE;
+ else
+ cmd_type = MMIO_CMD;
- if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
- pre_setmode();
+ switch (agp_size) {
+ case 0x80000:
+ temp = SIS_CMD_QUEUE_SIZE_512k;
+ break;
+ case 0x100000:
+ temp = SIS_CMD_QUEUE_SIZE_1M;
+ break;
+ case 0x200000:
+ temp = SIS_CMD_QUEUE_SIZE_2M;
+ break;
+ case 0x400000:
+ temp = SIS_CMD_QUEUE_SIZE_4M;
+ break;
+ }
- if (SiSSetMode(&HwExt, mode_no)) {
- DPRINTK("sisfb: set mode[0x%x]: failed\n",
- mode_no);
- return 1;
- }
+ switch (cmd_type) {
+ case AGP_CMD_QUEUE:
+#ifndef AGPOFF
+ DPRINTK ("AGP buffer base:0x%lx, offset:0x%x, size is %dK\n",
+ agp_info->aper_base, agp->physical, agp_size / 1024);
- post_setmode();
+ agp_phys = agp_info->aper_base + agp->physical;
- printk(KERN_DEBUG "Current Mode: %dx%dx%d-%d \n", sisbios_mode[mode_idx].xres,
- sisbios_mode[mode_idx].yres, sisbios_mode[mode_idx].bpp, ivideo.refresh_rate);
+ vgawb (CRTC_ADR, IND_SIS_AGP_IO_PAD);
+ vgawb (CRTC_DATA, 0);
+ vgawb (CRTC_DATA, SIS_AGP_2X);
- ivideo.video_bpp = sisbios_mode[mode_idx].bpp;
- ivideo.video_vwidth = ivideo.video_width = sisbios_mode[mode_idx].xres;
- ivideo.video_vheight = ivideo.video_height = sisbios_mode[mode_idx].yres;
- ivideo.org_x = ivideo.org_y = 0;
- video_linelength =
- ivideo.video_width * (ivideo.video_bpp >> 3);
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD);
+ vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD);
- DPRINTK("Current Mode: %dx%d-%d line_length=%d\n",
- ivideo.video_width, ivideo.video_height,
- ivideo.video_bpp, video_linelength);
- }
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET);
- return 0;
-}
+ *write_port = *read_port;
-/* ---------------------- Draw Funtions ----------------------------- */
+ temp |= SIS_AGP_CMDQUEUE_ENABLE;
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, temp);
-static void sis_get_glyph(struct GlyInfo *gly)
-{
- struct display *p = &fb_display[currcon];
- u16 c;
- u8 *cdat;
- int widthb;
- u8 *gbuf = gly->gmask;
- int size;
+ *cmdq_baseport = agp_phys;
+ sisfb_caps |= AGP_CMD_QUEUE_CAP;
+#endif
+ break;
- gly->fontheight = fontheight(p);
- gly->fontwidth = fontwidth(p);
- widthb = (fontwidth(p) + 7) / 8;
+ case VM_CMD_QUEUE:
+ sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+ sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
- c = gly->ch & p->charmask;
- if (fontwidth(p) <= 8)
- cdat = p->fontdata + c * fontheight(p);
- else
- cdat = p->fontdata + (c * fontheight(p) << 1);
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD);
+ vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD);
- size = fontheight(p) * widthb;
- memcpy(gbuf, cdat, size);
- gly->ngmask = size;
-}
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET);
+ *write_port = *read_port;
-/* ---------------------- HEAP Routines ----------------------------- */
+ temp |= SIS_VRAM_CMDQUEUE_ENABLE;
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, temp);
-/*
- * Heap Initialization
- */
+ *cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
-static int sisfb_heap_init(void)
-{
- struct OH *poh;
- u8 jTemp, tq_state;
+ sisfb_caps |= VM_CMD_QUEUE_CAP;
- if(ivideo.video_size > 0x800000)
- /* video ram is large than 8M */
- heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_8M;
- else
- heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_4M;
+ DPRINTK ("VM Cmd Queue offset = 0x%lx, size is %dK\n",
+ *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE / 1024);
+ break;
+ default:
+ vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+ vgawb (SEQ_DATA, SIS_MMIO_CMD_ENABLE);
+ break;
+ }
- heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
- heap_size = heap_end - heap_start;
+#endif
+#ifdef CONFIG_FB_SIS_300
+ if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) {
+ unsigned int tqueue_pos;
+ u8 tq_state;
- /* Setting for Turbo Queue */
- if (heap_size >= TURBO_QUEUE_AREA_SIZE) {
tqueue_pos =
- (ivideo.video_size -
- TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
- jTemp = (u8) (tqueue_pos & 0xff);
- vgawb(SEQ_ADR, IND_SIS_TURBOQUEUE_SET);
- tq_state = vgarb(SEQ_DATA);
+ (ivideo.video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
+ temp = (u8) (tqueue_pos & 0xff);
+ vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_SET);
+ tq_state = vgarb (SEQ_DATA);
tq_state |= 0xf0;
tq_state &= 0xfc;
tq_state |= (u8) (tqueue_pos >> 8);
- vgawb(SEQ_DATA, tq_state);
- vgawb(SEQ_ADR, IND_SIS_TURBOQUEUE_ADR);
- vgawb(SEQ_DATA, jTemp);
-
- caps |= TURBO_QUEUE_CAP;
-
- heap_end -= TURBO_QUEUE_AREA_SIZE;
- heap_size -= TURBO_QUEUE_AREA_SIZE;
+ vgawb (SEQ_DATA, tq_state);
+ vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_ADR);
+ vgawb (SEQ_DATA, temp);
+
+ sisfb_caps |= TURBO_QUEUE_CAP;
+
+ sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
+ sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
+ DPRINTK ("Turbo Queue: start at 0x%lx, size is %dK\n",
+ sisfb_heap_end, TURBO_QUEUE_AREA_SIZE / 1024);
}
+#endif
- /* Setting for HW cursor(4K) */
- if (heap_size >= HW_CURSOR_AREA_SIZE) {
- heap_end -= HW_CURSOR_AREA_SIZE;
- heap_size -= HW_CURSOR_AREA_SIZE;
- hwcursor_vbase = heap_end;
+ if (sisfb_heap_size >= HW_CURSOR_AREA_SIZE) {
+ sisfb_heap_end -= HW_CURSOR_AREA_SIZE;
+ sisfb_heap_size -= HW_CURSOR_AREA_SIZE;
+ sisfb_hwcursor_vbase = sisfb_heap_end;
- caps |= HW_CURSOR_CAP;
+ sisfb_caps |= HW_CURSOR_CAP;
+
+ DPRINTK ("Hardware Cursor: start at 0x%lx, size is %dK\n",
+ sisfb_heap_end, HW_CURSOR_AREA_SIZE / 1024);
}
- heap.pohaChain = NULL;
- heap.pohFreeList = NULL;
+ sisfb_heap.poha_chain = NULL;
+ sisfb_heap.poh_freelist = NULL;
- poh = poh_new_node();
+ poh = sisfb_poh_new_node ();
if (poh == NULL)
return 1;
- /* The first node describles the entire heap size */
- poh->pohNext = &heap.ohFree;
- poh->pohPrev = &heap.ohFree;
- poh->ulSize = heap_end - heap_start + 1;
- poh->ulOffset = heap_start - (unsigned long) ivideo.video_vbase;
-
- DPRINTK("sisfb:Heap start:0x%p, end:0x%p, len=%dk\n",
- (char *) heap_start, (char *) heap_end,
- (unsigned int) poh->ulSize / 1024);
-
- DPRINTK("sisfb:First Node offset:0x%x, size:%dk\n",
- (unsigned int) poh->ulOffset, (unsigned int) poh->ulSize / 1024);
-
- /* The second node in our free list sentinel */
- heap.ohFree.pohNext = poh;
- heap.ohFree.pohPrev = poh;
- heap.ohFree.ulSize = 0;
- heap.ulMaxFreeSize = poh->ulSize;
-
- /* Initialize the discardable list */
- heap.ohUsed.pohNext = &heap.ohUsed;
- heap.ohUsed.pohPrev = &heap.ohUsed;
- heap.ohUsed.ulSize = SENTINEL;
+ poh->poh_next = &sisfb_heap.oh_free;
+ poh->poh_prev = &sisfb_heap.oh_free;
+ poh->size = sisfb_heap_end - sisfb_heap_start + 1;
+ poh->offset = sisfb_heap_start - (unsigned long) ivideo.video_vbase;
+
+ DPRINTK ("sisfb:Heap start:0x%p, end:0x%p, len=%dk\n",
+ (char *) sisfb_heap_start, (char *) sisfb_heap_end,
+ (unsigned int) poh->size / 1024);
+
+ DPRINTK ("sisfb:First Node offset:0x%x, size:%dk\n",
+ (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
+
+ sisfb_heap.oh_free.poh_next = poh;
+ sisfb_heap.oh_free.poh_prev = poh;
+ sisfb_heap.oh_free.size = 0;
+ sisfb_heap.max_freesize = poh->size;
+
+ sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
+ sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
+ sisfb_heap.oh_used.size = SENTINEL;
return 0;
}
-/*
- * Allocates a basic memory unit in which we'll pack our data structures.
- */
-
-static struct OH *poh_new_node(void)
+static SIS_OH *sisfb_poh_new_node (void)
{
int i;
unsigned long cOhs;
- struct OHALLOC *poha;
- struct OH *poh;
+ SIS_OHALLOC *poha;
+ SIS_OH *poh;
- if (heap.pohFreeList == NULL) {
- poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
- if (!poha)
- return NULL;
+ if (sisfb_heap.poh_freelist == NULL) {
+ poha = kmalloc (OH_ALLOC_SIZE, GFP_KERNEL);
- poha->pohaNext = heap.pohaChain;
- heap.pohaChain = poha;
+ poha->poha_next = sisfb_heap.poha_chain;
+ sisfb_heap.poha_chain = poha;
cOhs =
(OH_ALLOC_SIZE -
- sizeof(struct OHALLOC)) / sizeof(struct OH) + 1;
+ sizeof (SIS_OHALLOC)) / sizeof (SIS_OH) + 1;
poh = &poha->aoh[0];
for (i = cOhs - 1; i != 0; i--) {
- poh->pohNext = poh + 1;
+ poh->poh_next = poh + 1;
poh = poh + 1;
}
- poh->pohNext = NULL;
- heap.pohFreeList = &poha->aoh[0];
+ poh->poh_next = NULL;
+ sisfb_heap.poh_freelist = &poha->aoh[0];
}
- poh = heap.pohFreeList;
- heap.pohFreeList = poh->pohNext;
+ poh = sisfb_heap.poh_freelist;
+ sisfb_heap.poh_freelist = poh->poh_next;
return (poh);
}
-/*
- * Allocates space, return NULL when failed
- */
-
-static struct OH *poh_allocate(unsigned long size)
+static SIS_OH *sisfb_poh_allocate (unsigned long size)
{
- struct OH *pohThis;
- struct OH *pohRoot;
+ SIS_OH *pohThis;
+ SIS_OH *pohRoot;
int bAllocated = 0;
- if (size > heap.ulMaxFreeSize) {
- DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
- (unsigned int) size / 1024);
+ if (size > sisfb_heap.max_freesize) {
+ DPRINTK ("sisfb: Can't allocate %dk size on offscreen\n",
+ (unsigned int) size / 1024);
return (NULL);
}
- pohThis = heap.ohFree.pohNext;
+ pohThis = sisfb_heap.oh_free.poh_next;
- while (pohThis != &heap.ohFree) {
- if (size <= pohThis->ulSize) {
+ while (pohThis != &sisfb_heap.oh_free) {
+ if (size <= pohThis->size) {
bAllocated = 1;
break;
}
- pohThis = pohThis->pohNext;
+ pohThis = pohThis->poh_next;
}
if (!bAllocated) {
- DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
- (unsigned int) size / 1024);
+ DPRINTK ("sisfb: Can't allocate %dk size on offscreen\n",
+ (unsigned int) size / 1024);
return (NULL);
}
- if (size == pohThis->ulSize) {
+ if (size == pohThis->size) {
pohRoot = pohThis;
- delete_node(pohThis);
+ sisfb_delete_node (pohThis);
} else {
- pohRoot = poh_new_node();
+ pohRoot = sisfb_poh_new_node ();
if (pohRoot == NULL) {
return (NULL);
}
- pohRoot->ulOffset = pohThis->ulOffset;
- pohRoot->ulSize = size;
+ pohRoot->offset = pohThis->offset;
+ pohRoot->size = size;
- pohThis->ulOffset += size;
- pohThis->ulSize -= size;
+ pohThis->offset += size;
+ pohThis->size -= size;
}
- heap.ulMaxFreeSize -= size;
+ sisfb_heap.max_freesize -= size;
- pohThis = &heap.ohUsed;
- insert_node(pohThis, pohRoot);
+ pohThis = &sisfb_heap.oh_used;
+ sisfb_insert_node (pohThis, pohRoot);
return (pohRoot);
}
-/*
- * To remove a node from a list.
- */
-
-static void delete_node(struct OH *poh)
+static void sisfb_delete_node (SIS_OH * poh)
{
- struct OH *pohPrev;
- struct OH *pohNext;
+ SIS_OH *poh_prev;
+ SIS_OH *poh_next;
+ poh_prev = poh->poh_prev;
+ poh_next = poh->poh_next;
- pohPrev = poh->pohPrev;
- pohNext = poh->pohNext;
-
- pohPrev->pohNext = pohNext;
- pohNext->pohPrev = pohPrev;
+ poh_prev->poh_next = poh_next;
+ poh_next->poh_prev = poh_prev;
return;
}
-/*
- * To insert a node into a list.
- */
-
-static void insert_node(struct OH *pohList, struct OH *poh)
+static void sisfb_insert_node (SIS_OH * pohList, SIS_OH * poh)
{
- struct OH *pohTemp;
+ SIS_OH *pohTemp;
- pohTemp = pohList->pohNext;
+ pohTemp = pohList->poh_next;
- pohList->pohNext = poh;
- pohTemp->pohPrev = poh;
+ pohList->poh_next = poh;
+ pohTemp->poh_prev = poh;
- poh->pohPrev = pohList;
- poh->pohNext = pohTemp;
+ poh->poh_prev = pohList;
+ poh->poh_next = pohTemp;
}
-/*
- * Frees an off-screen heap allocation.
- */
-
-static struct OH *poh_free(unsigned long base)
+static SIS_OH *sisfb_poh_free (unsigned long base)
{
- struct OH *pohThis;
- struct OH *pohFreed;
- struct OH *pohPrev;
- struct OH *pohNext;
+ SIS_OH *pohThis;
+ SIS_OH *poh_freed;
+ SIS_OH *poh_prev;
+ SIS_OH *poh_next;
unsigned long ulUpper;
unsigned long ulLower;
int foundNode = 0;
- pohFreed = heap.ohUsed.pohNext;
+ poh_freed = sisfb_heap.oh_used.poh_next;
- while (pohFreed != &heap.ohUsed) {
- if (pohFreed->ulOffset == base) {
+ while (poh_freed != &sisfb_heap.oh_used) {
+ if (poh_freed->offset == base) {
foundNode = 1;
break;
}
- pohFreed = pohFreed->pohNext;
+ poh_freed = poh_freed->poh_next;
}
if (!foundNode)
return (NULL);
- heap.ulMaxFreeSize += pohFreed->ulSize;
+ sisfb_heap.max_freesize += poh_freed->size;
- pohPrev = pohNext = NULL;
- ulUpper = pohFreed->ulOffset + pohFreed->ulSize;
- ulLower = pohFreed->ulOffset;
+ poh_prev = poh_next = NULL;
+ ulUpper = poh_freed->offset + poh_freed->size;
+ ulLower = poh_freed->offset;
- pohThis = heap.ohFree.pohNext;
+ pohThis = sisfb_heap.oh_free.poh_next;
- while (pohThis != &heap.ohFree) {
- if (pohThis->ulOffset == ulUpper) {
- pohNext = pohThis;
+ while (pohThis != &sisfb_heap.oh_free) {
+ if (pohThis->offset == ulUpper) {
+ poh_next = pohThis;
+ } else if ((pohThis->offset + pohThis->size) == ulLower) {
+ poh_prev = pohThis;
}
- else if ((pohThis->ulOffset + pohThis->ulSize) ==
- ulLower) {
- pohPrev = pohThis;
- }
- pohThis = pohThis->pohNext;
+ pohThis = pohThis->poh_next;
}
- delete_node(pohFreed);
+ sisfb_delete_node (poh_freed);
- if (pohPrev && pohNext) {
- pohPrev->ulSize += (pohFreed->ulSize + pohNext->ulSize);
- delete_node(pohNext);
- free_node(pohFreed);
- free_node(pohNext);
- return (pohPrev);
+ if (poh_prev && poh_next) {
+ poh_prev->size += (poh_freed->size + poh_next->size);
+ sisfb_delete_node (poh_next);
+ sisfb_free_node (poh_freed);
+ sisfb_free_node (poh_next);
+ return (poh_prev);
}
- if (pohPrev) {
- pohPrev->ulSize += pohFreed->ulSize;
- free_node(pohFreed);
- return (pohPrev);
+ if (poh_prev) {
+ poh_prev->size += poh_freed->size;
+ sisfb_free_node (poh_freed);
+ return (poh_prev);
}
- if (pohNext) {
- pohNext->ulSize += pohFreed->ulSize;
- pohNext->ulOffset = pohFreed->ulOffset;
- free_node(pohFreed);
- return (pohNext);
+ if (poh_next) {
+ poh_next->size += poh_freed->size;
+ poh_next->offset = poh_freed->offset;
+ sisfb_free_node (poh_freed);
+ return (poh_next);
}
- insert_node(&heap.ohFree, pohFreed);
+ sisfb_insert_node (&sisfb_heap.oh_free, poh_freed);
- return (pohFreed);
+ return (poh_freed);
}
-/*
- * Frees our basic data structure allocation unit by adding it to a free
- * list.
- */
-
-static void free_node(struct OH *poh)
+static void sisfb_free_node (SIS_OH * poh)
{
if (poh == NULL) {
return;
}
- poh->pohNext = heap.pohFreeList;
- heap.pohFreeList = poh;
+ poh->poh_next = sisfb_heap.poh_freelist;
+ sisfb_heap.poh_freelist = poh;
return;
}
-void sis_malloc(struct sis_memreq *req)
+void sis_malloc (struct sis_memreq *req)
{
- struct OH *poh;
+ SIS_OH *poh;
- poh = poh_allocate(req->size);
+ poh = sisfb_poh_allocate (req->size);
if (poh == NULL) {
req->offset = 0;
req->size = 0;
- DPRINTK("sisfb: VMEM Allocation Failed\n");
+ DPRINTK ("sisfb: VMEM Allocation Failed\n");
} else {
- DPRINTK("sisfb: VMEM Allocation Successed : 0x%p\n",
- (char *) (poh->ulOffset +
- (unsigned long) ivideo.video_vbase));
+ DPRINTK ("sisfb: VMEM Allocation Successed : 0x%p\n",
+ (char *) (poh->offset +
+ (unsigned long) ivideo.video_vbase));
- req->offset = poh->ulOffset;
- req->size = poh->ulSize;
+ req->offset = poh->offset;
+ req->size = poh->size;
}
}
-void sis_free(unsigned long base)
+void sis_free (unsigned long base)
{
- struct OH *poh;
+ SIS_OH *poh;
- poh = poh_free(base);
+ poh = sisfb_poh_free (base);
if (poh == NULL) {
- DPRINTK("sisfb: poh_free() failed at base 0x%x\n",
- (unsigned int) base);
+ DPRINTK ("sisfb: sisfb_poh_free() failed at base 0x%x\n",
+ (unsigned int) base);
}
}
-void sis_dispinfo(struct ap_data *rec)
+/* ------------------ SetMode Routines ------------------------------- */
+
+static void sisfb_pre_setmode (void)
{
- rec->minfo.bpp = ivideo.video_bpp;
- rec->minfo.xres = ivideo.video_width;
- rec->minfo.yres = ivideo.video_height;
- rec->minfo.v_xres = ivideo.video_vwidth;
- rec->minfo.v_yres = ivideo.video_vheight;
- rec->minfo.org_x = ivideo.org_x;
- rec->minfo.org_y = ivideo.org_y;
- rec->minfo.vrate = ivideo.refresh_rate;
- rec->iobase = ivideo.vga_base - 0x30;
- rec->mem_size = ivideo.video_size;
- rec->disp_state = ivideo.disp_state;
- switch(HwExt.jChipID)
- {
- case SIS_Glamour:
- rec->chip = SiS_300;
- break;
- case SIS_Trojan:
- if((HwExt.revision_id & 0xf0) == 0x30)
- rec->chip = SiS_630S;
- else
- rec->chip = SiS_630;
- break;
- case SIS_Spartan:
- rec->chip = SiS_540;
- break;
- case SIS_730:
- rec->chip = SiS_730;
+ u8 cr30 = 0, cr31 = 0;
+
+ vgawb (CRTC_ADR, 0x31);
+ cr31 = vgarb (CRTC_DATA) & ~0x60;
+
+ switch (ivideo.disp_state & DISPTYPE_DISP2) {
+ case DISPTYPE_CRT2:
+ cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+ cr31 |= SIS_DRIVER_MODE;
+ break;
+ case DISPTYPE_LCD:
+ cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
+ cr31 |= SIS_DRIVER_MODE;
+ break;
+ case DISPTYPE_TV:
+ if (ivideo.TV_type == TVMODE_HIVISION)
+ cr30 =
+ (SIS_VB_OUTPUT_HIVISION |
+ SIS_SIMULTANEOUS_VIEW_ENABLE);
+ else if (ivideo.TV_plug == TVPLUG_SVIDEO)
+ cr30 =
+ (SIS_VB_OUTPUT_SVIDEO |
+ SIS_SIMULTANEOUS_VIEW_ENABLE);
+ else if (ivideo.TV_plug == TVPLUG_COMPOSITE)
+ cr30 =
+ (SIS_VB_OUTPUT_COMPOSITE |
+ SIS_SIMULTANEOUS_VIEW_ENABLE);
+ else if (ivideo.TV_plug == TVPLUG_SCART)
+ cr30 =
+ (SIS_VB_OUTPUT_SCART |
+ SIS_SIMULTANEOUS_VIEW_ENABLE);
+ cr31 |= SIS_DRIVER_MODE;
+
+ /*karl */
+ if (sisfb_tvmode == 1)
+ cr31 |= 0x1;
+ if (sisfb_tvmode == 2)
+ cr31 &= ~0x1;
+
break;
default:
- rec->chip = SiS_UNKNOWN;
- break;
+ cr30 = 0x00;
+ cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
}
-}
-
-
-/* ---------------------- SetMode Routines -------------------------- */
-void SetReg1(u16 port, u16 index, u16 data)
-{
- outb((u8) (index & 0xff), port);
- port++;
- outb((u8) (data & 0xff), port);
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR30);
+ vgawb (CRTC_DATA, cr30);
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR31);
+ vgawb (CRTC_DATA, cr31);
+ vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR33);
+ vgawb (CRTC_DATA, sisfb_rate_idx & 0x0F);
}
-void SetReg3(u16 port, u16 data)
+static void sisfb_post_setmode (void)
{
- outb((u8) (data & 0xff), port);
-}
+ u8 reg;
-void SetReg4(u16 port, unsigned long data)
-{
- outl((u32) (data & 0xffffffff), port);
-}
+ vgawb (CRTC_ADR, 0x17);
+ reg = vgarb (CRTC_DATA);
-u8 GetReg1(u16 port, u16 index)
-{
- u8 data;
+ if ((ivideo.hasVB == HASVB_LVDS)
+ || (ivideo.hasVB == HASVB_LVDS_CHRONTEL)) if (ivideo.video_bpp == 8)
+ sisfb_crt1off = 0;
- outb((u8) (index & 0xff), port);
- port += 1;
- data = inb(port);
- return (data);
-}
+ if (sisfb_crt1off)
+ reg &= ~0x80;
+ else
+ reg |= 0x80;
+ vgawb (CRTC_DATA, reg);
-u8 GetReg2(u16 port)
-{
- u8 data;
+ vgawb (SEQ_ADR, IND_SIS_RAMDAC_CONTROL);
+ reg = vgarb (SEQ_DATA);
+ reg &= ~0x04;
+ vgawb (SEQ_DATA, reg);
+
+ if ((ivideo.disp_state & DISPTYPE_TV) && (ivideo.hasVB == HASVB_301)) {
+ /*karl */
+ vgawb (VB_PART4_ADR, 0x01);
+ reg = vgarb (VB_PART4_DATA);
+
+ if ((reg != 0xB1) && (reg != 0xB0)) { /*301B Revision ID */
+ // Eden Chen
+ switch (ivideo.video_width) {
+ case 320:
+ filter_tb =
+ (ivideo.TV_type == TVMODE_NTSC) ? 4 : 12;
+ break;
+ case 640:
+ filter_tb =
+ (ivideo.TV_type == TVMODE_NTSC) ? 5 : 13;
+ break;
+ case 720:
+ filter_tb =
+ (ivideo.TV_type == TVMODE_NTSC) ? 6 : 14;
+ break;
+ case 800:
+ filter_tb =
+ (ivideo.TV_type == TVMODE_NTSC) ? 7 : 15;
+ break;
+ default:
+ filter = -1;
+ break;
+ }
+ // ~Eden Chen
- data = inb(port);
+ // Eden Chen
+ //vgawb(VB_PART1_ADR, 0x24);
+ vgawb (VB_PART1_ADR, IND_SIS_CRT2_WRITE_ENABLE);
+ // ~Eden Chen
+ vgawb (VB_PART1_DATA, 0x1);
+
+ // Eden Chen for Debug
+ // ~Eden Chen
+
+ if (ivideo.TV_type == TVMODE_NTSC) {
+ vgawb (VB_PART2_ADR, 0x3A);
+ reg = vgarb (VB_PART2_DATA);
+ reg &= 0x1F;
+ vgawb (VB_PART2_DATA, reg);
+
+ if (ivideo.TV_plug == TVPLUG_SVIDEO) {
+ vgawb (VB_PART2_ADR, 0x30);
+ reg = vgarb (VB_PART2_DATA);
+ reg &= 0xDF;
+ vgawb (VB_PART2_DATA, reg);
+ } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
+ vgawb (VB_PART2_ADR, 0x30);
+ reg = vgarb (VB_PART2_DATA);
+ reg |= 0x20;
+ vgawb (VB_PART2_DATA, reg);
+
+ switch (ivideo.video_width) {
+ case 640:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xEB);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0x04);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x25);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x18);
+ break;
+ case 720:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xEE);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0x0C);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x22);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x08);
+ break;
+ case 800:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xEB);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0x15);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x25);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0xF6);
+ break;
+ }
+ }
+ } else if (ivideo.TV_type == TVMODE_PAL) {
+ vgawb (VB_PART2_ADR, 0x3A);
+ reg = vgarb (VB_PART2_DATA);
+ reg &= 0x1F;
+ vgawb (VB_PART2_DATA, reg);
+
+ if (ivideo.TV_plug == TVPLUG_SVIDEO) {
+ vgawb (VB_PART2_ADR, 0x30);
+ reg = vgarb (VB_PART2_DATA);
+ reg &= 0xDF;
+ vgawb (VB_PART2_DATA, reg);
+ } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
+ vgawb (VB_PART2_ADR, 0x30);
+ reg = vgarb (VB_PART2_DATA);
+ reg |= 0x20;
+ vgawb (VB_PART2_DATA, reg);
+
+ switch (ivideo.video_width) {
+ case 640:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xF1);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0xF7);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x1F);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x32);
+ break;
+ case 720:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xF3);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0x00);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x1D);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x20);
+ break;
+ case 800:
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA, 0xFC);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA, 0xFB);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA, 0x14);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA, 0x2A);
+ break;
+ }
+ }
+ }
+ // Eden
+ if ((filter >= 0) && (filter <= 7)) {
+ DPRINTK
+ ("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
+ filter_tb, filter,
+ sis_TV_filter[filter_tb].filter[filter][0],
+ sis_TV_filter[filter_tb].filter[filter][1],
+ sis_TV_filter[filter_tb].filter[filter][2],
+ sis_TV_filter[filter_tb].filter[filter][3]
+ );
+ vgawb (VB_PART2_ADR, 0x35);
+ vgawb (VB_PART2_DATA,
+ sis_TV_filter[filter_tb].
+ filter[filter][0]);
+ vgawb (VB_PART2_ADR, 0x36);
+ vgawb (VB_PART2_DATA,
+ sis_TV_filter[filter_tb].
+ filter[filter][1]);
+ vgawb (VB_PART2_ADR, 0x37);
+ vgawb (VB_PART2_DATA,
+ sis_TV_filter[filter_tb].
+ filter[filter][2]);
+ vgawb (VB_PART2_ADR, 0x38);
+ vgawb (VB_PART2_DATA,
+ sis_TV_filter[filter_tb].
+ filter[filter][3]);
+ }
+ // ~Eden
+ }
+ }
- return (data);
}
-u32 GetReg3(u16 port)
+static void sisfb_crtc_to_var (struct fb_var_screeninfo *var)
{
- u32 data;
-
- data = inl(port);
- return (data);
-}
+ u16 VRE, VBE, VRS, VBS, VDE, VT;
+ u16 HRE, HBE, HRS, HBS, HDE, HT;
+ u8 sr_data, cr_data, cr_data2, cr_data3, mr_data;
+ int A, B, C, D, E, F, temp;
+ double hrate, drate;
-void ClearDAC(u16 port)
-{
- int i,j;
+ vgawb (SEQ_ADR, IND_SIS_COLOR_MODE);
+ sr_data = vgarb (SEQ_DATA);
- vgawb(DAC_ADR, 0x00);
- for(i=0; i<256; i++)
- for(j=0; j<3; j++)
- vgawb(DAC_DATA, 0);
-}
+ if (sr_data & SIS_INTERLACED_MODE)
+ var->vmode = FB_VMODE_INTERLACED;
+ else
+ var->vmode = FB_VMODE_NONINTERLACED;
-void ClearBuffer(PHW_DEVICE_EXTENSION pHwExt)
-{
- memset((char *) ivideo.video_vbase, 0,
- video_linelength * ivideo.video_height);
-}
+ switch ((sr_data & 0x1C) >> 2) {
+ case SIS_8BPP_COLOR_MODE:
+ var->bits_per_pixel = 8;
+ break;
+ case SIS_16BPP_COLOR_MODE:
+ var->bits_per_pixel = 16;
+ break;
+ case SIS_32BPP_COLOR_MODE:
+ var->bits_per_pixel = 32;
+ break;
+ }
-static void pre_setmode(void)
-{
- unsigned char uCR30=0, uCR31=0;
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.length = 6;
+ var->green.length = 6;
+ var->blue.length = 6;
+ video_cmap_len = 256;
+ break;
+ case 16:
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ video_cmap_len = 16;
- switch(uDispType & MASK_DISPTYPE_DISP2)
- {
- case MASK_DISPTYPE_CRT2:
- uCR30 = 0x41;
- uCR31 = 0x40;
- break;
- case MASK_DISPTYPE_LCD:
- uCR30 = 0x21;
- uCR31 = 0x40;
- break;
- case MASK_DISPTYPE_TV:
- if(ivideo.TV_type == TVMODE_HIVISION)
- uCR30 = 0x81;
- else if(ivideo.TV_plug == TVPLUG_SVIDEO)
- uCR30 = 0x09;
- else if(ivideo.TV_plug == TVPLUG_COMPOSITE)
- uCR30 = 0x05;
- else if(ivideo.TV_plug == TVPLUG_SCART)
- uCR30 = 0x11;
- uCR31 = 0x40; /* CR31[0] will be set in setmode() */
break;
- default:
- uCR30 = 0x00;
- uCR31 = 0x60;
+ case 24:
+ 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;
+ video_cmap_len = 16;
+ break;
+ case 32:
+ 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 = 24;
+ var->transp.length = 8;
+ video_cmap_len = 16;
+ break;
}
- vgawb(CRTC_ADR, 0x30);
- vgawb(CRTC_DATA, uCR30);
- vgawb(CRTC_ADR, 0x31);
- vgawb(CRTC_DATA, uCR31);
- vgawb(CRTC_ADR, 0x33);
- vgawb(CRTC_DATA, rate_idx & 0x0f);
-}
+ vgawb (SEQ_ADR, 0xA);
+ sr_data = vgarb (SEQ_DATA);
-static void post_setmode(void)
-{
- u8 uTemp;
+ vgawb (CRTC_ADR, 0x6);
+ cr_data = vgarb (CRTC_DATA);
+ vgawb (CRTC_ADR, 0x7);
+ cr_data2 = vgarb (CRTC_DATA);
+ VT =
+ (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |
+ ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10);
+ A = VT + 2;
- vgawb(CRTC_ADR, 0x17);
- uTemp = vgarb(CRTC_DATA);
+ vgawb (CRTC_ADR, 0x12);
+ cr_data = vgarb (CRTC_DATA);
+ VDE =
+ (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |
+ ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);
+ E = VDE + 1;
- if(crt1off) /* turn off CRT1 */
- uTemp &= ~0x80;
- else /* turn on CRT1 */
- uTemp |= 0x80;
- vgawb(CRTC_DATA, uTemp);
+ vgawb (CRTC_ADR, 0x10);
+ cr_data = vgarb (CRTC_DATA);
+ VRS =
+ (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |
+ ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);
+ F = VRS + 1 - E;
- /* disable 24-bit palette RAM and Gamma correction */
- vgawb(SEQ_ADR, 0x07);
- uTemp = vgarb(SEQ_DATA);
- uTemp &= ~0x04;
- vgawb(SEQ_DATA, uTemp);
-}
+ vgawb (CRTC_ADR, 0x15);
+ cr_data = vgarb (CRTC_DATA);
+ vgawb (CRTC_ADR, 0x9);
+ cr_data3 = vgarb (CRTC_DATA);
+ VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |
+ ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);
+
+ vgawb (CRTC_ADR, 0x16);
+ cr_data = vgarb (CRTC_DATA);
+ VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
+ temp = VBE - ((E - 1) & 511);
+ B = (temp > 0) ? temp : (temp + 512);
-static void search_mode(const char *name)
-{
- int i = 0;
+ vgawb (CRTC_ADR, 0x11);
+ cr_data = vgarb (CRTC_DATA);
+ VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
+ temp = VRE - ((E + F - 1) & 31);
+ C = (temp > 0) ? temp : (temp + 32);
- if (name == NULL)
- return;
+ D = B - F - C;
- while (sisbios_mode[i].mode_no != 0) {
- if (!strcmp(name, sisbios_mode[i].name)) {
- mode_idx = i;
- break;
- }
- i++;
- }
+ var->yres = var->yres_virtual = E;
+ var->upper_margin = D;
+ var->lower_margin = F;
+ var->vsync_len = C;
- if (mode_idx < 0)
- DPRINTK("Invalid user mode : %s\n", name);
-}
+ vgawb (SEQ_ADR, 0xb);
+ sr_data = vgarb (SEQ_DATA);
-static u8 search_refresh_rate(unsigned int rate)
-{
- u16 xres, yres;
- int i = 0;
+ vgawb (CRTC_ADR, 0x0);
+ cr_data = vgarb (CRTC_DATA);
+ HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
+ A = HT + 5;
- xres = sisbios_mode[mode_idx].xres;
- yres = sisbios_mode[mode_idx].yres;
+ vgawb (CRTC_ADR, 0x1);
+ cr_data = vgarb (CRTC_DATA);
+ HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
+ E = HDE + 1;
- while ((vrate[i].idx != 0) && (vrate[i].xres <= xres)) {
- if ((vrate[i].xres == xres) && (vrate[i].yres == yres)
- && (vrate[i].refresh == rate)) {
- rate_idx = vrate[i].idx;
- return rate_idx;
- }
- i++;
- }
+ vgawb (CRTC_ADR, 0x4);
+ cr_data = vgarb (CRTC_DATA);
+ HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
+ F = HRS - E - 3;
- DPRINTK("sisfb: Unsupported rate %d in %dx%d mode\n", rate, xres,
- yres);
+ vgawb (CRTC_ADR, 0x2);
+ cr_data = vgarb (CRTC_DATA);
+ HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
+
+ vgawb (SEQ_ADR, 0xc);
+ sr_data = vgarb (SEQ_DATA);
+ vgawb (CRTC_ADR, 0x3);
+ cr_data = vgarb (CRTC_DATA);
+ vgawb (CRTC_ADR, 0x5);
+ cr_data2 = vgarb (CRTC_DATA);
+ HBE =
+ (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |
+ ((u16) (sr_data & 0x03) << 6);
+ HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
- return 0;
-}
+ temp = HBE - ((E - 1) & 255);
+ B = (temp > 0) ? temp : (temp + 256);
-/* ------------------ Public Routines ------------------------------- */
+ temp = HRE - ((E + F + 3) & 63);
+ C = (temp > 0) ? temp : (temp + 64);
-/*
- * Get the Fixed Part of the Display
- */
+ D = B - F - C;
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info)
-{
- DPRINTK("sisfb: sisfb_get_fix:[%d]\n", con);
+ var->xres = var->xres_virtual = E * 8;
+ var->left_margin = D * 8;
+ var->right_margin = F * 8;
+ var->hsync_len = C * 8;
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id, fb_info.modename);
+ var->activate = FB_ACTIVATE_NOW;
- fix->smem_start = ivideo.video_base;
- if(ivideo.video_size > 0x800000)
- fix->smem_len = RESERVED_MEM_SIZE_8M; /* reserved for Xserver */
+ var->sync = 0;
+
+ mr_data = vgarb (0x1C);
+ if (mr_data & 0x80)
+ var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+ else
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+ if (mr_data & 0x40)
+ var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
else
- fix->smem_len = RESERVED_MEM_SIZE_4M; /* reserved for Xserver */
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+
+ VT += 2;
+ VT <<= 1;
+ HT = (HT + 5) * 8;
+
+ hrate = (double) ivideo.refresh_rate * (double) VT / 2;
+ drate = hrate * HT;
+ var->pixclock = (u32) (1E12 / drate);
+}
+
+/* ------------------ Public Routines -------------------------------- */
+
+static int sisfb_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+ memset (fix, 0, sizeof (struct fb_fix_screeninfo));
+ strcpy (fix->id, fb_info.modename);
+
+ fix->smem_start = ivideo.video_base;
+
+ /*karl:10/01/2001 */
+ if (!sisfb_mem) {
+ if (ivideo.video_size > 0x800000)
+ fix->smem_len = 0x800000;
+ else
+ fix->smem_len = 0x400000;
+ } else
+ fix->smem_len = sisfb_mem * 0x100000;
fix->type = video_type;
fix->type_aux = 0;
@@ -1502,135 +2007,110 @@
fix->ywrapstep = 0;
fix->line_length = video_linelength;
fix->mmio_start = ivideo.mmio_base;
- fix->mmio_len = MMIO_SIZE;
+ fix->mmio_len = sisfb_mmio_size;
fix->accel = FB_ACCEL_SIS_GLAMOUR;
fix->reserved[0] = ivideo.video_size & 0xFFFF;
fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
- fix->reserved[2] = caps; /* capabilities */
+ fix->reserved[2] = sisfb_caps;
return 0;
-}
-
-/*
- * Get the User Defined Part of the Display
- */
-static int sisfb_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
- DPRINTK("sisfb: sisfb_get_var:[%d]\n", con);
+}
+static int sisfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
if (con == -1)
- memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
+ memcpy (var, &default_var, sizeof (struct fb_var_screeninfo));
else
*var = fb_display[con].var;
+
return 0;
}
-/*
- * Set the User Defined Part of the Display
- */
-
-static int sisfb_set_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)
{
int err;
unsigned int cols, rows;
fb_display[con].var.activate = FB_ACTIVATE_NOW;
- /* Set mode */
- if (do_set_var(var, con == currcon, info)) {
- crtc_to_var(var); /* return current mode to user */
+ if (sisfb_do_set_var (var, con == currcon, info)) {
+ sisfb_crtc_to_var (var);
return -EINVAL;
}
- /* get actual setting value */
- crtc_to_var(var);
+ sisfb_crtc_to_var (var);
- /* update display of current console */
- sisfb_set_disp(con, var);
+ sisfb_set_disp (con, var);
if (info->changevar)
(*info->changevar) (con);
- if ((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
+ if ((err = fb_alloc_cmap (&fb_display[con].cmap, 0, 0)))
return err;
- do_install_cmap(con, info);
+ sisfb_do_install_cmap (con, info);
- /* inform console to update struct display */
- cols = sisbios_mode[mode_idx].cols;
- rows = sisbios_mode[mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
+ cols = sisbios_mode[sisfb_mode_idx].cols;
+ rows = sisbios_mode[sisfb_mode_idx].rows;
+ vc_resize_con (rows, cols, fb_display[con].conp->vc_num);
return 0;
-}
+}
-/*
- * Get the Colormap
- */
-
-static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
+static int sisfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
{
- DPRINTK("sisfb: sisfb_get_cmap:[%d]\n", con);
-
if (con == currcon)
- return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
- else if (fb_display[con].cmap.len) /* non default colormap? */
- fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ return fb_get_cmap (cmap, kspc, sis_getcolreg, info);
+ else if (fb_display[con].cmap.len)
+ fb_copy_cmap (&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
- fb_copy_cmap(fb_default_cmap(video_cmap_len), cmap, kspc ? 0 : 2);
+ fb_copy_cmap (fb_default_cmap (video_cmap_len), cmap,
+ kspc ? 0 : 2);
+
return 0;
}
-/*
- * Set the Colormap
- */
-
-static int sisfb_set_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)
{
int err;
- if (!fb_display[con].cmap.len) { /* no colormap allocated */
- err = fb_alloc_cmap(&fb_display[con].cmap, video_cmap_len, 0);
+ if (!fb_display[con].cmap.len) {
+ err = fb_alloc_cmap (&fb_display[con].cmap, video_cmap_len, 0);
if (err)
return err;
}
- if (con == currcon) /* current console */
- return fb_set_cmap(cmap, kspc, sis_setcolreg, info);
+ if (con == currcon)
+ return fb_set_cmap (cmap, kspc, sis_setcolreg, info);
else
- fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ fb_copy_cmap (cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
}
-static int sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg, 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)
{
switch (cmd) {
case FBIO_ALLOC:
- if(!capable(CAP_SYS_RAWIO))
+ if (!capable (CAP_SYS_RAWIO))
return -EPERM;
- sis_malloc((struct sis_memreq *) arg);
+ sis_malloc ((struct sis_memreq *) arg);
break;
case FBIO_FREE:
- if(!capable(CAP_SYS_RAWIO))
+ if (!capable (CAP_SYS_RAWIO))
return -EPERM;
- sis_free(*(unsigned long *) arg);
+ sis_free (*(unsigned long *) arg);
break;
case FBIOGET_GLYPH:
- sis_get_glyph((struct GlyInfo *) arg);
+ sis_get_glyph ((SIS_GLYINFO *) arg);
break;
case FBIOGET_HWCINFO:
{
unsigned long *hwc_offset = (unsigned long *) arg;
- if (caps & HW_CURSOR_CAP)
- *hwc_offset = hwcursor_vbase -
+ if (sisfb_caps & HW_CURSOR_CAP)
+ *hwc_offset = sisfb_hwcursor_vbase -
(unsigned long) ivideo.video_vbase;
else
*hwc_offset = 0;
@@ -1638,32 +2118,31 @@
break;
}
case FBIOPUT_MODEINFO:
- {
- struct mode_info *x = (struct mode_info *)arg;
+ {
+ struct mode_info *x = (struct mode_info *) arg;
+
+ ivideo.video_bpp = x->bpp;
+ ivideo.video_width = x->xres;
+ ivideo.video_height = x->yres;
+ ivideo.video_vwidth = x->v_xres;
+ ivideo.video_vheight = x->v_yres;
+ ivideo.org_x = x->org_x;
+ ivideo.org_y = x->org_y;
+ ivideo.refresh_rate = x->vrate;
- /* Set Mode Parameters by XServer */
- ivideo.video_bpp = x->bpp;
- ivideo.video_width = x->xres;
- ivideo.video_height = x->yres;
- ivideo.video_vwidth = x->v_xres;
- ivideo.video_vheight = x->v_yres;
- ivideo.org_x = x->org_x;
- ivideo.org_y = x->org_y;
- ivideo.refresh_rate = x->vrate;
-
break;
}
case FBIOGET_DISPINFO:
- sis_dispinfo((struct ap_data *)arg);
+ sis_dispinfo ((struct ap_data *) arg);
break;
default:
return -EINVAL;
}
return 0;
+
}
-static int sisfb_mmap(struct fb_info *info, struct file *file,
- struct vm_area_struct *vma)
+static int sisfb_mmap (struct fb_info *info, struct file *file, struct vm_area_struct *vma)
{
struct fb_var_screeninfo var;
unsigned long start;
@@ -1674,18 +2153,16 @@
return -EINVAL;
off = vma->vm_pgoff << PAGE_SHIFT;
- /* frame buffer memory */
start = (unsigned long) ivideo.video_base;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
+ len = PAGE_ALIGN ((start & ~PAGE_MASK) + ivideo.video_size);
if (off >= len) {
- /* memory mapped io */
off -= len;
- sisfb_get_var(&var, currcon, info);
+ sisfb_get_var (&var, currcon, info);
if (var.accel_flags)
return -EINVAL;
start = (unsigned long) ivideo.mmio_base;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + MMIO_SIZE);
+ len = PAGE_ALIGN ((start & ~PAGE_MASK) + sisfb_mmio_size);
}
start &= PAGE_MASK;
@@ -1694,617 +2171,599 @@
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
if (boot_cpu_data.x86 > 3)
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+ pgprot_val (vma->vm_page_prot) |= _PAGE_PCD;
#endif
- if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
+ if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
return 0;
+
}
static struct fb_ops sisfb_ops = {
- owner: THIS_MODULE,
- fb_get_fix: sisfb_get_fix,
- fb_get_var: sisfb_get_var,
- fb_set_var: sisfb_set_var,
- fb_get_cmap: sisfb_get_cmap,
- fb_set_cmap: sisfb_set_cmap,
- fb_ioctl: sisfb_ioctl,
- fb_mmap: sisfb_mmap,
+ owner:THIS_MODULE,
+ fb_get_fix:sisfb_get_fix,
+ fb_get_var:sisfb_get_var,
+ fb_set_var:sisfb_set_var,
+ fb_get_cmap:sisfb_get_cmap,
+ fb_set_cmap:sisfb_set_cmap,
+ fb_ioctl:sisfb_ioctl,
+ fb_mmap:sisfb_mmap,
};
-int sisfb_setup(char *options)
-{
- char *this_opt;
-
- fb_info.fontname[0] = '\0';
- ivideo.refresh_rate = 0;
-
- if (!options || !*options)
- return 0;
-
- while (this_opt = strsep(&options, ",")) {
- if (!*this_opt)
- continue;
-
- if (!strcmp(this_opt, "inverse")) {
- inverse = 1;
- fb_invert_cmaps();
- } else if (!strncmp(this_opt, "font:", 5)) {
- strcpy(fb_info.fontname, this_opt + 5);
- } else if (!strncmp(this_opt, "mode:", 5)) {
- search_mode(this_opt + 5);
- } else if (!strncmp(this_opt, "vrate:", 6)) {
- ivideo.refresh_rate =
- simple_strtoul(this_opt + 6, NULL, 0);
- } else if (!strncmp(this_opt, "off", 3)) {
- sisfb_off = 1;
- } else if (!strncmp(this_opt, "crt1off", 7)) {
- crt1off = 1;
- } else
- DPRINTK("invalid parameter %s\n", this_opt);
- }
- return 0;
-}
+/* ------------ Interface to the low level console driver -------------*/
-static int sisfb_update_var(int con, struct fb_info *info)
+static int sisfb_update_var (int con, struct fb_info *info)
{
return 0;
}
-/*
- * Switch Console (called by fbcon.c)
- */
-
-static int sisfb_switch(int con, struct fb_info *info)
+static int sisfb_switch (int con, struct fb_info *info)
{
int cols, rows;
- DPRINTK("sisfb: switch console from [%d] to [%d]\n", currcon, con);
-
- /* update colormap of current console */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info);
+ fb_get_cmap (&fb_display[currcon].cmap, 1, sis_getcolreg, info);
fb_display[con].var.activate = FB_ACTIVATE_NOW;
- /* same mode, needn't change mode actually */
-
- if (!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof(struct fb_var_screeninfo)))
- {
+ if (!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof (struct fb_var_screeninfo))) {
currcon = con;
return 1;
}
currcon = con;
- do_set_var(&fb_display[con].var, 1, info);
+ sisfb_do_set_var (&fb_display[con].var, 1, info);
- sisfb_set_disp(con, &fb_display[con].var);
+ sisfb_set_disp (con, &fb_display[con].var);
- /* Install new colormap */
- do_install_cmap(con, info);
+ sisfb_do_install_cmap (con, info);
- cols = sisbios_mode[mode_idx].cols;
- rows = sisbios_mode[mode_idx].rows;
- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
+ cols = sisbios_mode[sisfb_mode_idx].cols;
+ rows = sisbios_mode[sisfb_mode_idx].rows;
+ vc_resize_con (rows, cols, fb_display[con].conp->vc_num);
- sisfb_update_var(con, info);
+ sisfb_update_var (con, info);
return 1;
}
-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-
-static void sisfb_blank(int blank, struct fb_info *info)
+static void sisfb_blank (int blank, struct fb_info *info)
{
- u8 CRData;
+ u8 reg;
- vgawb(CRTC_ADR, 0x17);
- CRData = vgarb(CRTC_DATA);
+ vgawb (CRTC_ADR, 0x17);
+ reg = vgarb (CRTC_DATA);
- if (blank > 0) /* turn off CRT1 */
- CRData &= 0x7f;
- else /* turn on CRT1 */
- CRData |= 0x80;
+ if (blank > 0)
+ reg &= 0x7f;
+ else
+ reg |= 0x80;
- vgawb(CRTC_ADR, 0x17);
- vgawb(CRTC_DATA, CRData);
+ vgawb (CRTC_ADR, 0x17);
+ vgawb (CRTC_DATA, reg);
}
-int has_VB(void)
+int sisfb_setup (char *options)
{
- u8 uSR38, uSR39, uVBChipID;
-
- vgawb(SEQ_ADR, 0x38);
- uSR38 = vgarb(SEQ_DATA);
- vgawb(SEQ_ADR, 0x39);
- uSR39 = vgarb(SEQ_DATA);
- vgawb(IND_SIS_CRT2_PORT_14, 0x0);
- uVBChipID = vgarb(IND_SIS_CRT2_PORT_14+1);
+ char *this_opt;
- if (
- ( (HwExt.jChipID == SIS_Glamour) && (uSR38 & 0x20) ) /* 300 */
- ||
- ( (HwExt.jChipID >= SIS_Trojan ) && (uSR38 & 0x20) && (!(uSR39 & 0x80)) ) /* 630/540 */
- ||
- ( (HwExt.jChipID == SIS_Trojan ) && ((HwExt.revision_id & 0xf0) == 0x30) && (uVBChipID == 1) ) /* 630s */
- ||
- ( (HwExt.jChipID == SIS_730) && (uVBChipID == 1) ) /* 730 */
- )
- {
- ivideo.hasVB = HASVB_301;
- return TRUE;
- }
- else
- {
- ivideo.hasVB = HASVB_NONE;
- return FALSE;
- }
-}
+ fb_info.fontname[0] = '\0';
+ ivideo.refresh_rate = 0;
-void sis_get301info(void)
-{
- u8 uCRData;
- unsigned long disp_state=0;
+ if (!options || !*options)
+ return 0;
- if (HwExt.jChipID >= SIS_Trojan)
- {
- if (!has_VB())
- {
- vgawb(CRTC_ADR, 0x37);
- uCRData = vgarb(CRTC_DATA);
+ for (this_opt = strtok (options, ","); this_opt;
+ this_opt = strtok (NULL, ",")) {
+ if (!*this_opt)
+ continue;
- switch((uCRData >> 1) & 0x07)
- {
- case 2:
- ivideo.hasVB = HASVB_LVDS;
- break;
- case 4:
- ivideo.hasVB = HASVB_LVDS_CHRONTEL;
- break;
- case 3:
- ivideo.hasVB = HASVB_TRUMPION;
- break;
- default:
- break;
- }
+ if (!strcmp (this_opt, "inverse")) {
+ sisfb_inverse = 1;
+ fb_invert_cmaps ();
+ } else if (!strncmp (this_opt, "font:", 5)) {
+ strcpy (fb_info.fontname, this_opt + 5);
+ } else if (!strncmp (this_opt, "mode:", 5)) {
+ sisfb_search_mode (this_opt + 5);
+ } else if (!strncmp (this_opt, "vrate:", 6)) {
+ ivideo.refresh_rate =
+ simple_strtoul (this_opt + 6, NULL, 0);
+ } else if (!strncmp (this_opt, "off", 3)) {
+ sisfb_off = 1;
+ } else if (!strncmp (this_opt, "crt1off", 7)) {
+ sisfb_crt1off = 1;
+ } else if (!strncmp (this_opt, "filter:", 7)) {
+ filter = (int) simple_strtoul (this_opt + 7, NULL, 0);
+ }
+ /*karl */
+ else if (!strncmp (this_opt, "tvmode:", 7)) {
+ if (!strncmp (this_opt + 7, "pal", 3))
+ sisfb_tvmode = 1;
+ if (!strncmp (this_opt + 7, "ntsc", 4))
+ sisfb_tvmode = 2;
}
- }
- else
- {
- has_VB();
- }
+ /*karl:10/01/2001 */
+ else if (!strncmp (this_opt, "mem:", 4)) {
- vgawb(CRTC_ADR, 0x32);
- uCRData = vgarb(CRTC_DATA);
-
- switch(uDispType)
- {
- case MASK_DISPTYPE_CRT2:
- disp_state = DISPTYPE_CRT2;
- break;
- case MASK_DISPTYPE_LCD:
- disp_state = DISPTYPE_LCD;
- break;
- case MASK_DISPTYPE_TV:
- disp_state = DISPTYPE_TV;
- break;
- }
+ sisfb_mem = simple_strtoul (this_opt + 4, NULL, 0);
- if(disp_state & 0x7)
- {
- if(crt1off)
- disp_state |= DISPMODE_SINGLE;
- else
- disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+ } else
+ DPRINTK ("invalid parameter %s\n", this_opt);
}
- else
- disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
-
- ivideo.disp_state = disp_state;
+ return 0;
}
-
-int __init sisfb_init(void)
+int __init sisfb_init (void)
{
struct pci_dev *pdev = NULL;
struct board *b;
int pdev_valid = 0;
- unsigned char jTemp;
- u8 uSRData, uCRData;
+ //unsigned long rom_vbase;
+ u32 reg32;
+ u16 reg16;
+ u8 reg;
+ int nRes;
- outb(0x77, 0x80);
+ outb (0x77, 0x80);
if (sisfb_off)
return -ENXIO;
- pci_for_each_dev(pdev) {
- for (b = dev_list; b->vendor; b++)
- {
+ pci_for_each_dev (pdev)
+ {
+ for (b = sisdev_list; b->vendor; b++) {
if ((b->vendor == pdev->vendor)
- && (b->device == pdev->device))
- {
+ && (b->device == pdev->device)) {
pdev_valid = 1;
- strcpy(fb_info.modename, b->name);
+ strcpy (fb_info.modename, b->name);
ivideo.chip_id = pdev->device;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &HwExt.revision_id);
+ pci_read_config_byte (pdev, PCI_REVISION_ID,
+ &ivideo.revision_id);
+ pci_read_config_word (pdev, PCI_COMMAND, ®16);
+ // Eden Chen
+ //sishw_ext.uRevisionID = ivideo.revision_id;
+ sishw_ext.jChipRevision = ivideo.revision_id;
+ // ~Eden Chen
+ sisvga_enabled = reg16 & 0x1;
break;
}
}
-
+
if (pdev_valid)
break;
}
-
+
if (!pdev_valid)
return -1;
-
- switch(ivideo.chip_id)
- {
+
+ // Eden Chen
+ switch (ivideo.chip_id) {
case PCI_DEVICE_ID_SI_300:
- HwExt.jChipID = SIS_Glamour;
+ ivideo.chip = SIS_300;
+ sisvga_engine = SIS_300_VGA;
break;
case PCI_DEVICE_ID_SI_630_VGA:
- HwExt.jChipID = SIS_Trojan;
+ {
+ sisfb_set_reg4 (0xCF8, 0x80000000);
+ reg32 = sisfb_get_reg3 (0xCFC);
+ if (reg32 == 0x07301039) {
+ ivideo.chip = SIS_730;
+ strcpy (fb_info.modename, "SIS 730");
+ } else
+ ivideo.chip = SIS_630;
+
+ sisvga_engine = SIS_300_VGA;
break;
+ }
case PCI_DEVICE_ID_SI_540_VGA:
- HwExt.jChipID = SIS_Spartan;
+ ivideo.chip = SIS_540;
+ sisvga_engine = SIS_300_VGA;
break;
- case PCI_DEVICE_ID_SI_730_VGA:
- HwExt.jChipID = SIS_730;
+ case PCI_DEVICE_ID_SI_315H:
+ ivideo.chip = SIS_315H;
+ sisvga_engine = SIS_315_VGA;
+ break;
+ case PCI_DEVICE_ID_SI_315:
+ ivideo.chip = SIS_315;
+ sisvga_engine = SIS_315_VGA;
+ break;
+ case PCI_DEVICE_ID_SI_315PRO:
+ ivideo.chip = SIS_315PRO;
+ sisvga_engine = SIS_315_VGA;
+ break;
+ case PCI_DEVICE_ID_SI_550_VGA:
+ ivideo.chip = SIS_550;
+ sisvga_engine = SIS_315_VGA;
break;
}
- ivideo.video_base = pci_resource_start(pdev, 0);
- ivideo.mmio_base = pci_resource_start(pdev, 1);
- ivideo.vga_base = pci_resource_start(pdev, 2) + 0x30;
-
- HwExt.IOAddress = (unsigned short)ivideo.vga_base;
- rom_base = 0x000C0000;
+ // Eden Chen
+ //sishw_ext.jChipID = ivideo.chip;
+ sishw_ext.jChipType = ivideo.chip;
+ // for Debug
+ if ((sishw_ext.jChipType == SIS_315PRO)
+ || (sishw_ext.jChipType == SIS_315))
+ sishw_ext.jChipType = SIS_315H;
+ // ~Eden Chen
+
+ DPRINTK ("%s is used as %s device(VGA Engine %d).\n",
+ fb_info.modename, sisvga_enabled ? "primary" : "secondary",
+ sisvga_engine);
+
+ ivideo.video_base = pci_resource_start (pdev, 0);
+ ivideo.mmio_base = pci_resource_start (pdev, 1);
+ // Eden Chen
+ //sishw_ext.IOAddress = (unsigned short) ivideo.vga_base
+ // = pci_resource_start(pdev, 2) + 0x30;
+ sishw_ext.ulIOAddress = (unsigned short) ivideo.vga_base = pci_resource_start (pdev, 2) + 0x30;
+ // ~Eden Chen
+
+ sisfb_mmio_size = pci_resource_len (pdev, 1);
+
+ if (!sisvga_enabled)
+ if (pci_enable_device (pdev))
+ return -EIO;
+
+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
- MMIO_SIZE = pci_resource_len(pdev, 1);
+#ifdef LINUXBIOS
+#ifdef CONFIG_FB_SIS_300
+ if (sisvga_engine == SIS_300_VGA)
+ {
+ vgawb (SEQ_ADR, 0x28);
+ vgawb (SEQ_DATA, 0x37);
-#ifdef NOBIOS
- if (pci_enable_device(pdev))
- return -EIO;
- /* Image file instead of VGA-bios */
- HwExt.VirtualRomBase = rom_vbase = (unsigned long) RomData;
-#else
-#ifdef CONFIG_FB_SIS_LINUXBIOS
- if (pci_enable_device(pdev))
- return -EIO;
- HwExt.VirtualRomBase = rom_vbase = 0;
-#else
- request_region(rom_base, 32, "sisfb");
- HwExt.VirtualRomBase = rom_vbase
- = (unsigned long) ioremap(rom_base, MAX_ROM_SCAN);
-#endif
-#endif
- /* set passwd */
- vgawb(SEQ_ADR, IND_SIS_PASSWORD);
- vgawb(SEQ_DATA, SIS_PASSWORD);
-
- /* Enable MMIO & PCI linear address */
- vgawb(SEQ_ADR, IND_SIS_PCI_ADDRESS_SET);
- jTemp = vgarb(SEQ_DATA);
- jTemp |= SIS_PCI_ADDR_ENABLE;
- jTemp |= SIS_MEM_MAP_IO_ENABLE;
- vgawb(SEQ_DATA, jTemp);
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
- pdev_valid = 0;
- pci_for_each_dev(pdev) {
- u8 uPCIData=0;
+ vgawb (SEQ_ADR, 0x29);
+ vgawb (SEQ_DATA, 0x61);
- if ((pdev->vendor == PCI_VENDOR_ID_SI) && (pdev->device==0x630))
- {
- pci_read_config_byte(pdev, 0x63, &uPCIData);
- uPCIData = (uPCIData & 0x70) >> 4;
- ivideo.video_size = (unsigned int)(1 << (uPCIData+21));
- pdev_valid = 1;
- break;
- }
+ vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
+ reg = vgarb (SEQ_DATA);
+ reg |= SIS_SCRATCH_REG_1A_MASK;
+ vgawb (SEQ_DATA, reg);
}
-
- if (!pdev_valid)
- return -1;
-#else
- vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE);
- ivideo.video_size = ((unsigned int) ((vgarb(SEQ_DATA) & 0x3f) + 1) << 20);
#endif
+#ifdef CONFIG_FB_SIS_315
+ if (ivideo.chip == SIS_550) {
+ vgawb (SEQ_ADR, 0x28);
+ vgawb (SEQ_DATA, 0x5A);
+
+ vgawb (SEQ_ADR, 0x29);
+ vgawb (SEQ_DATA, 0x64);
+ vgawb (CRTC_ADR, 0x3A);
+ vgawb (CRTC_DATA, 0x00);
+ }
+#endif
+#endif
- /* get CRT2 connection state */
- vgawb(SEQ_ADR, 0x17);
- uSRData = vgarb(SEQ_DATA);
- vgawb(CRTC_ADR, 0x32);
- uCRData = vgarb(CRTC_DATA);
-
- ivideo.TV_plug = ivideo.TV_type = 0;
- if((uSRData&0x0F) && (HwExt.jChipID>=SIS_Trojan))
- {
- /* CRT1 connect detection */
- if((uSRData & 0x01) && !crt1off)
- crt1off = 0;
- else
- {
- if(uSRData&0x0E) /* DISP2 connected */
- crt1off = 1;
- else
- crt1off = 0;
- }
-
- /* detection priority : CRT2 > LCD > TV */
- if(uSRData & 0x08 )
- uDispType = MASK_DISPTYPE_CRT2;
- else if(uSRData & 0x02)
- uDispType = MASK_DISPTYPE_LCD;
- else if(uSRData & 0x04)
- {
- if(uSRData & 0x80)
- {
- ivideo.TV_type = TVMODE_HIVISION;
- ivideo.TV_plug = TVPLUG_SVIDEO;
- }
- else if(uSRData & 0x20)
- ivideo.TV_plug = TVPLUG_SVIDEO;
- else if(uSRData & 0x10)
- ivideo.TV_plug = TVPLUG_COMPOSITE;
- else if(uSRData & 0x40)
- ivideo.TV_plug = TVPLUG_SCART;
-
- if(ivideo.TV_type == 0)
- {
- u8 uSR16;
- vgawb(SEQ_ADR, 0x16);
- uSR16 = vgarb(SEQ_DATA);
- if(uSR16 & 0x20)
- ivideo.TV_type = TVMODE_PAL;
- else
- ivideo.TV_type = TVMODE_NTSC;
- }
-
- uDispType = MASK_DISPTYPE_TV;
+ if (sisvga_engine == SIS_315_VGA) {
+ switch (ivideo.chip) {
+ case SIS_315H:
+ case SIS_315:
+ sishw_ext.bIntegratedMMEnabled = TRUE;
+ break;
+ case SIS_550:
+ // Eden Chen
+ //vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
+ //reg = vgarb(SEQ_DATA);
+ //if (reg & SIS_SCRATCH_REG_1A_MASK)
+ // sishw_ext.bIntegratedMMEnabled = TRUE;
+ //else
+ // sishw_ext.bIntegratedMMEnabled = FALSE;
+ //for Debug
+ sishw_ext.bIntegratedMMEnabled = TRUE;
+ // ~Eden Chen
+ break;
+ default:
+ break;
}
- }
- else
- {
- if((uCRData & 0x20) && !crt1off)
- crt1off = 0;
- else
- {
- if(uCRData&0x5F) /* DISP2 connected */
- crt1off = 1;
+ } else if (sisvga_engine == SIS_300_VGA) {
+ if (ivideo.chip == SIS_300) {
+ sishw_ext.bIntegratedMMEnabled = TRUE;
+ } else {
+ vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
+ reg = vgarb (SEQ_DATA);
+ if (reg & SIS_SCRATCH_REG_1A_MASK)
+ sishw_ext.bIntegratedMMEnabled = TRUE;
else
- crt1off = 0;
+ sishw_ext.bIntegratedMMEnabled = FALSE;
}
+ }
+ // Eden Chen
+ sishw_ext.pDevice = NULL;
+ sishw_ext.pjVirtualRomBase = NULL;
+ sishw_ext.pjCustomizedROMImage = NULL;
+ sishw_ext.bSkipDramSizing = 0;
+ sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;
+ sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
+ strcpy (sishw_ext.szVBIOSVer, "0.84");
+
+ sishw_ext.pSR = vmalloc (sizeof (SIS_DSReg) * SR_BUFFER_SIZE);
+ if (sishw_ext.pSR == NULL)
+ printk (KERN_DEBUG "Allocated SRReg space fail.\n");
+ sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
+
+ sishw_ext.pCR = vmalloc (sizeof (SIS_DSReg) * CR_BUFFER_SIZE);
+ if (sishw_ext.pCR == NULL)
+ printk (KERN_DEBUG "Allocated CRReg space fail.\n");
+ sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;
+ // ~Eden Chen
+
+ #ifdef CONFIG_FB_SIS_300
+ if (sisvga_engine == SIS_300_VGA) {
+ if (!sisvga_enabled) {
+ // Eden Chen
+ sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x2000000);
+ //SiSInit300(&sishw_ext);
+ SiSInit (&sishw_ext);
+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
+ // ~Eden Chen
+ }
+#ifdef LINUXBIOS
+ else {
+ // Eden Chen
+ sishw_ext.pjVideoMemoryAddress
+ = ioremap (ivideo.video_base, 0x2000000);
+ //SiSInit300(&sishw_ext);
+ SiSInit (&sishw_ext);
+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
+ // ~Eden Chen
+ }
+ vgawb (SEQ_ADR, 0x7);
+ reg = vgarb (SEQ_DATA);
+ reg |= 0x10;
+ vgawb (SEQ_DATA, reg);
+#endif
+ sisfb_get_dram_size_300 ();
+ }
+#endif
- if(uCRData & 0x10)
- uDispType = MASK_DISPTYPE_CRT2;
- else if(uCRData & 0x08)
- uDispType = MASK_DISPTYPE_LCD;
- else if(uCRData & 0x47)
- {
- uDispType = MASK_DISPTYPE_TV;
-
- if(uCRData & 0x40)
- {
- ivideo.TV_type = TVMODE_HIVISION;
- ivideo.TV_plug = TVPLUG_SVIDEO;
- }
- else if(uCRData & 0x02)
- ivideo.TV_plug = TVPLUG_SVIDEO;
- else if(uCRData & 0x01)
- ivideo.TV_plug = TVPLUG_COMPOSITE;
- else if(uCRData & 0x04)
- ivideo.TV_plug = TVPLUG_SCART;
+ #ifdef CONFIG_FB_SIS_315
+ if (sisvga_engine == SIS_315_VGA) {
+ if (!sisvga_enabled) {
+ /* Mapping Max FB Size for 315 Init */
+ // Eden Chen
+ //sishw_ext.VirtualVideoMemoryAddress
+ sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);
+ //SiSInit310(&sishw_ext);
+ SiSInit (&sishw_ext);
+
+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
+
+ sishw_ext.bSkipDramSizing = TRUE;
+ vgawb (SEQ_ADR, 0x13);
+ sishw_ext.pSR[0].jIdx = 0x13;
+ sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);
+ vgawb (SEQ_ADR, 0x14);
+ sishw_ext.pSR[1].jIdx = 0x14;
+ sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);
+ sishw_ext.pSR[2].jIdx = 0xFF;
+ sishw_ext.pSR[2].jVal = 0xFF;
+ // Eden Chen
+ }
+#ifdef LINUXBIOS
+ else {
+ sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);
+ SiSInit (&sishw_ext);
+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
+
+ sishw_ext.bSkipDramSizing = TRUE;
+ vgawb (SEQ_ADR, 0x13);
+ sishw_ext.pSR[0].jIdx = 0x13;
+ sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);
+ vgawb (SEQ_ADR, 0x14);
+ sishw_ext.pSR[1].jIdx = 0x14;
+ sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);
+ sishw_ext.pSR[2].jIdx = 0xFF;
+ sishw_ext.pSR[2].jVal = 0xFF;
+ }
+#endif
+ sisfb_get_dram_size_315 ();
+ }
+#endif
+ //Eden Chen
+ vgawb (SEQ_ADR, IND_SIS_PCI_ADDRESS_SET);
+ reg = vgarb (SEQ_DATA);
+ reg |= SIS_PCI_ADDR_ENABLE;
+ reg |= SIS_MEM_MAP_IO_ENABLE;
+ vgawb (SEQ_DATA, reg);
+
+ vgawb (SEQ_ADR, IND_SIS_MODULE_ENABLE);
+ reg = vgarb (SEQ_DATA);
+ reg |= SIS_ENABLE_2D;
+ vgawb (SEQ_DATA, reg);
+ //~Eden Chen
+
+ // Eden Chen
+ sishw_ext.ulVideoMemorySize = ivideo.video_size;
+ // ~Eden Chen
+ if (!request_mem_region (ivideo.video_base, ivideo.video_size, "sisfb FB")) {
+ printk (KERN_ERR "sisfb: cannot reserve frame buffer memory\n");
+ return -ENODEV;
+ }
- if(ivideo.TV_type == 0)
- {
- u8 uTemp;
- uTemp = *((u8 *)(HwExt.VirtualRomBase+0x52));
- if(uTemp&0x40)
- {
- uTemp=*((u8 *)(HwExt.VirtualRomBase+0x53));
- }
- else
- {
- vgawb(SEQ_ADR, 0x38);
- uTemp = vgarb(SEQ_DATA);
- }
- if(uTemp & 0x01)
- ivideo.TV_type = TVMODE_PAL;
- else
- ivideo.TV_type = TVMODE_NTSC;
- }
+ if (!request_mem_region (ivideo.mmio_base, sisfb_mmio_size, "sisfb MMIO")) {
+ printk (KERN_ERR "sisfb: cannot reserve MMIO region\n");
+ release_mem_region (ivideo.video_base, ivideo.video_size);
+ return -ENODEV;
+ }
+ // Eden Chen
+ //sishw_ext.VirtualVideoMemoryAddress = ivideo.video_vbase
+ sishw_ext.pjVideoMemoryAddress = ivideo.video_vbase = ioremap (ivideo.video_base, ivideo.video_size);
+ // Eden Chen
+ ivideo.mmio_vbase = ioremap (ivideo.mmio_base, sisfb_mmio_size);
+
+ printk (KERN_INFO
+ "sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
+ ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024);
+
+ printk (KERN_INFO
+ "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
+ ivideo.mmio_base, ivideo.mmio_vbase, sisfb_mmio_size / 1024);
+
+ #ifdef CONFIG_FB_SIS_300
+ if (sisvga_engine == SIS_300_VGA) {
+ sisfb_get_VB_type_300 ();
+ if (ivideo.hasVB != HASVB_NONE) {
+ sisfb_detect_VB_connect_300 ();
}
}
+#endif
- if(uDispType == MASK_DISPTYPE_LCD) // LCD conntected
- {
- // TODO: set LCDType by EDID
- HwExt.usLCDType = LCD1024;
+#ifdef CONFIG_FB_SIS_315
+ if (sisvga_engine == SIS_315_VGA) {
+ sisfb_get_VB_type_315 ();
+ if (ivideo.hasVB != HASVB_NONE) {
+ sisfb_detect_VB_connect_315 ();
+ }
}
+#endif
- if (HwExt.jChipID >= SIS_Trojan)
- {
- vgawb(SEQ_ADR, 0x1A);
- uSRData = vgarb(SEQ_DATA);
- if (uSRData & 0x10)
- HwExt.bIntegratedMMEnabled = TRUE;
+ // Eden Chen
+sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
+sishw_ext.usExternalChip = 0;
+
+ switch (ivideo.hasVB) {
+ case HASVB_301:
+ /*karl */
+ vgawb (VB_PART4_ADR, 0x01);
+ reg = vgarb (VB_PART4_DATA);
+ if ((reg != 0xB1) && (reg != 0xB0))
+ sishw_ext.ujVBChipID = VB_CHIP_301;
else
- HwExt.bIntegratedMMEnabled = FALSE;
+ sishw_ext.ujVBChipID = VB_CHIP_301B;
+ break;
+ case HASVB_302:
+ sishw_ext.ujVBChipID = VB_CHIP_302;
+ break;
+ case HASVB_303:
+ sishw_ext.ujVBChipID = VB_CHIP_303;
+ break;
+ case HASVB_LVDS:
+ sishw_ext.usExternalChip = 0x1;
+ break;
+ case HASVB_TRUMPION:
+ sishw_ext.usExternalChip = 0x2;
+ break;
+ case HASVB_CHRONTEL:
+ sishw_ext.usExternalChip = 0x4;
+ break;
+ case HASVB_LVDS_CHRONTEL:
+ sishw_ext.usExternalChip = 0x5;
+ break;
+ default:
+ break;
}
- if(mode_idx >= 0) /* mode found */
- {
- /* Filtering mode for VB */
- switch(uDispType & MASK_DISPTYPE_DISP2)
- {
- case MASK_DISPTYPE_LCD:
- switch(HwExt.usLCDType)
- {
- case LCD1024:
- if(sisbios_mode[mode_idx].xres > 1024)
- mode_idx = -1;
- break;
- case LCD1280:
- if(sisbios_mode[mode_idx].xres > 1280)
- mode_idx = -1;
- break;
- case LCD2048:
- if(sisbios_mode[mode_idx].xres > 2048)
- mode_idx = -1;
- break;
- case LCD1920:
- if(sisbios_mode[mode_idx].xres > 1920)
- mode_idx = -1;
- break;
- case LCD1600:
- if(sisbios_mode[mode_idx].xres > 1600)
- mode_idx = -1;
- break;
- case LCD800:
- if(sisbios_mode[mode_idx].xres > 800)
- mode_idx = -1;
- break;
- case LCD640:
- if(sisbios_mode[mode_idx].xres > 640)
- mode_idx = -1;
- break;
- default:
- mode_idx = -1;
- }
+ // ~Eden Chen
- if(sisbios_mode[mode_idx].xres == 720) /* only for TV */
- mode_idx = -1;
+ if (ivideo.disp_state & DISPTYPE_DISP2) {
+ if (sisfb_crt1off)
+ ivideo.disp_state |= DISPMODE_SINGLE;
+ else
+ ivideo.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+ } else
+ ivideo.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
+
+ if (ivideo.disp_state & DISPTYPE_LCD) {
+ vgawb (CRTC_ADR, IND_SIS_LCD_PANEL);
+ reg = vgarb (CRTC_DATA);
+ // Eden Chen
+ switch (reg) {
+ case SIS_LCD_PANEL_800X600:
+ sishw_ext.ulCRT2LCDType = LCD_800x600;
break;
- case MASK_DISPTYPE_TV:
- switch(sisbios_mode[mode_idx].xres)
- {
- case 800:
- case 640:
- break;
- case 720:
- if(ivideo.TV_type == TVMODE_NTSC)
- {
- if(sisbios_mode[mode_idx].yres != 480)
- mode_idx = -1;
- }
- else if(ivideo.TV_type == TVMODE_PAL)
- {
- if(sisbios_mode[mode_idx].yres != 576)
- mode_idx = -1;
- }
- break;
- default:
- /* illegal mode */
- mode_idx = -1;
- }
+ case SIS_LCD_PANEL_1024X768:
+ sishw_ext.ulCRT2LCDType = LCD_1024x768;
+ break;
+ case SIS_LCD_PANEL_1280X1024:
+ sishw_ext.ulCRT2LCDType = LCD_1280x1024;
+ break;
+ case SIS_LCD_PANEL_640X480:
+ sishw_ext.ulCRT2LCDType = LCD_640x480;
+ break;
+ case SIS_LCD_PANEL_1280X960:
+ sishw_ext.ulCRT2LCDType = LCD_1280x960;
+ break;
+ default:
+ sishw_ext.ulCRT2LCDType = LCD_1024x768;
break;
}
- }
+ // ~Eden Chen
+ }
+
+ if (sisfb_mode_idx >= 0)
+ sisfb_validate_mode ();
- if (mode_idx < 0)
- {
- switch(uDispType & MASK_DISPTYPE_DISP2)
- {
- case MASK_DISPTYPE_LCD:
- mode_idx = DEFAULT_LCDMODE;
+ if (sisfb_mode_idx < 0) {
+ switch (ivideo.disp_state & DISPTYPE_DISP2) {
+ case DISPTYPE_LCD:
+ sisfb_mode_idx = DEFAULT_LCDMODE;
break;
- case MASK_DISPTYPE_TV:
- mode_idx = DEFAULT_TVMODE;
+ case DISPTYPE_TV:
+ sisfb_mode_idx = DEFAULT_TVMODE;
break;
default:
- mode_idx = DEFAULT_MODE;
+ sisfb_mode_idx = DEFAULT_MODE;
+ break;
}
}
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
- mode_idx = DEFAULT_MODE;
- rate_idx = sisbios_mode[mode_idx].rate_idx;
- /* set to default refresh rate 60MHz */
- ivideo.refresh_rate = 60;
-#endif
-
- mode_no = sisbios_mode[mode_idx].mode_no;
-
+
+ sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+
if (ivideo.refresh_rate != 0)
- search_refresh_rate(ivideo.refresh_rate);
+ sisfb_search_refresh_rate (ivideo.refresh_rate);
- if (rate_idx == 0) {
- rate_idx = sisbios_mode[mode_idx].rate_idx;
- /* set to default refresh rate 60MHz */
+ if (sisfb_rate_idx == 0) {
+ sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
ivideo.refresh_rate = 60;
}
- ivideo.video_bpp = sisbios_mode[mode_idx].bpp;
- ivideo.video_vwidth = ivideo.video_width = sisbios_mode[mode_idx].xres;
- ivideo.video_vheight = ivideo.video_height = sisbios_mode[mode_idx].yres;
+ ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
+ ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
+ ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
ivideo.org_x = ivideo.org_y = 0;
video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
- printk(KERN_DEBUG "FB base: 0x%lx, size: 0x%dK\n",
- ivideo.video_base, (unsigned int)ivideo.video_size/1024);
- printk(KERN_DEBUG "MMIO base: 0x%lx, size: 0x%dK\n",
- ivideo.mmio_base, (unsigned int)MMIO_SIZE/1024);
-
-
- if (!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB"))
- {
- printk(KERN_ERR "sisfb: cannot reserve frame buffer memory\n");
- return -ENODEV;
- }
-
- if (!request_mem_region(ivideo.mmio_base, MMIO_SIZE, "sisfb MMIO"))
- {
- printk(KERN_ERR "sisfb: cannot reserve MMIO region\n");
- release_mem_region(ivideo.video_base, ivideo.video_size);
- return -ENODEV;
- }
-
- HwExt.VirtualVideoMemoryAddress = ivideo.video_vbase
- = ioremap(ivideo.video_base, ivideo.video_size);
- ivideo.mmio_vbase = ioremap(ivideo.mmio_base, MMIO_SIZE);
-
-#ifdef NOBIOS
- SiSInit300(&HwExt);
-#else
-#ifdef CONFIG_FB_SIS_LINUXBIOS
- SiSInit300(&HwExt);
-#endif
-#endif
- printk(KERN_INFO
- "sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
- ivideo.video_base, ivideo.video_vbase,
- ivideo.video_size / 1024);
- printk(KERN_INFO "sisfb: mode is %dx%dx%d, linelength=%d\n",
- ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
- video_linelength);
-
- /* enable 2D engine */
- vgawb(SEQ_ADR, IND_SIS_MODULE_ENABLE);
- jTemp = vgarb(SEQ_DATA);
- jTemp |= SIS_2D_ENABLE;
- vgawb(SEQ_DATA, jTemp);
+ printk (KERN_INFO "sisfb: mode is %dx%dx%d, linelength=%d\n",
+ ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
+ video_linelength);
+
+ // Eden Chen
+ // Check interface correction For Debug
+ DPRINTK ("VM Adr=0x%p\n", sishw_ext.pjVideoMemoryAddress);
+ DPRINTK ("VM Size=%ldK\n", sishw_ext.ulVideoMemorySize / 1024);
+ DPRINTK ("IO Adr=0x%lx\n", sishw_ext.ulIOAddress);
+ DPRINTK ("Chip=%d\n", sishw_ext.jChipType);
+ DPRINTK ("ChipRevision=%d\n", sishw_ext.jChipRevision);
+ DPRINTK ("VBChip=%d\n", sishw_ext.ujVBChipID);
+ DPRINTK ("ExtVB=%d\n", sishw_ext.usExternalChip);
+ DPRINTK ("LCD=%ld\n", sishw_ext.ulCRT2LCDType);
+ DPRINTK ("bIntegratedMMEnabled=%d\n", sishw_ext.bIntegratedMMEnabled);
+ // ~Eden Chen
- pre_setmode();
+ sisfb_pre_setmode ();
- if (SiSSetMode(&HwExt, mode_no)) {
- DPRINTK("sisfb: set mode[0x%x]: failed\n", mode_no);
+ if (SiSSetMode (&sishw_ext, sisfb_mode_no) == 0) {
+ DPRINTK ("set mode[0x%x]: failed\n", sisfb_mode_no);
return -1;
}
+ vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+ vgawb (SEQ_DATA, SIS_PASSWORD);
+ // Eden Chen
- post_setmode();
-
- /* Get VB functions */
- sis_get301info();
+ sisfb_post_setmode ();
- crtc_to_var(&default_var);
+ sisfb_crtc_to_var (&default_var);
fb_info.changevar = NULL;
fb_info.node = -1;
@@ -2315,20 +2774,22 @@
fb_info.blank = &sisfb_blank;
fb_info.flags = FBINFO_FLAG_DEFAULT;
- sisfb_set_disp(-1, &default_var);
+ sisfb_set_disp (-1, &default_var);
- if (sisfb_heap_init()) {
- DPRINTK("sisfb: Failed to enable offscreen heap\n");
+ if (sisfb_heap_init ()) {
+ DPRINTK ("sisfb: Failed to enable offscreen heap\n");
}
+
+ /*H.C. */
+ nRes = mtrr_add ((unsigned int) ivideo.video_base, (unsigned int) ivideo.video_size, MTRR_TYPE_WRCOMB, 1);
+ vc_resize_con (1, 1, 0);
- /* to avoid the inversed bgcolor bug of the initial state */
- vc_resize_con(1, 1, 0);
-
- if (register_framebuffer(&fb_info) < 0)
+ if (register_framebuffer (&fb_info) < 0)
return -EINVAL;
- printk(KERN_INFO "fb%d: %s frame buffer device\n",
- GET_FB_IDX(fb_info.node), fb_info.modename);
+ printk (KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
+ GET_FB_IDX (fb_info.node), fb_info.modename, VER_MAJOR, VER_MINOR,
+ VER_LEVEL);
return 0;
}
@@ -2339,35 +2800,36 @@
static unsigned int rate = 0;
static unsigned int crt1 = 1;
-MODULE_PARM(mode, "s");
-MODULE_PARM(rate, "i");
-MODULE_PARM(crt1, "i"); /* default: CRT1 enable */
+MODULE_PARM (mode, "s");
+MODULE_PARM (rate, "i");
+MODULE_PARM (crt1, "i");
+MODULE_PARM (filter, "i");
-int init_module(void)
+int init_module (void)
{
if (mode)
- search_mode(mode);
+ sisfb_search_mode (mode);
ivideo.refresh_rate = rate;
- if(crt1 == 0)
- crt1off = 1;
+ if (crt1 == 0)
+ sisfb_crt1off = 1;
else
- crt1off = 0;
-
- sisfb_init();
+ sisfb_crt1off = 0;
+
+ sisfb_init ();
return 0;
}
-void cleanup_module(void)
+void cleanup_module (void)
{
- unregister_framebuffer(&fb_info);
+ unregister_framebuffer (&fb_info);
}
-#endif /* MODULE */
-
+#endif
-EXPORT_SYMBOL(sis_malloc);
-EXPORT_SYMBOL(sis_free);
+EXPORT_SYMBOL (sis_malloc);
+EXPORT_SYMBOL (sis_free);
+EXPORT_SYMBOL (sis_dispinfo);
-EXPORT_SYMBOL(ivideo);
+EXPORT_SYMBOL (ivideo);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)