watchdog: sbc_fitpc2_wdt: fixed "scheduling while atomic" bug.
[safe/jmp/linux-2.6] / drivers / video / gbefb.c
index 2a02328..7d8c55d 100644 (file)
@@ -9,11 +9,11 @@
  *  more details.
  */
 
-#include <linux/config.h>
 #include <linux/delay.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
+#include <linux/gfp.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -76,7 +76,7 @@ struct gbefb_par {
 static unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024;
 static void *gbe_mem;
 static dma_addr_t gbe_dma_addr;
-unsigned long gbe_mem_phys;
+static unsigned long gbe_mem_phys;
 
 static struct {
        uint16_t *cpu;
@@ -87,7 +87,9 @@ static int gbe_revision;
 
 static int ypan, ywrap;
 
-static uint32_t pseudo_palette[256];
+static uint32_t pseudo_palette[16];
+static uint32_t gbe_cmap[256];
+static int gbe_turned_on; /* 0 turned off, 1 turned on */
 
 static char *mode_option __initdata = NULL;
 
@@ -184,8 +186,8 @@ static struct fb_videomode default_mode_LCD __initdata = {
        .vmode          = FB_VMODE_NONINTERLACED,
 };
 
-struct fb_videomode *default_mode = &default_mode_CRT;
-struct fb_var_screeninfo *default_var = &default_var_CRT;
+static struct fb_videomode *default_mode __initdata = &default_mode_CRT;
+static struct fb_var_screeninfo *default_var __initdata = &default_var_CRT;
 
 static int flat_panel_enabled = 0;
 
@@ -204,11 +206,13 @@ static void gbe_reset(void)
  *              console.
  */
 
-void gbe_turn_off(void)
+static void gbe_turn_off(void)
 {
        int i;
        unsigned int val, x, y, vpixen_off;
 
+       gbe_turned_on = 0;
+
        /* check if pixel counter is on */
        val = gbe->vt_xy;
        if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1)
@@ -372,6 +376,22 @@ static void gbe_turn_on(void)
        }
        if (i == 10000)
                printk(KERN_ERR "gbefb: turn on DMA timed out\n");
+
+       gbe_turned_on = 1;
+}
+
+static void gbe_loadcmap(void)
+{
+       int i, j;
+
+       for (i = 0; i < 256; i++) {
+               for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++)
+                       udelay(10);
+               if (j == 1000)
+                       printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
+
+               gbe->cmap[i] = gbe_cmap[i];
+       }
 }
 
 /*
@@ -383,6 +403,7 @@ static int gbefb_blank(int blank, struct fb_info *info)
        switch (blank) {
        case FB_BLANK_UNBLANK:          /* unblank */
                gbe_turn_on();
+               gbe_loadcmap();
                break;
 
        case FB_BLANK_NORMAL:           /* blank */
@@ -656,12 +677,15 @@ static int gbefb_set_par(struct fb_info *info)
        switch (bytesPerPixel) {
        case 1:
                SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_I8);
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
                break;
        case 2:
                SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_ARGB5);
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
                break;
        case 4:
                SET_GBE_FIELD(WID, TYP, val, GBE_CMODE_RGB8);
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
                break;
        }
        SET_GBE_FIELD(WID, BUF, val, GBE_BMODE_BOTH);
@@ -678,7 +702,7 @@ static int gbefb_set_par(struct fb_info *info)
           blocks of 512x128, 256x128 or 128x128 pixels, respectively for 8bit,
           16bit and 32 bit modes (64 kB). They cover the screen with partial
           tiles on the right and/or bottom of the screen if needed.
-          For exemple in 640x480 8 bit mode the mapping is:
+          For example in 640x480 8 bit mode the mapping is:
 
           <-------- 640 ----->
           <---- 512 ----><128|384 offscreen>
@@ -794,16 +818,10 @@ static int gbefb_set_par(struct fb_info *info)
                gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8);
 
        /* Initialize the color map */
-       for (i = 0; i < 256; i++) {
-               int j;
-
-               for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++)
-                       udelay(10);
-               if (j == 1000)
-                       printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
+       for (i = 0; i < 256; i++)
+               gbe_cmap[i] = (i << 8) | (i << 16) | (i << 24);
 
-               gbe->cmap[i] = (i << 8) | (i << 16) | (i << 24);
-       }
+       gbe_loadcmap();
 
        return 0;
 }
