 Documentation/devices.txt        |    7 
 arch/i386/boot/compressed/misc.c |    2 
 arch/i386/boot/video.S           |   34 +
 arch/i386/kernel/setup.c         |    4 
 drivers/video/aty/aty128fb.c     |   16 
 drivers/video/cfbimgblt.c        |    4 
 drivers/video/console/fbcon.c    |  285 +++++-------
 drivers/video/console/fbcon.h    |    1 
 drivers/video/controlfb.c        |   18 
 drivers/video/edid.h             |  138 +++++
 drivers/video/fbcmap.c           |   33 -
 drivers/video/fbmem.c            |  190 ++++----
 drivers/video/fbmon.c            |  922 +++++++++++++++++++++++++++++++--------
 drivers/video/i810/i810.h        |    7 
 drivers/video/i810/i810_accel.c  |  140 +++--
 drivers/video/i810/i810_dvt.c    |    3 
 drivers/video/i810/i810_gtf.c    |    7 
 drivers/video/i810/i810_main.c   |  199 +++-----
 drivers/video/i810/i810_main.h   |    4 
 drivers/video/imsttfb.c          |    4 
 drivers/video/logo/logo.c        |   71 +--
 drivers/video/modedb.c           |  105 ++++
 drivers/video/platinumfb.c       |   28 -
 drivers/video/pm2fb.c            |   22 
 drivers/video/radeonfb.c         |   28 -
 drivers/video/retz3fb.c          |   16 
 drivers/video/riva/fbdev.c       |  230 ++++-----
 drivers/video/sis/sis_main.h     |   62 +-
 drivers/video/softcursor.c       |   67 +-
 drivers/video/tdfxfb.c           |   18 
 drivers/video/tgafb.c            |    2 
 drivers/video/tridentfb.c        |    8 
 drivers/video/vesafb.c           |   23 
 drivers/video/vga16fb.c          |    4 
 include/asm-i386/setup.h         |    1 
 include/linux/fb.h               |   29 -
 include/linux/linux_logo.h       |    2 
 include/linux/pci_ids.h          |    1 
 include/video/edid.h             |   27 +
 39 files changed, 1798 insertions(+), 964 deletions(-)

diff -puN arch/i386/boot/compressed/misc.c~fbdev arch/i386/boot/compressed/misc.c
--- 25/arch/i386/boot/compressed/misc.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/arch/i386/boot/compressed/misc.c	2003-04-13 22:00:13.000000000 -0700
@@ -12,6 +12,7 @@
 #include <linux/linkage.h>
 #include <linux/vmalloc.h>
 #include <linux/tty.h>
+#include <video/edid.h>
 #include <asm/io.h>
 
 /*
@@ -91,6 +92,7 @@ static unsigned char *real_mode; /* Poin
 #define ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
 #endif
 #define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+#define EDID_INFO   (*(struct edid_info *)(real_mode+0x440))
 
 extern char input_data[];
 extern int input_len;
diff -puN arch/i386/boot/video.S~fbdev arch/i386/boot/video.S
--- 25/arch/i386/boot/video.S~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/arch/i386/boot/video.S	2003-04-13 22:00:13.000000000 -0700
@@ -135,6 +135,7 @@ vid1:
 #endif /* CONFIG_VIDEO_RETAIN */
 #endif /* CONFIG_VIDEO_SELECT */
 	call	mode_params			# Store mode parameters
+	call	store_edid
 	popw	%ds				# Restore original DS
 	ret
 
@@ -1887,6 +1888,39 @@ skip10:	movb	%ah, %al
 	popw	%ax
 	ret
 
+store_edid:
+	pushw	%es				# just save all registers 
+	pushw	%ax				
+	pushw	%bx
+	pushw   %cx
+	pushw	%dx
+	pushw   %di
+
+	pushw	%fs                             
+	popw    %es
+
+	movl	$0x13131313, %eax		# memset block with 0x13
+	movw    $32, %cx
+	movw	$0x440, %di
+	cld
+	rep 
+	stosl  
+
+	movw	$0x4f15, %ax                    # do VBE/DDC 
+	movw	$0x01, %bx
+	movw	$0x00, %cx
+	movw    $0x01, %dx
+	movw	$0x440, %di
+	int	$0x10	
+
+	popw	%di				# restore all registers        
+	popw	%dx
+	popw	%cx
+	popw	%bx
+	popw	%ax
+	popw	%es	
+	ret
+
 # VIDEO_SELECT-only variables
 mt_end:		.word	0	# End of video mode table if built
 edit_buf:	.space	6	# Line editor buffer
diff -puN arch/i386/kernel/setup.c~fbdev arch/i386/kernel/setup.c
--- 25/arch/i386/kernel/setup.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/arch/i386/kernel/setup.c	2003-04-13 22:00:13.000000000 -0700
@@ -37,6 +37,7 @@
 #include <linux/console.h>
 #include <linux/root_dev.h>
 #include <linux/highmem.h>
+#include <video/edid.h>
 #include <asm/e820.h>
 #include <asm/mpspec.h>
 #include <asm/edd.h>
@@ -85,7 +86,7 @@ struct sys_desc_table_struct {
 	unsigned short length;
 	unsigned char table[0];
 };
-
+struct edid_info edid_info;
 struct e820map e820;
 
 unsigned char aux_device_present;
@@ -883,6 +884,7 @@ void __init setup_arch(char **cmdline_p)
  	ROOT_DEV = ORIG_ROOT_DEV;
  	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
+	edid_info = EDID_INFO;
 	apm_info.bios = APM_BIOS_INFO;
 	saved_videomode = VIDEO_MODE;
 	printk("Video mode to be used for restore is %lx\n", saved_videomode);
diff -puN Documentation/devices.txt~fbdev Documentation/devices.txt
--- 25/Documentation/devices.txt~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/Documentation/devices.txt	2003-04-13 22:00:13.000000000 -0700
@@ -693,13 +693,6 @@ Your cooperation is appreciated.
 		    ...
 		 31 = /dev/fb31		32nd frame buffer
 
-		For backwards compatibility {2.6} the following
-		progression is also handled by current kernels:
-		  0 = /dev/fb0
-		 32 = /dev/fb1
-		    ...
-		224 = /dev/fb7
-
     block	Aztech/Orchid/Okano/Wearnes CD-ROM
 		  0 = /dev/aztcd	Aztech CD-ROM
 
diff -puN drivers/video/aty/aty128fb.c~fbdev drivers/video/aty/aty128fb.c
--- 25/drivers/video/aty/aty128fb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/aty/aty128fb.c	2003-04-13 22:00:13.000000000 -0700
@@ -62,7 +62,7 @@
 #ifdef CONFIG_ALL_PPC
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
-#include "macmodes.h"
+#include "../macmodes.h"
 #endif
 
 #ifdef CONFIG_ADB_PMU
