All of lore.kernel.org
 help / color / mirror / Atom feed
* - fbdev-driver-for-s3-trio-virge-update.patch removed from -mm tree
@ 2007-02-12  7:25 akpm
  0 siblings, 0 replies; only message in thread
From: akpm @ 2007-02-12  7:25 UTC (permalink / raw)
  To: santiago, jsimmons, mm-commits


The patch titled
     fbdev driver for S3 Trio/Virge update
has been removed from the -mm tree.  Its filename was
     fbdev-driver-for-s3-trio-virge-update.patch

This patch was dropped because it was folded into fbdev-driver-for-s3-trio-virge.patch

------------------------------------------------------
Subject: fbdev driver for S3 Trio/Virge update
From: Ondrej Zajicek <santiago@crfreenet.org>

 * proper Virge VX support
 * suspend/resume support
 * S3 fasttext support
 * several minor bugs corrected

Signed-off-by: Ondrej Zajicek <santiago@crfreenet.org>
Cc: James Simmons <jsimmons@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 Documentation/fb/s3fb.txt |   15 -
 drivers/video/Kconfig     |    2 
 drivers/video/s3fb.c      |  422 +++++++++++++-----------------------
 drivers/video/svgalib.c   |  238 +++++++++++++++++---
 include/linux/fb.h        |    7 
 include/linux/svga.h      |   29 +-
 6 files changed, 398 insertions(+), 315 deletions(-)

diff -puN Documentation/fb/s3fb.txt~fbdev-driver-for-s3-trio-virge-update Documentation/fb/s3fb.txt
--- a/Documentation/fb/s3fb.txt~fbdev-driver-for-s3-trio-virge-update
+++ a/Documentation/fb/s3fb.txt
@@ -16,7 +16,8 @@ Supported Hardware
 	- only BIOS initialized VGA devices supported
 	- probably not working on big endian
 
-I tested s3fb on Trio64 (plain, V+ and V2/DX) and Virge DX, all on i386.
+I tested s3fb on Trio64 (plain, V+ and V2/DX) and Virge (plain, VX, DX),
+all on i386.
 
 
 Supported Features
@@ -25,11 +26,13 @@ Supported Features
 	*  4 bpp pseudocolor modes (with 18bit palette, two variants)
 	*  8 bpp pseudocolor mode (with 18bit palette)
 	* 16 bpp truecolor modes (RGB 555 and RGB 565)
-	* 32 bpp truecolor mode (RGB 888)
+	* 24 bpp truecolor mode (RGB 888) on (only on Virge VX)
+	* 32 bpp truecolor mode (RGB 888) on (not on Virge VX)
 	* text mode (activated by bpp = 0)
 	* interlaced mode variant (not available in text mode)
 	* doublescan mode variant (not available in text mode)
 	* panning in both directions
+	* suspend/resume support
 	* DPMS support
 
 Text mode is supported even in higher resolutions, but there is limitation
@@ -42,17 +45,19 @@ packed pixels, high nibble first. Second
 with interleaved planes (1 byte interleave), MSB first. Both modes support
 8bit wide fonts only (driver limitation).
 
+Suspend/resume works on systems that initialize video card during resume and
+if device is active (for example used by fbcon).
+
 
 Missing Features
 ================
 (alias TODO list)
 
 	* secondary (not initialized by BIOS) device support
-	* suspend/resume support
    	* big endian support
 	* Zorro bus support
 	* MMIO support
-	* 24 bpp mode support
+	* 24 bpp mode support on more cards
 	* support for fontwidths != 8 in 4 bpp modes
 	* support for fontheight != 16 in text mode
 	* composite and external sync (is anyone able to test this?)
@@ -68,8 +73,6 @@ Known bugs
 ==========
 
 	* cursor disable in text mode doesn't work
-	* there is some small (but larger than usual) difference between
-	  requested and used timings
 
 --
 Ondrej Zajicek <santiago@crfreenet.org>
diff -puN drivers/video/Kconfig~fbdev-driver-for-s3-trio-virge-update drivers/video/Kconfig
--- a/drivers/video/Kconfig~fbdev-driver-for-s3-trio-virge-update
+++ a/drivers/video/Kconfig
@@ -1206,7 +1206,6 @@ config FB_SAVAGE_ACCEL
           the resulting framebuffer console has bothersome glitches, then
           choose N here.
 
-
 config FB_SIS
 	tristate "SiS/XGI display support"
 	depends on FB && PCI
@@ -1354,7 +1353,6 @@ config FB_TRIDENT_ACCEL
 	This will compile the Trident frame buffer device with
 	acceleration functions.
 
-
 config FB_PM3
 	tristate "Permedia3 support"
 	depends on FB && PCI && BROKEN
diff -puN drivers/video/s3fb.c~fbdev-driver-for-s3-trio-virge-update drivers/video/s3fb.c
--- a/drivers/video/s3fb.c~fbdev-driver-for-s3-trio-virge-update
+++ a/drivers/video/s3fb.c
@@ -1,15 +1,15 @@
 /*
-*  linux/drivers/video/s3fb.c -- Frame buffer device driver for S3 Trio32/64
-*
-*  Copyright (c) 2006 Ondrej Zajicek <santiago@crfreenet.org>
-*
-*  This file is subject to the terms and conditions of the GNU General Public
-*  License.  See the file COPYING in the main directory of this archive for
-*  more details.
-*
-*  Code is based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
-*  which is based on the code of neofb.
-*/
+ * linux/drivers/video/s3fb.c -- Frame buffer device driver for S3 Trio/Virge
+ *
+ * Copyright (c) 2006 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Code is based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
+ * which is based on the code of neofb.
+ */
 
 #include <linux/version.h>
 #include <linux/module.h>
@@ -24,7 +24,7 @@
 #include <linux/svga.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-// #include <linux/console.h> /* Why should fb driver call console functions? strange ...*/
+#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */
 #include <video/vga.h>
 
 #ifdef CONFIG_MTRR
@@ -46,25 +46,24 @@ struct s3fb_info {
 
 static const struct svga_fb_format s3fb_formats[] = {
 	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_TEXT, 5,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
+		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,	FB_VISUAL_PSEUDOCOLOR, 8, 16},
 	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,	FB_VISUAL_PSEUDOCOLOR, 8, 16},
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
 	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
-		FB_TYPE_INTERLEAVED_PLANES, 1,	FB_VISUAL_PSEUDOCOLOR, 8, 16},
+		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
 	{ 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,	FB_VISUAL_PSEUDOCOLOR, 4, 8},
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 4, 8},
 	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,	FB_VISUAL_TRUECOLOR, 2, 4},
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
 	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,	FB_VISUAL_TRUECOLOR, 2, 4},
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
+	{24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
 	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
-		FB_TYPE_PACKED_PIXELS, 0,	FB_VISUAL_TRUECOLOR, 1, 2},
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
 	SVGA_FORMAT_END
 };
 
