fbdev: move FBIO_WAITFORVSYNC to linux/fb.h
[safe/jmp/linux-2.6] / drivers / video / bfin-t350mcqb-fb.c
index a2bb2de..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,10 +88,10 @@ 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 */
+       u32 pseudo_pal[16];
 };
 
 static int nocursor;
@@ -182,13 +183,13 @@ static void bfin_t350mcqb_config_dma(struct bfin_t350mcqbfb_info *fbi)
 
 }
 
-static int bfin_t350mcqb_request_ports(int action)
-{
-       u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+static u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
                            P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
                            P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
                            P_PPI0_D6, P_PPI0_D7, 0};
 
+static int bfin_t350mcqb_request_ports(int action)
+{
        if (action) {
                if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) {
                        printk(KERN_ERR "Requesting Peripherals faild\n");
@@ -234,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);
@@ -253,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;
        }
@@ -263,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;
        }
 
@@ -273,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;
-
-       return 0;
-}
-
 int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
        if (nocursor)
@@ -357,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,
 };
@@ -368,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,
 };
 
@@ -395,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;
@@ -433,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;
@@ -474,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;
 
@@ -502,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
@@ -513,23 +499,12 @@ 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;
 
        fbinfo->fbops = &bfin_t350mcqb_fb_ops;
 
-       fbinfo->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
-       if (!fbinfo->pseudo_palette) {
-               printk(KERN_ERR DRIVER_NAME
-                      "Fail to allocate pseudo_palette\n");
-
-               ret = -ENOMEM;
-               goto out4;
-       }
-
-       memset(fbinfo->pseudo_palette, 0, sizeof(u32) * 16);
+       fbinfo->pseudo_palette = &info->pseudo_pal;
 
        if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
            < 0) {
@@ -537,7 +512,7 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
                       "Fail to allocate colormap (%d entries)\n",
                       BFIN_LCD_NBR_PALETTE_ENTRIES);
                ret = -EFAULT;
-               goto out5;
+               goto out4;
        }
 
        if (bfin_t350mcqb_request_ports(1)) {
@@ -552,11 +527,11 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
                goto out7;
        }
 
-       if (request_irq(info->irq, (void *)bfin_t350mcqb_irq_error, IRQF_DISABLED,
-                       "PPI ERROR", info) < 0) {
+       ret = request_irq(info->irq, bfin_t350mcqb_irq_error, IRQF_DISABLED,
+                       "PPI ERROR", info);
+       if (ret < 0) {
                printk(KERN_ERR DRIVER_NAME
                       ": unable to request PPI ERROR IRQ\n");
-               ret = -EFAULT;
                goto out7;
        }
 
@@ -567,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");
@@ -578,17 +559,17 @@ static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
 
        return 0;
 
+out9:
+       unregister_framebuffer(fbinfo);
 out8:
        free_irq(info->irq, info);
 out7:
        bfin_t350mcqb_request_ports(0);
 out6:
        fb_dealloc_cmap(&fbinfo->cmap);
-out5:
-       kfree(fbinfo->pseudo_palette);
 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:
@@ -599,20 +580,22 @@ 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);
        struct bfin_t350mcqbfb_info *info = fbinfo->par;
 
+       unregister_framebuffer(fbinfo);
+
        free_dma(CH_PPI);
        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);
 
-       kfree(fbinfo->pseudo_palette);
        fb_dealloc_cmap(&fbinfo->cmap);
 
 #ifndef NO_BL_SUPPORT
@@ -620,10 +603,11 @@ static int bfin_t350mcqb_remove(struct platform_device *pdev)
        backlight_device_unregister(bl_dev);
 #endif
 
-       unregister_framebuffer(fbinfo);
-
        bfin_t350mcqb_request_ports(0);
 
+       platform_set_drvdata(pdev, NULL);
+       framebuffer_release(fbinfo);
+
        printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
 
        return 0;
@@ -633,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;
 }
@@ -645,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;
 }
@@ -659,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 = {
@@ -668,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);
 }