@@ -1994,23 +1994,21 @@ aty128fb_setcolreg(u_int regno, u_int re
 
 	if (regno < 16) {
 		int i;
+		u32 *pal = info->pseudo_palette;
+
 		switch (par->crtc.depth) {
 		case 15:
-			((u16 *) (info->pseudo_palette))[regno] =
-			    (regno << 10) | (regno << 5) | regno;
+			pal[regno] = (regno << 10) | (regno << 5) | regno;
 			break;
 		case 16:
-			((u16 *) (info->pseudo_palette))[regno] =
-			    (regno << 11) | (regno << 6) | regno;
+			pal[regno] = (regno << 11) | (regno << 6) | regno;
 			break;
 		case 24:
-			((u32 *) (info->pseudo_palette))[regno] =
-			    (regno << 16) | (regno << 8) | regno;
+			pal[regno] = (regno << 16) | (regno << 8) | regno;
 			break;
 		case 32:
 			i = (regno << 8) | regno;
-			((u32 *) (info->pseudo_palette))[regno] =
-			    (i << 16) | i;
+			pal[regno] = (i << 16) | i;
 			break;
 		}
 	}
diff -puN drivers/video/cfbimgblt.c~fbdev drivers/video/cfbimgblt.c
--- 25/drivers/video/cfbimgblt.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/cfbimgblt.c	2003-04-13 22:00:13.000000000 -0700
@@ -329,7 +329,7 @@ void cfb_imageblit(struct fb_info *p, co
 	if (p->fbops->fb_sync)
 		p->fbops->fb_sync(p);
 
-	if (image->depth == 0) {
+	if (image->depth == 1) {
 		if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
 		    p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
 			fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
@@ -346,7 +346,7 @@ void cfb_imageblit(struct fb_info *p, co
 		else 
 			slow_imageblit(image, p, dst1, fgcolor, bgcolor,
 					start_index, pitch_index);
-	} else if (image->depth == bpp) 
+	} else if (image->depth <= bpp) 
 		color_imageblit(image, p, dst1, start_index, pitch_index);
 }
 
diff -puN drivers/video/console/fbcon.c~fbdev drivers/video/console/fbcon.c
--- 25/drivers/video/console/fbcon.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/console/fbcon.c	2003-04-13 22:00:13.000000000 -0700
@@ -139,8 +139,6 @@ static int fbcon_set_origin(struct vc_da
 
 static int vbl_cursor_cnt;
 static int cursor_blink_rate;
-static int cursor_drawn;
-static int cursor_on;
 
 #define divides(a, b)	((!(a) || (b)%(a)) ? 0 : 1)
 
@@ -173,7 +171,6 @@ static int fbcon_scrolldelta(struct vc_d
  */
 static void fbcon_set_display(struct vc_data *vc, int init, int logo);
 static __inline__ int real_y(struct display *p, int ypos);
-static void fb_vbl_handler(int irq, void *dummy, struct pt_regs *fp);
 static __inline__ void updatescrollmode(struct display *p, struct vc_data *vc);
 static __inline__ void ywrap_up(struct vc_data *vc, int count);
 static __inline__ void ywrap_down(struct vc_data *vc, int count);
@@ -194,6 +191,27 @@ static void fb_vbl_detect(int irq, void 
 }
 #endif
 
+static void fb_flashcursor(void *private)
+{
+	struct fb_info *info = (struct fb_info *) private;
+
+	/* Test to see if the cursor is erased but still on */
+	if (!info || (info->cursor.rop == ROP_COPY))
+		return;
+	info->cursor.enable ^= 1;
+	info->fbops->fb_cursor(info, &info->cursor);
+}
+
+static void fb_vbl_handler(int irq, void *dev_id, struct pt_regs *fp)
+{
+	struct fb_info *info = dev_id;
+
+	if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) {
+		schedule_work(&info->queue);	
+		vbl_cursor_cnt = cursor_blink_rate; 
+	}
+}
+	
 static void cursor_timer_handler(unsigned long dev_addr);
 
 static struct timer_list cursor_timer =
@@ -203,8 +221,8 @@ static void cursor_timer_handler(unsigne
 {
 	struct fb_info *info = (struct fb_info *) dev_addr;
 	
-	fb_vbl_handler(0, info, NULL);
-	cursor_timer.expires = jiffies + HZ / 50;
+	schedule_work(&info->queue);	
+	cursor_timer.expires = jiffies + HZ / 5;
 	add_timer(&cursor_timer);
 }
 
@@ -290,14 +308,14 @@ static void putcs_unaligned(struct vc_da
 			    const unsigned short *s)
 {
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	unsigned int width = (vc->vc_font.width + 7)/8;
+	unsigned int width = (vc->vc_font.width + 7) >> 3;
 	unsigned int cellsize = vc->vc_font.height * width;
 	unsigned int maxcnt = info->pixmap.size/cellsize;
 	unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
 	unsigned int shift_high = 8, size, pitch, cnt, k;
 	unsigned int buf_align = info->pixmap.buf_align - 1;
 	unsigned int scan_align = info->pixmap.scan_align - 1;
-	unsigned int idx = vc->vc_font.width/8;
+	unsigned int idx = vc->vc_font.width >> 3;
 	u8 mask, *src, *dst, *dst0;
 
 	while (count) {
@@ -307,7 +325,7 @@ static void putcs_unaligned(struct vc_da
 			cnt = k = count;
 
 		image->width = vc->vc_font.width * cnt;
-		pitch = (image->width + 7)/8 + scan_align;
+		pitch = ((image->width + 7) >> 3) + scan_align;
 		pitch &= ~scan_align;
 		size = pitch * vc->vc_font.height + buf_align;
 		size &= ~buf_align;
@@ -338,7 +356,7 @@ static void putcs_aligned(struct vc_data
 			  const unsigned short *s)
 {
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	unsigned int width = vc->vc_font.width/8;
+	unsigned int width = vc->vc_font.width >> 3;
 	unsigned int cellsize = vc->vc_font.height * width;
 	unsigned int maxcnt = info->pixmap.size/cellsize;
 	unsigned int scan_align = info->pixmap.scan_align - 1;
@@ -411,7 +429,7 @@ static void accel_putc(struct vc_data *v
                       int c, int ypos, int xpos)
 {
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	unsigned int width = (vc->vc_font.width + 7)/8;
+	unsigned int width = (vc->vc_font.width + 7) >> 3;
 	unsigned int scan_align = info->pixmap.scan_align - 1;
 	unsigned int buf_align = info->pixmap.buf_align - 1;
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
@@ -426,7 +444,7 @@ static void accel_putc(struct vc_data *v
 	image.height = vc->vc_font.height;
 	image.fg_color = attr_fgcol(fgshift, c);
 	image.bg_color = attr_bgcol(bgshift, c);
-	image.depth = 0;
+	image.depth = 1;
 
 	pitch = width + scan_align;
 	pitch &= ~scan_align;
@@ -457,7 +475,7 @@ void accel_putcs(struct vc_data *vc, str
 	image.dx = xx * vc->vc_font.width;
 	image.dy = yy * vc->vc_font.height;
 	image.height = vc->vc_font.height;
-	image.depth = 0;
+	image.depth = 1;
 
 	if (!(vc->vc_font.width & 7))
                putcs_aligned(vc, info, &image, count, s);
@@ -501,7 +519,6 @@ void accel_clear_margins(struct vc_data 
  *  Low Level Operations
  */
 /* NOTE: fbcon cannot be __init: it may be called from take_over_console later */
-
 static const char *fbcon_startup(void)
 {
 	const char *display_desc = "frame buffer device";
@@ -559,6 +576,12 @@ static const char *fbcon_startup(void)
 
 	vc = (struct vc_data *) kmalloc(sizeof(struct vc_data), GFP_ATOMIC); 
 
+	if (!vc) {
+		if (softback_buf)
+			kfree((void *) softback_buf);
+		return NULL;
+	}
+
 	/* Setup default font */
 	vc->vc_font.data = font->data;
 	vc->vc_font.width = font->width;
@@ -639,9 +662,12 @@ static const char *fbcon_startup(void)
 	irqres = request_irq(IRQ_VSYNCPULSE, fb_vbl_handler, SA_SHIRQ,
 			     "framebuffer vbl", info);
 #endif
-
-	if (irqres) {
-		cursor_blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+	/* Initialize the work queue. If the driver provides its
+	 * own work queue this means it will use something besides 
+	 * default timer to flash the cursor. */
+	if (!info->queue.func) {
+		INIT_WORK(&info->queue, fb_flashcursor, info);
+		
 		cursor_timer.expires = jiffies + HZ / 50;
 		cursor_timer.data = (unsigned long ) info;
 		add_timer(&cursor_timer);
@@ -956,112 +982,17 @@ static void fbcon_putcs(struct vc_data *
 	accel_putcs(vc, info, s, count, real_y(p, ypos), xpos);
 }
 
-void accel_cursor(struct vc_data *vc, struct fb_info *info, struct fb_cursor *cursor,
-		  int yy)
+static void fbcon_cursor(struct vc_data *vc, int mode)
 {
+	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
-	int height, width, size, c;
-	int w, cur_height, i = 0;
-	char *font, *mask, *data;
-	
-	if (cursor->set & FB_CUR_SETCUR)
-		cursor->enable = 1;
-	else
-		cursor->enable = 0;
-
-	cursor->set |= FB_CUR_SETPOS;
-
-	height = info->cursor.image.height;
-	width = info->cursor.image.width;
-
-	if (width != vc->vc_font.width || 
-	    height != vc->vc_font.height) {
-		width = vc->vc_font.width;
-		height = vc->vc_font.height;
-		cursor->set |= FB_CUR_SETSIZE;
-	}	
-
-	size = ((width + 7) >> 3) * height;
-
-	data = kmalloc(size, GFP_KERNEL);
-	mask = kmalloc(size, GFP_KERNEL);
-	
-	if (cursor->set & FB_CUR_SETSIZE) {
-		memset(data, 0xff, size);
-		cursor->set |= FB_CUR_SETSHAPE;
-	}
-
-	c = scr_readw((u16 *) vc->vc_pos);
-
-	if (info->cursor.image.fg_color != attr_fgcol(fgshift, c) ||
-	    info->cursor.image.bg_color != attr_bgcol(bgshift, c)) {
-		cursor->image.fg_color = attr_fgcol(fgshift, c);
-		cursor->image.bg_color = attr_bgcol(bgshift, c);
-		cursor->set |= FB_CUR_SETCMAP;
-	}
-	font = vc->vc_font.data + ((c & charmask) * size);
-	if (font != info->cursor.dest) {
-		cursor->dest = font;
-		cursor->set |= FB_CUR_SETDEST;
-	}
-
-	w = (width + 7) >> 3;
-
-	switch (vc->vc_cursor_type & 0x0f) {
-		case CUR_NONE:
-			cur_height = 0;
-			break;
-		case CUR_UNDERLINE:
-			cur_height = (height < 10) ? 1 : 2;
-			break;
-		case CUR_LOWER_THIRD:
-			cur_height = height/3;
-			break;
-		case CUR_LOWER_HALF:
-			cur_height = height/2;
-			break;
-		case CUR_TWO_THIRDS:
-			cur_height = (height * 2)/3;
-			break;
-		case CUR_BLOCK:
-		default:
-			cur_height = height;
-			break;
-	}
-
-	size = (height - cur_height) * w;
-	while (size--)
-		mask[i++] = 0;
-	size = cur_height * w;
-	while (size--)
-		mask[i++] = 0xff;
-
-	if (!info->cursor.mask ||  (memcmp(mask, info->cursor.mask, w*height)))
-		cursor->set |= FB_CUR_SETSHAPE;
-
-	cursor->image.width = width;
-	cursor->image.height = height;
-	cursor->image.dx = vc->vc_x * width;
-	cursor->image.dy = yy * height;
-	cursor->image.depth = 0;
-	cursor->image.data = data;
-	cursor->mask = mask;
-	cursor->rop = ROP_XOR;
-
-	info->fbops->fb_cursor(info, cursor);
-	kfree(data);
-	kfree(mask);
-}
-	
-static void fbcon_cursor(struct vc_data *vc, int mode)
-{
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
+	int w = (vc->vc_font.width + 7) >> 3, c;
+	int y = real_y(p, vc->vc_y);
 	struct fb_cursor cursor;
-	int y = vc->vc_y;
-
+	
 	if (mode & CM_SOFTBACK) {
 		mode &= ~CM_SOFTBACK;
 		if (softback_lines) {
@@ -1073,55 +1004,93 @@ static void fbcon_cursor(struct vc_data 
 	} else if (softback_lines)
 		fbcon_set_origin(vc);
 
-	/* Avoid flickering if there's no real change. */
-	if ((mode == CM_ERASE) == !cursor_on)
-		return;
-
-	cursor_on = 0;
+ 	c = scr_readw((u16 *) vc->vc_pos);
 
+	cursor.image.data = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+	cursor.set = FB_CUR_SETCUR;
+	cursor.image.depth = 1;
+	
 	switch (mode) {
 	case CM_ERASE:
-		if (cursor_drawn) {
-			cursor.set = 0;
-			accel_cursor(vc, info, &cursor,
-				     real_y(p, y));
+		if (info->cursor.rop == ROP_XOR) {
+			info->cursor.enable = 0;
+			info->cursor.rop = ROP_COPY;
+			info->fbops->fb_cursor(info, &cursor);
 		}	
-		cursor_drawn = 0;
 		break;
 	case CM_MOVE:
 	case CM_DRAW:
-		if (cursor_drawn) {
-			cursor.set = FB_CUR_SETCUR;
-			accel_cursor(vc, info, &cursor, 
-				     real_y(p, y));
-		}	
+		info->cursor.enable = 1;
+		
+		if (info->cursor.image.fg_color != attr_fgcol(fgshift, c) ||
+	    	    info->cursor.image.bg_color != attr_bgcol(bgshift, c)) {
+			cursor.image.fg_color = attr_fgcol(fgshift, c);
+			cursor.image.bg_color = attr_bgcol(bgshift, c);
+			cursor.set |= FB_CUR_SETCMAP;
+		}
+		
+		if ((info->cursor.image.dx != (vc->vc_font.width * vc->vc_x)) ||
+		    (info->cursor.image.dy != (vc->vc_font.height * y))) {
+			cursor.image.dx = vc->vc_font.width * vc->vc_x;
+			cursor.image.dy = vc->vc_font.height * y;
+			cursor.set |= FB_CUR_SETPOS;
+		}
+
+		if (info->cursor.image.height != vc->vc_font.height ||
+		    info->cursor.image.width != vc->vc_font.width) {
+			cursor.image.height = vc->vc_font.height;
+			cursor.image.width = vc->vc_font.width;
+			cursor.set |= FB_CUR_SETSIZE;
+		}
+
+		if ((cursor.set & FB_CUR_SETSIZE) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)) {
+			char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
+			int cur_height, size, i = 0;
+
+			if (!mask)	return;	
+		
+			if (info->cursor.mask)
+				kfree(info->cursor.mask);
+			info->cursor.mask = mask;
+	
+			p->cursor_shape = vc->vc_cursor_type & 0x0f;
+			cursor.set |= FB_CUR_SETSHAPE;
+
+			switch (vc->vc_cursor_type & 0x0f) {
+			case CUR_NONE:
+				cur_height = 0;
+				break;
+			case CUR_UNDERLINE:
+				cur_height = (vc->vc_font.height < 10) ? 1 : 2;
+				break;
+			case CUR_LOWER_THIRD:
+				cur_height = vc->vc_font.height/3;
+				break;
+			case CUR_LOWER_HALF:
+				cur_height = vc->vc_font.height >> 1;
+				break;
+			case CUR_TWO_THIRDS:
+				cur_height = (vc->vc_font.height << 1)/3;
+				break;
+			case CUR_BLOCK:
+			default:
+				cur_height = vc->vc_font.height;
+				break;
+			}
+			size = (vc->vc_font.height - cur_height) * w;
+			while (size--)
+				mask[i++] = 0;
+			size = cur_height * w;
+			while (size--)
+				mask[i++] = 0xff;
+		}
+        	info->cursor.rop = ROP_XOR;
+		info->fbops->fb_cursor(info, &cursor);
 		vbl_cursor_cnt = CURSOR_DRAW_DELAY;
-		cursor_on = 1;
 		break;
 	}
 }
 
-static void fb_vbl_handler(int irq, void *dev_id, struct pt_regs *fp)
-{
-	struct fb_info *info = dev_id;
-	struct display *p = &fb_display[fg_console];
-	struct vc_data *vc = vc_cons[fg_console].d;
-	struct fb_cursor cursor;
-	
-	if (!cursor_on)
-		return;
-
-	if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) {
-		cursor.set = 0;
-
-		if (!cursor_drawn)
-			cursor.set = FB_CUR_SETCUR;
-		accel_cursor(vc, info, &cursor, real_y(p, vc->vc_y));
-		cursor_drawn ^= 1;
-		vbl_cursor_cnt = cursor_blink_rate; 
-	}
-}	
-	
 static int scrollback_phys_max = 0;
 static int scrollback_max = 0;
 static int scrollback_current = 0;
@@ -1129,7 +1098,7 @@ static int scrollback_current = 0;
 int update_var(int con, struct fb_info *info)
 {
 	if (con == info->currcon) 
-		return fb_pan_display(&info->var, info);
+		return fb_pan_display(info, &info->var);
 	return 0;
 }
 
@@ -1632,16 +1601,16 @@ static int fbcon_resize(struct vc_data *
 	if (x_diff < 0 || x_diff > fw ||
 	   (y_diff < 0 || y_diff > fh)) {
 		var.activate = FB_ACTIVATE_TEST;
-		err = fb_set_var(&var, info);
+		err = fb_set_var(info, &var);
 		if (err || width > var.xres/fw ||
 		    height > var.yres/fh)
 			return -EINVAL;
 		DPRINTK("resize now %ix%i\n", var.xres, var.yres);
 		var.activate = FB_ACTIVATE_NOW;
-		fb_set_var(&var, info);
+		fb_set_var(info, &var);
 	}
 	p->vrows = var.yres_virtual/fh;
-	if(var.yres > (fh * (height + 1)))
+	if (var.yres > (fh * (height + 1)))
 		p->vrows -= (var.yres - (fh * height)) / fh;
 	return 0;
 }
@@ -1748,7 +1717,7 @@ static int fbcon_blank(struct vc_data *v
 			update_screen(vc->vc_num);
 		return 0;
 	} else
-		return fb_blank(blank, info);
+		return fb_blank(info, blank);
 }
 
 static void fbcon_free_font(struct display *p)
diff -puN drivers/video/console/fbcon.h~fbdev drivers/video/console/fbcon.h
--- 25/drivers/video/console/fbcon.h~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/console/fbcon.h	2003-04-13 22:00:13.000000000 -0700
@@ -33,6 +33,7 @@ struct display {
     u_short scrollmode;             /* Scroll Method */
     short yscroll;                  /* Hardware scrolling */
     int vrows;                      /* number of virtual rows */
+    int cursor_shape;
 };
 
 /* drivers/video/console/fbcon.c */
diff -puN drivers/video/controlfb.c~fbdev drivers/video/controlfb.c
--- 25/drivers/video/controlfb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/controlfb.c	2003-04-13 22:00:13.000000000 -0700
@@ -376,13 +376,12 @@ static int controlfb_setcolreg(u_int reg
 		int i;
 		switch (p->par.cmode) {
 		case CMODE_16:
-			((u16 *) (info->pseudo_palette))[regno] =
+			p->pseudo_palette[regno] =
 			    (regno << 10) | (regno << 5) | regno;
 			break;
 		case CMODE_32:
 			i = (regno << 8) | regno;
-			((u32 *) (info->pseudo_palette))[regno] =
-			    (i << 16) | i;
+			p->pseudo_palette[regno] = (i << 16) | i;
 			break;
 		}
 	}
@@ -475,7 +474,6 @@ try_again:
 		var.yres_virtual = vyres;
 
 	/* Apply default var */
-	p->info.var = var;
 	var.activate = FB_ACTIVATE_NOW;
 	rc = fb_set_var(&var, &p->info);
 	if (rc && (vmode != VMODE_640_480_60 || cmode != CMODE_8))
@@ -1068,17 +1066,7 @@ void __init control_setup(char *options)
 		return;
 
 	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "font:", 5)) {
-			char *p;
-			int i;
-
-			p = this_opt +5;
-			for (i = 0; i < sizeof(fontname) - 1; i++)
-				if (!*p || *p == ' ' || *p == ',')
-					break;
-			memcpy(fontname, this_opt + 5, i);
-			fontname[i] = 0;
-		} else if (!strncmp(this_opt, "vmode:", 6)) {
+		if (!strncmp(this_opt, "vmode:", 6)) {
 			int vmode = simple_strtoul(this_opt+6, NULL, 0);
 			if (vmode > 0 && vmode <= VMODE_MAX &&
 			    control_mac_modes[vmode - 1].m[1] >= 0)
diff -puN /dev/null drivers/video/edid.h
--- /dev/null	2002-08-30 16:31:37.000000000 -0700
+++ 25-akpm/drivers/video/edid.h	2003-04-13 22:00:13.000000000 -0700
@@ -0,0 +1,138 @@
+/* 
+ * drivers/video/edid.h - EDID/DDC Header
+ *
+ * Based on:
+ *   1. XFree86 4.3.0, edid.h
+ *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ * 
+ *   2. John Fremlin <vii@users.sourceforge.net> and 
+ *      Ani Joshi <ajoshi@unixbox.com>
+ *
+ * DDC is a Trademark of VESA (Video Electronics Standard Association).
+ *
+ * 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.
+*/
+
+#ifndef __EDID_H__
+#define __EDID_H__
+
+#define EDID_LENGTH				0x80
+#define EDID_HEADER				0x00
+#define EDID_HEADER_END				0x07
+
+#define ID_MANUFACTURER_NAME			0x08
+#define ID_MANUFACTURER_NAME_END		0x09
+#define ID_MODEL				0x0a
+
+#define ID_SERIAL_NUMBER			0x0c
+
+#define MANUFACTURE_WEEK			0x10
+#define MANUFACTURE_YEAR			0x11
+
+#define EDID_STRUCT_VERSION			0x12
+#define EDID_STRUCT_REVISION			0x13
+
+#define EDID_STRUCT_DISPLAY                     0x14
+
+#define DPMS_FLAGS				0x18
+#define ESTABLISHED_TIMING_1			0x23
+#define ESTABLISHED_TIMING_2			0x24
+#define MANUFACTURERS_TIMINGS			0x25
+
+/* standard timings supported */
+#define STD_TIMING                              8
+#define STD_TIMING_DESCRIPTION_SIZE             2
+#define STD_TIMING_DESCRIPTIONS_START           0x26
+
+#define DETAILED_TIMING_DESCRIPTIONS_START	0x36
+#define DETAILED_TIMING_DESCRIPTION_SIZE	18
+#define NO_DETAILED_TIMING_DESCRIPTIONS		4
+
+#define DETAILED_TIMING_DESCRIPTION_1		0x36
+#define DETAILED_TIMING_DESCRIPTION_2		0x48
+#define DETAILED_TIMING_DESCRIPTION_3		0x5a
+#define DETAILED_TIMING_DESCRIPTION_4		0x6c
+
+#define DESCRIPTOR_DATA				5
+
+#define UPPER_NIBBLE( x ) \
+        (((128|64|32|16) & (x)) >> 4)
+
+#define LOWER_NIBBLE( x ) \
+        ((1|2|4|8) & (x))
+
+#define COMBINE_HI_8LO( hi, lo ) \
+        ( (((unsigned)hi) << 8) | (unsigned)lo )
+
+#define COMBINE_HI_4LO( hi, lo ) \
+        ( (((unsigned)hi) << 4) | (unsigned)lo )
+
+#define PIXEL_CLOCK_LO     (unsigned)block[ 0 ]
+#define PIXEL_CLOCK_HI     (unsigned)block[ 1 ]
+#define PIXEL_CLOCK	   (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
+#define H_ACTIVE_LO        (unsigned)block[ 2 ]
+#define H_BLANKING_LO      (unsigned)block[ 3 ]
+#define H_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_ACTIVE           COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
+#define H_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_BLANKING         COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
+
+#define V_ACTIVE_LO        (unsigned)block[ 5 ]
+#define V_BLANKING_LO      (unsigned)block[ 6 ]
+#define V_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_ACTIVE           COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
+#define V_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_BLANKING         COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
+
+#define H_SYNC_OFFSET_LO   (unsigned)block[ 8 ]
+#define H_SYNC_WIDTH_LO    (unsigned)block[ 9 ]
+
+#define V_SYNC_OFFSET_LO   UPPER_NIBBLE( (unsigned)block[ 10 ] )
+#define V_SYNC_WIDTH_LO    LOWER_NIBBLE( (unsigned)block[ 10 ] )
+
+#define V_SYNC_WIDTH_HI    ((unsigned)block[ 11 ] & (1|2))
+#define V_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (4|8)) >> 2)
+
+#define H_SYNC_WIDTH_HI    (((unsigned)block[ 11 ] & (16|32)) >> 4)
+#define H_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (64|128)) >> 6)
+
+#define V_SYNC_WIDTH       COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
+#define V_SYNC_OFFSET      COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
+
+#define H_SYNC_WIDTH       COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
+#define H_SYNC_OFFSET      COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
+
+#define H_SIZE_LO          (unsigned)block[ 12 ]
+#define V_SIZE_LO          (unsigned)block[ 13 ]
+
+#define H_SIZE_HI          UPPER_NIBBLE( (unsigned)block[ 14 ] )
+#define V_SIZE_HI          LOWER_NIBBLE( (unsigned)block[ 14 ] )
+
+#define H_SIZE             COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
+#define V_SIZE             COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
+
+#define H_BORDER           (unsigned)block[ 15 ]
+#define V_BORDER           (unsigned)block[ 16 ]
+
+#define FLAGS              (unsigned)block[ 17 ]
+
+#define INTERLACED         (FLAGS&128)
+#define SYNC_TYPE          (FLAGS&3<<3)	/* bits 4,3 */
+#define SYNC_SEPARATE      (3<<3)
+#define HSYNC_POSITIVE     (FLAGS & 4)
+#define VSYNC_POSITIVE     (FLAGS & 2)
+
+#define V_MIN_RATE              block[ 5 ]
+#define V_MAX_RATE              block[ 6 ]
+#define H_MIN_RATE              block[ 7 ]
+#define H_MAX_RATE              block[ 8 ]
+#define MAX_PIXEL_CLOCK         (((int)block[ 9 ]) * 10)
+#define GTF_SUPPORT		block[10]
+
+#define DPMS_ACTIVE_OFF		(1 << 5)
+#define DPMS_SUSPEND		(1 << 6)
+#define DPMS_STANDBY		(1 << 7)
+
+#endif /* __EDID_H__ */
diff -puN drivers/video/fbcmap.c~fbdev drivers/video/fbcmap.c
--- 25/drivers/video/fbcmap.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/fbcmap.c	2003-04-13 22:00:13.000000000 -0700
@@ -154,11 +154,11 @@ void fb_dealloc_cmap(struct fb_cmap *cma
  *
  */
 
-void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
 {
-    int size;
     int tooff = 0, fromoff = 0;
-
+    int size;
+    
     if (to->start > from->start)
 	fromoff = to->start-from->start;
     else
@@ -167,7 +167,7 @@ void fb_copy_cmap(struct fb_cmap *from, 
     if (size > (int) (from->len - fromoff))
 	size = from->len-fromoff;
     if (size <= 0)
-	return;
+	return -EINVAL;
     size *= sizeof(u16);
     
     switch (fsfromto) {
@@ -179,20 +179,29 @@ void fb_copy_cmap(struct fb_cmap *from, 
 	    memcpy(to->transp+tooff, from->transp+fromoff, size);
         break;
     case 1:
-	copy_from_user(to->red+tooff, from->red+fromoff, size);
-	copy_from_user(to->green+tooff, from->green+fromoff, size);
-	copy_from_user(to->blue+tooff, from->blue+fromoff, size);
+	if (copy_from_user(to->red+tooff, from->red+fromoff, size))
+		return -EFAULT;
+	if (copy_from_user(to->green+tooff, from->green+fromoff, size))
+		return -EFAULT;	
+	if (copy_from_user(to->blue+tooff, from->blue+fromoff, size))
+		return -EFAULT;
 	if (from->transp && to->transp)
-            copy_from_user(to->transp+tooff, from->transp+fromoff, size);
+            if (copy_from_user(to->transp+tooff, from->transp+fromoff, size))
+		    return -EFAULT;	
 	break;
     case 2:
-	copy_to_user(to->red+tooff, from->red+fromoff, size);
-	copy_to_user(to->green+tooff, from->green+fromoff, size);
-	copy_to_user(to->blue+tooff, from->blue+fromoff, size);
+	if (copy_to_user(to->red+tooff, from->red+fromoff, size))
+		return -EFAULT;
+	if (copy_to_user(to->green+tooff, from->green+fromoff, size))
+		return -EFAULT;
+	if (copy_to_user(to->blue+tooff, from->blue+fromoff, size))
+		return -EFAULT;
 	if (from->transp && to->transp)
-	    copy_to_user(to->transp+tooff, from->transp+fromoff, size);
+		if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
+			return -EFAULT;
 	break;
     }
+    return 0;
 }
 
 /**
diff -puN drivers/video/fbmem.c~fbdev drivers/video/fbmem.c
--- 25/drivers/video/fbmem.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/fbmem.c	2003-04-13 22:00:13.000000000 -0700
@@ -403,22 +403,22 @@ u8 sys_inbuf(u8 *src)
 	return *src;
 }
 
-void sys_outbuf(u8 src, u8 *dst)
+void sys_outbuf(u8 *src, u8 *dst, unsigned int size)
 {
-	*dst = src;
+	memcpy(dst, src, size);
 }	
 
 void move_buf_aligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch, 
 			u32 s_pitch, u32 height)
 {
-	int i, j;
-	
+	int i;
+
 	for (i = height; i--; ) {
-		for (j = 0; j < s_pitch; j++)
-			info->pixmap.outbuf(*src++, dst+j);
+		info->pixmap.outbuf(src, dst, s_pitch);
+		src += s_pitch;
 		dst += d_pitch;
-	}	
-}	
+	}
+}
 
 void move_buf_unaligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch, 
 			u32 height, u32 mask, u32 shift_high, u32 shift_low,
@@ -432,20 +432,23 @@ void move_buf_unaligned(struct fb_info *
 			tmp = info->pixmap.inbuf(dst+j);
 			tmp &= mask;
 			tmp |= *src >> shift_low;
-			info->pixmap.outbuf(tmp, dst+j);
-			info->pixmap.outbuf(*src << shift_high, dst+j+1);
+			info->pixmap.outbuf(&tmp, dst+j, 1);
+			tmp = *src << shift_high;
+			info->pixmap.outbuf(&tmp, dst+j+1, 1);
 			src++;
 		}
 		tmp = info->pixmap.inbuf(dst+idx);
 		tmp &= mask;
 		tmp |= *src >> shift_low;
-		info->pixmap.outbuf(tmp, dst+idx);
-		if (shift_high < mod)
-			info->pixmap.outbuf(*src<<shift_high, dst+idx+1);
+		info->pixmap.outbuf(&tmp, dst+idx, 1);
+		if (shift_high < mod) {
+			tmp = *src << shift_high;
+			info->pixmap.outbuf(&tmp, dst+idx+1, 1);
+		}	
 		src++;
 		dst += d_pitch;
-	}	
-}	
+	}
+}
 
 /*
  * we need to lock this section since fb_cursor
@@ -456,8 +459,7 @@ u32 fb_get_buffer_offset(struct fb_info 
 	u32 align = info->pixmap.buf_align - 1;
 	u32 offset, count = 1000;
 
-	spin_lock_irqsave(&info->pixmap.lock,
-			  info->pixmap.lock_flags);
+	spin_lock(&info->pixmap.lock);
 	offset = info->pixmap.offset + align;
 	offset &= ~align;
 	if (offset + size > info->pixmap.size) {
@@ -468,12 +470,9 @@ u32 fb_get_buffer_offset(struct fb_info 
 		offset = 0;
 	}
 	info->pixmap.offset = offset + size;
-
 	atomic_inc(&info->pixmap.count);	
 	smp_mb__after_atomic_inc();
-
-	spin_unlock_irqrestore(&info->pixmap.lock,
-			       info->pixmap.lock_flags);
+	spin_unlock(&info->pixmap.lock);
 	return offset;
 }
 
@@ -566,13 +565,13 @@ static void __init fb_set_logo_directpal
 
 static void __init fb_set_logo(struct fb_info *info,
 			       const struct linux_logo *logo, u8 *dst,
-			       int needs_logo)
+			       int depth)
 {
 	int i, j, shift;
 	const u8 *src = logo->data;
 	u8 d, xor = 0;
 
-	switch (needs_logo) {
+	switch (depth) {
 	case 4:
 		for (i = 0; i < logo->height; i++)
 			for (j = 0; j < logo->width; src++) {
@@ -620,20 +619,18 @@ static void __init fb_set_logo(struct fb
  * to set the DAC or the pseudo_palette.  However, the bitmap is packed, ie,
  * each byte contains color information for two pixels (upper and lower nibble).
  * To be consistent with fb_imageblit() usage, we therefore separate the two
- * nibbles into separate bytes. The "needs_logo" flag will be set to 4.
+ * nibbles into separate bytes. The "depth" flag will be set to 4.
  *
  * Case 3 - linux_logo_mono:
  * This is similar with Case 2.  Each byte contains information for 8 pixels.
- * We isolate each bit and expand each into a byte. The "needs_logo" flag will
+ * We isolate each bit and expand each into a byte. The "depth" flag will
  * be set to 1.
  */
 static struct logo_data {
 	int depth;
-	int needs_logo;
 	int needs_directpalette;
 	int needs_truepalette;
 	int needs_cmapreset;
-	int type;
 	const struct linux_logo *logo;
 } fb_logo;
 
@@ -641,74 +638,48 @@ int fb_prepare_logo(struct fb_info *info
 {
 	memset(&fb_logo, 0, sizeof(struct logo_data));
 
-	fb_logo.depth = info->var.bits_per_pixel;
-
 	switch (info->fix.visual) {
 	case FB_VISUAL_TRUECOLOR:
-		if (fb_logo.depth >= 8) {
+		if (info->var.bits_per_pixel >= 8)
 			fb_logo.needs_truepalette = 1;
-			fb_logo.needs_logo = 8;
-		} else if (fb_logo.depth >= 4)
-			fb_logo.needs_logo = 4;
-		else 
-			fb_logo.needs_logo = 1;
 		break;
 	case FB_VISUAL_DIRECTCOLOR:
-		if (fb_logo.depth >= 24) {
+		if (info->var.bits_per_pixel >= 24) {
 			fb_logo.needs_directpalette = 1;
 			fb_logo.needs_cmapreset = 1;
-			fb_logo.needs_logo = 8;
-		} else if (fb_logo.depth >= 16)	/* 16 colors */
-			fb_logo.needs_logo = 4;
-		else
-			fb_logo.needs_logo = 1;	/* 2 colors */
-		break;
-	case FB_VISUAL_MONO01:
-		/* reversed 0 = fg, 1 = bg */
-		fb_logo.needs_logo = ~1;
-		break;
-	case FB_VISUAL_MONO10:
-		fb_logo.needs_logo = 1;
+		}
 		break;
 	case FB_VISUAL_PSEUDOCOLOR:
-	case FB_VISUAL_STATIC_PSEUDOCOLOR:
-		if (fb_logo.depth >= 8) {
-			fb_logo.needs_logo = 8;
-			if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
-				fb_logo.needs_cmapreset = 1;
-		} else if (fb_logo.depth >= 4)
-			fb_logo.needs_logo = 4;	/* 16 colors */
-		else
-			fb_logo.needs_logo = 1;	
+		fb_logo.needs_cmapreset = 1;
 		break;
 	}
 
-	if (fb_logo.needs_logo >= 8)
-		fb_logo.type = LINUX_LOGO_CLUT224;
-	else if (fb_logo.needs_logo >= 4)
-		fb_logo.type = LINUX_LOGO_VGA16;
-	else
-		fb_logo.type = LINUX_LOGO_MONO;
-
 	/* Return if no suitable logo was found */
-	fb_logo.logo = fb_find_logo(fb_logo.type);
+	fb_logo.logo = find_logo(info->var.bits_per_pixel);
+	
 	if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) {
 		fb_logo.logo = NULL;
 		return 0;
 	}
+	/* What depth we asked for might be different from what we get */
+	if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
+		fb_logo.depth = 8;
+	else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
+		fb_logo.depth = 4;
+	else
+		fb_logo.depth = 1;		
 	return fb_logo.logo->height;
 }
 
 int fb_show_logo(struct fb_info *info)
 {
-	unsigned char *fb = info->screen_base, *logo_new = NULL;
 	u32 *palette = NULL, *saved_pseudo_palette = NULL;
+	unsigned char *logo_new = NULL;
 	struct fb_image image;
 	int x;
 
 	/* Return if the frame buffer is not mapped */
-	if (!fb || !info->fbops->fb_imageblit ||
-	    fb_logo.logo == NULL)
+	if (fb_logo.logo == NULL)
 		return 0;
 
 	image.depth = fb_logo.depth;
@@ -732,7 +703,7 @@ int fb_show_logo(struct fb_info *info)
 		info->pseudo_palette = palette;
 	}
 
-	if (fb_logo.needs_logo != 8) {
+	if (fb_logo.depth == 4) {
 		logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height, 
 				   GFP_KERNEL);
 		if (logo_new == NULL) {
@@ -742,9 +713,8 @@ int fb_show_logo(struct fb_info *info)
 				info->pseudo_palette = saved_pseudo_palette;
 			return 0;
 		}
-
 		image.data = logo_new;
-		fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.needs_logo);
+		fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth);
 	}
 
 	image.width = fb_logo.logo->width;
@@ -755,8 +725,8 @@ int fb_show_logo(struct fb_info *info)
 	     x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) {
 		image.dx = x;
 		info->fbops->fb_imageblit(info, &image);
-		atomic_dec(&info->pixmap.count);
-		smp_mb__after_atomic_dec();
+		//atomic_dec(&info->pixmap.count);
+		//smp_mb__after_atomic_dec();
 	}
 	
 	if (palette != NULL)
@@ -876,7 +846,54 @@ static void try_to_load(int fb)
 #endif /* CONFIG_KMOD */
 
 int
-fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+fb_cursor(struct fb_info *info, struct fb_cursor *sprite)
+{
+	struct fb_cursor cursor;
+	int err;
+	
+	if (copy_from_user(&cursor, sprite, sizeof(struct fb_cursor)))
+		return -EFAULT;
+
+	if (cursor.set & FB_CUR_SETCUR)
+		info->cursor.enable = 1;
+	
+	if (cursor.set & FB_CUR_SETCMAP) {
+		err = fb_copy_cmap(&cursor.image.cmap, &sprite->image.cmap, 1);
+		if (err)
+			return err;
+	}
+	
+	if (cursor.set & FB_CUR_SETSHAPE) {
+		int size = ((cursor.image.width + 7) >> 3) * cursor.image.height;		
+		if ((cursor.image.height != info->cursor.image.height) ||
+		    (cursor.image.width != info->cursor.image.width))
+			cursor.set |= FB_CUR_SETSIZE;
+		
+		cursor.image.data = kmalloc(size, GFP_KERNEL);
+		if (!cursor.image.data)
+			return -ENOMEM;
+		
+		cursor.mask = kmalloc(size, GFP_KERNEL);
+		if (!cursor.mask) {
+			kfree(cursor.image.data);
+			return -ENOMEM;
+		}
+		
+		if (copy_from_user(&cursor.image.data, sprite->image.data, size) ||
+		    copy_from_user(cursor.mask, sprite->mask, size)) { 
+			kfree(cursor.image.data);
+			kfree(cursor.mask);
+			return -EFAULT;
+		}
+	}
+	info->cursor.set = cursor.set;
+	info->cursor.rop = cursor.rop;
+	err = info->fbops->fb_cursor(info, &cursor);
+	return err;
+}
+
+int
+fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
 {
         int xoffset = var->xoffset;
         int yoffset = var->yoffset;
@@ -898,7 +915,7 @@ fb_pan_display(struct fb_var_screeninfo 
 }
 
 int
-fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info)
+fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
 {
 	int err;
 
@@ -917,7 +934,7 @@ fb_set_var(struct fb_var_screeninfo *var
 			if (info->fbops->fb_set_par)
 				info->fbops->fb_set_par(info);
 
-			fb_pan_display(&info->var, info);
+			fb_pan_display(info, &info->var);
 
 			fb_set_cmap(&info->cmap, 1, info);
 		}
@@ -926,7 +943,7 @@ fb_set_var(struct fb_var_screeninfo *var
 }
 
 int
-fb_blank(int blank, struct fb_info *info)
+fb_blank(struct fb_info *info, int blank)
 {	
 	/* ??? Varible sized stack allocation.  */
 	u16 black[info->cmap.len];
@@ -960,7 +977,7 @@ fb_ioctl(struct inode *inode, struct fil
 	struct fb_cmap cmap;
 	int i;
 	
-	if (! fb)
+	if (!fb)
 		return -ENODEV;
 	switch (cmd) {
 	case FBIOGET_VSCREENINFO:
@@ -969,7 +986,7 @@ fb_ioctl(struct inode *inode, struct fil
 	case FBIOPUT_VSCREENINFO:
 		if (copy_from_user(&var, (void *) arg, sizeof(var)))
 			return -EFAULT;
-		i = fb_set_var(&var, info);
+		i = fb_set_var(info, &var);
 		if (i) return i;
 		if (copy_to_user((void *) arg, &var, sizeof(var)))
 			return -EFAULT;
@@ -983,16 +1000,17 @@ fb_ioctl(struct inode *inode, struct fil
 	case FBIOGETCMAP:
 		if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
 			return -EFAULT;
-		fb_copy_cmap(&info->cmap, &cmap, 0);
-		return 0;
+		return (fb_copy_cmap(&info->cmap, &cmap, 0));
 	case FBIOPAN_DISPLAY:
 		if (copy_from_user(&var, (void *) arg, sizeof(var)))
 			return -EFAULT;
-		if ((i = fb_pan_display(&var, info)))
+		if ((i = fb_pan_display(info, &var)))
 			return i;
 		if (copy_to_user((void *) arg, &var, sizeof(var)))
 			return -EFAULT;
-		return i;
+		return 0;
+	case FBIO_CURSOR:
+		return (fb_cursor(info, (struct fb_cursor *) arg));
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
 	case FBIOGET_CON2FBMAP:
 		if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
@@ -1022,7 +1040,7 @@ fb_ioctl(struct inode *inode, struct fil
 		return 0;
 #endif	/* CONFIG_FRAMEBUFFER_CONSOLE */
 	case FBIOBLANK:
-		return fb_blank(arg, info);
+		return fb_blank(info, arg);
 	default:
 		if (fb->fb_ioctl == NULL)
 			return -EINVAL;
@@ -1136,6 +1154,8 @@ fb_open(struct inode *inode, struct file
 	struct fb_info *info;
 	int res = 0;
 
+	if (fbidx >= FB_MAX)
+		return -ENODEV;
 #ifdef CONFIG_KMOD
 	if (!(info = registered_fb[fbidx]))
 		try_to_load(fbidx);
@@ -1219,7 +1239,7 @@ register_framebuffer(struct fb_info *fb_
 	if (fb_info->pixmap.inbuf == NULL)
 		fb_info->pixmap.inbuf = sys_inbuf;
 	spin_lock_init(&fb_info->pixmap.lock);
-	
+
 	registered_fb[i] = fb_info;
 	sprintf(name_buf, "fb/%d", i);
 	devfs_register(NULL, name_buf, DEVFS_FL_DEFAULT,
diff -puN drivers/video/fbmon.c~fbdev drivers/video/fbmon.c
--- 25/drivers/video/fbmon.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/fbmon.c	2003-04-13 22:00:13.000000000 -0700
@@ -1,7 +1,25 @@
 /*
- *   linux/drivers/video/fbmon.c
+ * linux/drivers/video/fbmon.c
  *
- *  Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
+ * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
+ *
+ * Credits:
+ * 
+ * The EDID Parser is a conglomeration from the following sources:
+ *
+ *   1. SciTech SNAP Graphics Architecture
+ *      Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
+ *
+ *   2. XFree86 4.3.0, interpret_edid.c
+ *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ * 
+ *   3. John Fremlin <vii@users.sourceforge.net> and 
+ *      Ani Joshi <ajoshi@unixbox.com>
+ *  
+ * Generalized Timing Formula is derived from:
+ *
+ *      GTF Spreadsheet by Andy Morrish (1/5/97) 
+ *      available at http://www.vesa.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
@@ -11,124 +29,32 @@
 #include <linux/tty.h>
 #include <linux/fb.h>
 #include <linux/module.h>
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#endif
 #ifdef CONFIG_ALL_PPC
+#include <linux/pci.h>
 #include <asm/prom.h>
 #endif
+#include <video/edid.h>
+#include "edid.h"
 
 /* 
  * EDID parser
- *
- * portions of this file were based on the EDID parser by
- * John Fremlin <vii@users.sourceforge.net> and Ani Joshi <ajoshi@unixbox.com>
  */
 
-#define EDID_LENGTH				0x80
-#define EDID_HEADER				0x00
-#define EDID_HEADER_END				0x07
-
-#define ID_MANUFACTURER_NAME			0x08
-#define ID_MANUFACTURER_NAME_END		0x09
-#define ID_MODEL				0x0a
-
-#define ID_SERIAL_NUMBER			0x0c
-
-#define MANUFACTURE_WEEK			0x10
-#define MANUFACTURE_YEAR			0x11
-
-#define EDID_STRUCT_VERSION			0x12
-#define EDID_STRUCT_REVISION			0x13
-
-#define DPMS_FLAGS				0x18
-#define ESTABLISHED_TIMING_1			0x23
-#define ESTABLISHED_TIMING_2			0x24
-#define MANUFACTURERS_TIMINGS			0x25
-
-#define DETAILED_TIMING_DESCRIPTIONS_START	0x36
-#define DETAILED_TIMING_DESCRIPTION_SIZE	18
-#define NO_DETAILED_TIMING_DESCRIPTIONS		4
-
-#define DETAILED_TIMING_DESCRIPTION_1		0x36
-#define DETAILED_TIMING_DESCRIPTION_2		0x48
-#define DETAILED_TIMING_DESCRIPTION_3		0x5a
-#define DETAILED_TIMING_DESCRIPTION_4		0x6c
-
-#define DESCRIPTOR_DATA				5
-
-#define UPPER_NIBBLE( x ) \
-        (((128|64|32|16) & (x)) >> 4)
-
-#define LOWER_NIBBLE( x ) \
-        ((1|2|4|8) & (x))
-
-#define COMBINE_HI_8LO( hi, lo ) \
-        ( (((unsigned)hi) << 8) | (unsigned)lo )
-
-#define COMBINE_HI_4LO( hi, lo ) \
-        ( (((unsigned)hi) << 4) | (unsigned)lo )
-
-#define PIXEL_CLOCK_LO     (unsigned)block[ 0 ]
-#define PIXEL_CLOCK_HI     (unsigned)block[ 1 ]
-#define PIXEL_CLOCK	   (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*1000)
-#define H_ACTIVE_LO        (unsigned)block[ 2 ]
-#define H_BLANKING_LO      (unsigned)block[ 3 ]
-#define H_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 4 ] )
-#define H_ACTIVE           COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
-#define H_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 4 ] )
-#define H_BLANKING         COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
-
-#define V_ACTIVE_LO        (unsigned)block[ 5 ]
-#define V_BLANKING_LO      (unsigned)block[ 6 ]
-#define V_ACTIVE_HI        UPPER_NIBBLE( (unsigned)block[ 7 ] )
-#define V_ACTIVE           COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
-#define V_BLANKING_HI      LOWER_NIBBLE( (unsigned)block[ 7 ] )
-#define V_BLANKING         COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
-
-#define H_SYNC_OFFSET_LO   (unsigned)block[ 8 ]
-#define H_SYNC_WIDTH_LO    (unsigned)block[ 9 ]
-
-#define V_SYNC_OFFSET_LO   UPPER_NIBBLE( (unsigned)block[ 10 ] )
-#define V_SYNC_WIDTH_LO    LOWER_NIBBLE( (unsigned)block[ 10 ] )
-
-#define V_SYNC_WIDTH_HI    ((unsigned)block[ 11 ] & (1|2))
-#define V_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (4|8)) >> 2)
-
-#define H_SYNC_WIDTH_HI    (((unsigned)block[ 11 ] & (16|32)) >> 4)
-#define H_SYNC_OFFSET_HI   (((unsigned)block[ 11 ] & (64|128)) >> 6)
-
-#define V_SYNC_WIDTH       COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
-#define V_SYNC_OFFSET      COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
-
-#define H_SYNC_WIDTH       COMBINE_HI_4LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
-#define H_SYNC_OFFSET      COMBINE_HI_4LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
-
-#define H_SIZE_LO          (unsigned)block[ 12 ]
-#define V_SIZE_LO          (unsigned)block[ 13 ]
-
-#define H_SIZE_HI          UPPER_NIBBLE( (unsigned)block[ 14 ] )
-#define V_SIZE_HI          LOWER_NIBBLE( (unsigned)block[ 14 ] )
-
-#define H_SIZE             COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
-#define V_SIZE             COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
-
-#define H_BORDER           (unsigned)block[ 15 ]
-#define V_BORDER           (unsigned)block[ 16 ]
-
-#define FLAGS              (unsigned)block[ 17 ]
-
-#define INTERLACED         (FLAGS&128)
-#define SYNC_TYPE          (FLAGS&3<<3)	/* bits 4,3 */
-#define SYNC_SEPARATE      (3<<3)
-#define HSYNC_POSITIVE     (FLAGS & 4)
-#define VSYNC_POSITIVE     (FLAGS & 2)
-
 const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
 	0xff, 0xff, 0xff, 0x00
 };
 const unsigned char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
 
+static void copy_string(unsigned char *c, unsigned char *s)
+{
+  int i;
+  c = c + 5;
+  for (i = 0; (i < 13 && *c != 0x0A); i++)
+    *(s++) = *(c++);
+  *s = 0;
+  while (i-- && (*--s == 0x20)) *s = 0;
+}
+
 static int edid_checksum(unsigned char *edid)
 {
 	unsigned char i, csum = 0;
@@ -157,138 +83,785 @@ static int edid_check_header(unsigned ch
 	return 1;
 }
 
-
-static char *edid_get_vendor(unsigned char *block)
+static void parse_vendor_block(unsigned char *block)
 {
-	static char sign[4];
-	unsigned short h;
+	unsigned char c[4];
 
-	h = COMBINE_HI_8LO(block[0], block[1]);
-	sign[0] = ((h >> 10) & 0x1f) + 'A' - 1;
-	sign[1] = ((h >> 5) & 0x1f) + 'A' - 1;
-	sign[2] = (h & 0x1f) + 'A' - 1;
-	sign[3] = 0;
+	c[0] = ((block[0] & 0x7c) >> 2) + '@';
+	c[1] = ((block[0] & 0x03) << 3) + ((block[1] & 0xe0) >> 5) + '@';
+	c[2] = (block[1] & 0x1f) + '@';
+	c[3] = 0;
+	printk("   Manufacturer: %s ", c);
+	printk("Model: %x ", block[2] + (block[3] << 8));
+	printk("Serial#: %u\n", block[4] + (block[5] << 8) + 
+	       (block[6] << 16) + (block[7] << 24));
+	printk("   Year: %u Week %u\n", block[9] + 1990, block[8]);
+}
 
-	return sign;
+static void parse_dpms_capabilities(unsigned char flags)
+{
+	printk("      DPMS: Active %s, Suspend %s, Standby %s\n",
+	       (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
+	       (flags & DPMS_SUSPEND)    ? "yes" : "no",
+	       (flags & DPMS_STANDBY)    ? "yes" : "no");
 }
+	
+static void print_chroma(unsigned char *block)
+{
+	int tmp;
 
-static char *edid_get_monitor(unsigned char *block)
+	/* Chromaticity data */
+	printk("      Chromaticity: ");
+	tmp = ((block[5] & (3 << 6)) >> 6) | (block[0x7] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	printk("RedX:   0.%03d ", tmp/1024);
+
+	tmp = ((block[5] & (3 << 4)) >> 4) | (block[0x8] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	printk("RedY:   0.%03d\n", tmp/1024);
+
+	tmp = ((block[5] & (3 << 2)) >> 2) | (block[0x9] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	printk("                    GreenX: 0.%03d ", tmp/1024);
+
+	tmp = (block[5] & 3) | (block[0xa] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	printk("GreenY: 0.%03d\n", tmp/1024);
+
+	tmp = ((block[6] & (3 << 6)) >> 6) | (block[0xb] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	printk("                    BlueX:  0.%03d ", tmp/1024);
+
+	tmp = ((block[6] & (3 << 4)) >> 4) | (block[0xc] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	printk("BlueY:  0.%03d\n", tmp/1024);
+	
+	tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	printk("                    WhiteX: 0.%03d ", tmp/1024);
+
+	tmp = (block[6] & 3) | (block[0xe] << 2);
+	tmp *= 1000;
+	tmp += 512;
+	printk("WhiteY: 0.%03d\n", tmp/1024);
+}
+
+static void parse_display_block(unsigned char *block)
 {
-	static char name[13];
-	unsigned i;
-	const unsigned char *ptr = block + DESCRIPTOR_DATA;
+	unsigned char c;
 
-	for (i = 0; i < 13; i++, ptr++) {
-		if (*ptr == 0xa) {
-			name[i] = 0x00;
-			return name;
+	c = (block[0] & 0x80) >> 7;
+	if (c) 
+		printk("      Digital Display Input");
+	else {
+		printk("      Analog Display Input: Input Voltage - ");
+		switch ((block[0] & 0x60) >> 5) {
+		case 0:
+			printk("0.700V/0.300V");
+			break;
+		case 1:
+			printk("0.714V/0.286V");
+			break;
+		case 2:
+			printk("1.000V/0.400V");
+			break;
+		case 3:
+			printk("0.700V/0.000V");
+			break;
+		default:
+			printk("unknown");
 		}
-		name[i] = *ptr;
+		printk("\n");
 	}
-	return name;
+	c = (block[0] & 0x10) >> 4;
+	if (c)
+		printk("      Configurable signal level\n");
+	printk("      Sync: ");
+	c = block[0] & 0x0f;
+	if (c & 0x10)
+		printk("Blank to Blank ");
+	if (c & 0x08)
+		printk("Separate ");
+	if (c & 0x04)
+		printk("Composite ");
+	if (c & 0x02)
+		printk("Sync on Green ");
+	if (c & 0x01)
+		printk("Serration on ");
+	printk("\n");
+
+	printk("      Max H-size in cm: ");
+	c = block[1];
+	if (c) 
+		printk("%d\n", c);
+	else
+		printk("variable\n");
+	
+	printk("      Max V-size in cm: ");
+	c = block[2];
+	if (c)
+		printk("%d\n", c);
+	else
+		printk("variable\n");
+
+	c = block[3];
+	printk("      Gamma: ");
+	printk("%d.%d\n", (c + 100)/100, (c+100) % 100);
+
+	parse_dpms_capabilities(block[4]);
+
+	switch ((block[4] & 0x18) >> 3) {
+	case 0:
+		printk("      Monochrome/Grayscale\n");
+		break;
+	case 1:
+		printk("      RGB Color Display\n");
+		break;
+	case 2:
+		printk("      Non-RGB Multicolor Display\n");
+		break;
+	default:
+		printk("      Unknown\n");
+		break;
+	}
+
+	print_chroma(block);
+	
+	c = block[4] & 0x7;
+	if (c & 0x04)
+		printk("      Default color format is primary\n");
+	if (c & 0x02)
+		printk("      First DETAILED Timing is preferred\n");
+	if (c & 0x01)
+		printk("      Display is GTF capable\n");
 }
 
+static void parse_std_md_block(unsigned char *block)
+{
+	unsigned char c;
+
+	c = block[0];
+	if (c&0x80) printk("      720x400@70Hz\n");
+	if (c&0x40) printk("      720x400@88Hz\n");
+	if (c&0x20) printk("      640x480@60Hz\n");
+	if (c&0x10) printk("      640x480@67Hz\n");
+	if (c&0x08) printk("      640x480@72Hz\n");
+	if (c&0x04) printk("      640x480@75Hz\n");
+	if (c&0x02) printk("      800x600@56Hz\n");
+	if (c&0x01) printk("      800x600@60Hz\n");
+
+	c = block[1];
+	if (c&0x80) printk("      800x600@72Hz\n");
+	if (c&0x40) printk("      800x600@75Hz\n");
+	if (c&0x20) printk("      832x624@75Hz\n");
+	if (c&0x10) printk("      1024x768@87Hz (interlaced)\n");
+	if (c&0x08) printk("      1024x768@60Hz\n");
+	if (c&0x04) printk("      1024x768@70Hz\n");
+	if (c&0x02) printk("      1024x768@75Hz\n");
+	if (c&0x01) printk("      1280x1024@75Hz\n");
+
+	c = block[2];
+	if (c&0x80) printk("      1152x870@75Hz\n");
+	printk("      Manufacturer's mask: %x\n",c&0x7F);
+}
+		
+		
 static int edid_is_timing_block(unsigned char *block)
 {
-	if ((block[0] == 0x00) && (block[1] == 0x00))
+	if ((block[0] != 0x00) || (block[1] != 0x00) || 
+	    (block[2] != 0x00) || (block[4] != 0x00)) 
+		return 1;
+	else
 		return 0;
+}
+
+static int edid_is_serial_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) && 
+	    (block[2] == 0x00) && (block[3] == 0xff) &&
+	    (block[4] == 0x00))
+		return 1;
 	else
+		return 0;
+}
+
+static int edid_is_ascii_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) && 
+	    (block[2] == 0x00) && (block[3] == 0xfe) &&
+	    (block[4] == 0x00))
 		return 1;
+	else
+		return 0;
+}
+
+static int edid_is_limits_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) && 
+	    (block[2] == 0x00) && (block[3] == 0xfd) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
 }
 
 static int edid_is_monitor_block(unsigned char *block)
 {
-	if ((block[0] == 0x00) && (block[1] == 0x00) && (block[3] == 0xfc))
+	if ((block[0] == 0x00) && (block[1] == 0x00) && 
+	    (block[2] == 0x00) && (block[3] == 0xfc) &&
+	    (block[4] == 0x00))
 		return 1;
 	else
 		return 0;
 }
 
-static void parse_timing_block(unsigned char *block,
-			       struct fb_var_screeninfo *var)
+static int edid_is_color_block(unsigned char *block)
 {
-	var->xres = var->xres_virtual = H_ACTIVE;
-	var->yres = var->yres_virtual = V_ACTIVE;
-	var->height = var->width = -1;
-	var->right_margin = H_SYNC_OFFSET;
-	var->left_margin = (H_ACTIVE + H_BLANKING) -
-	    (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
-	var->upper_margin = V_BLANKING - V_SYNC_OFFSET - V_SYNC_WIDTH;
-	var->lower_margin = V_SYNC_OFFSET;
-	var->hsync_len = H_SYNC_WIDTH;
-	var->vsync_len = V_SYNC_WIDTH;
-	var->pixclock = PIXEL_CLOCK;
-	var->pixclock /= 1000;
-	var->pixclock = KHZ2PICOS(var->pixclock);
+	if ((block[0] == 0x00) && (block[1] == 0x00) && 
+	    (block[2] == 0x00) && (block[3] == 0xfb) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
 
-	if (HSYNC_POSITIVE)
-		var->sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (VSYNC_POSITIVE)
-		var->sync |= FB_SYNC_VERT_HIGH_ACT;
+static int edid_is_std_timings_block(unsigned char *block)
+{
+	if ((block[0] == 0x00) && (block[1] == 0x00) && 
+	    (block[2] == 0x00) && (block[3] == 0xfa) &&
+	    (block[4] == 0x00))
+		return 1;
+	else
+		return 0;
+}
+
+static void parse_serial_block(unsigned char *block)
+{
+	unsigned char c[13];
+	
+	copy_string(block, c);
+	printk("      Serial No     : %s\n", c);
+}
+
+static void parse_ascii_block(unsigned char *block)
+{
+	unsigned char c[13];
+	
+	copy_string(block, c);
+	printk("      %s\n", c);
+}
+
+static void parse_limits_block(unsigned char *block)
+{
+	printk("      HorizSync     : %d-%d KHz\n", H_MIN_RATE, H_MAX_RATE);
+	printk("      VertRefresh   : %d-%d Hz\n", V_MIN_RATE, V_MAX_RATE);
+	if (MAX_PIXEL_CLOCK != 10*0xff)
+		printk("      Max Pixelclock: %d MHz\n", (int) MAX_PIXEL_CLOCK);
+}
+
+static void parse_monitor_block(unsigned char *block)
+{
+	unsigned char c[13];
+	
+	copy_string(block, c);
+	printk("      Monitor Name  : %s\n", c);
+}
+
+static void parse_color_block(unsigned char *block)
+{
+	printk("      Color Point    : unimplemented\n");
+}
+
+static void parse_std_timing_block(unsigned char *block)
+{
+	int xres, yres = 0, refresh, ratio, err = 1;
+	
+	xres = (block[0] + 31) * 8;
+	if (xres <= 256)
+		return;
+
+	ratio = (block[1] & 0xc0) >> 6;
+	switch (ratio) {
+	case 0:
+		yres = xres;
+		break;
+	case 1:
+		yres = (xres * 3)/4;
+		break;
+	case 2:
+		yres = (xres * 4)/5;
+		break;
+	case 3:
+		yres = (xres * 9)/16;
+		break;
+	}
+	refresh = (block[1] & 0x3f) + 60;
+	printk("      %dx%d@%dHz\n", xres, yres, refresh);
+	err = 0;
+}
+
+static void parse_dst_timing_block(unsigned char *block)
+{
+	int i;
+
+	block += 5;
+	for (i = 0; i < 5; i++, block += STD_TIMING_DESCRIPTION_SIZE)
+		parse_std_timing_block(block);
+}
+
+static void parse_detailed_timing_block(unsigned char *block)
+{
+	printk("      %d MHz ",  PIXEL_CLOCK/1000000);
+	printk("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET, 
+	       H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
+	printk("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET, 
+	       V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
+	printk("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-", 
+	       (VSYNC_POSITIVE) ? "+" : "-");
 }
 
 int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 {
-	unsigned char *block, *vendor, *monitor = NULL;
 	int i;
+	unsigned char *block;
+
+	if (edid == NULL || var == NULL)
+		return 1;
 
 	if (!(edid_checksum(edid)))
-		return 0;
+		return 1;
 
 	if (!(edid_check_header(edid)))
+		return 1;
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+
+	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (edid_is_timing_block(block)) {
+			var->xres = var->xres_virtual = H_ACTIVE;
+			var->yres = var->yres_virtual = V_ACTIVE;
+			var->height = var->width = -1;
+			var->right_margin = H_SYNC_OFFSET;
+			var->left_margin = (H_ACTIVE + H_BLANKING) -
+				(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+			var->upper_margin = V_BLANKING - V_SYNC_OFFSET - 
+				V_SYNC_WIDTH;
+			var->lower_margin = V_SYNC_OFFSET;
+			var->hsync_len = H_SYNC_WIDTH;
+			var->vsync_len = V_SYNC_WIDTH;
+			var->pixclock = PIXEL_CLOCK;
+			var->pixclock /= 1000;
+			var->pixclock = KHZ2PICOS(var->pixclock);
+
+			if (HSYNC_POSITIVE)
+				var->sync |= FB_SYNC_HOR_HIGH_ACT;
+			if (VSYNC_POSITIVE)
+				var->sync |= FB_SYNC_VERT_HIGH_ACT;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static void calc_mode_timings(int xres, int yres, int refresh, struct fb_videomode *mode)
+{
+	struct fb_var_screeninfo var;
+	struct fb_info info;
+	
+	var.xres = xres;
+	var.yres = yres;
+	fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 
+		    refresh, &var, &info);
+	mode->xres = xres;
+	mode->yres = yres;
+	mode->pixclock = var.pixclock;
+	mode->refresh = refresh;
+	mode->left_margin = var.left_margin;
+	mode->right_margin = var.right_margin;
+	mode->upper_margin = var.upper_margin;
+	mode->lower_margin = var.lower_margin;
+	mode->hsync_len = var.hsync_len;
+	mode->vsync_len = var.vsync_len;
+	mode->vmode = 0;
+	mode->sync = 0;
+}
+
+static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
+{
+	int num = 0;
+	unsigned char c;
+
+	c = block[0];
+	if (c&0x80) 
+		calc_mode_timings(720, 400, 70, &mode[num++]);
+	if (c&0x40) 
+		calc_mode_timings(720, 400, 88, &mode[num++]);
+	if (c&0x20)
+		mode[num++] = vesa_modes[3];
+	if (c&0x10)
+		calc_mode_timings(640, 480, 67, &mode[num++]);
+	if (c&0x08)
+		mode[num++] = vesa_modes[4];
+	if (c&0x04)
+		mode[num++] = vesa_modes[5];
+	if (c&0x02)
+		mode[num++] = vesa_modes[7];
+	if (c&0x01)
+		mode[num++] = vesa_modes[8];
+
+	c = block[1];
+	if (c&0x80)
+ 		mode[num++] = vesa_modes[9];
+	if (c&0x40)
+ 		mode[num++] = vesa_modes[10];
+	if (c&0x20)
+		calc_mode_timings(832, 624, 75, &mode[num++]);
+	if (c&0x10)
+		mode[num++] = vesa_modes[12];
+	if (c&0x08)
+		mode[num++] = vesa_modes[13];
+	if (c&0x04)
+		mode[num++] = vesa_modes[14];
+	if (c&0x02)
+		mode[num++] = vesa_modes[15];
+	if (c&0x01)
+		mode[num++] = vesa_modes[21];
+
+	c = block[2];
+	if (c&0x80)
+		mode[num++] = vesa_modes[17];
+
+	return num;
+}
+
+static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
+{
+	int xres, yres = 0, refresh, ratio, i;
+	
+	xres = (block[0] + 31) * 8;
+	if (xres <= 256)
 		return 0;
 
-	printk("EDID ver %d rev %d\n", (int) edid[EDID_STRUCT_VERSION],
-	       (int) edid[EDID_STRUCT_REVISION]);
+	ratio = (block[1] & 0xc0) >> 6;
+	switch (ratio) {
+	case 0:
+		yres = xres;
+		break;
+	case 1:
+		yres = (xres * 3)/4;
+		break;
+	case 2:
+		yres = (xres * 4)/5;
+		break;
+	case 3:
+		yres = (xres * 9)/16;
+		break;
+	}
+	refresh = (block[1] & 0x3f) + 60;
 
-	vendor = edid_get_vendor(edid + ID_MANUFACTURER_NAME);
+	for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+		if (vesa_modes[i].xres == xres && 
+		    vesa_modes[i].yres == yres &&
+		    vesa_modes[i].refresh == refresh) {
+			*mode = vesa_modes[i];
+			break;
+		} else {
+			calc_mode_timings(xres, yres, refresh, mode);
+			break;
+		}
+	}
+	return 1;
+}
 
-	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+static int get_dst_timing(unsigned char *block,
+			  struct fb_videomode *mode)
+{
+	int j, num = 0;
 
-	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
-		if (edid_is_monitor_block(block)) {
-			monitor = edid_get_monitor(block);
+	for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE) 
+		num += get_std_timing(block, &mode[num]);
+
+	return num;
+}
+
+static void get_detailed_timing(unsigned char *block, 
+				struct fb_videomode *mode)
+{
+	mode->xres = H_ACTIVE;
+	mode->yres = V_ACTIVE;
+	mode->pixclock = PIXEL_CLOCK;
+	mode->pixclock /= 1000;
+	mode->pixclock = KHZ2PICOS(mode->pixclock);
+	mode->right_margin = H_SYNC_OFFSET;
+	mode->left_margin = (H_ACTIVE + H_BLANKING) -
+		(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+	mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - 
+		V_SYNC_WIDTH;
+	mode->lower_margin = V_SYNC_OFFSET;
+	mode->hsync_len = H_SYNC_WIDTH;
+	mode->vsync_len = V_SYNC_WIDTH;
+	if (HSYNC_POSITIVE)
+		mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (VSYNC_POSITIVE)
+		mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+	mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
+				     (V_ACTIVE + V_BLANKING));
+	mode->vmode = 0;
+}
+
+/**
+ * fb_create_modedb - create video mode database
+ * @edid: EDID data
+ * @dbsize: database size
+ *
+ * RETURNS: struct fb_videomode, @dbsize contains length of database
+ *
+ * DESCRIPTION:
+ * This function builds a mode database using the contents of the EDID
+ * data
+ */
+struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
+{
+	struct fb_videomode *mode, *m;
+	unsigned char *block;
+	int num = 0, i;
+
+	mode = kmalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
+	if (mode == NULL)
+		return NULL;
+	memset(mode, 0, 50 * sizeof(struct fb_videomode));
+
+	if (edid == NULL || !edid_checksum(edid) || 
+	    !edid_check_header(edid)) {
+		kfree(mode);
+		return NULL;
+	}
+
+	*dbsize = 0;
+
+	block = edid + ESTABLISHED_TIMING_1;
+	num += get_est_timing(block, &mode[num]);
+
+	block = edid + STD_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) 
+		num += get_std_timing(block, &mode[num]);
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (block[0] == 0x00 && block[1] == 0x00) {
+			if (block[3] == 0xfa) {
+				num += get_dst_timing(block + 5, &mode[num]);
+			}
+		} else  {
+			get_detailed_timing(block, &mode[num]);
+			num++;
 		}
 	}
+	
+	/* Yikes, EDID data is totally useless */
+	if (!num) {
+		kfree(mode);
+		return NULL;
+	}
+
+	*dbsize = num;
+	m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
+	if (!m)
+		return mode;
+	memmove(m, mode, num * sizeof(struct fb_videomode));
+	kfree(mode);
+	return m;
+}
 
-	printk("EDID: detected %s %s\n", vendor, monitor);
+/**
+ * fb_destroy_modedb - destroys mode database
+ * @modedb: mode database to destroy
+ *
+ * DESCRIPTION:
+ * Destroy mode database created by fb_create_modedb
+ */
+void fb_destroy_modedb(struct fb_videomode *modedb)
+{
+	if (modedb)
+		kfree(modedb);
+}
 
+/**
+ * fb_get_monitor_limits - get monitor operating limits
+ * @edid: EDID data
+ * @specs: fb_monspecs structure pointer
+ *
+ * DESCRIPTION:
+ * Gets monitor operating limits from EDID data and places them in 
+ * @specs
+ */
+int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
+{
+	int i, retval = 1;
+	unsigned char *block;
+
+	if (edid == NULL || specs == NULL)
+		return 1;
+
+	if (!(edid_checksum(edid)))
+		return 1;
+
+	if (!(edid_check_header(edid)))
+		return 1;
+
+	memset(specs, 0, sizeof(struct fb_monspecs));
 	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 
+	printk("Monitor Operating Limits: ");
 	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
-		if (edid_is_timing_block(block)) {
-			parse_timing_block(block, var);
+		if (edid_is_limits_block(block)) {
+			specs->hfmin = H_MIN_RATE * 1000;
+			specs->hfmax = H_MAX_RATE * 1000;
+			specs->vfmin = V_MIN_RATE;
+			specs->vfmax = V_MAX_RATE;
+			specs->dclkmax = (MAX_PIXEL_CLOCK != 10*0xff) ?
+				MAX_PIXEL_CLOCK * 1000000 : 0;
+			specs->gtf = (GTF_SUPPORT) ? 1 : 0;
+			specs->dpms = edid[DPMS_FLAGS];
+			retval = 0;
+			printk("From EDID\n");
+			break;
 		}
 	}
-	return 1;
+	
+	/* estimate monitor limits based on modes supported */
+	if (retval) {
+		struct fb_videomode *modes;
+		int num_modes, i, hz, hscan, pixclock;
+
+		modes = fb_create_modedb(edid, &num_modes);
+		if (!modes) {
+			printk("None Available\n");
+			return 1;
+		}
+
+		retval = 0;
+		for (i = 0; i < num_modes; i++) {
+			hz = modes[i].refresh;
+			pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
+			hscan = (modes[i].yres * 105 * hz + 5000)/100;
+			
+			if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
+				specs->dclkmax = pixclock;
+			if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
+				specs->dclkmin = pixclock;
+			if (specs->hfmax == 0 || specs->hfmax < hscan)
+				specs->hfmax = hscan;
+			if (specs->hfmin == 0 || specs->hfmin > hscan)
+				specs->hfmin = hscan;
+			if (specs->vfmax == 0 || specs->vfmax < hz)
+				specs->vfmax = hz;
+			if (specs->vfmin == 0 || specs->vfmin > hz)
+				specs->vfmin = hz;
+		}
+		printk("Extrapolated\n");
+		fb_destroy_modedb(modes);
+	}
+	printk("     H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n", specs->hfmin/1000, specs->hfmax/1000, 
+	       specs->vfmin, specs->vfmax, specs->dclkmax/1000000);
+	return retval;
 }
 
-#ifdef CONFIG_PCI
-char *get_EDID(struct pci_dev *pdev)
+void show_edid(unsigned char *edid)
 {
+	unsigned char *block;
+	int i;
+
+	if (edid == NULL)
+		return;
+
+	if (!(edid_checksum(edid)))
+		return;
+
+	if (!(edid_check_header(edid)))
+		return;
+	printk("========================================\n");
+	printk("Display Information (EDID)\n");
+	printk("========================================\n");
+	printk("   EDID Version %d.%d\n", (int) edid[EDID_STRUCT_VERSION],
+	       (int) edid[EDID_STRUCT_REVISION]);
+
+	parse_vendor_block(edid + ID_MANUFACTURER_NAME);
+
+	printk("   Display Characteristics:\n");
+	parse_display_block(edid + EDID_STRUCT_DISPLAY);
+
+	printk("   Standard Timings\n");
+	block = edid + STD_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) 
+		parse_std_timing_block(block);
+
+	printk("   Supported VESA Modes\n");
+	parse_std_md_block(edid + ESTABLISHED_TIMING_1);
+
+	printk("   Detailed Monitor Information\n");
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (edid_is_serial_block(block)) {
+			parse_serial_block(block);
+		} else if (edid_is_ascii_block(block)) {
+			parse_ascii_block(block);
+		} else if (edid_is_limits_block(block)) {
+			parse_limits_block(block);
+		} else if (edid_is_monitor_block(block)) {
+			parse_monitor_block(block);
+		} else if (edid_is_color_block(block)) {
+			parse_color_block(block);
+		} else if (edid_is_std_timings_block(block)) {
+			parse_dst_timing_block(block);
+		} else if (edid_is_timing_block(block)) {
+			parse_detailed_timing_block(block);
+		}
+	}
+	printk("========================================\n");
+}
+
 #ifdef CONFIG_ALL_PPC
+char *get_EDID_from_OF(struct pci_dev *pdev)
+{
 	static char *propnames[] =
 	    { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL };
 	unsigned char *pedid = NULL;
 	struct device_node *dp;
 	int i;
 
+	if (pdev == NULL)
+		return NULL;
 	dp = pci_device_to_OF_node(pdev);
 	while (dp != NULL) {
 		for (i = 0; propnames[i] != NULL; ++i) {
-			pedid =
-			    (unsigned char *) get_property(dp,
-							   propnames[i],
-							   NULL);
+			pedid = (unsigned char *) get_property(dp, propnames[i], NULL);
 			if (pedid != NULL)
 				return pedid;
 		}
 		dp = dp->child;
 	}
+	show_edid(pedid);
 	return pedid;
-#else
-	return NULL;
+}
 #endif
+
+#ifdef CONFIG_X86
+char *get_EDID_from_BIOS(void *dummy)
+{
+	unsigned char *pedid = edid_info.dummy;
+	
+	if (!pedid)
+		return NULL;
+	show_edid(pedid);
+	return pedid;				
 }
 #endif
 
@@ -679,8 +1252,15 @@ int fb_validate_mode(struct fb_var_scree
 }
 
 EXPORT_SYMBOL(parse_edid);
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(get_EDID);
+EXPORT_SYMBOL(show_edid);
+#ifdef CONFIG_X86
+EXPORT_SYMBOL(get_EDID_from_BIOS);
+#endif
+#ifdef CONFIG_ALL_PPC
+EXPORT_SYMBOL(get_EDID_from_OF);
 #endif
+EXPORT_SYMBOL(fb_get_monitor_limits);
 EXPORT_SYMBOL(fb_get_mode);
 EXPORT_SYMBOL(fb_validate_mode);
+EXPORT_SYMBOL(fb_create_modedb);
+EXPORT_SYMBOL(fb_destroy_modedb);
diff -puN drivers/video/i810/i810_accel.c~fbdev drivers/video/i810/i810_accel.c
--- 25/drivers/video/i810/i810_accel.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/i810/i810_accel.c	2003-04-13 22:00:13.000000000 -0700
@@ -9,6 +9,7 @@
  *  more details.
  */
 #include <linux/kernel.h>
+#include <linux/string.h>
 #include <linux/fb.h>
 
 #include "i810_regs.h"
@@ -54,8 +55,9 @@ static inline void i810_report_error(u8 
  * The function waits until a free space from the ringbuffer
  * is available 
  */	
-static inline int wait_for_space(struct i810fb_par *par, u32 space)
+static inline int wait_for_space(struct fb_info *info, u32 space)
 {
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
 	u32 head, count = WAIT_COUNT, tail;
 	u8 *mmio = par->mmio_start_virtual;
 
@@ -72,6 +74,7 @@ static inline int wait_for_space(struct 
 	printk("ringbuffer lockup!!!\n");
 	i810_report_error(mmio); 
 	par->dev_flags |= LOCKUP;
+	info->pixmap.scan_align = 1;
 	return 1;
 }
 
@@ -83,11 +86,15 @@ static inline int wait_for_space(struct 
  * This waits for lring(0), iring(1), and batch(3), etc to finish and
  * waits until ringbuffer is empty.
  */
-static inline int wait_for_engine_idle(struct i810fb_par *par)
+static inline int wait_for_engine_idle(struct fb_info *info)
 {
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
 	u8 *mmio = par->mmio_start_virtual;
 	int count = WAIT_COUNT;
 
+	if (wait_for_space(info, par->iring.size)) /* flush */
+		return 1;
+
 	while((i810_readw(INSTDONE, mmio) & 0x7B) != 0x7B && --count); 
 	if (count) return 0;
 
@@ -95,6 +102,7 @@ static inline int wait_for_engine_idle(s
 	printk("INSTDONE: 0x%04x\n", i810_readl(INSTDONE, mmio));
 	i810_report_error(mmio); 
 	par->dev_flags |= LOCKUP;
+	info->pixmap.scan_align = 1;
 	return 1;
 }
 
@@ -106,11 +114,13 @@ static inline int wait_for_engine_idle(s
  * Checks/waits for sufficent space in ringbuffer of size
  * space.  Returns the tail of the buffer
  */ 
-static inline u32 begin_iring(struct i810fb_par *par, u32 space)
+static inline u32 begin_iring(struct fb_info *info, u32 space)
 {
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
+
 	if (par->dev_flags & ALWAYS_SYNC) 
-		wait_for_engine_idle(par);
-	return wait_for_space(par, space);
+		wait_for_engine_idle(info);
+	return wait_for_space(info, space);
 }
 
 /**
@@ -149,9 +159,11 @@ static inline void end_iring(struct i810
  */
 static inline void source_copy_blit(int dwidth, int dheight, int dpitch, 
 				    int xdir, int src, int dest, int rop, 
-				    int blit_bpp, struct i810fb_par *par)
+				    int blit_bpp, struct fb_info *info)
 {
-	if (begin_iring(par, 24 + IRING_PAD)) return;
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
+
+	if (begin_iring(info, 24 + IRING_PAD)) return;
 
 	PUT_RING(BLIT | SOURCE_COPY_BLIT | 4);
 	PUT_RING(xdir | rop << 16 | dpitch | DYN_COLOR_EN | blit_bpp);
@@ -181,9 +193,11 @@ static inline void source_copy_blit(int 
  */
 static inline void color_blit(int width, int height, int pitch,  int dest, 
 			      int rop, int what, int blit_bpp, 
-			      struct i810fb_par *par)
+			      struct fb_info *info)
 {
-	if (begin_iring(par, 24 + IRING_PAD)) return;
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
+
+	if (begin_iring(info, 24 + IRING_PAD)) return;
 
 	PUT_RING(BLIT | COLOR_BLT | 3);
 	PUT_RING(rop << 16 | pitch | SOLIDPATTERN | DYN_COLOR_EN | blit_bpp);
@@ -220,9 +234,11 @@ static inline void color_blit(int width,
 static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
 					  int dsize, int blit_bpp, int rop,
 					  int dest, const u32 *src, int bg,
-					  int fg, struct i810fb_par *par)
+					  int fg, struct fb_info *info)
 {
-	if (begin_iring(par, 24 + (dsize << 2) + IRING_PAD)) return;
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
+
+	if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return;
 
 	PUT_RING(BLIT | MONO_SOURCE_COPY_IMMEDIATE | (4 + dsize));
 	PUT_RING(DYN_COLOR_EN | blit_bpp | rop << 16 | dpitch);
@@ -261,9 +277,11 @@ static inline void mono_src_copy_imm_bli
 static inline void mono_src_copy_blit(int dwidth, int dheight, int dpitch, 
 				      int qsize, int blit_bpp, int rop, 
 				      int dest, int src, int bg,
-				      int fg, struct i810fb_par *par)
+				      int fg, struct fb_info *info)
 {
-	if (begin_iring(par, 32 + IRING_PAD)) return;
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
+
+	if (begin_iring(info, 32 + IRING_PAD)) return;
 
 	PUT_RING(BLIT | MONO_SOURCE_COPY_BLIT | 6);
 	PUT_RING(DYN_COLOR_EN | blit_bpp | rop << 16 | dpitch | 1 << 27);
@@ -277,19 +295,23 @@ static inline void mono_src_copy_blit(in
 	end_iring(par);
 }
 
-static u32 get_buffer_offset(u32 size, struct i810fb_par *par) 
+static inline void load_front(int offset, struct fb_info *info)
 {
-	u32 offset;
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
 
-	if (par->pixmap_offset + size > par->pixmap.size) {
-		wait_for_engine_idle(par);
-		par->pixmap_offset = 0;
-	}
+	if (begin_iring(info, 8 + IRING_PAD)) return;
 
-	offset = par->pixmap_offset;
-	par->pixmap_offset += size;
+	PUT_RING(PARSER | FLUSH);
+	PUT_RING(NOP);
 
-	return offset;
+	end_iring(par);
+
+	if (begin_iring(info, 8 + IRING_PAD)) return;
+
+	PUT_RING(PARSER | FRONT_BUFFER | ((par->pitch >> 3) << 8));
+	PUT_RING((par->fb.offset << 12) + offset);
+
+	end_iring(par);
 }
 
 /**
@@ -338,7 +360,7 @@ void i810fb_fillrect(struct fb_info *inf
 
 	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
 	color_blit(width, height, info->fix.line_length, dest, rop, color, 
-		   par->blit_bpp, par);
+		   par->blit_bpp, info);
 }
 	
 void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) 
@@ -377,17 +399,16 @@ void i810fb_copyarea(struct fb_info *inf
 	dest = info->fix.smem_start + (dy * info->fix.line_length) + dx;
 
 	source_copy_blit(width, height, pitch, xdir, src, dest,
-			 PAT_COPY_ROP, par->blit_bpp, par);
+			 PAT_COPY_ROP, par->blit_bpp, info);
 }
 
 void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct i810fb_par *par = (struct i810fb_par *) info->par;
-	u32 fg = 0, bg = 0, s_pitch, d_pitch, size, offset, dst, i, j;
-	u8 *s_addr, *d_addr;
+	u32 fg = 0, bg = 0, size, dst;
 	
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
-	    par->depth == 4 || image->depth != 0) 
+	    par->depth == 4 || image->depth != 1) 
 		return cfb_imageblit(info, image);
 
 	switch (info->var.bits_per_pixel) {
@@ -405,43 +426,17 @@ void i810fb_imageblit(struct fb_info *in
 	dst = info->fix.smem_start + (image->dy * info->fix.line_length) + 
 		(image->dx * par->depth);
 
-	s_pitch = (image->width+7)/8;
-	d_pitch = (s_pitch + 1) & ~1;
-	size = d_pitch * image->height;
-	if (s_pitch != d_pitch || size & 7) {
-		size += 7;
-		size &= ~7;
-		offset = get_buffer_offset(size, par);		
-		d_addr = par->pixmap.virtual + offset;
-		s_addr = (u8 *) image->data;
-		
-		if (s_pitch == d_pitch) {
-			memcpy_toio(d_addr, s_addr, s_pitch * image->height);
-		} else { 
-			for (i = image->height; i--; ) {
-				for (j = 0; j < s_pitch; j++) 
-					i810_writeb(j, d_addr, s_addr[j]);
-				s_addr += s_pitch;
-				d_addr += d_pitch;
-			}
-		}
-		mono_src_copy_blit(image->width * par->depth, image->height, 
-				   info->fix.line_length, size/8, 
-				   par->blit_bpp, PAT_COPY_ROP, dst, 
-				   par->pixmap.physical + offset,
-				   bg, fg, par);
-	}
-	/*
-	 * immediate blit if width is a multiple of 16 (hardware requirement)
-	 */
-	else {
-		mono_src_copy_imm_blit(image->width * par->depth, 
-				       image->height, info->fix.line_length, 
-				       size/4, par->blit_bpp,
-				       PAT_COPY_ROP, dst, (u32 *) image->data, 
-				       bg, fg, par);
-	} 
-}
+	size = (image->width+7)/8 + 1;
+	size &= ~1;
+	size *= image->height;
+	size += 7;
+	size &= ~7;
+	mono_src_copy_imm_blit(image->width * par->depth, 
+			       image->height, info->fix.line_length, 
+			       size/4, par->blit_bpp,
+			       PAT_COPY_ROP, dst, (u32 *) image->data, 
+			       bg, fg, info);
+} 
 
 int i810fb_sync(struct fb_info *info)
 {
@@ -450,9 +445,19 @@ int i810fb_sync(struct fb_info *info)
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
 		return 0;
 
-	return wait_for_engine_idle(par);
+	return wait_for_engine_idle(info);
 }
 
+void i810fb_load_front(u32 offset, struct fb_info *info)
+{
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
+	u8 *mmio = par->mmio_start_virtual;
+
+	if (!info->var.accel_flags || par->dev_flags & LOCKUP)
+		i810_writel(DPLYBASE, mmio, par->fb.physical + offset);
+	else 
+		load_front(offset, info);
+}
 
 /**
  * i810fb_init_ringbuffer - initialize the ringbuffer
@@ -463,12 +468,13 @@ int i810fb_sync(struct fb_info *info)
  * size and location of the ringbuffer.  It also sets 
  * the head and tail pointers = 0
  */
-void i810fb_init_ringbuffer(struct i810fb_par *par)
+void i810fb_init_ringbuffer(struct fb_info *info)
 {
+	struct i810fb_par *par = (struct i810fb_par *) info->par;
 	u32 tmp1, tmp2;
 	u8 *mmio = par->mmio_start_virtual;
 	
-	wait_for_engine_idle(par);
+	wait_for_engine_idle(info);
 	i810fb_iring_enable(par, OFF);
 	i810_writel(IRING, mmio, 0);
 	i810_writel(IRING + 4, mmio, 0);
diff -puN drivers/video/i810/i810_dvt.c~fbdev drivers/video/i810/i810_dvt.c
--- 25/drivers/video/i810/i810_dvt.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/i810/i810_dvt.c	2003-04-13 22:00:13.000000000 -0700
@@ -289,8 +289,7 @@ u32 i810_get_watermark(struct fb_var_scr
 		case 32:
 			wmark = params->bpp24_100;
 		}
-	}
-	else {					
+	} else {					
 		switch (var->bits_per_pixel) {
 		case 8:
 			wmark = params->bpp8_133;
diff -puN drivers/video/i810/i810_gtf.c~fbdev drivers/video/i810/i810_gtf.c
--- 25/drivers/video/i810/i810_gtf.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/i810/i810_gtf.c	2003-04-13 22:00:13.000000000 -0700
@@ -1,5 +1,5 @@
 /*-*- linux-c -*-
- *  linux/drivers/video/i810_main.h -- Intel 810 Nondiscrete Video Timings 
+ *  linux/drivers/video/i810_main.h -- Intel 810 Non-discrete Video Timings 
  *                                     (VESA GTF)
  *
  *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
@@ -213,7 +213,7 @@ void i810fb_fill_var_timings(struct fb_v
  * @par: pointer to i810fb_par structure
  *
  * DESCRIPTION:
- * Get's the required watermark based on 
+ * Gets the required watermark based on 
  * pixelclock and RAMBUS frequency.
  * 
  * RETURNS:
@@ -240,8 +240,7 @@ u32 i810_get_watermark(const struct fb_v
 			wmark = i810_wm_24_100;
 			size = ARRAY_SIZE(i810_wm_24_100);
 		}
-	}	
-	else {
+	} else {
 		switch(var->bits_per_pixel) {
 		case 8:
 			wmark = i810_wm_8_133;
diff -puN drivers/video/i810/i810.h~fbdev drivers/video/i810/i810.h
--- 25/drivers/video/i810/i810.h~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/i810/i810.h	2003-04-13 22:00:13.000000000 -0700
@@ -120,7 +120,6 @@
 #define MMIO_SIZE                   (512*1024)
 #define GTT_SIZE                    (16*1024) 
 #define RINGBUFFER_SIZE             (64*1024)
-#define PIXMAP_SIZE                 (4 * 4096)
 #define CURSOR_SIZE                 4096 
 #define OFF                         0
 #define ON                          1
@@ -251,7 +250,6 @@ struct i810fb_par {
 	struct heap_data         fb;
 	struct heap_data         iring;
 	struct heap_data         cursor_heap;
-	struct heap_data         pixmap;
 	struct vgastate          state;
 	drm_agp_t                *drm_agp;
 	atomic_t                 use_count;
@@ -259,11 +257,6 @@ struct i810fb_par {
 	u32 pci_state[16];
 	unsigned long mmio_start_phys;
 	u8 *mmio_start_virtual;
-	u32 cursor_reset;
-	u8  red[64];
-	u8  green[64];
-	u8  blue[64];
-	u32 pixmap_offset;
 	u32 pitch;
 	u32 pixconf;
 	u32 watermark;
diff -puN drivers/video/i810/i810_main.c~fbdev drivers/video/i810/i810_main.c
--- 25/drivers/video/i810/i810_main.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/i810/i810_main.c	2003-04-13 22:00:13.000000000 -0700
@@ -631,8 +631,7 @@ static void i810_calc_dclk(u32 freq, u32
 		if (f_out <= target_freq) {
 			n_reg++;
 			diff = target_freq - f_out;
-		}
-		else {
+		} else {
 			m_reg++;
 			diff = f_out - target_freq;
 		}
@@ -926,20 +925,21 @@ static int i810_check_params(struct fb_v
 	/*
 	 * Monitor limit
 	 */
+	switch (var->bits_per_pixel) {
+	case 8:
+		info->monspecs.dclkmax = 234000000;
+		break;
+	case 16:
+		info->monspecs.dclkmax = 229000000;
+		break;
+	case 24:
+	case 32:
+		info->monspecs.dclkmax = 204000000;
+		break;
+	}
+	info->monspecs.dclkmin = 15000000;
+
 	if (fb_validate_mode(var, info)) {
-		switch (var->bits_per_pixel) {
-		case 8:
-			info->monspecs.dclkmax = 234000000;
-			break;
-		case 16:
-			info->monspecs.dclkmax = 229000000;
-			break;
-		case 24:
-		case 32:
-			info->monspecs.dclkmax = 204000000;
-			break;
-		}
-		info->monspecs.dclkmin = 15000000;
 		if (fb_get_mode(FB_MAXTIMINGS, 0, var, info))
 			return -EINVAL;
 	}
@@ -1177,31 +1177,21 @@ static int i810fb_setcolreg(unsigned reg
 		for (i = 0; i < 8; i++) 
 			i810_write_dac((u8) (regno * 8) + i, (u8) red, 
 				       (u8) green, (u8) blue, mmio);
-	}
-				
-	else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
+	} else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
 		 info->var.green.length == 6) {
-		if (!regno) {
-			memset(par->red, 0, 64);
-			memset(par->green, 0, 64);
-			memset(par->blue, 0, 64);
-		}
-
-		par->red[regno] = (u8) red;
-		par->green[regno] = (u8) green;
-		par->blue[regno] = (u8) blue;
+		u8 r, g, b;
 
 		if (regno < 32) {
 			for (i = 0; i < 8; i++) 
 				i810_write_dac((u8) (regno * 8) + i,
-					       (u8) red, par->green[regno*2], 
+					       (u8) red, (u8) green, 
 					       (u8) blue, mmio);
 		}
+		i810_read_dac((u8) (regno*4), &r, &g, &b, mmio);
 		for (i = 0; i < 4; i++) 
-			i810_write_dac((u8) (regno*4) + i, par->red[regno/2],
-				       (u8) green, par->blue[regno/2], mmio);
-	}
-	else {
+			i810_write_dac((u8) (regno*4) + i, r, (u8) green, 
+				       b, mmio);
+	} else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
 		i810_write_dac((u8) regno, (u8) red, (u8) green,
 			       (u8) blue, mmio);
 	}
@@ -1220,16 +1210,14 @@ static int i810fb_setcolreg(unsigned reg
 					((u32 *)info->pseudo_palette)[regno] = 
 						(regno << 11) | (regno << 5) |
 						regno;
-			}
-			else {
+			} else {
 				if (info->var.green.length == 5) {
 					/* RGB 555 */
 					((u32 *)info->pseudo_palette)[regno] = 
 						((red & 0xf800) >> 1) |
 						((green & 0xf800) >> 6) |
 						((blue & 0xf800) >> 11);
-				}
-				else {
+				} else {
 					/* RGB 565 */
 					((u32 *)info->pseudo_palette)[regno] =
 						(red & 0xf800) |
@@ -1260,11 +1248,10 @@ static int i810fb_pan_display(struct fb_
 {
 	struct i810fb_par *par = (struct i810fb_par *) info->par;
 	u32 total;
-	u8 *mmio = par->mmio_start_virtual;
 	
 	total = var->xoffset * par->depth + 
 		var->yoffset * info->fix.line_length;
-	i810_writel(DPLYBASE, mmio, par->fb.physical + total);
+	i810fb_load_front(total, info);
 
 	return 0;
 }
@@ -1314,9 +1301,14 @@ static int i810fb_set_par(struct fb_info
 	decode_var(&info->var, par);
 	i810_load_regs(par);
 	i810_init_cursor(par);
-	par->cursor_reset = 1;
+
 	encode_fix(&info->fix, info);
 
+	if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) 
+		info->pixmap.scan_align = 2;
+	else 
+		info->pixmap.scan_align = 1;
+	
 	return 0;
 }
 
@@ -1345,78 +1337,73 @@ static int i810fb_check_var(struct fb_va
 
 static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	static u8 data[64 * 8];
 	struct i810fb_par *par = (struct i810fb_par *)info->par;
 	u8 *mmio = par->mmio_start_virtual;	
-	u16 flags = cursor->set;
-
+	u8 data[64 * 8];
+	
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP) 
 		return soft_cursor(info, cursor);
 
-	if (cursor->image.width > 64 || cursor->image.height > 64 ||
-	    (cursor->dest == NULL && cursor->rop == ROP_XOR))
-		return 1;
+	if (cursor->image.width > 64 || cursor->image.height > 64)
+		return -ENXIO;
 
-	if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) {
+	if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical)
 		i810_init_cursor(par);
-		par->cursor_reset = 1;
-	}
 
-	if (par->cursor_reset) {
-		flags = FB_CUR_SETALL;
-		par->cursor_reset = 0;
-	}
-	
 	i810_enable_cursor(mmio, OFF);
 
-	if (flags & FB_CUR_SETPOS) {
+	if (cursor->set & FB_CUR_SETHOT)
+		info->cursor.hot = cursor->hot;
+	
+	if (cursor->set & FB_CUR_SETPOS) {
 		u32 tmp;
 
+		info->cursor.image.dx = cursor->image.dx;
+		info->cursor.image.dy = cursor->image.dy;
+		
 		tmp = cursor->image.dx - info->var.xoffset;
 		tmp |= (cursor->image.dy - info->var.yoffset) << 16;
 	    
 		i810_writel(CURPOS, mmio, tmp);
 	}
 
-	if (flags & FB_CUR_SETSIZE) {
+	if (cursor->set & FB_CUR_SETSIZE) {
+		info->cursor.image.height = cursor->image.height;
+		info->cursor.image.width = cursor->image.width;
 		i810_reset_cursor_image(par);
 	}
 
-	if (flags & FB_CUR_SETCMAP) {
+	if (cursor->set & FB_CUR_SETCMAP) {
+		info->cursor.image.fg_color = cursor->image.fg_color;
+		info->cursor.image.bg_color = cursor->image.bg_color;
 		i810_load_cursor_colors(cursor->image.fg_color,
 					cursor->image.bg_color,
 					info);
 	}
 
-	if (flags & (FB_CUR_SETDEST | FB_CUR_SETSHAPE)) {
-		int size = ((cursor->image.width + 7)/8) * 
-			cursor->image.height;
+	if (cursor->set & FB_CUR_SETSHAPE) {
+		int size = ((info->cursor.image.width + 7) >> 3) * 
+			     info->cursor.image.height;
 		int i;
 
-		switch (cursor->rop) {
+		switch (info->cursor.rop) {
 		case ROP_XOR:
-			for (i = 0; i < size; i++) {
-				data[i] = ((cursor->image.data[i] & 
-					    cursor->mask[i]) ^
-					   cursor->dest[i]);
-			}
+			for (i = 0; i < size; i++)
+				data[i] = cursor->image.data[i] ^ info->cursor.mask[i]; 
 			break;
 		case ROP_COPY:
 		default:
-			for (i = 0; i < size; i++) {
-				data[i] = cursor->image.data[i] & 
-					cursor->mask[i];
-			}
+			for (i = 0; i < size; i++)
+				data[i] = cursor->image.data[i] & info->cursor.mask[i]; 
 			break;
 		}
-		i810_load_cursor_image(cursor->image.width, 
-				       cursor->image.height, data,
+		i810_load_cursor_image(info->cursor.image.width, 
+				       info->cursor.image.height, data,
 				       par);
 	}
 
-	if (cursor->enable)
+	if (info->cursor.enable)
 		i810_enable_cursor(mmio, ON);
-		
 	return 0;
 }
 
@@ -1512,10 +1499,6 @@ static void __init i810_fix_pointers(str
 		(par->iring.offset << 12);
 	par->cursor_heap.virtual = par->aperture.virtual+
 		(par->cursor_heap.offset << 12);
-	par->pixmap.virtual = par->aperture.virtual + 
-		(par->pixmap.offset << 12);
-	par->pixmap.physical = par->aperture.physical + 
-		(par->pixmap.offset << 12);
 }
 
 static void __init i810_fix_offsets(struct i810fb_par *par)
@@ -1531,10 +1514,7 @@ static void __init i810_fix_offsets(stru
 	par->fb.offset = v_offset_default << 20;
 	par->fb.offset >>= 12;
 
-	par->pixmap.offset = par->fb.offset + (par->fb.size >> 12);
-	par->pixmap.size = PIXMAP_SIZE;
-
-	par->iring.offset = par->pixmap.offset + (PIXMAP_SIZE >> 12);
+	par->iring.offset = par->fb.offset + (par->fb.size >> 12);
 	par->iring.size = RINGBUFFER_SIZE;
 
 	par->cursor_heap.offset = par->iring.offset + (RINGBUFFER_SIZE >> 12);
@@ -1547,7 +1527,7 @@ static int __init i810_alloc_agp_mem(str
 	int size;
 	
 	i810_fix_offsets(par);
-	size = par->fb.size + par->iring.size + par->pixmap.size;
+	size = par->fb.size + par->iring.size;
 
 	par->drm_agp = (drm_agp_t *) inter_module_get("drm_agp");
 	if (!par->drm_agp) {
@@ -1637,23 +1617,20 @@ static void __init i810_init_monspecs(st
 static void __init i810_init_defaults(struct i810fb_par *par, 
 				      struct fb_info *info)
 {
-	if (voffset) {
+	if (voffset) 
 		v_offset_default = voffset;
-	}
-	else {
-		if (par->aperture.size > 32 * 1024 * 1024)
-			v_offset_default = 16;
-		else
-			v_offset_default = 8;
-	}
+	else if (par->aperture.size > 32 * 1024 * 1024)
+		v_offset_default = 16;
+	else
+		v_offset_default = 8;
 
 	if (!vram) 
 		vram = 1;
 
-	if (accel)
+	if (accel) 
 		par->dev_flags |= HAS_ACCELERATION;
 
-	if (sync)
+	if (sync) 
 		par->dev_flags |= ALWAYS_SYNC;
 
 	if (bpp < 8)
@@ -1698,8 +1675,6 @@ static void __init i810_init_device(stru
 	pci_read_config_byte(par->dev, 0x50, &reg);
 	reg &= FREQ_MASK;
 	par->mem_freq = (reg) ? 133 : 100;
-
-	i810fb_init_ringbuffer(par);
 }
 
 static int __init 
@@ -1718,8 +1693,7 @@ i810_allocate_pci_resource(struct i810fb
 		par->aperture.physical = pci_resource_start(par->dev, 0);
 		par->aperture.size = pci_resource_len(par->dev, 0);
 		par->mmio_start_phys = pci_resource_start(par->dev, 1);
-	}
-	else {
+	} else {
 		par->aperture.physical = pci_resource_start(par->dev, 1);
 		par->aperture.size = pci_resource_len(par->dev, 1);
 		par->mmio_start_phys = pci_resource_start(par->dev, 0);
@@ -1737,7 +1711,7 @@ i810_allocate_pci_resource(struct i810fb
 	}
 	par->res_flags |= FRAMEBUFFER_REQ;
 
-	par->aperture.virtual = ioremap(par->aperture.physical, 
+	par->aperture.virtual = ioremap_nocache(par->aperture.physical, 
 					par->aperture.size);
 	if (!par->aperture.virtual) {
 		printk("i810fb_init: cannot remap framebuffer region\n");
@@ -1766,7 +1740,6 @@ int __init i810fb_setup(char *options)
 {
 	char *this_opt, *suffix = NULL;
 
-	i810_init = 1;
 	if (!options || !*options)
 		return 0;
 	
@@ -1795,13 +1768,11 @@ int __init i810fb_setup(char *options)
 			hsync1 = simple_strtoul(this_opt+7, &suffix, 0);
 			if (strncmp(suffix, "H", 1)) 
 				hsync1 *= 1000;
-		} 
-		else if (!strncmp(this_opt, "hsync2:", 7)) {
+		} else if (!strncmp(this_opt, "hsync2:", 7)) {
 			hsync2 = simple_strtoul(this_opt+7, &suffix, 0);
 			if (strncmp(suffix, "H", 1)) 
 				hsync2 *= 1000;
-		} 
-		else if (!strncmp(this_opt, "vsync1:", 7)) 
+		} else if (!strncmp(this_opt, "vsync1:", 7)) 
 			vsync1 = simple_strtoul(this_opt+7, NULL, 0);
 		else if (!strncmp(this_opt, "vsync2:", 7))
 			vsync2 = simple_strtoul(this_opt+7, NULL, 0);
@@ -1812,15 +1783,12 @@ int __init i810fb_setup(char *options)
 }
 
 static int __init i810fb_init_pci (struct pci_dev *dev, 
-				      const struct pci_device_id *entry)
+				   const struct pci_device_id *entry)
 {
 	struct fb_info    *info;
 	struct i810fb_par *par = NULL;
 	int err, vfreq, hfreq, pixclock;
 
-	if (!i810_init)
-		return -EINVAL;
-
 	if (!(info = kmalloc(sizeof(struct fb_info), GFP_KERNEL))) {
 		i810fb_release_resource(info, par);
 		return -ENOMEM;
@@ -1836,6 +1804,15 @@ static int __init i810fb_init_pci (struc
 	par->dev = dev;
 	info->par = par;
 
+	if (!(info->pixmap.addr = kmalloc(64*1024, GFP_KERNEL))) {
+		i810fb_release_resource(info, par);
+		return -ENOMEM;
+	}
+	memset(info->pixmap.addr, 0, 64*1024);
+	info->pixmap.size = 64*1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
 	if ((err = i810_allocate_pci_resource(par, entry))) {
 		i810fb_release_resource(info, par);
 		return err;
@@ -1864,6 +1841,7 @@ static int __init i810fb_init_pci (struc
 	}
 	encode_fix(&info->fix, info); 
 	 	    
+	i810fb_init_ringbuffer(info);
 	err = register_framebuffer(info);
 	if (err < 0) {
     		i810fb_release_resource(info, par); 
@@ -1894,7 +1872,7 @@ static int __init i810fb_init_pci (struc
 }
 
 /***************************************************************
- *                     Deinitialization                        *
+ *                     De-initialization                        *
  ***************************************************************/
 
 static void i810fb_release_resource(struct fb_info *info, 
@@ -1931,7 +1909,7 @@ static void i810fb_release_resource(stru
 
 		kfree(par);
 	}
-	if (info)
+	if (info) 
 		kfree(info);
 }
 
@@ -1974,7 +1952,6 @@ int __init i810fb_init(void)
 
 int __init i810fb_init(void)
 {
-	i810_init = 1;
 	hsync1 *= 1000;
 	hsync2 *= 1000;
 
@@ -1994,14 +1971,14 @@ MODULE_PARM(bpp, "i");
 MODULE_PARM_DESC(bpp, "Color depth for display in bits per pixel"
 		 " (default = 8)");
 MODULE_PARM(xres, "i");
-MODULE_PARM_DESC(xres, "Hozizontal resolution in pixels (default = 640)");
+MODULE_PARM_DESC(xres, "Horizontal resolution in pixels (default = 640)");
 MODULE_PARM(yres, "i");
 MODULE_PARM_DESC(yres, "Vertical resolution in scanlines (default = 480)");
 MODULE_PARM(vyres, "i");
 MODULE_PARM_DESC(vyres, "Virtual vertical resolution in scanlines"
 		 " (default = 480)");
 MODULE_PARM(hsync1, "i");
-MODULE_PARM_DESC(hsync1, "Mimimum horizontal frequency of monitor in KHz"
+MODULE_PARM_DESC(hsync1, "Minimum horizontal frequency of monitor in KHz"
 		 " (default = 31)");
 MODULE_PARM(hsync2, "i");
 MODULE_PARM_DESC(hsync2, "Maximum horizontal frequency of monitor in KHz"
diff -puN drivers/video/i810/i810_main.h~fbdev drivers/video/i810/i810_main.h
--- 25/drivers/video/i810/i810_main.h~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/i810/i810_main.h	2003-04-13 22:00:13.000000000 -0700
@@ -55,7 +55,6 @@ static struct pci_driver i810fb_driver =
 	.resume   =     i810fb_resume,
 };	
 
-static int i810_init  __initdata = 0;
 static int vram       __initdata = 4;
 static int bpp        __initdata = 8;
 static int mtrr       __initdata = 0;
@@ -132,7 +131,8 @@ extern void i810fb_copyarea (struct fb_i
 extern void i810fb_imageblit(struct fb_info *p, const struct fb_image *image);
 extern int  i810fb_sync     (struct fb_info *p);
 
-extern void i810fb_init_ringbuffer   (struct i810fb_par *par);
+extern void i810fb_init_ringbuffer(struct fb_info *info);
+extern void i810fb_load_front     (u32 offset, struct fb_info *info);
 
 /* Conditionals */
 #if defined(__i386__)
diff -puN drivers/video/imsttfb.c~fbdev drivers/video/imsttfb.c
--- 25/drivers/video/imsttfb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/imsttfb.c	2003-04-13 22:00:13.000000000 -0700
@@ -409,7 +409,7 @@ static void imsttfb_remove(struct pci_de
 static inline u32 read_reg_le32(volatile u32 *base, int regindex)
 {
 #ifdef __powerpc__
-	in_le32((volatile u32 *) (base + regindex));
+	return in_le32((volatile u32 *) (base + regindex));
 #else
 	return readl(base + regindex);
 #endif
@@ -1211,7 +1211,7 @@ imsttfb_cursor(struct fb_info *info, str
 	if (flags & FB_CUR_SETSIZE) {
         }
 
-        if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETDEST)) {
+        if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) {
                 int fg_idx = cursor->image.fg_color;
                 int width = (cursor->image.width+7)/8;
                 u8 *dat = (u8 *) cursor->image.data;
diff -puN drivers/video/logo/logo.c~fbdev drivers/video/logo/logo.c
--- 25/drivers/video/logo/logo.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/logo/logo.c	2003-04-13 22:00:13.000000000 -0700
@@ -33,69 +33,64 @@ extern const struct linux_logo logo_supe
 extern const struct linux_logo logo_superh_clut224;
 
 
-const struct linux_logo * __init fb_find_logo(int type)
+const struct linux_logo * __init find_logo(int depth)
 {
 	const struct linux_logo *logo = 0;
 
-	switch (type) {
-		case LINUX_LOGO_MONO:
+	if (depth >= 1) {
 #ifdef CONFIG_LOGO_LINUX_MONO
-			/* Generic Linux logo */
-			logo = &logo_linux_mono;
+		/* Generic Linux logo */
+		logo = &logo_linux_mono;
 #endif
 #ifdef CONFIG_LOGO_SUPERH_MONO
-			/* SuperH Linux logo */
-			logo = &logo_superh_mono;
+		/* SuperH Linux logo */
+		logo = &logo_superh_mono;
 #endif
-			break;
-
-		case LINUX_LOGO_VGA16:
+	}
+	
+	if (depth >= 4) {
 #ifdef CONFIG_LOGO_LINUX_VGA16
-			/* Generic Linux logo */
-			logo = &logo_linux_vga16;
+		/* Generic Linux logo */
+		logo = &logo_linux_vga16;
 #endif
 #ifdef CONFIG_LOGO_SUPERH_VGA16
-			/* SuperH Linux logo */
-			logo = &logo_superh_vga16;
+		/* SuperH Linux logo */
+		logo = &logo_superh_vga16;
 #endif
-			break;
-
-		case LINUX_LOGO_CLUT224:
+	}
+	
+	if (depth >= 8) {
 #ifdef CONFIG_LOGO_LINUX_CLUT224
-			/* Generic Linux logo */
-			logo = &logo_linux_clut224;
+		/* Generic Linux logo */
+		logo = &logo_linux_clut224;
 #endif
 #ifdef CONFIG_LOGO_DEC_CLUT224
-			/* DEC Linux logo on MIPS/MIPS64 */
-			if (mips_machgroup == MACH_GROUP_SGI)
-				logo = &logo_dec_clut224;
+		/* DEC Linux logo on MIPS/MIPS64 */
+		if (mips_machgroup == MACH_GROUP_SGI)
+			logo = &logo_dec_clut224;
 #endif
 #ifdef CONFIG_LOGO_MAC_CLUT224
-			/* Macintosh Linux logo on m68k */
-			if (MACH_IS_MAC)
-				logo = &logo_mac_clut224;
+		/* Macintosh Linux logo on m68k */
+		if (MACH_IS_MAC)
+			logo = &logo_mac_clut224;
 #endif
 #ifdef CONFIG_LOGO_PARISC_CLUT224
-			/* PA-RISC Linux logo */
-			logo = &logo_parisc_clut224;
+		/* PA-RISC Linux logo */
+		logo = &logo_parisc_clut224;
 #endif
 #ifdef CONFIG_LOGO_SGI_CLUT224
-			/* SGI Linux logo on MIPS/MIPS64 ans VisWs 320/540 */
-#ifndef CONFIG_X86_VISWS
-			if (mips_machgroup == MACH_GROUP_SGI)
-#endif
-				logo = &logo_sgi_clut224;
+		/* SGI Linux logo on MIPS/MIPS64 */
+		if (mips_machgroup == MACH_GROUP_SGI)
+			logo = &logo_sgi_clut224;
 #endif
 #ifdef CONFIG_LOGO_SUN_CLUT224
-			/* Sun Linux logo */
-			logo = &logo_sun_clut224;
+		/* Sun Linux logo */
+		logo = &logo_sun_clut224;
 #endif
 #ifdef CONFIG_LOGO_SUPERH_CLUT224
-			/* SuperH Linux logo */
-			logo = &logo_superh_clut224;
+		/* SuperH Linux logo */
+		logo = &logo_superh_clut224;
 #endif
-			break;
-
 	}
 	return logo;
 }
diff -puN drivers/video/modedb.c~fbdev drivers/video/modedb.c
--- 25/drivers/video/modedb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/modedb.c	2003-04-13 22:00:13.000000000 -0700
@@ -251,6 +251,110 @@ static const struct fb_videomode modedb[
     },
 };
 
+const struct fb_videomode vesa_modes[] = {
+	/* 0 640x350-85 VESA */
+	{ NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 1 640x400-85 VESA */
+	{ NULL, 85, 640, 400, 31746,  96, 32, 41, 01, 64, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 2 720x400-85 VESA */
+	{ NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 3 640x480-60 VESA */
+	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2, 
+	  0, FB_VMODE_NONINTERLACED },
+	/* 4 640x480-72 VESA */
+	{ NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2, 
+	  0, FB_VMODE_NONINTERLACED },
+	/* 5 640x480-75 VESA */
+	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+	  0, FB_VMODE_NONINTERLACED },
+	/* 6 640x480-85 VESA */
+	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+	  0, FB_VMODE_NONINTERLACED },
+	/* 7 800x600-56 VESA */
+	{ NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 8 800x600-60 VESA */
+	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 9 800x600-72 VESA */
+	{ NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 10 800x600-75 VESA */
+	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 11 800x600-85 VESA */
+	{ NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+        /* 12 1024x768i-43 VESA */
+	{ NULL, 53, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED },
+	/* 13 1024x768-60 VESA */
+	{ NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED },
+	/* 14 1024x768-70 VESA */
+	{ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED },
+	/* 15 1024x768-75 VESA */
+	{ NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 16 1024x768-85 VESA */
+	{ NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 17 1152x864-75 VESA */
+	{ NULL, 75, 1153, 864, 9259, 256, 64, 32, 1, 128, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 18 1280x960-60 VESA */
+	{ NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 19 1280x960-85 VESA */
+	{ NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 20 1280x1024-60 VESA */
+	{ NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 21 1280x1024-75 VESA */
+	{ NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 22 1280x1024-85 VESA */
+	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 23 1600x1200-60 VESA */
+	{ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 24 1600x1200-65 VESA */
+	{ NULL, 65, 1600, 1200, 5698, 304,  64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 25 1600x1200-70 VESA */
+	{ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 26 1600x1200-75 VESA */
+	{ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, 
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 27 1600x1200-85 VESA */
+	{ NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 28 1792x1344-60 VESA */
+	{ NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 29 1792x1344-75 VESA */
+	{ NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 30 1856x1392-60 VESA */
+	{ NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 31 1856x1392-75 VESA */
+	{ NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 32 1920x1440-60 VESA */
+	{ NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+	/* 33 1920x1440-75 VESA */
+	{ NULL, 60, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+};
 
 static int __init my_atoi(const char *name)
 {
@@ -432,3 +536,4 @@ done:
 }
 
 EXPORT_SYMBOL(__fb_try_mode);
+EXPORT_SYMBOL(vesa_modes);
diff -puN drivers/video/platinumfb.c~fbdev drivers/video/platinumfb.c
--- 25/drivers/video/platinumfb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/platinumfb.c	2003-04-13 22:00:13.000000000 -0700
@@ -36,8 +36,8 @@
 #include <asm/prom.h>
 #include <asm/pgtable.h>
 
-#include "platinumfb.h"
 #include "macmodes.h"
+#include "platinumfb.h"
 
 static int default_vmode = VMODE_NVRAM;
 static int default_cmode = CMODE_NVRAM;
@@ -219,15 +219,14 @@ static int platinumfb_setcolreg(u_int re
 
 	if (regno < 16) {
 		int i;
+		u32 *pal = info->pseudo_palette;
 		switch (p->par.cmode) {
 		case CMODE_16:
-			((u16 *) (info->pseudo_palette))[regno] =
-			    (regno << 10) | (regno << 5) | regno;
+			pal[regno] = (regno << 10) | (regno << 5) | regno;
 			break;
 		case CMODE_32:
 			i = (regno << 8) | regno;
-			((u32 *) (info->pseudo_palette))[regno] =
-			    (i << 16) | i;
+			pal[regno] = (i << 16) | i;
 			break;
 		}
 	}
@@ -401,7 +400,7 @@ try_again:
 	/* Apply default var */
 	p->info.var = var;
 	var.activate = FB_ACTIVATE_NOW;
-	rc = gen_set_var(&var, -1, &p->info);
+	rc = fb_set_var(&var, &p->info);
 	if (rc && (default_vmode != VMODE_640_480_60 || default_cmode != CMODE_8))
 		goto try_again;
 
@@ -410,7 +409,7 @@ try_again:
 		return 0;
 
 	printk(KERN_INFO "fb%d: platinum frame buffer device\n",
-	       GET_FB_IDX(p->info.node));
+	       minor(p->info.node));
 
 	return 1;
 }
@@ -607,21 +606,10 @@ int __init platinum_setup(char *options)
 		return 0;
 
 	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "font:", 5)) {
-			char *p;
-			int i;
-
-			p = this_opt + 5;
-			for (i = 0; i < sizeof(fontname) - 1; i++)
-				if (!*p || *p == ' ' || *p == ',')
-					break;
-			memcpy(fontname, this_opt + 5, i);
-			fontname[i] = 0;
-		}
 		if (!strncmp(this_opt, "vmode:", 6)) {
 	    		int vmode = simple_strtoul(this_opt+6, NULL, 0);
-	    	if (vmode > 0 && vmode <= VMODE_MAX)
-			default_vmode = vmode;
+			if (vmode > 0 && vmode <= VMODE_MAX)
+				default_vmode = vmode;
 		} else if (!strncmp(this_opt, "cmode:", 6)) {
 			int depth = simple_strtoul(this_opt+6, NULL, 0);
 			switch (depth) {
diff -puN drivers/video/pm2fb.c~fbdev drivers/video/pm2fb.c
--- 25/drivers/video/pm2fb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/pm2fb.c	2003-04-13 22:00:13.000000000 -0700
@@ -1434,24 +1434,24 @@ static void pm2fb_clear_margins8(struct 
 }
 
 static struct display_switch pm2_cfb8 = {
-	.setup =	fbcon_cfb8_setup,
-	.bmove =	pm2fb_pp_bmove,
+	.setup		= fbcon_cfb8_setup,
+	.bmove		= pm2fb_pp_bmove,
 #ifdef __alpha__
 	/* Not sure why, but this works and the other does not. */
 	/* Also, perhaps we need a separate routine to wait for the
 	   blitter to stop before doing this? */
 	/* In addition, maybe we need to do this for 16 and 32 bit depths? */
-	.clear =	fbcon_cfb8_clear,
+	.clear		= fbcon_cfb8_clear,
 #else
-	.clear =	pm2fb_clear8,
+	.clear		= pm2fb_clear8,
 #endif
-	.putc =		fbcon_cfb8_putc,
-	.putcs =	fbcon_cfb8_putcs,
-	.revc =		fbcon_cfb8_revc,
-	.cursor =	pm2fb_cursor,
-	.set_font =	pm2fb_set_font,
-	.clear_margins =pm2fb_clear_margins8,
-	fontwidthmask:	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
+	.putc		= fbcon_cfb8_putc,
+	.putcs		= fbcon_cfb8_putcs,
+	.revc		= fbcon_cfb8_revc,
+	.cursor		= pm2fb_cursor,
+	.set_font	= pm2fb_set_font,
+	.clear_margins	= pm2fb_clear_margins8,
+	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
 #endif /* FBCON_HAS_CFB8 */
 
 #ifdef FBCON_HAS_CFB16
diff -puN drivers/video/radeonfb.c~fbdev drivers/video/radeonfb.c
--- 25/drivers/video/radeonfb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/radeonfb.c	2003-04-13 22:00:13.000000000 -0700
@@ -121,7 +121,8 @@ enum radeon_chips {
 	RADEON_ND,
 	RADEON_NE,
 	RADEON_NF,
-	RADEON_NG
+	RADEON_NG,
+	RADEON_QM
 };
 
 enum radeon_arch {
@@ -168,7 +169,8 @@ static struct radeon_chip_info {
 	{ "9700 ND", RADEON_R300 },
 	{ "9700 NE", RADEON_R300 },
 	{ "9700 NF", RADEON_R300 },
-	{ "9700 NG", RADEON_R300 }
+	{ "9700 NG", RADEON_R300 },
+	{ "9100 QM", RADEON_R200 }
 };
 
 
@@ -213,6 +215,7 @@ static struct pci_device_id radeonfb_pci
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NE},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NF},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NG},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QM},
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, radeonfb_pci_table);
@@ -881,6 +884,16 @@ static void radeon_get_pllinfo(struct ra
 				rinfo->pll.ref_div = 12;
 				rinfo->pll.ref_clk = 2700;
 				break;
+			case PCI_DEVICE_ID_ATI_RADEON_ND:
+			case PCI_DEVICE_ID_ATI_RADEON_NE:
+			case PCI_DEVICE_ID_ATI_RADEON_NF:
+			case PCI_DEVICE_ID_ATI_RADEON_NG:
+				rinfo->pll.ppll_max = 40000;
+				rinfo->pll.ppll_min = 20000;
+				rinfo->pll.xclk = 27000;
+				rinfo->pll.ref_div = 12;
+				rinfo->pll.ref_clk = 2700;
+				break;
 			case PCI_DEVICE_ID_ATI_RADEON_QD:
 			case PCI_DEVICE_ID_ATI_RADEON_QE:
 			case PCI_DEVICE_ID_ATI_RADEON_QF:
@@ -1287,7 +1300,6 @@ static int __devinit radeon_init_disp (s
 	fb_alloc_cmap(&info->cmap, 256, 0);
 
 	var.activate = FB_ACTIVATE_NOW;
-	fb_set_var(&var, info);
         return 0;
 }
 
@@ -2926,7 +2938,7 @@ static int radeonfb_pci_register (struct
 		switch (pdev->device) {
 			case PCI_DEVICE_ID_ATI_RADEON_LY:
 			case PCI_DEVICE_ID_ATI_RADEON_LZ:
-				rinfo->video_ram = 8192;
+				rinfo->video_ram = 8192 * 1024;
 				break;
 			default:
 				break;
@@ -3111,10 +3123,10 @@ static void __devexit radeonfb_pci_unreg
 
 
 static struct pci_driver radeonfb_driver = {
-	name:		"radeonfb",
-	id_table:	radeonfb_pci_table,
-	probe:		radeonfb_pci_register,
-	remove:		__devexit_p(radeonfb_pci_unregister),
+	.name		= "radeonfb",
+	.id_table	= radeonfb_pci_table,
+	.probe		= radeonfb_pci_register,
+	.remove		= __devexit_p(radeonfb_pci_unregister),
 };
 
 
diff -puN drivers/video/retz3fb.c~fbdev drivers/video/retz3fb.c
--- 25/drivers/video/retz3fb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/retz3fb.c	2003-04-13 22:00:13.000000000 -0700
@@ -1589,13 +1589,13 @@ static void retz3_clear_margins(struct v
 
 
 static struct display_switch fbcon_retz3_8 = {
-    setup:		fbcon_cfb8_setup,
-    bmove:		retz3_8_bmove,
-    clear:		retz3_8_clear,
-    putc:		retz3_putc,
-    putcs:		retz3_putcs,
-    revc:		retz3_revc,
-    clear_margins:	retz3_clear_margins,
-    fontwidthmask:	FONTWIDTH(8)
+	.setup		= fbcon_cfb8_setup,
+	.bmove		= retz3_8_bmove,
+	.clear		= retz3_8_clear,
+	.putc		= retz3_putc,
+	.putcs		= retz3_putcs,
+	.revc		= retz3_revc,
+	.clear_margins	= retz3_clear_margins,
+	.fontwidthmask	= FONTWIDTH(8)
 };
 #endif
diff -puN drivers/video/riva/fbdev.c~fbdev drivers/video/riva/fbdev.c
--- 25/drivers/video/riva/fbdev.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/riva/fbdev.c	2003-04-13 22:00:13.000000000 -0700
@@ -420,6 +420,50 @@ static inline unsigned char MISCin(struc
 	return (VGA_RD08(par->riva.PVIO, 0x3cc));
 }
 
+static u8 byte_rev[256] = {
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+static inline void reverse_order(u32 *l)
+{
+	u8 *a = (u8 *)l;
+	*a = byte_rev[*a], a++;
+	*a = byte_rev[*a], a++;
+	*a = byte_rev[*a], a++;
+	*a = byte_rev[*a];
+}
+
 /* ------------------------------------------------------------------------- *
  *
  * cursor stuff
@@ -429,7 +473,6 @@ static inline unsigned char MISCin(struc
 /**
  * rivafb_load_cursor_image - load cursor image to hardware
  * @data: address to monochrome bitmap (1 = foreground color, 0 = background)
- * @mask: address to mask (1 = write image pixel, 0 = do not write pixel)
  * @par:  pointer to private data
  * @w:    width of cursor image in pixels
  * @h:    height of cursor image in scanlines
@@ -438,16 +481,15 @@ static inline unsigned char MISCin(struc
  *
  * DESCRIPTiON:
  * Loads cursor image based on a monochrome source and mask bitmap.  The
- * mask bit determines if the image pixel is to be written to the framebuffer
- * or not.  The imaage bits determines the color of the pixel, 0 for
- * background, 1 for foreground.  Only the affected region (as determined
- * by @w and @h parameters) will be updated.
+ * image bits determines the color of the pixel, 0 for background, 1 for
+ * foreground.  Only the affected region (as determined by @w and @h 
+ * parameters) will be updated.
  *
  * CALLED FROM:
  * rivafb_cursor()
  */
-static void rivafb_load_cursor_image(u8 *data, u8 *mask, struct riva_par *par,
-                                     int w, int h, u16 bg, u16 fg)
+static void rivafb_load_cursor_image(struct riva_par *par, u8 *data, 
+				     u8 *mask, u16 bg, u16 fg, u32 w, u32 h)
 {
 	int i, j, k = 0;
 	u32 b, m, tmp;
@@ -455,25 +497,40 @@ static void rivafb_load_cursor_image(u8 
 	for (i = 0; i < h; i++) {
 		b = *((u32 *)data)++;
 		m = *((u32 *)mask)++;
+		reverse_order(&b);
+		
 		for (j = 0; j < w/2; j++) {
 			tmp = 0;
 #if defined (__BIG_ENDIAN)
-			if (m & (1 << 31))
-				tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
+			if (m & (1 << 31)) {
+				fg |= 1 << 15;
+				bg |= 1 << 15;
+			}
+			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
 			b <<= 1;
 			m <<= 1;
 
-			if (m & (1 << 31))
-				tmp |= (b & (1 << 31)) ? fg : bg;
+			if (m & (1 << 31)) {
+				fg |= 1 << 15;
+				bg |= 1 << 15;
+			}
+			tmp |= (b & (1 << 31)) ? fg : bg;
 			b <<= 1;
 			m <<= 1;
 #else
-			if (m & 1)
-				tmp = (b & 1) ? fg : bg;
+			if (m & 1) {
+				fg |= 1 << 15;
+				bg |= 1 << 15;
+			}
+			tmp = (b & 1) ? fg : bg;
 			b >>= 1;
 			m >>= 1;
-			if (m & 1)
-				tmp |= (b & 1) ? fg << 16 : bg << 16;
+			
+			if (m & 1) {
+				fg |= 1 << 15;
+				bg |= 1 << 15;
+			}
+			tmp |= (b & 1) ? fg << 16 : bg << 16;
 			b >>= 1;
 			m >>= 1;
 #endif
@@ -1104,14 +1161,6 @@ static int rivafb_pan_display(struct fb_
 
 	par->riva.SetStartAddress(&par->riva, base);
 
-	/*
-	 * HACK: The hardware cursor occasionally disappears during fast scrolling.
-	 *       We just reset the cursor each time we change the start address.
-	 *       This also has a beneficial side effect of restoring the cursor
-	 *       image when switching from X.
-	 */
-	par->cursor_reset = 1;
-
 	info->var.xoffset = var->xoffset;
 	info->var.yoffset = var->yoffset;
 
@@ -1311,50 +1360,6 @@ static void rivafb_copyarea(struct fb_in
 	wait_for_idle(par);
 }
 
-static u8 byte_rev[256] = {
-	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
-	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
-	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
-	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
-	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
-	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
-	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
-	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
-	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
-	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
-	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
-	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
-	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
-	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
-	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
-	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
-};
-
-static inline void reverse_order(u32 *l)
-{
-	u8 *a = (u8 *)l;
-	*a = byte_rev[*a], a++;
-	*a = byte_rev[*a], a++;
-	*a = byte_rev[*a], a++;
-	*a = byte_rev[*a];
-}
-
 static inline void convert_bgcolor_16(u32 *col)
 {
 	*col = ((*col & 0x00007C00) << 9)
@@ -1388,7 +1393,7 @@ static void rivafb_imageblit(struct fb_i
 	volatile u32 *d;
 	int i, size;
 
-	if (image->depth != 0) {
+	if (image->depth != 1) {
 		cfb_imageblit(info, image);
 		return;
 	}
@@ -1463,29 +1468,19 @@ static void rivafb_imageblit(struct fb_i
  */
 static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	static u8 data[MAX_CURS*MAX_CURS/8], mask[MAX_CURS*MAX_CURS/8];
 	struct riva_par *par = (struct riva_par *) info->par;
 	int i, j, d_idx = 0, s_idx = 0;
-	u16 flags = cursor->set, fg, bg;
-
-	/*
-	 * Can't do invert if one of the operands (dest) is missing,
-	 * ie, only opaque cursor supported.  This should be
-	 * standard for GUI apps.
-	 */
-	if (cursor->dest == NULL && cursor->rop == ROP_XOR)
-		return 1;
-
-	if (par->cursor_reset) {
-		flags = FB_CUR_SETALL;
-		par->cursor_reset = 0;
-	}
+	u8 data[MAX_CURS * MAX_CURS/8];
+	u8 mask[MAX_CURS * MAX_CURS/8];
+	u16 fg, bg;
 
 	par->riva.ShowHideCursor(&par->riva, 0);
 
-	if (flags & FB_CUR_SETPOS) {
+	if (cursor->set & FB_CUR_SETPOS) {
 		u32 xx, yy, temp;
 
+		info->cursor.image.dx = cursor->image.dx;
+		info->cursor.image.dy = cursor->image.dy;
 		yy = cursor->image.dy - info->var.yoffset;
 		xx = cursor->image.dx - info->var.xoffset;
 		temp = xx & 0xFFFF;
@@ -1494,58 +1489,58 @@ static int rivafb_cursor(struct fb_info 
 		par->riva.PRAMDAC[0x0000300/4] = temp;
 	}
 
-	if (flags & FB_CUR_SETSIZE) {
-		memset(data, 0, MAX_CURS * MAX_CURS/8);
-		memset(mask, 0, MAX_CURS * MAX_CURS/8);
+	if (cursor->set & FB_CUR_SETSIZE) {
+		info->cursor.image.height = cursor->image.height;
+		info->cursor.image.width = cursor->image.width;
 		memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
 	}
 
-	if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETDEST)) {
-		int bg_idx = cursor->image.bg_color;
-		int fg_idx = cursor->image.fg_color;
-		int width = (cursor->image.width+7)/8;
-		u8 *dat = (u8 *) cursor->image.data;
-		u8 *dst = (u8 *) cursor->dest;
-		u8 *msk = (u8 *) cursor->mask;
+	if (cursor->set & FB_CUR_SETCMAP) {
+		info->cursor.image.bg_color = cursor->image.bg_color;
+		info->cursor.image.fg_color = cursor->image.fg_color;
+	}
 
-		switch (cursor->rop) {
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) {
+		u32 bg_idx = info->cursor.image.bg_color;
+		u32 fg_idx = info->cursor.image.fg_color;
+		u32 s_pitch = (info->cursor.image.width+7) >> 3;
+		u32 d_pitch = MAX_CURS/8;
+		u8 *dat = (u8 *) cursor->image.data;
+		u8 *msk = (u8 *) info->cursor.mask;
+		u8 src[64];	
+		
+		switch (info->cursor.rop) {
 		case ROP_XOR:
-			for (i = 0; i < cursor->image.height; i++) {
-				for (j = 0; j < width; j++) {
-					d_idx = i * MAX_CURS/8  + j;
-					data[d_idx] =  byte_rev[dat[s_idx] ^ 
-								dst[s_idx]];
-					mask[d_idx] = byte_rev[msk[s_idx]];
-					s_idx++;
-				}
-			}
+			for (i = 0; i < s_pitch * info->cursor.image.height; i++)
+					src[i] = dat[i] ^ msk[i];
 			break;
 		case ROP_COPY:
 		default:
-			for (i = 0; i < cursor->image.height; i++) {
-				for (j = 0; j < width; j++) {
-					d_idx = i * MAX_CURS/8 + j;
-					data[d_idx] = byte_rev[dat[s_idx]];
-					mask[d_idx] = byte_rev[msk[s_idx]];
-					s_idx++;
-				}
-			}
+			for (i = 0; i < s_pitch * info->cursor.image.height; i++)
+				
+					src[i] = dat[i] & msk[i];
 			break;
 		}
+		
+		move_buf_aligned(info, data, src, d_pitch, s_pitch, info->cursor.image.height);
+
+		move_buf_aligned(info, mask, msk, d_pitch, s_pitch, info->cursor.image.height);
 
 		bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
 		     ((info->cmap.green[bg_idx] & 0xf8) << 2) |
-		     ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;
+		     ((info->cmap.blue[bg_idx] & 0xf8) >> 3);
 
 		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
 		     ((info->cmap.green[fg_idx] & 0xf8) << 2) |
-		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
+		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3);
 
 		par->riva.LockUnlock(&par->riva, 0);
-		rivafb_load_cursor_image(data, mask, par, cursor->image.width,
-		cursor->image.height, bg, fg);
+
+		rivafb_load_cursor_image(par, data, mask, bg, fg,
+					 info->cursor.image.width, 
+					 info->cursor.image.height);
 	}
-	if (cursor->enable)
+	if (info->cursor.enable)
 		par->riva.ShowHideCursor(&par->riva, 1);
 	return 0;
 }
@@ -1609,7 +1604,6 @@ static int __init riva_set_fbinfo(struct
 	info->pixmap.buf_align = 4;
 	info->pixmap.scan_align = 4;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-
 	return 0;
 }
 
diff -puN drivers/video/sis/sis_main.h~fbdev drivers/video/sis/sis_main.h
--- 25/drivers/video/sis/sis_main.h~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/sis/sis_main.h	2003-04-13 22:00:13.000000000 -0700
@@ -286,43 +286,43 @@ static struct fb_info sis_fb_info;
 static int    video_type = FB_TYPE_PACKED_PIXELS;
 
 static struct fb_var_screeninfo default_var = {
-	xres:           0,
-	yres:           0,
-	xres_virtual:   0,
-	yres_virtual:   0,
-	xoffset:        0,
-	yoffset:        0,
-	bits_per_pixel: 0,
-	grayscale:      0,
-	red:            {0, 8, 0},
-	green:          {0, 8, 0},
-	blue:           {0, 8, 0},
-	transp:         {0, 0, 0},
-	nonstd:         0,
-	activate:       FB_ACTIVATE_NOW,
-	height:         -1,
-	width:          -1,
-	accel_flags:    0,
-	pixclock:       0,
-	left_margin:    0,
-	right_margin:   0,
-	upper_margin:   0,
-	lower_margin:   0,
-	hsync_len:      0,
-	vsync_len:      0,
-	sync:           0,
-	vmode:          FB_VMODE_NONINTERLACED,
+	.xres		= 0,
+	.yres		= 0,
+	.xres_virtual	= 0,
+	.yres_virtual	= 0,
+	.xoffset	= 0,
+	.yoffset	= 0,
+	.bits_per_pixel	= 0,
+	.grayscale	= 0,
+	.red		= {0, 8, 0},
+	.green		= {0, 8, 0},
+	.blue		= {0, 8, 0},
+	.transp		= {0, 0, 0},
+	.nonstd		= 0,
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.accel_flags	= 0,
+	.pixclock	= 0,
+	.left_margin	= 0,
+	.right_margin	= 0,
+	.upper_margin	= 0,
+	.lower_margin	= 0,
+	.hsync_len	= 0,
+	.vsync_len	= 0,
+	.sync		= 0,
+	.vmode		= FB_VMODE_NONINTERLACED,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
-	reserved:       {0, 0, 0, 0, 0, 0}
+	.reserved	= {0, 0, 0, 0, 0, 0}
 #endif	
 };
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 static struct fb_fix_screeninfo sisfb_fix = {
-	id:		"SiS",
-	type:		FB_TYPE_PACKED_PIXELS,
-	xpanstep:	1,
-	ypanstep:	1,
+	.id		= "SiS",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.xpanstep	= 1,
+	.ypanstep	= 1,
 };
 static char myid[20];
 static u32 pseudo_palette[17];
diff -puN drivers/video/softcursor.c~fbdev drivers/video/softcursor.c
--- 25/drivers/video/softcursor.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/softcursor.c	2003-04-13 22:00:13.000000000 -0700
@@ -24,30 +24,9 @@ int soft_cursor(struct fb_info *info, st
 	unsigned int i, size, dsize, s_pitch, d_pitch;
 	u8 *dst, src[64];
 
-	info->cursor.enable = (cursor->set & FB_CUR_SETCUR) ? 1 : 0;
-
 	if (cursor->set & FB_CUR_SETSIZE) {
-		info->cursor.image.width = cursor->image.width;
 		info->cursor.image.height = cursor->image.height;
-		cursor->set |= FB_CUR_SETSHAPE;
-	}
-
-	s_pitch = (info->cursor.image.width + 7) >> 3;
-	dsize = s_pitch * info->cursor.image.height;
-	d_pitch = (s_pitch + scan_align) & ~scan_align;
-	size = d_pitch * info->cursor.image.height + buf_align;
-	size &= ~buf_align;
-	dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
-	info->cursor.image.data = dst;
-
-	if (cursor->set & FB_CUR_SETSHAPE) {
-		if (info->cursor.mask)
-			kfree(info->cursor.mask);
-		info->cursor.mask = kmalloc(dsize, GFP_KERNEL);
-		if (cursor->mask)
-			memcpy(info->cursor.mask, cursor->mask, dsize);
-		else
-			memset(info->cursor.mask, 0, dsize);
+		info->cursor.image.width = cursor->image.width;
 	}
 
 	if (cursor->set & FB_CUR_SETPOS) {
@@ -57,9 +36,9 @@ int soft_cursor(struct fb_info *info, st
 
 	if (cursor->set & FB_CUR_SETHOT)
 		info->cursor.hot = cursor->hot;
-
+	
 	if (cursor->set & FB_CUR_SETCMAP) {
-		if (cursor->image.depth == 0) {
+		if (cursor->image.depth == 1) {
 			info->cursor.image.bg_color = cursor->image.bg_color;
 			info->cursor.image.fg_color = cursor->image.fg_color;
 		} else {
@@ -67,37 +46,41 @@ int soft_cursor(struct fb_info *info, st
 				fb_copy_cmap(&cursor->image.cmap, &info->cursor.image.cmap, 0);
 		}
 		info->cursor.image.depth = cursor->image.depth;
-	}
+	}	
+
+	s_pitch = (info->cursor.image.width + 7) >> 3;
+	dsize = s_pitch * info->cursor.image.height;
+	d_pitch = (s_pitch + scan_align) & ~scan_align;
+	size = d_pitch * info->cursor.image.height + buf_align;
+	size &= ~buf_align;
+	dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
 
 	if (info->cursor.enable) {
-		switch (cursor->rop) {
+		switch (info->cursor.rop) {
 		case ROP_XOR:
-			for (i = 0; i < dsize; i++) {
-				src[i] = (cursor->image.data[i] &
-					  cursor->mask[i]) ^
-				    	  cursor->dest[i];
-			}
+			for (i = 0; i < dsize; i++)
+				src[i] = cursor->image.data[i] ^ info->cursor.mask[i]; 
 			break;
 		case ROP_COPY:
 		default:
-			for (i = 0; i < dsize; i++) {
-				src[i] = cursor->image.data[i] &
-				    	 cursor->mask[i];
-			}
+			for (i = 0; i < dsize; i++)
+				src[i] = cursor->image.data[i] & info->cursor.mask[i];
 			break;
 		}
-		move_buf_aligned(info, dst, src, d_pitch, s_pitch,
-				 cursor->image.height);
-	} else {
-		move_buf_aligned(info, dst, cursor->dest, s_pitch, d_pitch,
-				 cursor->image.height);
-	}
+	} else 
+		memcpy(src, cursor->image.data, dsize);
+	
+	move_buf_aligned(info, dst, src, d_pitch, s_pitch, info->cursor.image.height);
+	info->cursor.image.data = dst;
+	
 	info->fbops->fb_imageblit(info, &info->cursor.image);
+	atomic_dec(&info->pixmap.count);
+	smp_mb__after_atomic_dec();
 	return 0;
 }
 
 EXPORT_SYMBOL(soft_cursor);
-
+ 
 MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
 MODULE_DESCRIPTION("Generic software cursor");
 MODULE_LICENSE("GPL");
diff -puN drivers/video/tdfxfb.c~fbdev drivers/video/tdfxfb.c
--- 25/drivers/video/tdfxfb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/tdfxfb.c	2003-04-13 22:00:13.000000000 -0700
@@ -930,34 +930,34 @@ static void tdfxfb_copyarea(struct fb_in
 	banshee_wait_idle(info);
 }
 
-static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *pixmap) 
+static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) 
 {
 	struct tdfx_par *par = (struct tdfx_par *) info->par;
-	int size = pixmap->height*((pixmap->width*pixmap->depth + 7)>>3);
+	int size = image->height * ((image->width * image->depth + 7)>>3);
 	int i, stride = info->fix.line_length;
 	u32 bpp = info->var.bits_per_pixel;
 	u32 dstfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); 
-	u8 *chardata = (u8 *) pixmap->data;
+	u8 *chardata = (u8 *) image->data;
 	u32 srcfmt;
 
-	if (pixmap->depth != 0) {
+	if (image->depth != 1) {
 		//banshee_make_room(par, 6 + ((size + 3) >> 2));
 		//srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
-		cfb_imageblit(info, pixmap);
+		cfb_imageblit(info, image);
 		return;
 	} else {
 		banshee_make_room(par, 8 + ((size + 3) >> 2));
-		tdfx_outl(par, COLORFORE, pixmap->fg_color);
-		tdfx_outl(par, COLORBACK, pixmap->bg_color);
+		tdfx_outl(par, COLORFORE, image->fg_color);
+		tdfx_outl(par, COLORBACK, image->bg_color);
 		srcfmt = 0x400000;
 	}	
 
 	tdfx_outl(par,	SRCXY,     0);
-	tdfx_outl(par,	DSTXY,     pixmap->dx | (pixmap->dy << 16));
+	tdfx_outl(par,	DSTXY,     image->dx | (image->dy << 16));
 	tdfx_outl(par,	COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
 	tdfx_outl(par,	SRCFORMAT, srcfmt);
 	tdfx_outl(par,	DSTFORMAT, dstfmt);
-	tdfx_outl(par,	DSTSIZE,   pixmap->width | (pixmap->height << 16));
+	tdfx_outl(par,	DSTSIZE,   image->width | (image->height << 16));
 
 	/* Send four bytes at a time of data */	
 	for (i = (size >> 2) ; i > 0; i--) { 
diff -puN drivers/video/tgafb.c~fbdev drivers/video/tgafb.c
--- 25/drivers/video/tgafb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/tgafb.c	2003-04-13 22:00:13.000000000 -0700
@@ -583,7 +583,7 @@ tgafb_imageblit(struct fb_info *info, co
 	   can do better than the generic code.  */
 	/* ??? There is a DMA write mode; I wonder if that could be
 	   made to pull the data from the image buffer...  */
-	if (image->depth > 0) {
+	if (image->depth > 1) {
 		cfb_imageblit(info, image);
 		return;
 	}
diff -puN drivers/video/tridentfb.c~fbdev drivers/video/tridentfb.c
--- 25/drivers/video/tridentfb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/tridentfb.c	2003-04-13 22:00:13.000000000 -0700
@@ -1204,10 +1204,10 @@ static struct pci_device_id trident_devi
 MODULE_DEVICE_TABLE(pci,trident_devices); 
 
 static struct pci_driver tridentfb_pci_driver = {
-	name:"tridentfb",
-	id_table:trident_devices,
-	probe:trident_pci_probe,
-	remove:__devexit_p(trident_pci_remove)
+	.name		= "tridentfb",
+	.id_table	= trident_devices,
+	.probe		= trident_pci_probe,
+	.remove		= __devexit_p(trident_pci_remove)
 };
 
 int __init tridentfb_init(void)
diff -puN drivers/video/vesafb.c~fbdev drivers/video/vesafb.c
--- 25/drivers/video/vesafb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/vesafb.c	2003-04-13 22:00:13.000000000 -0700
@@ -19,7 +19,9 @@
 #include <linux/fb.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-
+#ifdef __i386__
+#include <video/edid.h>
+#endif
 #include <asm/io.h>
 #include <asm/mtrr.h>
 
@@ -213,6 +215,7 @@ int __init vesafb_setup(char *options)
 int __init vesafb_init(void)
 {
 	int video_cmap_len;
+	char *edid = 0;
 	int i;
 
 	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
@@ -296,12 +299,20 @@ int __init vesafb_init(void)
 		vesafb_defined.yres_virtual = vesafb_defined.yres;
 		ypan = 0;
 	}
-	
-	/* some dummy values for timing to make fbset happy */
-	vesafb_defined.pixclock     = 10000000 / vesafb_defined.xres * 1000 / vesafb_defined.yres;
-	vesafb_defined.left_margin  = (vesafb_defined.xres / 8) & 0xf8;
-	vesafb_defined.hsync_len    = (vesafb_defined.xres / 8) & 0xf8;
 
+#ifdef __i386__
+	edid = get_EDID_from_BIOS(0);
+	if (edid)
+		parse_edid(edid, &vesafb_defined);	
+	else		
+#endif
+	{	
+		/* some dummy values for timing to make fbset happy */
+		vesafb_defined.pixclock     = 10000000 / vesafb_defined.xres * 1000 / vesafb_defined.yres;
+		vesafb_defined.left_margin  = (vesafb_defined.xres / 8) & 0xf8;
+		vesafb_defined.hsync_len    = (vesafb_defined.xres / 8) & 0xf8;
+	}
+	
 	if (vesafb_defined.bits_per_pixel > 8) {
 		vesafb_defined.red.offset    = screen_info.red_pos;
 		vesafb_defined.red.length    = screen_info.red_size;
diff -puN drivers/video/vga16fb.c~fbdev drivers/video/vga16fb.c
--- 25/drivers/video/vga16fb.c~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/drivers/video/vga16fb.c	2003-04-13 22:00:13.000000000 -0700
@@ -1304,9 +1304,9 @@ void vga_imageblit_color(struct fb_info 
 				
 void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
-	if (image->depth == 0)
+	if (image->depth == 1)
 		vga_imageblit_expand(info, image);
-	else if (image->depth == info->var.bits_per_pixel)
+	else if (image->depth <= info->var.bits_per_pixel)
 		vga_imageblit_color(info, image);
 }
 
diff -puN include/asm-i386/setup.h~fbdev include/asm-i386/setup.h
--- 25/include/asm-i386/setup.h~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/include/asm-i386/setup.h	2003-04-13 22:00:13.000000000 -0700
@@ -37,6 +37,7 @@
 #define KERNEL_START (*(unsigned long *) (PARAM+0x214))
 #define INITRD_START (*(unsigned long *) (PARAM+0x218))
 #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
+#define EDID_INFO   (*(struct edid_info *) (PARAM+0x440))
 #define EDD_NR     (*(unsigned char *) (PARAM+EDDNR))
 #define EDD_BUF     ((struct edd_info *) (PARAM+EDDBUF))
 #define COMMAND_LINE ((char *) (PARAM+2048))
diff -puN include/linux/fb.h~fbdev include/linux/fb.h
--- 25/include/linux/fb.h~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/include/linux/fb.h	2003-04-13 22:00:13.000000000 -0700
@@ -2,6 +2,7 @@
 #define _LINUX_FB_H
 
 #include <linux/tty.h>
+#include <linux/workqueue.h>
 #include <asm/types.h>
 #include <asm/io.h>
 
@@ -310,7 +311,6 @@ struct fb_image {
 #define FB_CUR_SETCMAP  0x08
 #define FB_CUR_SETSHAPE 0x10
 #define FB_CUR_SETSIZE	0x20
-#define FB_CUR_SETDEST	0x40
 #define FB_CUR_SETALL   0xFF
 
 struct fbcurpos {
@@ -322,7 +322,6 @@ struct fb_cursor {
 	__u16 enable;		/* cursor on/off */
 	__u16 rop;		/* bitop operation */
 	char *mask;		/* cursor mask bits */
-	char *dest;		/* destination */
 	struct fbcurpos hot;	/* cursor hot spot */
 	struct fb_image	image;	/* Cursor image */
 };
@@ -339,9 +338,9 @@ struct fb_pixmap {
 	__u32 buf_align;                  /* byte alignment of each bitmap */
 	__u32 scan_align;                 /* alignment per scanline        */
 	__u32 flags;                      /* see FB_PIXMAP_*               */
-	void (*outbuf)(u8 dst, u8 *addr); /* access methods                */
+					  /* access methods                */
+	void (*outbuf)(u8 *dst, u8 *addr, unsigned int size); 
 	u8   (*inbuf) (u8 *addr);
-	unsigned long lock_flags;         /* flags for locking             */
 	spinlock_t lock;                  /* spinlock                      */
 	atomic_t count;
 };
@@ -406,8 +405,9 @@ struct fb_info {
    struct fb_fix_screeninfo fix;        /* Current fix */
    struct fb_monspecs monspecs;         /* Current Monitor specs */
    struct fb_cursor cursor;		/* Current cursor */	
-   struct fb_cmap cmap;                 /* Current cmap */
+   struct work_struct queue;		/* Framebuffer event queue */
    struct fb_pixmap pixmap;	        /* Current pixmap */
+   struct fb_cmap cmap;                 /* Current cmap */
    struct fb_ops *fbops;
    char *screen_base;                   /* Virtual address */
    struct vc_data *display_fg;		/* Console visible on this display */
@@ -469,9 +469,9 @@ struct fb_info {
      *  `Generic' versions of the frame buffer device operations
      */
 
-extern int fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info); 
-extern int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); 
-extern int fb_blank(int blank, struct fb_info *info);
+extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var); 
+extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var); 
+extern int fb_blank(struct fb_info *info, int blank);
 extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
 extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); 
 extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); 
@@ -505,12 +505,21 @@ extern int fb_get_mode(int flags, u32 va
 		       struct fb_info *info);
 extern int fb_validate_mode(struct fb_var_screeninfo *var,
 			    struct fb_info *info);
+extern int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
+extern int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs);
+extern struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize);
+extern void fb_destroy_modedb(struct fb_videomode *modedb);
+extern void show_edid(unsigned char *edid);
+
+/* drivers/video/modedb.c */
+#define VESA_MODEDB_SIZE 34
+extern const struct fb_videomode vesa_modes[];
 
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
 extern void fb_dealloc_cmap(struct fb_cmap *cmap);
-extern void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to,
-			 int fsfromto);
+extern int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to,
+			int fsfromto);
 extern int fb_set_cmap(struct fb_cmap *cmap, int kspc, struct fb_info *fb_info);
 extern struct fb_cmap *fb_default_cmap(int len);
 extern void fb_invert_cmaps(void);
diff -puN include/linux/linux_logo.h~fbdev include/linux/linux_logo.h
--- 25/include/linux/linux_logo.h~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/include/linux/linux_logo.h	2003-04-13 22:00:13.000000000 -0700
@@ -32,6 +32,6 @@ struct linux_logo {
 	const unsigned char *data;
 };
 
-extern const struct linux_logo * __init fb_find_logo(int type);
+extern const struct linux_logo * __init find_logo(int depth);
 
 #endif /* _LINUX_LINUX_LOGO_H */
diff -puN include/linux/pci_ids.h~fbdev include/linux/pci_ids.h
--- 25/include/linux/pci_ids.h~fbdev	2003-04-13 22:00:13.000000000 -0700
+++ 25-akpm/include/linux/pci_ids.h	2003-04-13 22:00:19.000000000 -0700
@@ -287,6 +287,7 @@
 #define PCI_DEVICE_ID_ATI_RADEON_Ie	0x4965
 #define PCI_DEVICE_ID_ATI_RADEON_If	0x4966
 #define PCI_DEVICE_ID_ATI_RADEON_Ig	0x4967
+#define PCI_DEVICE_ID_ATI_RADEON_QM	0x514d
 /* Radeon R300 (9700) */
 #define PCI_DEVICE_ID_ATI_RADEON_ND	0x4e44
 #define PCI_DEVICE_ID_ATI_RADEON_NE	0x4e45
diff -puN /dev/null include/video/edid.h
--- /dev/null	2002-08-30 16:31:37.000000000 -0700
+++ 25-akpm/include/video/edid.h	2003-04-13 22:00:19.000000000 -0700
@@ -0,0 +1,27 @@
+#ifndef __linux_video_edid_h__
+#define __linux_video_edid_h__
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#ifdef CONFIG_ALL_PPC
+#include <linux/pci.h>
+#endif
+
+#ifdef CONFIG_X86
+struct edid_info {
+	unsigned char dummy[128];
+};
+
+extern struct edid_info edid_info;
+extern char *get_EDID_from_BIOS(void *);
+
+#endif /* CONFIG_X86 */
+
+#ifdef CONFIG_ALL_PPC
+extern char *get_EDID_from_OF(struct pci_dev *pdev);
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __linux_video_edid_h__ */

_