-//	{24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
-//	 FB_TYPE_PACKED_PIXELS,	0, FB_VISUAL_TRUECOLOR, 4, 8},
-
 
 static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3,
 	60000, 240000, 14318};
@@ -78,12 +77,12 @@ static const char * const s3_names[] = {
 			"S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P"};
 
 #define CHIP_UNKNOWN		0x00
-#define CHIP_732_TRIO32 	0x01
+#define CHIP_732_TRIO32		0x01
 #define CHIP_764_TRIO64		0x02
 #define CHIP_765_TRIO64VP	0x03
 #define CHIP_767_TRIO64UVP	0x04
-#define	CHIP_775_TRIO64V2_DX	0x05
-#define	CHIP_785_TRIO64V2_GX	0x06
+#define CHIP_775_TRIO64V2_DX	0x05
+#define CHIP_785_TRIO64V2_GX	0x06
 #define CHIP_551_PLATO_PX	0x07
 #define CHIP_M65_AURORA64VP	0x08
 #define CHIP_325_VIRGE		0x09
@@ -113,7 +112,6 @@ static const struct vga_regset s3_h_sync
 static const struct vga_regset s3_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x5E, 0, 0}, VGA_REGSET_END};
 static const struct vga_regset s3_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x5E, 1, 1}, VGA_REGSET_END};
 static const struct vga_regset s3_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x5E, 2, 2}, VGA_REGSET_END};
-// const struct vga_regset s3_v_blank_end_regs[]    = {{0x16, 0, 6}, VGA_REGSET_END};
 static const struct vga_regset s3_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
 static const struct vga_regset s3_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x5E, 4, 4}, VGA_REGSET_END};
 static const struct vga_regset s3_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
@@ -138,30 +136,36 @@ static const struct svga_timing_regs s3_
 static char *mode = "640x480-8@60";
 
 #ifdef CONFIG_MTRR
-static int mtrr   = 1;
+static int mtrr = 1;
 #endif
 
+static int fasttext = 1;
+
 #ifdef MODULE
 
 MODULE_AUTHOR("(c) 2006 Ondrej Zajicek <santiago@crfreenet.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("fbdev driver for S3 Trio/Virge");
 
-module_param(mode, charp, 0);
-MODULE_PARM_DESC(mode, "Preferred video mode ('640x480-8@60', etc)");
+module_param(mode, charp, 0444);
+MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc)");
 
 #ifdef CONFIG_MTRR
-module_param(mtrr, int, 0);
+module_param(mtrr, int, 0444);
 MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
 #endif
 
+module_param(fasttext, int, 0644);
+MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, default=1)");
+
 #endif
 
 /* ------------------------------------------------------------------------- */
 
-/* Set font in text (tileblit) mode */
+/* Set font in S3 fast text mode */
 
