fbdev: move FBIO_WAITFORVSYNC to linux/fb.h
[safe/jmp/linux-2.6] / drivers / video / bfin-t350mcqb-fb.c
index 135d6dd..c2ec3dc 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/gfp.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -87,7 +88,6 @@ struct bfin_t350mcqbfb_info {
        struct device *dev;
        unsigned char *fb_buffer;       /* RGB Buffer */
        dma_addr_t dma_handle;
-       int lq043_mmap;
        int lq043_open_cnt;
        int irq;
        spinlock_t lock;        /* lock */
@@ -235,14 +235,12 @@ static int bfin_t350mcqb_fb_release(struct fb_info *info, int user)
        spin_lock(&fbi->lock);
 
        fbi->lq043_open_cnt--;
-       fbi->lq043_mmap = 0;
 
        if (fbi->lq043_open_cnt <= 0) {
                bfin_t350mcqb_disable_ppi();
                SSYNC();
                disable_dma(CH_PPI);
                bfin_t350mcqb_stop_timers();
-               memset(fbi->fb_buffer, 0, info->fix.smem_len);
        }
 
        spin_unlock(&fbi->lock);
@@ -254,8 +252,21 @@ static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var,
                                   struct fb_info *info)
 {
 
-       if (var->bits_per_pixel != LCD_BPP) {
-               pr_debug("%s: depth not supported: %u BPP\n", __FUNCTION__,
+       switch (var->bits_per_pixel) {
+       case 24:/* TRUECOLOUR, 16m */
+               var->red.offset = 0;
+               var->green.offset = 8;
+               var->blue.offset = 16;
+               var->red.length = var->green.length = var->blue.length = 8;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               var->transp.msb_right = 0;
+               var->red.msb_right = 0;
+               var->green.msb_right = 0;
+               var->blue.msb_right = 0;
+               break;
+       default:
+               pr_debug("%s: depth not supported: %u BPP\n", __func__,
                         var->bits_per_pixel);
                return -EINVAL;
        }
@@ -264,7 +275,7 @@ static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var,
            info->var.xres_virtual != var->xres_virtual ||
            info->var.yres_virtual != var->yres_virtual) {
                pr_debug("%s: Resolution not supported: X%u x Y%u \n",
-                        __FUNCTION__, var->xres, var->yres);
+                        __func__, var->xres, var->yres);
                return -EINVAL;
        }
 
@@ -274,39 +285,13 @@ static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var,
 
        if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
                pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
-                        __FUNCTION__, var->yres_virtual);
+                        __func__, var->yres_virtual);
                return -ENOMEM;
        }
 
        return 0;
 }
 
-static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-       struct bfin_t350mcqbfb_info *fbi = info->par;
-
-       if (fbi->lq043_mmap)
-               return -1;
-
-       spin_lock(&fbi->lock);
-       fbi->lq043_mmap = 1;
-       spin_unlock(&fbi->lock);
-
-       vma->vm_start = (unsigned long)(fbi->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET);
-
-       vma->vm_end = vma->vm_start + info->fix.smem_len;
-       /* For those who don't understand how mmap works, go read
-        *   Documentation/nommu-mmap.txt.
-        * For those that do, you will know that the VM_MAYSHARE flag
-        * must be set in the vma->vm_flags structure on noMMU
-        *   Other flags can be set, and are documented in
-        *   include/linux/mm.h
-        */
-       vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
-
-       return 0;
-}
-
 int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
        if (nocursor)
@@ -358,7 +343,6 @@ static struct fb_ops bfin_t350mcqb_fb_ops = {
        .fb_fillrect = cfb_fillrect,
        .fb_copyarea = cfb_copyarea,
        .fb_imageblit = cfb_imageblit,
-       .fb_mmap = bfin_t350mcqb_fb_mmap,
        .fb_cursor = bfin_t350mcqb_fb_cursor,
        .fb_setcolreg = bfin_t350mcqb_fb_setcolreg,
 };
@@ -369,7 +353,7 @@ static int bl_get_brightness(struct backlight_device *bd)
        return 0;
 }
 
-static struct backlight_ops bfin_lq043fb_bl_ops = {
+static const struct backlight_ops bfin_lq043fb_bl_ops = {
        .get_brightness = bl_get_brightness,
 };
 
@@ -396,7 +380,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
        return 0;
 }
 