@@ -852,33 +870,37 @@ static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,
        green >>= 8;
        blue >>= 8;
 
-       switch (info->var.bits_per_pixel) {
-       case 8:
-               /* wait for the color map FIFO to have a free entry */
-               for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
-                       udelay(10);
-               if (i == 1000) {
-                       printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
-                       return 1;
+       if (info->var.bits_per_pixel <= 8) {
+               gbe_cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
+               if (gbe_turned_on) {
+                       /* wait for the color map FIFO to have a free entry */
+                       for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
+                               udelay(10);
+                       if (i == 1000) {
+                               printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
+                               return 1;
+                       }
+                       gbe->cmap[regno] = gbe_cmap[regno];
+               }
+       } else if (regno < 16) {
+               switch (info->var.bits_per_pixel) {
+               case 15:
+               case 16:
+                       red >>= 3;
+                       green >>= 3;
+                       blue >>= 3;
+                       pseudo_palette[regno] =
+                               (red << info->var.red.offset) |
+                               (green << info->var.green.offset) |
+                               (blue << info->var.blue.offset);
+                       break;
+               case 32:
+                       pseudo_palette[regno] =
+                               (red << info->var.red.offset) |
+                               (green << info->var.green.offset) |
+                               (blue << info->var.blue.offset);
+                       break;
                }
-               gbe->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
-               break;
-       case 15:
-       case 16:
-               red >>= 3;
-               green >>= 3;
-               blue >>= 3;
-               pseudo_palette[regno] =
-                       (red << info->var.red.offset) |
-                       (green << info->var.green.offset) |
-                       (blue << info->var.blue.offset);
-               break;
-       case 32:
-               pseudo_palette[regno] =
-                       (red << info->var.red.offset) |
-                       (green << info->var.green.offset) |
-                       (blue << info->var.blue.offset);
-               break;
        }
 
        return 0;
@@ -891,6 +913,7 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
        unsigned int line_length;
        struct gbe_timing_info timing;
+       int ret;
 
        /* Limit bpp to 8, 16, and 32 */
        if (var->bits_per_pixel <= 8)
@@ -909,8 +932,10 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 
        var->grayscale = 0;     /* No grayscale for now */
 
-       if ((var->pixclock = compute_gbe_timing(var, &timing)) < 0)
-               return(-EINVAL);
+       ret = compute_gbe_timing(var, &timing);
+       var->pixclock = ret;
+       if (ret < 0)
+               return -EINVAL;
 
        /* Adjust virtual resolution, if necessary */
        if (var->xres > var->xres_virtual || (!ywrap && !ypan))
@@ -979,7 +1004,7 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        return 0;
 }
 
-static int gbefb_mmap(struct fb_info *info, struct file *file,
+static int gbefb_mmap(struct fb_info *info,
                        struct vm_area_struct *vma)
 {
        unsigned long size = vma->vm_end - vma->vm_start;
@@ -1000,7 +1025,6 @@ static int gbefb_mmap(struct fb_info *info, struct file *file,
                pgprot_fb(pgprot_val(vma->vm_page_prot));
 
        vma->vm_flags |= VM_IO | VM_RESERVED;
-       vma->vm_file = file;
 
        /* look for the starting tile */
        tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];
@@ -1038,21 +1062,20 @@ static struct fb_ops gbefb_ops = {
        .fb_fillrect    = cfb_fillrect,
        .fb_copyarea    = cfb_copyarea,
        .fb_imageblit   = cfb_imageblit,
-       .fb_cursor      = soft_cursor,
 };
 
 /*
  * sysfs
  */
 
-static ssize_t gbefb_show_memsize(struct device *dev, char *buf)
+static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
 {
        return snprintf(buf, PAGE_SIZE, "%d\n", gbe_mem_size);
 }
 
 static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
 
-static ssize_t gbefb_show_rev(struct device *device, char *buf)
+static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf)
 {
        return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision);
 }
@@ -1075,7 +1098,7 @@ static void gbefb_create_sysfs(struct device *dev)
  * Initialization
  */
 
-int __init gbefb_setup(char *options)
+static int __init gbefb_setup(char *options)
 {
        char *this_opt;
 
@@ -1106,12 +1129,11 @@ int __init gbefb_setup(char *options)
        return 0;
 }
 
-static int __init gbefb_probe(struct device *dev)
+static int __devinit gbefb_probe(struct platform_device *p_dev)
 {
        int i, ret = 0;
        struct fb_info *info;
        struct gbefb_par *par;
-       struct platform_device *p_dev = to_platform_device(dev);
 #ifndef MODULE
        char *options = NULL;
 #endif
@@ -1152,12 +1174,24 @@ static int __init gbefb_probe(struct device *dev)
        if (gbe_mem_phys) {
                /* memory was allocated at boot time */
                gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size);
+               if (!gbe_mem) {
+                       printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
+                       ret = -ENOMEM;
+                       goto out_tiles_free;
+               }
+
                gbe_dma_addr = 0;
        } else {
                /* try to allocate memory with the classical allocator
                 * this has high chance to fail on low memory machines */
                gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr,
                                             GFP_KERNEL);
+               if (!gbe_mem) {
+                       printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n");
+                       ret = -ENOMEM;
+                       goto out_tiles_free;
+               }
+
                gbe_mem_phys = (unsigned long) gbe_dma_addr;
        }
 