-void s3fb_settile(struct fb_info *info, struct fb_tilemap *map) {
+static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
+{
 	const u8 *font = map->data;
 	u8* fb = (u8 *) info->screen_base;
 	int i, c;
@@ -169,156 +173,35 @@ void s3fb_settile(struct fb_info *info, 
 	if ((map->width != 8) || (map->height != 16) ||
 	    (map->depth != 1) || (map->length != 256)) {
 	    	printk(KERN_ERR "fb%d: unsupported font parameters: width %d, height %d, depth %d, length %d\n",
-			map->width, map->height, map->depth, map->length, info->node);
+			info->node, map->width, map->height, map->depth, map->length);
 		return;
 	}
 
 	fb += 2;
-	for (c = 0; c < map->length; c++) {
-		for (i = 0; i < map->height; i++) {
-			fb[i * 4] = font[i];
-		}
-		fb += 128;
-		font += map->height;
-	}
-}
-
-/* Copy area in text (tileblit) mode */
-
-void s3fb_tilecopy(struct fb_info *info, struct fb_tilearea *area) {
-	int dx, dy;
-//	int colstride = 4;
-	int colstride = 2;
-	int rowstride = colstride * (info->var.xres_virtual / 8);
-	u16 *fb = (u16 *) info->screen_base;
-	u16 *src, *dst;
-
-	if ((area->sy > area->dy) ||
-	    ((area->sy == area->dy) && (area->sx > area->dx))) {
-		src = fb + area->sx * colstride + area->sy * rowstride;
-		dst = fb + area->dx * colstride + area->dy * rowstride;
-	    } else {
-		src = fb + (area->sx + area->width - 1) * colstride
-			 + (area->sy + area->height - 1) * rowstride;
-		dst = fb + (area->dx + area->width - 1) * colstride
-			 + (area->dy + area->height - 1) * rowstride;
-
-		colstride = -colstride;
-		rowstride = -rowstride;
-	    }
-
-	for (dy = 0; dy < area->height; dy++) {
-		u16* src2 = src;
-		u16* dst2 = dst;
-		for (dx = 0; dx < area->width; dx++) {
-			*dst2 = *src2;
-			src2 += colstride;
-			dst2 += colstride;
+	for (i = 0; i < map->height; i++) {
+		for (c = 0; c < map->length; c++) {
+			fb[c * 4] = font[c * map->height + i];
 		}
-		src += rowstride;
-		dst += rowstride;
+		fb += 1024;
 	}
 }
 
-/* Fill area in text (tileblit) mode */
-
-void s3fb_tilefill(struct fb_info *info, struct fb_tilerect *rect) {
-	int dx, dy;
-//	int colstride = 8;
-	int colstride = 4;
-	int rowstride = colstride * (info->var.xres_virtual / 8);
-	int attr = (0x0F & rect->bg) << 4 | (0x0F & rect->fg);
-	u8  *fb = (u8 *) info->screen_base;
-	fb += rect->sx * colstride + rect->sy * rowstride;
-
-	for (dy = 0; dy < rect->height; dy++) {
-		u8* fb2 = fb;
-		for (dx = 0; dx < rect->width; dx++) {
-			fb2[0] = rect->index;
-			fb2[1] = attr;
-			fb2 += colstride;
-		}
-		fb += rowstride;
-	}
-}
-
-/* Write text in text (tileblit) mode */
-
-void s3fb_tileblit(struct fb_info *info, struct fb_tileblit *blit) {
-	int dx, dy, i;
-//	int colstride = 8;
-	int colstride = 4;
-	int rowstride = colstride * (info->var.xres_virtual / 8);
-	int attr = (0x0F & blit->bg) << 4 | (0x0F & blit->fg);
-	u8* fb = (u8 *) info->screen_base;
-	fb += blit->sx * colstride + blit->sy * rowstride;
-
-	i=0;
-	for (dy=0; dy < blit->height; dy ++) {
-		u8* fb2 = fb;
-		for (dx = 0; dx < blit->width; dx ++) {
-			fb2[0] = blit->indices[i];
-			fb2[1] = attr;
-			fb2 += colstride;
-			i ++;
-			if (i == blit->length) return;
-		}
-		fb += rowstride;
-	}
-
-}
-
-/* Set cursor in text (tileblit) mode */
-
-void s3fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) {
-	u8 cs = 0x0d;
-	u8 ce = 0x0e;
-	u16 pos =  cursor->sx + (info->var.xoffset /  8)
-		+ (cursor->sy + (info->var.yoffset / 16))
-		   * (info->var.xres_virtual / 8);
-
-	if (! cursor -> mode)
-		return;
-
-	svga_wcrt_mask(0x0A, 0x20, 0x20); /* disable cursor */
-
-	if (cursor -> shape == FB_TILE_CURSOR_NONE)
-		return;
-
-	switch (cursor -> shape)
-	{
-		case FB_TILE_CURSOR_UNDERLINE:
-			cs = 0x0d;
-			break;
-		case FB_TILE_CURSOR_LOWER_THIRD:
-			cs = 0x09;
-			break;
-		case FB_TILE_CURSOR_LOWER_HALF:
-			cs = 0x07;
-			break;
-		case FB_TILE_CURSOR_TWO_THIRDS:
-			cs = 0x05;
-			break;
-		case FB_TILE_CURSOR_BLOCK:
-			cs = 0x01;
-			break;
-	}
-
-	/* set cursor position */
-	vga_wcrt(NULL, 0x0E, pos >> 8);
-	vga_wcrt(NULL, 0x0F, pos & 0xFF);
-
-	vga_wcrt(NULL, 0x0B, ce); /* set cursor end */
-	vga_wcrt(NULL, 0x0A, cs); /* set cursor start and enable it */
-}
 
 
 static struct fb_tile_ops s3fb_tile_ops = {
-	.fb_settile	= s3fb_settile,
-	.fb_tilecopy	= s3fb_tilecopy,
-	.fb_tilefill    = s3fb_tilefill,
-	.fb_tileblit    = s3fb_tileblit,
-	.fb_tilecursor  = s3fb_tilecursor,
+	.fb_settile	= svga_settile,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = svga_tilecursor,
+};
+
+static struct fb_tile_ops s3fb_fast_tile_ops = {
+	.fb_settile	= s3fb_settile_fast,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = svga_tilecursor,
 };
 
 
@@ -460,7 +343,7 @@ static void s3_set_pixclock(struct fb_in
 	udelay(1000);
 
 	/* Activate clock - write 0, 1, 0 to seq/15 bit 5 */
-	regval = vga_rseq (NULL, 0x15);
+	regval = vga_rseq (NULL, 0x15); /* | 0x80; */
 	vga_wseq(NULL, 0x15, regval & ~(1<<5));
 	vga_wseq(NULL, 0x15, regval |  (1<<5));
 	vga_wseq(NULL, 0x15, regval & ~(1<<5));
@@ -509,12 +392,13 @@ static int s3fb_release(struct fb_info *
 
 static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct s3fb_info *par = (struct s3fb_info *) info;
 	int rv, mem, step;
 
 	/* Find appropriate format */
 	rv = svga_match_format (s3fb_formats, var, NULL);
-	if (rv < 0)
-	{
+	if ((rv < 0) || ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 7) : (rv == 6)))
+	{		/* 24bpp on VIRGE VX, 32bpp on others */
 		printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node);
 		return rv;
 	}
@@ -553,7 +437,7 @@ static int s3fb_check_var(struct fb_var_
 static int s3fb_set_par(struct fb_info *info)
 {
 	struct s3fb_info *par = (struct s3fb_info *) info;
-	u32 value, mode, hmul, offset_value, screen_size;
+	u32 value, mode, hmul, offset_value, screen_size, multiplex;
 	u32 bpp = info->var.bits_per_pixel;
 
 	if (bpp != 0) {
@@ -570,11 +454,10 @@ static int s3fb_set_par(struct fb_info *
 		info->fix.line_length = 0;
 
 		info->flags |= FBINFO_MISC_TILEBLITTING;
-		info->tileops = &s3fb_tile_ops;
+		info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops;
 
 		offset_value = info->var.xres_virtual / 16;
 		screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
-		// FIXME test screen_size
 	}
 
 	info->var.xoffset = 0;
@@ -603,36 +486,27 @@ static int s3fb_set_par(struct fb_info *
 	svga_wcrt_mask(0x58, 0x10, 0x10); /* enable linear framebuffer */
 	svga_wcrt_mask(0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */
 
-	svga_wcrt_mask(0x33, 0x08, 0x08); // DDR ?
-	svga_wcrt_mask(0x43, 0x01, 0x01); // DDR ?
-
+/*	svga_wcrt_mask(0x33, 0x08, 0x08); */ /* DDR ?	*/
+/*	svga_wcrt_mask(0x43, 0x01, 0x01); */ /* DDR ?	*/
+	svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ?	*/
+	svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ?	*/
 
-//	svga_wcrt_mask(0x58, 0x03, 0x03); /* XXX */
+	svga_wcrt_mask(0x5D, 0x00, 0x28); // Clear strange HSlen bits
 
-//	svga_wcrt_mask(0x53, 0x12, 0x13); /* enable MMIO */
-//	svga_wcrt_mask(0x40, 0x08, 0x08); /* enable write buffer */
-
-//	pr_debug "fb%d: MCLK reg values %x %x\n", info->node,
-//			  vga_rseq(NULL, 0x10), vga_rseq(NULL, 0x11));
+/*	svga_wcrt_mask(0x58, 0x03, 0x03); */
 
+/*	svga_wcrt_mask(0x53, 0x12, 0x13); */ /* enable MMIO */
+/*	svga_wcrt_mask(0x40, 0x08, 0x08); */ /* enable write buffer */
 
 
 	/* Set the offset register */
 	pr_debug("fb%d: offset register       : %d\n", info->node, offset_value);
 	svga_wcrt_multi(s3_offset_regs, offset_value);
 
-		/* Set the fetch count register */
-/*		value = (info->var.xres / 8) + 8;
-		pr_debug( "viafb: fetch count register  : %d\n", value);
-		via_wseq_multi(via_fetch_count_regs, value);
-*/
-
-
-//	vga_wcrt(NULL, 0x54, info->var.nonstd << 3); // M parameter 0x18
-	vga_wcrt(NULL, 0x54, 0x18); // M parameter 0x18
-	vga_wcrt(NULL, 0x60, 0xff); // N parameter
-	vga_wcrt(NULL, 0x61, 0xff); // L parameter
-	vga_wcrt(NULL, 0x62, 0xff); // L parameter
+	vga_wcrt(NULL, 0x54, 0x18); /* M parameter */
+	vga_wcrt(NULL, 0x60, 0xff); /* N parameter */
+	vga_wcrt(NULL, 0x61, 0xff); /* L parameter */
+	vga_wcrt(NULL, 0x62, 0xff); /* L parameter */
 
 	vga_wcrt(NULL, 0x3A, 0x35);
 	svga_wattr(0x33, 0x00);
@@ -652,14 +526,30 @@ static int s3fb_set_par(struct fb_info *
 	/* Disable Streams engine */
 	svga_wcrt_mask(0x67, 0x00, 0x0C);
 
+
+
+	mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix));
+
 	/* S3 virge DX hack */
 	if (par->chip == CHIP_375_VIRGE_DX) {
 		vga_wcrt(NULL, 0x86, 0x80);
 		vga_wcrt(NULL, 0x90, 0x00);
 	}
 
+	/* S3 virge VX hack */
+	if (par->chip == CHIP_988_VIRGE_VX) {
+		vga_wcrt(NULL, 0x50, 0x00);
+		vga_wcrt(NULL, 0x67, 0x50);
+
+		vga_wcrt(NULL, 0x63, (mode <= 2) ? 0x90 : 0x09);
+		vga_wcrt(NULL, 0x66, 0x90);
+	}
+
+	svga_wcrt_mask(0x31, 0x00, 0x40);
+	multiplex = 0;
+	hmul = 1;
+
 	/* Set mode-specific register values */
-	mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix));
 	switch (mode) {
 		case 0:
 			pr_debug("fb%d: text mode\n", info->node);
@@ -672,7 +562,10 @@ static int s3fb_set_par(struct fb_info *
 			/* Disable enhanced mode */
 			svga_wcrt_mask(0x3A, 0x00, 0x30);
 
-			hmul = 1;
+			if (fasttext) {
+				pr_debug("fb%d: high speed text mode set\n", info->node);
+				svga_wcrt_mask(0x31, 0x40, 0x40);
+			}
 		break;
 		case 1:
 			pr_debug("fb%d: 4 bit pseudocolor\n", info->node);
@@ -684,8 +577,6 @@ static int s3fb_set_par(struct fb_info *
 
 			/* disable enhanced mode */
 			svga_wcrt_mask(0x3A, 0x00, 0x30);
-
-			hmul = 1;
 		break;
 		case 2:
 			pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);
@@ -696,57 +587,71 @@ static int s3fb_set_par(struct fb_info *
 
 			/* disable enhanced mode */
 			svga_wcrt_mask(0x3A, 0x00, 0x30);
-
-			hmul = 1;
 		break;
 		case 3:
 			pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
-			svga_wcrt_mask(0x50, 0x00, 0x30);
-			svga_wcrt_mask(0x67, 0x00, 0xF0);
-			hmul = 1;
+			if (info->var.pixclock > 20000) {
+				svga_wcrt_mask(0x50, 0x00, 0x30);
+				svga_wcrt_mask(0x67, 0x00, 0xF0);
+			} else {
+				svga_wcrt_mask(0x50, 0x00, 0x30);
+				svga_wcrt_mask(0x67, 0x10, 0xF0);
+				multiplex = 1;
+			}
 		break;
 		case 4:
 			pr_debug("fb%d: 5/5/5 truecolor\n", info->node);
-			svga_wcrt_mask(0x50, 0x10, 0x30);
-			svga_wcrt_mask(0x67, 0x30, 0xF0);
-			hmul = 2;
+			if (par->chip == CHIP_988_VIRGE_VX) {
+				if (info->var.pixclock > 20000)
+					svga_wcrt_mask(0x67, 0x20, 0xF0);
+				else
+					svga_wcrt_mask(0x67, 0x30, 0xF0);
+			} else {
+				svga_wcrt_mask(0x50, 0x10, 0x30);
+				svga_wcrt_mask(0x67, 0x30, 0xF0);
+				hmul = 2;
+			}
 		break;
 		case 5:
 			pr_debug("fb%d: 5/6/5 truecolor\n", info->node);
-			svga_wcrt_mask(0x50, 0x10, 0x30);
-			svga_wcrt_mask(0x67, 0x50, 0xF0);
-			hmul = 2;
+			if (par->chip == CHIP_988_VIRGE_VX) {
+				if (info->var.pixclock > 20000)
+					svga_wcrt_mask(0x67, 0x40, 0xF0);
+				else
+					svga_wcrt_mask(0x67, 0x50, 0xF0);
+			} else {
+				svga_wcrt_mask(0x50, 0x10, 0x30);
+				svga_wcrt_mask(0x67, 0x50, 0xF0);
+				hmul = 2;
+			}
 		break;
 		case 6:
+			/* VIRGE VX case */
 			pr_debug("fb%d: 8/8/8 truecolor\n", info->node);
-			svga_wcrt_mask(0x50, 0x30, 0x30);
 			svga_wcrt_mask(0x67, 0xD0, 0xF0);
-			hmul = 1;
 		break;
 		case 7:
-/*
-			pr_debug("fb%d: 8/8/8 truecolor X\n", info->node);
+			pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node);
 			svga_wcrt_mask(0x50, 0x30, 0x30);
-			svga_wcrt_mask(0x67, 0x70, 0xF0);
-*/
-			/* disable enhanced mode */
-			svga_wcrt_mask(0x3A, 0x00, 0x30);
-			/* swap nibbles */
-//			svga_wcrt_mask(0x53, 0x40, 0x40);
-
-//			svga_wattr(VGA_ATC_MODE, 0x41);
-			hmul = 1;
+			svga_wcrt_mask(0x67, 0xD0, 0xF0);
 		break;
 		default:
 			printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node);
 			return -EINVAL;
 	}
 
+	if (par->chip != CHIP_988_VIRGE_VX) {
+		svga_wseq_mask(0x15, multiplex ? 0x10 : 0x00, 0x10);
+		svga_wseq_mask(0x18, multiplex ? 0x80 : 0x00, 0x80);
+	}
+
 	s3_set_pixclock(info, info->var.pixclock);
 	svga_set_timings(&s3_timing_regs, &(info->var), hmul, 1,
 			 (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
 			 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
-			 info->node);
+			 hmul, info->node);
+
+
 
 	/* Set interlaced mode start/end register */
 	value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
@@ -754,7 +659,6 @@ static int s3fb_set_par(struct fb_info *
 	vga_wcrt(NULL, 0x3C, (value + 1) / 2);
 
 	memset((u8*)info->screen_base, 0x00, screen_size);
-
 	/* Device and screen back on */
 	svga_wcrt_mask(0x17, 0x80, 0x80);
 	svga_wseq_mask(0x01, 0x00, 0x20);
@@ -783,9 +687,6 @@ static int s3fb_setcolreg(u_int regno, u
 			outb(red >> 10, VGA_PEL_D);
 			outb(green >> 10, VGA_PEL_D);
 			outb(blue >> 10, VGA_PEL_D);
-
-			((u32*)fb->pseudo_palette)[regno] = ((blue & 0xFF00) >> 8) |
-				(green & 0xFF00) | ((red & 0xFF00) << 8);
 		break;
 		case 8:
 			if (regno >= 256) return -EINVAL;
@@ -794,10 +695,6 @@ static int s3fb_setcolreg(u_int regno, u
 			outb(red >> 10, VGA_PEL_D);
 			outb(green >> 10, VGA_PEL_D);
 			outb(blue >> 10, VGA_PEL_D);
-			if (regno < 16)
-				((u32*)fb->pseudo_palette)[regno] = ((blue & 0xFF00) >> 8) |
-					(green & 0xFF00) | ((red & 0xFF00) << 8);
-
 		break;
 		case 16:
 			if (regno >= 16) return -EINVAL;
@@ -821,6 +718,7 @@ static int s3fb_setcolreg(u_int regno, u
 	return 0;
 }
 
+
 /* Set the display blanking state */
 
 static int s3fb_blank(int blank_mode, struct fb_info *info)
@@ -863,7 +761,7 @@ static int s3fb_pan_display(struct fb_va
 
 	unsigned int offset;
 
-	/* Validate the offsets - At the moment, only the Y offset can be changed */
+	/* Validate the offsets */
 	if ((var->xoffset + var->xres) > var->xres_virtual) return -EINVAL;
 	if ((var->yoffset + var->yres) > var->yres_virtual) return -EINVAL;
 
@@ -883,8 +781,6 @@ static int s3fb_pan_display(struct fb_va
 	return 0;
 }
 
-
-
 /* ------------------------------------------------------------------------- */
 
 /* Frame buffer operations */
@@ -945,6 +841,7 @@ static int __devinit s3_identification(i
 	return CHIP_UNKNOWN;
 }
 
+
 /* PCI probe */
 
 static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -954,6 +851,12 @@ static int __devinit s3_pci_probe(struct
 	int rc;
 	u8 regval, cr38, cr39;
 
+	/* Ignore secondary VGA device because there is no VGA arbitration */
+	if (! svga_primary_device(dev)) {
+		printk(KERN_INFO "s3fb: ignoring secondary device %s\n",  pci_name(dev));
+		return -ENODEV;
+	}
+
 	/* Allocate and fill driver data structure */
 
 	info = framebuffer_alloc(sizeof(struct s3fb_info), NULL);
@@ -1075,6 +978,7 @@ err_enable_device:
 	return rc;
 }
 
+
 /* PCI remove */
 
 static void __devexit s3_pci_remove(struct pci_dev *dev)
@@ -1105,13 +1009,12 @@ static void __devexit s3_pci_remove(stru
 
 /* PCI suspend */
 
-/*
-static int s3_pci_suspend (struct pci_dev* dev, pm_message_t state)
+static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state)
 {
 	struct fb_info *info = pci_get_drvdata(dev);
-	unsigned int count = atomic_read(&(((struct s3_info*)info)->par.ref_count));
+	unsigned int count = atomic_read(&(((struct s3fb_info *) info)->ref_count));
 
-	printk(KERN_INFO "fb%d: suspend\n");
+	printk(KERN_INFO "fb%d: suspend\n", info->node);
 
 	if ((state.event == PM_EVENT_FREEZE) || (!count)) {
 		return 0;
@@ -1127,16 +1030,16 @@ static int s3_pci_suspend (struct pci_de
 
 	return 0;
 }
-*/
+
 
 /* PCI resume */
-/*
-static int s3_pci_resume (struct pci_dev* dev)
+
+static int s3_pci_resume(struct pci_dev* dev)
 {
 	struct fb_info *info = pci_get_drvdata(dev);
-	unsigned int count = atomic_read(&(((struct s3_info*)info)->par.ref_count));
+	unsigned int count = atomic_read(&(((struct s3fb_info *) info)->ref_count));
 
-	printk(KERN_INFO "fb%d: resume\n");
+	printk(KERN_INFO "fb%d: resume\n", info->node);
 
 	if (!count) {
 		return 0;
@@ -1148,13 +1051,13 @@ static int s3_pci_resume (struct pci_dev
 	pci_enable_device(dev);
 	pci_set_master(dev);
 
-	s3fb_set_par (info);
-	fb_set_suspend (info, 0);
+	s3fb_set_par(info);
+	fb_set_suspend(info, 0);
 	release_console_sem();
 
 	return 0;
 }
-*/
+
 
 /* List of boards that we are trying to support */
 
@@ -1177,18 +1080,15 @@ static struct pci_device_id s3_devices[]
 };
 
 
-
-
-
 MODULE_DEVICE_TABLE(pci, s3_devices);
 
 static struct pci_driver s3fb_pci_driver = {
-	name:"s3fb",
-	id_table:s3_devices,
-	probe:s3_pci_probe,
-	remove:__devexit_p(s3_pci_remove),
-//	suspend:s3_pci_suspend,
-//	resume:s3_pci_resume,
+	.name		= "s3fb",
+	.id_table	= s3_devices,
+	.probe		= s3_pci_probe,
+	.remove		= __devexit_p(s3_pci_remove),
+	.suspend	= s3_pci_suspend,
+	.resume		= s3_pci_resume,
 };
 
 /* Parse user speficied options */
@@ -1209,6 +1109,8 @@ static int  __init s3fb_setup(char *opti
 		else if (!strcmp(opt, "mtrr:"))
 			mtrr = simple_strtoul(opt + 5, NULL, 0);
 #endif
+		else if (!strcmp(opt, "fasttext:"))
+			mtrr = simple_strtoul(opt + 9, NULL, 0);
 		else
 			mode = opt;
 	}
@@ -1228,7 +1130,7 @@ static void __exit s3fb_cleanup(void)
 
 /* Driver Initialisation */
 
-int __init s3fb_init(void)
+static int __init s3fb_init(void)
 {
 
 #ifndef MODULE
diff -puN drivers/video/svgalib.c~fbdev-driver-for-s3-trio-virge-update drivers/video/svgalib.c
--- a/drivers/video/svgalib.c~fbdev-driver-for-s3-trio-virge-update
+++ a/drivers/video/svgalib.c
@@ -1,16 +1,15 @@
 /*
- *  Common utility functions for VGA-based graphics cards.
+ * Common utility functions for VGA-based graphics cards.
  *
- *  Copyright (c) 2006 Ondrej Zajicek <santiago@crfreenet.org>
+ * Copyright (c) 2006 Ondrej Zajicek <santiago@crfreenet.org>
  *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
  *
- *  Some parts are based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
+ * Some parts are based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
  */
 
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -22,7 +21,6 @@
 
 
 /* Write a CRT register value spread across multiple registers */
-
 void svga_wcrt_multi(const struct vga_regset *regset, u32 value) {
 
 	u8 regval, bitval, bitnum;
@@ -43,7 +41,6 @@ void svga_wcrt_multi(const struct vga_re
 }
 
 /* Write a sequence register value spread across multiple registers */
-
 void svga_wseq_multi(const struct vga_regset *regset, u32 value) {
 
 	u8 regval, bitval, bitnum;
@@ -63,7 +60,7 @@ void svga_wseq_multi(const struct vga_re
 	}
 }
 
-unsigned int svga_regset_size(const struct vga_regset *regset)
+static unsigned int svga_regset_size(const struct vga_regset *regset)
 {
 	u8 count = 0;
 
@@ -88,10 +85,10 @@ void svga_set_default_gfx_regs(void)
 	vga_wgfx(NULL, VGA_GFX_DATA_ROTATE, 0x00);
 	vga_wgfx(NULL, VGA_GFX_PLANE_READ, 0x00);
 	vga_wgfx(NULL, VGA_GFX_MODE, 0x00);
-//	vga_wgfx(NULL, VGA_GFX_MODE, 0x20);
-//	vga_wgfx(NULL, VGA_GFX_MODE, 0x40);
+/*	vga_wgfx(NULL, VGA_GFX_MODE, 0x20); */
+/*	vga_wgfx(NULL, VGA_GFX_MODE, 0x40); */
 	vga_wgfx(NULL, VGA_GFX_MISC, 0x05);
-//	vga_wgfx(NULL, VGA_GFX_MISC, 0x01);
+/*	vga_wgfx(NULL, VGA_GFX_MISC, 0x01); */
 	vga_wgfx(NULL, VGA_GFX_COMPARE_MASK, 0x0F);
 	vga_wgfx(NULL, VGA_GFX_BIT_MASK, 0xFF);
 }
@@ -99,17 +96,23 @@ void svga_set_default_gfx_regs(void)
 /* Set attribute controller registers to sane values */
 void svga_set_default_atc_regs(void)
 {
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x00);
+
 	/* All standard ATC registers (AR00 - AR14) */
 	u8 count;
 	for (count = 0; count <= 0xF; count ++)
 		svga_wattr(count, count);
 
 	svga_wattr(VGA_ATC_MODE, 0x01);
-//	svga_wattr(VGA_ATC_MODE, 0x41);
+/*	svga_wattr(VGA_ATC_MODE, 0x41); */
 	svga_wattr(VGA_ATC_OVERSCAN, 0x00);
 	svga_wattr(VGA_ATC_PLANE_ENABLE, 0x0F);
 	svga_wattr(VGA_ATC_PEL, 0x00);
 	svga_wattr(VGA_ATC_COLOR_PAGE, 0x00);
+
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x20);
 }
 
 /* Set sequencer registers to sane values */
@@ -119,7 +122,7 @@ void svga_set_default_seq_regs(void)
 	vga_wseq(NULL, VGA_SEQ_CLOCK_MODE, VGA_SR01_CHAR_CLK_8DOTS);
 	vga_wseq(NULL, VGA_SEQ_PLANE_WRITE, VGA_SR02_ALL_PLANES);
 	vga_wseq(NULL, VGA_SEQ_CHARACTER_MAP, 0x00);
-//	vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M);
+/*	vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M); */
 	vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE);
 }
 
@@ -163,6 +166,7 @@ void svga_set_textmode_vga_regs(void)
 	vga_w(NULL, VGA_ATT_W, 0x20);
 }
 
+#if 0
 void svga_dump_var(struct fb_var_screeninfo *var, int node)
 {
 	pr_debug("fb%d: var.vmode         : 0x%X\n", node, var->vmode);
@@ -180,6 +184,162 @@ void svga_dump_var(struct fb_var_screeni
 	pr_debug("fb%d: var.sync          : 0x%X\n", node, var->sync);
 	pr_debug("fb%d: var.pixclock      : %d\n\n", node, var->pixclock);
 }
+#endif  /*  0  */
+
+
+/* ------------------------------------------------------------------------- */
+
+
+void svga_settile(struct fb_info *info, struct fb_tilemap *map)
+{
+	const u8 *font = map->data;
+	u8* fb = (u8 *) info->screen_base;
+	int i, c;
+
+	if ((map->width != 8) || (map->height != 16) ||
+	    (map->depth != 1) || (map->length != 256)) {
+	    	printk(KERN_ERR "fb%d: unsupported font parameters: width %d, height %d, depth %d, length %d\n",
+			info->node, map->width, map->height, map->depth, map->length);
+		return;
+	}
+
+	fb += 2;
+	for (c = 0; c < map->length; c++) {
+		for (i = 0; i < map->height; i++) {
+			fb[i * 4] = font[i];
+		}
+		fb += 128;
+		font += map->height;
+	}
+}
+
+/* Copy area in text (tileblit) mode */
+void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area)
+{
+	int dx, dy;
+	/*  colstride is halved in this function because u16 are used */
+	int colstride = 1 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	u16 *fb = (u16 *) info->screen_base;
+	u16 *src, *dst;
+
+	if ((area->sy > area->dy) ||
+	    ((area->sy == area->dy) && (area->sx > area->dx))) {
+		src = fb + area->sx * colstride + area->sy * rowstride;
+		dst = fb + area->dx * colstride + area->dy * rowstride;
+	    } else {
+		src = fb + (area->sx + area->width - 1) * colstride
+			 + (area->sy + area->height - 1) * rowstride;
+		dst = fb + (area->dx + area->width - 1) * colstride
+			 + (area->dy + area->height - 1) * rowstride;
+
+		colstride = -colstride;
+		rowstride = -rowstride;
+	    }
+
+	for (dy = 0; dy < area->height; dy++) {
+		u16* src2 = src;
+		u16* dst2 = dst;
+		for (dx = 0; dx < area->width; dx++) {
+			*dst2 = *src2;
+			src2 += colstride;
+			dst2 += colstride;
+		}
+		src += rowstride;
+		dst += rowstride;
+	}
+}
+
+/* Fill area in text (tileblit) mode */
+void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect)
+{
+	int dx, dy;
+	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	int attr = (0x0F & rect->bg) << 4 | (0x0F & rect->fg);
+	u8  *fb = (u8 *) info->screen_base;
+	fb += rect->sx * colstride + rect->sy * rowstride;
+
+	for (dy = 0; dy < rect->height; dy++) {
+		u8* fb2 = fb;
+		for (dx = 0; dx < rect->width; dx++) {
+			fb2[0] = rect->index;
+			fb2[1] = attr;
+			fb2 += colstride;
+		}
+		fb += rowstride;
+	}
+}
+
+/* Write text in text (tileblit) mode */
+void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit)
+{
+	int dx, dy, i;
+	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	int attr = (0x0F & blit->bg) << 4 | (0x0F & blit->fg);
+	u8* fb = (u8 *) info->screen_base;
+	fb += blit->sx * colstride + blit->sy * rowstride;
+
+	i=0;
+	for (dy=0; dy < blit->height; dy ++) {
+		u8* fb2 = fb;
+		for (dx = 0; dx < blit->width; dx ++) {
+			fb2[0] = blit->indices[i];
+			fb2[1] = attr;
+			fb2 += colstride;
+			i ++;
+			if (i == blit->length) return;
+		}
+		fb += rowstride;
+	}
+
+}
+
+/* Set cursor in text (tileblit) mode */
+void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
+{
+	u8 cs = 0x0d;
+	u8 ce = 0x0e;
+	u16 pos =  cursor->sx + (info->var.xoffset /  8)
+		+ (cursor->sy + (info->var.yoffset / 16))
+		   * (info->var.xres_virtual / 8);
+
+	if (! cursor -> mode)
+		return;
+
+	svga_wcrt_mask(0x0A, 0x20, 0x20); /* disable cursor */
+
+	if (cursor -> shape == FB_TILE_CURSOR_NONE)
+		return;
+
+	switch (cursor -> shape)
+	{
+		case FB_TILE_CURSOR_UNDERLINE:
+			cs = 0x0d;
+			break;
+		case FB_TILE_CURSOR_LOWER_THIRD:
+			cs = 0x09;
+			break;
+		case FB_TILE_CURSOR_LOWER_HALF:
+			cs = 0x07;
+			break;
+		case FB_TILE_CURSOR_TWO_THIRDS:
+			cs = 0x05;
+			break;
+		case FB_TILE_CURSOR_BLOCK:
+			cs = 0x01;
+			break;
+	}
+
+	/* set cursor position */
+	vga_wcrt(NULL, 0x0E, pos >> 8);
+	vga_wcrt(NULL, 0x0F, pos & 0xFF);
+
+	vga_wcrt(NULL, 0x0B, ce); /* set cursor end */
+	vga_wcrt(NULL, 0x0A, cs); /* set cursor start and enable it */
+}
+
 
 /* ------------------------------------------------------------------------- */
 
@@ -263,45 +423,45 @@ int svga_check_timings(const struct svga
 	var->right_margin = (var->right_margin+7)&~7;
 	var->hsync_len    = (var->hsync_len+7)&~7;
 
-	// Check horizontal total
+	/* Check horizontal total */
 	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
 	if (((value / 8) - 5) >= svga_regset_size (tm->h_total_regs)) return -EINVAL;
 
-	// Check horizontal display and blank start
+	/* Check horizontal display and blank start */
 	value = var->xres;
 	if (((value / 8) - 1) >= svga_regset_size (tm->h_display_regs)) return -EINVAL;
 	if (((value / 8) - 1) >= svga_regset_size (tm->h_blank_start_regs)) return -EINVAL;
 
-	// Check horizontal sync start
+	/* Check horizontal sync start */
 	value = var->xres + var->right_margin;
 	if (((value / 8) - 1) >= svga_regset_size (tm->h_sync_start_regs)) return -EINVAL;
 
-	// Check horizontal blank end (or length)
+	/* Check horizontal blank end (or length) */
 	value = var->left_margin + var->right_margin + var->hsync_len;
 	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_blank_end_regs))) return -EINVAL;
 
-	// Check horizontal sync end (or length)
+	/* Check horizontal sync end (or length) */
 	value = var->hsync_len;
 	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_sync_end_regs))) return -EINVAL;
 
