vserver 1.9.3
[linux-2.6.git] / drivers / video / sgivwfb.c
index 136c9d8..4fc5482 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/mtrr.h>
 
 #define INCLUDE_TIMING_TABLE_DATA
-#define DBE_REG_BASE default_par.regs
+#define DBE_REG_BASE par->regs
 #include <video/sgivw.h>
 
 struct sgivw_par {
@@ -44,9 +44,6 @@ struct sgivw_par {
 extern unsigned long sgivwfb_mem_phys;
 extern unsigned long sgivwfb_mem_size;
 
-static struct sgivw_par default_par;
-static u32 pseudo_palette[17];
-static struct fb_info fb_info;
 static int ypan = 0;
 static int ywrap = 0;
 
@@ -162,7 +159,7 @@ static unsigned long get_line_length(int xres_virtual, int bpp)
  *              console.
  */
 
-static void dbe_TurnOffDma(void)
+static void dbe_TurnOffDma(struct sgivw_par *par)
 {
        unsigned int readVal;
        int i;
@@ -367,7 +364,7 @@ static int sgivwfb_check_var(struct fb_var_screeninfo *var,
 /*
  *  Setup flatpanel related registers.
  */
-static void sgivwfb_setup_flatpanel(struct dbe_timing_info *currentTiming)
+static void sgivwfb_setup_flatpanel(struct sgivw_par *par, struct dbe_timing_info *currentTiming)
 {
        int fp_wid, fp_hgt, fp_vbs, fp_vbe;
        u32 outputVal = 0;
@@ -429,7 +426,7 @@ static int sgivwfb_set_par(struct fb_info *info)
        /* Turn on dotclock PLL */
        DBE_SETREG(ctrlstat, 0x20000000);
 
-       dbe_TurnOffDma();
+       dbe_TurnOffDma(par);
 
        /* dbe_CalculateScreenParams(); */
        maxPixelsPerTileX = 512 / bytesPerPixel;
@@ -453,7 +450,7 @@ static int sgivwfb_set_par(struct fb_info *info)
                DBE_SETREG(vt_xy, 0x00000000);
                udelay(1);
        } else
-               dbe_TurnOffDma();
+               dbe_TurnOffDma(par);
 
        /* dbe_Initdbe(); */
        for (i = 0; i < 256; i++) {
@@ -567,7 +564,7 @@ static int sgivwfb_set_par(struct fb_info *info)
        DBE_SETREG(vt_hcmap, outputVal);
 
        if (flatpanel_id != -1)
-               sgivwfb_setup_flatpanel(currentTiming);
+               sgivwfb_setup_flatpanel(par, currentTiming);
 
        outputVal = 0;
        temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
@@ -752,16 +749,30 @@ int __init sgivwfb_setup(char *options)
 /*
  *  Initialisation
  */
-int __init sgivwfb_init(void)
+static void sgivwfb_release(struct device *device)
+{
+}
+
+static int __init sgivwfb_probe(struct device *device)
 {
+       struct platform_device *dev = to_platform_device(device);
+       struct sgivw_par *par;
+       struct fb_info *info;
        char *monitor;
 
+       info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 256, &dev->dev);
+       if (!info)
+               return -ENOMEM;
+       par = info->par;
+
        if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
                printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
+               framebuffer_release(info);
                return -EBUSY;
        }
-       default_par.regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
-       if (!default_par.regs) {
+
+       par->regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
+       if (!par->regs) {
                printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
                goto fail_ioremap_regs;
        }
@@ -773,66 +784,118 @@ int __init sgivwfb_init(void)
        sgivwfb_fix.ywrapstep = ywrap;
        sgivwfb_fix.ypanstep = ypan;
 
-       fb_info.fix = sgivwfb_fix;
+       info->fix = sgivwfb_fix;
 
        switch (flatpanel_id) {
                case FLATPANEL_SGI_1600SW:
-                       fb_info.var = sgivwfb_var1600sw;
+                       info->var = sgivwfb_var1600sw;
                        monitor = "SGI 1600SW flatpanel";
                        break;
                default:
-                       fb_info.var = sgivwfb_var;
+                       info->var = sgivwfb_var;
                        monitor = "CRT";
        }
 
        printk(KERN_INFO "sgivwfb: %s monitor selected\n", monitor);
 
-       fb_info.fbops = &sgivwfb_ops;
-       fb_info.pseudo_palette = pseudo_palette;
-       fb_info.par = &default_par;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
+       info->fbops = &sgivwfb_ops;
+       info->pseudo_palette = (void *) (par + 1);
+       info->flags = FBINFO_DEFAULT;
 
-       fb_info.screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
-       if (!fb_info.screen_base) {
+       info->screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
+       if (!info->screen_base) {
                printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
                goto fail_ioremap_fbmem;
        }
 
-       fb_alloc_cmap(&fb_info.cmap, 256, 0);
+       if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+               goto fail_color_map;
 
-       if (register_framebuffer(&fb_info) < 0) {
+       if (register_framebuffer(info) < 0) {
                printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
                goto fail_register_framebuffer;
        }
 
+       dev_set_drvdata(&dev->dev, info);
+
        printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n",      
-               fb_info.node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
+               info->node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
        return 0;
 
 fail_register_framebuffer:
-       iounmap((char *) fb_info.screen_base);
+       fb_dealloc_cmap(&info->cmap);
+fail_color_map:
+       iounmap((char *) info->screen_base);
 fail_ioremap_fbmem:
-       iounmap(default_par.regs);
+       iounmap(par->regs);
 fail_ioremap_regs:
        release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+       framebuffer_release(info);
        return -ENXIO;
 }
 
-#ifdef MODULE
-MODULE_LICENSE("GPL");
+static int sgivwfb_remove(struct device *device)
+{
+       struct fb_info *info = dev_get_drvdata(device);
+
+       if (info) {
+               struct sgivw_par *par = info->par;
+
+               unregister_framebuffer(info);
+               dbe_TurnOffDma(par);
+               iounmap(par->regs);
+               iounmap(info->screen_base);
+               release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+       }
+       return 0;
+}
+
+static struct device_driver sgivwfb_driver = {
+       .name   = "sgivwfb",
+       .bus    = &platform_bus_type,
+       .probe  = sgivwfb_probe,
+       .remove = sgivwfb_remove,
+};
 
-int init_module(void)
+static struct platform_device sgivwfb_device = {
+       .name   = "sgivwfb",
+       .id     = 0,
+       .dev    = {
+               .release = sgivwfb_release,
+       }
+};
+
+int __init sgivwfb_init(void)
 {
-       return sgivwfb_init();
+       int ret;
+
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("sgivwfb", &option))
+               return -ENODEV;
+       sgivwfb_setup(option);
+#endif
+       ret = driver_register(&sgivwfb_driver);
+       if (!ret) {
+               ret = platform_device_register(&sgivwfb_device);
+               if (ret)
+                       driver_unregister(&sgivwfb_driver);
+       }
+       return ret;
 }
 
-void cleanup_module(void)
+module_init(sgivwfb_init);
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+static void __exit sgivwfb_exit(void)
 {
-       unregister_framebuffer(&fb_info);
-       dbe_TurnOffDma();
-       iounmap(regs);
-       iounmap(&fb_info.screen_base);
-       release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+       platform_device_unregister(&sgivwfb_device);
+       driver_unregister(&sgivwfb_driver);
 }
 
+module_exit(sgivwfb_exit);
+
 #endif                         /* MODULE */