@@ -1165,12 +1199,6 @@ static int __init gbefb_probe(struct device *dev)
        mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1);
 #endif
 
-       if (!gbe_mem) {
-               printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
-               ret = -ENXIO;
-               goto out_tiles_free;
-       }
-
        /* map framebuffer memory into tiles table */
        for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
                gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
@@ -1199,8 +1227,8 @@ static int __init gbefb_probe(struct device *dev)
                goto out_gbe_unmap;
        }
 
-       dev_set_drvdata(&p_dev->dev, info);
-       gbefb_create_sysfs(dev);
+       platform_set_drvdata(p_dev, info);
+       gbefb_create_sysfs(&p_dev->dev);
 
        printk(KERN_INFO "fb%d: %s rev %d @ 0x%08x using %dkB memory\n",
               info->node, info->fix.id, gbe_revision, (unsigned) GBE_BASE,
@@ -1226,10 +1254,9 @@ out_release_framebuffer:
        return ret;
 }
 
-static int __devexit gbefb_remove(struct device* dev)
+static int __devexit gbefb_remove(struct platform_device* p_dev)
 {
-       struct platform_device *p_dev = to_platform_device(dev);
-       struct fb_info *info = dev_get_drvdata(&p_dev->dev);
+       struct fb_info *info = platform_get_drvdata(p_dev);
 
        unregister_framebuffer(info);
        gbe_turn_off();
@@ -1241,37 +1268,44 @@ static int __devexit gbefb_remove(struct device* dev)
                          (void *)gbe_tiles.cpu, gbe_tiles.dma);
        release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
        iounmap(gbe);
-       gbefb_remove_sysfs(dev);
+       gbefb_remove_sysfs(&p_dev->dev);
        framebuffer_release(info);
 
        return 0;
 }
 
-static struct device_driver gbefb_driver = {
-       .name = "gbefb",
-       .bus = &platform_bus_type,
+static struct platform_driver gbefb_driver = {
        .probe = gbefb_probe,
        .remove = __devexit_p(gbefb_remove),
+       .driver = {
+               .name = "gbefb",
+       },
 };
 
-static struct platform_device gbefb_device = {
-       .name = "gbefb",
-};
+static struct platform_device *gbefb_device;
 
-int __init gbefb_init(void)
+static int __init gbefb_init(void)
 {
-       int ret = driver_register(&gbefb_driver);
+       int ret = platform_driver_register(&gbefb_driver);
        if (!ret) {
-               ret = platform_device_register(&gbefb_device);
-               if (ret)
-                       driver_unregister(&gbefb_driver);
+               gbefb_device = platform_device_alloc("gbefb", 0);
+               if (gbefb_device) {
+                       ret = platform_device_add(gbefb_device);
+               } else {
+                       ret = -ENOMEM;
+               }
+               if (ret) {
+                       platform_device_put(gbefb_device);
+                       platform_driver_unregister(&gbefb_driver);
+               }
        }
        return ret;
 }
 
-void __exit gbefb_exit(void)
+static void __exit gbefb_exit(void)
 {
-        driver_unregister(&gbefb_driver);
+       platform_device_unregister(gbefb_device);
+       platform_driver_unregister(&gbefb_driver);
 }
 
 module_init(gbefb_init);