X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=drivers%2Fvideo%2Famba-clcd.c;h=6c9dc2e69c82f69d5a24a7e590fab50070451b9c;hb=5cbded585d129d0226cb48ac4202b253c781be26;hp=a3c2c45e29e03e7d9e42a64036501904305ee4df;hpb=cb8a55e4cda017ed37a3ee051365f33a86956312;p=linux-2.6-omap-h63xx.git diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index a3c2c45e29e..6c9dc2e69c8 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -21,12 +21,11 @@ #include #include #include +#include +#include +#include #include -#include -#include - -#include #define to_clcd(info) container_of(info, struct clcd_fb, fb) @@ -117,9 +116,10 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) int ret = 0; memset(&var->transp, 0, sizeof(var->transp)); - memset(&var->red, 0, sizeof(var->red)); - memset(&var->green, 0, sizeof(var->green)); - memset(&var->blue, 0, sizeof(var->blue)); + + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; switch (var->bits_per_pixel) { case 1: @@ -134,34 +134,20 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) var->blue.offset = 0; break; case 16: - var->red.length = 5; - var->green.length = 6; - var->blue.length = 5; - if (fb->panel->cntl & CNTL_BGR) { - var->red.offset = 11; - var->green.offset = 5; - var->blue.offset = 0; - } else { - var->red.offset = 0; - var->green.offset = 5; - var->blue.offset = 11; - } + var->red.length = 5; + var->blue.length = 5; + /* + * Green length can be 5 or 6 depending whether + * we're operating in RGB555 or RGB565 mode. + */ + if (var->green.length != 5 && var->green.length != 6) + var->green.length = 6; break; case 32: if (fb->panel->cntl & CNTL_LCDTFT) { var->red.length = 8; var->green.length = 8; var->blue.length = 8; - - if (fb->panel->cntl & CNTL_BGR) { - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; - } else { - var->red.offset = 0; - var->green.offset = 8; - var->blue.offset = 16; - } break; } default: @@ -169,6 +155,23 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) break; } + /* + * >= 16bpp displays have separate colour component bitfields + * encoded in the pixel data. Calculate their position from + * the bitfield length defined above. + */ + if (ret == 0 && var->bits_per_pixel >= 16) { + if (fb->panel->cntl & CNTL_BGR) { + var->blue.offset = 0; + var->green.offset = var->blue.offset + var->blue.length; + var->red.offset = var->green.offset + var->green.length; + } else { + var->red.offset = 0; + var->green.offset = var->red.offset + var->red.length; + var->blue.offset = var->green.offset + var->green.length; + } + } + return ret; } @@ -308,7 +311,7 @@ static int clcdfb_blank(int blank_mode, struct fb_info *info) return 0; } -static int clcdfb_mmap(struct fb_info *info, struct file *file, +static int clcdfb_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct clcd_fb *fb = to_clcd(info); @@ -346,10 +349,6 @@ static int clcdfb_register(struct clcd_fb *fb) goto out; } - ret = clk_use(fb->clk); - if (ret) - goto free_clk; - fb->fb.fix.mmio_start = fb->dev->res.start; fb->fb.fix.mmio_len = SZ_4K; @@ -357,7 +356,7 @@ static int clcdfb_register(struct clcd_fb *fb) if (!fb->regs) { printk(KERN_ERR "CLCD: unable to remap registers\n"); ret = -ENOMEM; - goto unuse_clk; + goto free_clk; } fb->fb.fbops = &clcdfb_ops; @@ -427,8 +426,6 @@ static int clcdfb_register(struct clcd_fb *fb) printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret); iounmap(fb->regs); - unuse_clk: - clk_unuse(fb->clk); free_clk: clk_put(fb->clk); out: @@ -450,7 +447,7 @@ static int clcdfb_probe(struct amba_device *dev, void *id) goto out; } - fb = (struct clcd_fb *) kmalloc(sizeof(struct clcd_fb), GFP_KERNEL); + fb = kmalloc(sizeof(struct clcd_fb), GFP_KERNEL); if (!fb) { printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n"); ret = -ENOMEM; @@ -489,7 +486,6 @@ static int clcdfb_remove(struct amba_device *dev) clcdfb_disable(fb); unregister_framebuffer(&fb->fb); iounmap(fb->regs); - clk_unuse(fb->clk); clk_put(fb->clk); fb->board->remove(fb);