-	// Check vertical total
+	/* Check vertical total */
 	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
 	if ((value - 1) >= svga_regset_size(tm->v_total_regs)) return -EINVAL;
 
-	// Check vertical display and blank start
+	/* Check vertical display and blank start */
 	value = var->yres;
 	if ((value - 1) >= svga_regset_size(tm->v_display_regs)) return -EINVAL;
 	if ((value - 1) >= svga_regset_size(tm->v_blank_start_regs)) return -EINVAL;
 
-	// Check vertical sync start
+	/* Check vertical sync start */
 	value = var->yres + var->lower_margin;
 	if ((value - 1) >= svga_regset_size(tm->v_sync_start_regs)) return -EINVAL;
 
-	// Check vertical blank end (or length)
+	/* Check vertical blank end (or length) */
 	value = var->upper_margin + var->lower_margin + var->vsync_len;
 	if ((value == 0) || (value >= svga_regset_size (tm->v_blank_end_regs))) return -EINVAL;
 
-	// Check vertical sync end  (or length)
+	/* Check vertical sync end  (or length) */
 	value = var->vsync_len;
 	if ((value == 0) || (value >= svga_regset_size (tm->v_sync_end_regs))) return -EINVAL;
 
@@ -310,7 +470,7 @@ int svga_check_timings(const struct svga
 
 /* Set CRT timing registers */
 void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var,
-			u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, int node)
+			u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node)
 {
 	u8 regval;
 	u32 value;
@@ -318,8 +478,7 @@ void svga_set_timings(const struct svga_
 	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
 	value = (value * hmul) / hdiv;
 	pr_debug("fb%d: horizontal total      : %d\n", node, value);
-	svga_wcrt_multi(tm->h_total_regs, (value / 8));
-	vga_wcrt(NULL, 0x3B, (value / 8) - 5);
+	svga_wcrt_multi(tm->h_total_regs, (value / 8) - 5);
 
 	value = var->xres;
 	value = (value * hmul) / hdiv;
@@ -329,22 +488,22 @@ void svga_set_timings(const struct svga_
 	value = var->xres;
 	value = (value * hmul) / hdiv;
 	pr_debug("fb%d: horizontal blank start: %d\n", node, value);
-	svga_wcrt_multi(tm->h_blank_start_regs, (value / 8));
+	svga_wcrt_multi(tm->h_blank_start_regs, (value / 8) - 1 + hborder);
 
 	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
 	value = (value * hmul) / hdiv;
 	pr_debug("fb%d: horizontal blank end  : %d\n", node, value);
-	svga_wcrt_multi(tm->h_blank_end_regs, (value / 8) - 2); /* really -2 ? */
+	svga_wcrt_multi(tm->h_blank_end_regs, (value / 8) - 1 - hborder);
 
 	value = var->xres + var->right_margin;
 	value = (value * hmul) / hdiv;
 	pr_debug("fb%d: horizontal sync start : %d\n", node, value);
-	svga_wcrt_multi(tm->h_sync_start_regs, (value / 8) + 2); /* why not -1 ? */
+	svga_wcrt_multi(tm->h_sync_start_regs, (value / 8));
 
 	value = var->xres + var->right_margin + var->hsync_len;
 	value = (value * hmul) / hdiv;
 	pr_debug("fb%d: horizontal sync end   : %d\n", node, value);
-	svga_wcrt_multi(tm->h_sync_end_regs, (value / 8) + 1); /* why not -1 ? */
+	svga_wcrt_multi(tm->h_sync_end_regs, (value / 8));
 
 	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
 	value = (value * vmul) / vdiv;
@@ -364,17 +523,17 @@ void svga_set_timings(const struct svga_
 	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
 	value = (value * vmul) / vdiv;
 	pr_debug("fb%d: vertical blank end    : %d\n", node, value);
-	svga_wcrt_multi(tm->v_blank_end_regs, value - 2); /* really -2 ? */
+	svga_wcrt_multi(tm->v_blank_end_regs, value - 2);
 
 	value = var->yres + var->lower_margin;
 	value = (value * vmul) / vdiv;
 	pr_debug("fb%d: vertical sync start   : %d\n", node, value);
-	svga_wcrt_multi(tm->v_sync_start_regs, value - 1);
+	svga_wcrt_multi(tm->v_sync_start_regs, value);
 
 	value = var->yres + var->lower_margin + var->vsync_len;
 	value = (value * vmul) / vdiv;
 	pr_debug("fb%d: vertical sync end     : %d\n", node, value);
-	svga_wcrt_multi(tm->v_sync_end_regs, value - 1);
+	svga_wcrt_multi(tm->v_sync_end_regs, value);
 
 	/* Set horizontal and vertical sync pulse polarity in misc register */
 
@@ -433,9 +592,8 @@ int svga_match_format(const struct svga_
 }
 
 
-EXPORT_SYMBOL(svga_wseq_multi);
 EXPORT_SYMBOL(svga_wcrt_multi);
-EXPORT_SYMBOL(svga_regset_size);
+EXPORT_SYMBOL(svga_wseq_multi);
 
 EXPORT_SYMBOL(svga_set_default_gfx_regs);
 EXPORT_SYMBOL(svga_set_default_atc_regs);
@@ -443,7 +601,11 @@ EXPORT_SYMBOL(svga_set_default_seq_regs)
 EXPORT_SYMBOL(svga_set_default_crt_regs);
 EXPORT_SYMBOL(svga_set_textmode_vga_regs);
 
-EXPORT_SYMBOL(svga_dump_var);
+EXPORT_SYMBOL(svga_settile);
+EXPORT_SYMBOL(svga_tilecopy);
+EXPORT_SYMBOL(svga_tilefill);
+EXPORT_SYMBOL(svga_tileblit);
+EXPORT_SYMBOL(svga_tilecursor);
 
 EXPORT_SYMBOL(svga_compute_pll);
 EXPORT_SYMBOL(svga_check_timings);
diff -puN include/linux/fb.h~fbdev-driver-for-s3-trio-virge-update include/linux/fb.h
--- a/include/linux/fb.h~fbdev-driver-for-s3-trio-virge-update
+++ a/include/linux/fb.h
@@ -49,6 +49,13 @@
 #define FB_AUX_TEXT_S3_MMIO	2	/* S3 MMIO fasttext */
 #define FB_AUX_TEXT_MGA_STEP16	3	/* MGA Millenium I: text, attr, 14 reserved bytes */
 #define FB_AUX_TEXT_MGA_STEP8	4	/* other MGAs:      text, attr,  6 reserved bytes */
+#define FB_AUX_TEXT_SVGA_GROUP	8	/* 8-15: SVGA tileblit compatible modes */
+#define FB_AUX_TEXT_SVGA_MASK	7	/* lower three bits says step */
+#define FB_AUX_TEXT_SVGA_STEP2	8	/* SVGA text mode:  text, attr */
+#define FB_AUX_TEXT_SVGA_STEP4	9	/* SVGA text mode:  text, attr,  2 reserved bytes */
+#define FB_AUX_TEXT_SVGA_STEP8	10	/* SVGA text mode:  text, attr,  6 reserved bytes */
+#define FB_AUX_TEXT_SVGA_STEP16	11	/* SVGA text mode:  text, attr, 14 reserved bytes */
+#define FB_AUX_TEXT_SVGA_LAST	15	/* reserved up to 15 */
 
 #define FB_AUX_VGA_PLANES_VGA4		0	/* 16 color planes (EGA/VGA) */
 #define FB_AUX_VGA_PLANES_CFB4		1	/* CFB4 in planes (VGA) */
diff -puN include/linux/svga.h~fbdev-driver-for-s3-trio-virge-update include/linux/svga.h
--- a/include/linux/svga.h~fbdev-driver-for-s3-trio-virge-update
+++ a/include/linux/svga.h
@@ -3,6 +3,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/pci.h>
 #include <video/vga.h>
 
 /* Terminator for register set */
@@ -68,8 +69,8 @@ struct svga_pll {
 
 /* Write a value to the attribute register */
 
-static inline void svga_wattr(u8 index, u8 data) {
-
+static inline void svga_wattr(u8 index, u8 data)
+{
 	inb(0x3DA);
 	outb(index, 0x3C0);
 	outb(data, 0x3C0);
@@ -77,22 +78,28 @@ static inline void svga_wattr(u8 index, 
 
 /* Write a value to a sequence register with a mask */
 
-static inline void svga_wseq_mask(u8 index, u8 data, u8 mask) {
-
+static inline void svga_wseq_mask(u8 index, u8 data, u8 mask)
+{
 	vga_wseq(NULL, index, (data & mask) | (vga_rseq(NULL, index) & ~mask));
 }
 
 /* Write a value to a CRT register with a mask */
 
-static inline void svga_wcrt_mask(u8 index, u8 data, u8 mask) {
-
+static inline void svga_wcrt_mask(u8 index, u8 data, u8 mask)
+{
 	vga_wcrt(NULL, index, (data & mask) | (vga_rcrt(NULL, index) & ~mask));
 }
 
+static inline int svga_primary_device(struct pci_dev *dev)
+{
+	u16 flags;
+	pci_read_config_word(dev, PCI_COMMAND, &flags);
+	return (flags & PCI_COMMAND_IO);
+}
+
 
 void svga_wcrt_multi(const struct vga_regset *regset, u32 value);
 void svga_wseq_multi(const struct vga_regset *regset, u32 value);
-unsigned int svga_regset_size(const struct vga_regset *regset);
 
 void svga_set_default_gfx_regs(void);
 void svga_set_default_atc_regs(void);
@@ -100,11 +107,15 @@ void svga_set_default_seq_regs(void);
 void svga_set_default_crt_regs(void);
 void svga_set_textmode_vga_regs(void);
 
-void svga_dump_var(struct fb_var_screeninfo *var, int node);
+void svga_settile(struct fb_info *info, struct fb_tilemap *map);
+void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area);
+void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect);
+void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit);
+void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor);
 
 int svga_compute_pll(const struct svga_pll *pll, u32 f_wanted, u16 *m, u16 *n, u16 *r, int node);
 int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, int node);
-void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, int node);
+void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node);
 
 int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix);
 
_

Patches currently in -mm which might be from santiago@crfreenet.org are

fbdev-driver-for-s3-trio-virge.patch
fbdev-driver-for-s3-trio-virge-update.patch
fbdev-driver-for-s3-trio-virge-update-2.patch
fbdev-driver-for-s3-trio-virge-update-2-fix.patch

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2007-02-12  7:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-12  7:25 - fbdev-driver-for-s3-trio-virge-update.patch removed from -mm tree akpm

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.