vserver 1.9.3
[linux-2.6.git] / drivers / video / vesafb.c
index 88571b3..c5c649d 100644 (file)
@@ -47,15 +47,12 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = {
        .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;
+static unsigned short  *pmi_base  = NULL;
 static void            (*pmi_start)(void);
 static void            (*pmi_pal)(void);
 
@@ -90,15 +87,17 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
        return 0;
 }
 
-static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
+static void vesa_setpalette(int regno, unsigned red, unsigned green,
+                           unsigned blue, struct fb_var_screeninfo *var)
 {
 #ifdef __i386__
        struct { u_char blue, green, red, pad; } entry;
+       int shift = 16 - var->green.length;
 
        if (pmi_setpal) {
-               entry.red   = red   >> 10;
-               entry.green = green >> 10;
-               entry.blue  = blue  >> 10;
+               entry.red   = red   >> shift;
+               entry.green = green >> shift;
+               entry.blue  = blue  >> shift;
                entry.pad   = 0;
                __asm__ __volatile__(
                 "call *(%%esi)"
@@ -112,9 +111,9 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned bl
        } else {
                /* without protected mode interface, try VGA registers... */
                outb_p(regno,       dac_reg);
-               outb_p(red   >> 10, dac_val);
-               outb_p(green >> 10, dac_val);
-               outb_p(blue  >> 10, dac_val);
+               outb_p(red   >> shift, dac_val);
+               outb_p(green >> shift, dac_val);
+               outb_p(blue  >> shift, dac_val);
        }
 #endif
 }
@@ -135,7 +134,7 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
        switch (info->var.bits_per_pixel) {
        case 8:
-               vesa_setpalette(regno,red,green,blue);
+               vesa_setpalette(regno,red,green,blue, &info->var);
                break;
        case 16:
                if (info->var.red.offset == 10) {
@@ -210,14 +209,17 @@ int __init vesafb_setup(char *options)
                        mtrr=1;
                else if (! strcmp(this_opt, "nomtrr"))
                        mtrr=0;
+               else if (! strncmp(this_opt, "vram:", 5))
+                       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 +231,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)
+               vesafb_fix.smem_len = vram * 1024 * 1024;
+
        vesafb_fix.visual   = (vesafb_defined.bits_per_pixel == 8) ?
                FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
 
@@ -251,17 +264,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);
 
@@ -312,32 +333,26 @@ int __init vesafb_init(void)
        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;
-               vesafb_defined.green.offset  = screen_info.green_pos;
-               vesafb_defined.green.length  = screen_info.green_size;
-               vesafb_defined.blue.offset   = screen_info.blue_pos;
-               vesafb_defined.blue.length   = screen_info.blue_size;
-               vesafb_defined.transp.offset = screen_info.rsvd_pos;
-               vesafb_defined.transp.length = screen_info.rsvd_size;
-               printk(KERN_INFO "vesafb: directcolor: "
-                      "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
-                      screen_info.rsvd_size,
-                      screen_info.red_size,
-                      screen_info.green_size,
-                      screen_info.blue_size,
-                      screen_info.rsvd_pos,
-                      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_defined.red.offset    = screen_info.red_pos;
+       vesafb_defined.red.length    = screen_info.red_size;
+       vesafb_defined.green.offset  = screen_info.green_pos;
+       vesafb_defined.green.length  = screen_info.green_size;
+       vesafb_defined.blue.offset   = screen_info.blue_pos;
+       vesafb_defined.blue.length   = screen_info.blue_size;
+       vesafb_defined.transp.offset = screen_info.rsvd_pos;
+       vesafb_defined.transp.length = screen_info.rsvd_size;
+       printk(KERN_INFO "vesafb: %s: "
+              "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+              (vesafb_defined.bits_per_pixel > 8) ?
+              "Truecolor" : "Pseudocolor",
+              screen_info.rsvd_size,
+              screen_info.red_size,
+              screen_info.green_size,
+              screen_info.blue_size,
+              screen_info.rsvd_pos,
+              screen_info.red_pos,
+              screen_info.green_pos,
+              screen_info.blue_pos);
 
        vesafb_fix.ypanstep  = ypan     ? 1 : 0;
        vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
@@ -358,21 +373,58 @@ 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 |
+               (ypan) ? FBINFO_HWACCEL_YPAN : 0;
+
+       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;
+       char *option = NULL;
+
+       /* ignore error return of fb_get_options */
+       fb_get_options("vesafb", &option);
+       vesafb_setup(option);
+       ret = driver_register(&vesafb_driver);
+
+       if (!ret) {
+               ret = platform_device_register(&vesafb_device);
+               if (ret)
+                       driver_unregister(&vesafb_driver);
+       }
+       return ret;
 }
+module_init(vesafb_init);
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.