-static int bfin_lcd_check_fb(struct fb_info *fi)
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
 {
        if (!fi || (fi == &bfin_t350mcqb_fb))
                return 1;
@@ -434,8 +418,9 @@ static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
+static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
 {
+       struct backlight_properties props;
        struct bfin_t350mcqbfb_info *info;
        struct fb_info *fbinfo;
        int ret;
@@ -475,8 +460,8 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
 
        fbinfo->var.nonstd = 0;
        fbinfo->var.activate = FB_ACTIVATE_NOW;
-       fbinfo->var.height = -1;
-       fbinfo->var.width = -1;
+       fbinfo->var.height = 53;
+       fbinfo->var.width = 70;
        fbinfo->var.accel_flags = 0;
        fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
 
@@ -503,9 +488,9 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
        fbinfo->fbops = &bfin_t350mcqb_fb_ops;
        fbinfo->flags = FBINFO_FLAG_DEFAULT;
 
-       info->fb_buffer =
-           dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
-                              GFP_KERNEL);
+       info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len +
+                               ACTIVE_VIDEO_MEM_OFFSET,
+                               &info->dma_handle, GFP_KERNEL);
 
        if (NULL == info->fb_buffer) {
                printk(KERN_ERR DRIVER_NAME
@@ -514,8 +499,6 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
                goto out3;
        }
 
-       memset(info->fb_buffer, 0, fbinfo->fix.smem_len);
-
        fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
        fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
 
@@ -559,10 +542,16 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
                goto out8;
        }
 #ifndef NO_BL_SUPPORT
-       bl_dev =
-           backlight_device_register("bf52x-bl", NULL, NULL,
-                                     &bfin_lq043fb_bl_ops);
-       bl_dev->props.max_brightness = 255;
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.max_brightness = 255;
+       bl_dev = backlight_device_register("bf52x-bl", NULL, NULL,
+                                          &bfin_lq043fb_bl_ops, &props);
+       if (IS_ERR(bl_dev)) {
+               printk(KERN_ERR DRIVER_NAME
+                       ": unable to register backlight.\n");
+               ret = -EINVAL;
+               goto out9;
+       }
 
        lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
        lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
@@ -570,6 +559,8 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
 
        return 0;
 
+out9:
+       unregister_framebuffer(fbinfo);
 out8:
        free_irq(info->irq, info);
 out7:
@@ -577,8 +568,8 @@ out7:
 out6:
        fb_dealloc_cmap(&fbinfo->cmap);
 out4:
-       dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
-                         info->dma_handle);
+       dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET,
+                        info->fb_buffer, info->dma_handle);
 out3:
        framebuffer_release(fbinfo);
 out2:
@@ -589,7 +580,7 @@ out1:
        return ret;
 }
 
-static int bfin_t350mcqb_remove(struct platform_device *pdev)
+static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev)
 {
 
        struct fb_info *fbinfo = platform_get_drvdata(pdev);
@@ -601,8 +592,9 @@ static int bfin_t350mcqb_remove(struct platform_device *pdev)
        free_irq(info->irq, info);
 
        if (info->fb_buffer != NULL)
-               dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
-                                 info->dma_handle);
+               dma_free_coherent(NULL, fbinfo->fix.smem_len +
+                       ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer,
+                       info->dma_handle);
 
        fb_dealloc_cmap(&fbinfo->cmap);
 
@@ -625,11 +617,15 @@ static int bfin_t350mcqb_remove(struct platform_device *pdev)
 static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct fb_info *fbinfo = platform_get_drvdata(pdev);
-       struct bfin_t350mcqbfb_info *info = fbinfo->par;
+       struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
+
+       if (fbi->lq043_open_cnt) {
+               bfin_t350mcqb_disable_ppi();
+               disable_dma(CH_PPI);
+               bfin_t350mcqb_stop_timers();
+               bfin_write_PPI_STATUS(-1);
+       }
 
-       bfin_t350mcqb_disable_ppi();
-       disable_dma(CH_PPI);
-       bfin_write_PPI_STATUS(0xFFFF);
 
        return 0;
 }
@@ -637,10 +633,18 @@ static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t stat
 static int bfin_t350mcqb_resume(struct platform_device *pdev)
 {
        struct fb_info *fbinfo = platform_get_drvdata(pdev);
-       struct bfin_t350mcqbfb_info *info = fbinfo->par;
+       struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
 
-       enable_dma(CH_PPI);
-       bfin_t350mcqb_enable_ppi();
+       if (fbi->lq043_open_cnt) {
+               bfin_t350mcqb_config_dma(fbi);
+               bfin_t350mcqb_config_ppi(fbi);
+               bfin_t350mcqb_init_timers();
+
+               /* start dma */
+               enable_dma(CH_PPI);
+               bfin_t350mcqb_enable_ppi();
+               bfin_t350mcqb_start_timers();
+       }
 
        return 0;
 }
@@ -651,7 +655,7 @@ static int bfin_t350mcqb_resume(struct platform_device *pdev)
 
 static struct platform_driver bfin_t350mcqb_driver = {
        .probe = bfin_t350mcqb_probe,
-       .remove = bfin_t350mcqb_remove,
+       .remove = __devexit_p(bfin_t350mcqb_remove),
        .suspend = bfin_t350mcqb_suspend,
        .resume = bfin_t350mcqb_resume,
        .driver = {
@@ -660,7 +664,7 @@ static struct platform_driver bfin_t350mcqb_driver = {
                   },
 };
 
-static int __devinit bfin_t350mcqb_driver_init(void)
+static int __init bfin_t350mcqb_driver_init(void)
 {
        return platform_driver_register(&bfin_t350mcqb_driver);
 }