From: James Simmons <jsimmons@infradead.org>

This patch migrates the Vesa Framebuffer driver over to the
framebuffer_alloc/framebuffer_release api.  It also fixes the error
handling paths.  The mtrr issue that Geert brought up has been fixed.


---

 25-akpm/drivers/video/vesafb.c |   98 ++++++++++++++++++++++++++++++-----------
 1 files changed, 73 insertions(+), 25 deletions(-)

diff -puN drivers/video/vesafb.c~vesa-fbdev-update drivers/video/vesafb.c
--- 25/drivers/video/vesafb.c~vesa-fbdev-update	2004-04-25 22:14:41.144503448 -0700
+++ 25-akpm/drivers/video/vesafb.c	2004-04-25 22:14:41.148502840 -0700
@@ -47,12 +47,9 @@ static struct fb_fix_screeninfo vesafb_f
 	.accel	= FB_ACCEL_NONE,
 };
 
-static struct fb_info fb_info;
-static u32 pseudo_palette[17];
-
 static int             inverse   = 0;
 static int             mtrr      = 1;
-
+static int	       vram __initdata = 0; /* Set amount of memory to be used */
 static int             pmi_setpal = 0;	/* pmi for palette changes ??? */
 static int             ypan       = 0;  /* 0..nothing, 1..ypan, 2..ywrap */
 static unsigned short  *pmi_base  = 0;
@@ -210,14 +207,17 @@ int __init vesafb_setup(char *options)
 			mtrr=1;
 		else if (! strcmp(this_opt, "nomtrr"))
 			mtrr=0;
+		else if (! strcmp(this_opt, "vram"))
+			vram = simple_strtoul(this_opt+5, NULL, 0);
 	}
 	return 0;
 }
 
-int __init vesafb_init(void)
+static int __init vesafb_probe(struct device *device)
 {
-	int video_cmap_len;
-	int i;
+	struct platform_device *dev = to_platform_device(device);
+	struct fb_info *info;
+	int i, err;
 
 	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
 		return -ENXIO;
@@ -229,7 +229,18 @@ int __init vesafb_init(void)
 	vesafb_defined.xres = screen_info.lfb_width;
 	vesafb_defined.yres = screen_info.lfb_height;
 	vesafb_fix.line_length = screen_info.lfb_linelength;
-	vesafb_fix.smem_len = screen_info.lfb_size * 65536;
+
+	/* Allocate enough memory for double buffering */
+	vesafb_fix.smem_len = screen_info.lfb_width * screen_info.lfb_height * vesafb_defined.bits_per_pixel >> 2;
+
+	/* check that we don't remap more memory than old cards have */
+	if (vesafb_fix.smem_len > (screen_info.lfb_size * 65536))
+		vesafb_fix.smem_len = screen_info.lfb_size * 65536;
+
+	/* Set video size according to vram boot option */
+	if (vram && vram * 1024 * 1024 != vesafb_fix.smem_len)
+		vesafb_fix.smem_len = vram * 1024 * 1024;
+
 	vesafb_fix.visual   = (vesafb_defined.bits_per_pixel == 8) ?
 		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
 
@@ -251,17 +262,25 @@ int __init vesafb_init(void)
 		   spaces our resource handlers simply don't know about */
 	}
 
-        fb_info.screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
-	if (!fb_info.screen_base) {
+	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
+	if (!info) {
 		release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len);
+		return -ENOMEM;
+	}
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+
+        info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
+	if (!info->screen_base) {
 		printk(KERN_ERR
 		       "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
 			vesafb_fix.smem_len, vesafb_fix.smem_start);
-		return -EIO;
+		err = -EIO;
+		goto err;
 	}
 
 	printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
-	       vesafb_fix.smem_start, fb_info.screen_base, vesafb_fix.smem_len/1024);
+	       vesafb_fix.smem_start, info->screen_base, vesafb_fix.smem_len/1024);
 	printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
 	       vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages);
 
@@ -331,12 +350,10 @@ int __init vesafb_init(void)
 		       screen_info.red_pos,
 		       screen_info.green_pos,
 		       screen_info.blue_pos);
-		video_cmap_len = 16;
 	} else {
 		vesafb_defined.red.length   = 6;
 		vesafb_defined.green.length = 6;
 		vesafb_defined.blue.length  = 6;
-		video_cmap_len = 256;
 	}
 
 	vesafb_fix.ypanstep  = ypan     ? 1 : 0;
@@ -358,20 +375,51 @@ int __init vesafb_init(void)
 		}
 	}
 	
-	fb_info.fbops = &vesafb_ops;
-	fb_info.var = vesafb_defined;
-	fb_info.fix = vesafb_fix;
-	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &vesafb_ops;
+	info->var = vesafb_defined;
+	info->fix = vesafb_fix;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		err = -ENXIO;
+		goto err;
+	}
+	if (register_framebuffer(info)<0) {
+		err = -EINVAL;
+		fb_dealloc_cmap(&info->cmap);
+		goto err;
+	}
+	printk(KERN_INFO "fb%d: %s frame buffer device\n",
+	       info->node, info->fix.id);
+	return 0;
+err:
+	framebuffer_release(info);
+	release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len);
+	return err;
+}
 
-	fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
+static struct device_driver vesafb_driver = {
+	.name	= "vesafb",
+	.bus	= &platform_bus_type,
+	.probe	= vesafb_probe,
+};
 
-	if (register_framebuffer(&fb_info)<0)
-		return -EINVAL;
+static struct platform_device vesafb_device = {
+	.name	= "vesafb",
+};
 
-	printk(KERN_INFO "fb%d: %s frame buffer device\n",
-	       fb_info.node, fb_info.fix.id);
-	return 0;
+int __init vesafb_init(void)
+{
+	int ret;
+
+	ret = driver_register(&vesafb_driver);
+
+	if (!ret) {
+		ret = platform_device_register(&vesafb_device);
+		if (ret)
+			driver_unregister(&vesafb_driver);
+	}
+	return ret;
 }
 
 /*

_