[ARM] 5164/1: pxafb: Support for RGB666, RGBT666, RGB888 and RGBT888
authorStefan Schmidt <stefan@datenfreihafen.org>
Wed, 9 Jul 2008 07:06:32 +0000 (08:06 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 10 Jul 2008 12:44:53 +0000 (13:44 +0100)
Add the .depth field to pxafb_mode_info and use it to set pixel data format
as 18(RGB666), 19(RGBT666), 24(RGB888) or 25(RGBT888)

Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com>
Acked-by: Eric Miao <eric.miao@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
drivers/video/pxafb.c
include/asm-arm/arch-pxa/pxafb.h

index 3682bbd7e50e5c2dcbd13aec75664dae594fd1e8..295ff4e1955ee9006d23831bf071e4ae95fcc5b4 100644 (file)
@@ -227,6 +227,22 @@ static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
        case 4:  ret = LCCR3_4BPP; break;
        case 8:  ret = LCCR3_8BPP; break;
        case 16: ret = LCCR3_16BPP; break;
+       case 24:
+               switch (var->red.length + var->green.length +
+                               var->blue.length + var->transp.length) {
+               case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break;
+               case 19: ret = LCCR3_19BPP_P; break;
+               }
+               break;
+       case 32:
+               switch (var->red.length + var->green.length +
+                               var->blue.length + var->transp.length) {
+               case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break;
+               case 19: ret = LCCR3_19BPP; break;
+               case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break;
+               case 25: ret = LCCR3_25BPP; break;
+               }
+               break;
        }
        return ret;
 }
@@ -345,6 +361,41 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                var->green.offset = 5;  var->green.length = 6;
                var->blue.offset  = 0;  var->blue.length  = 5;
                var->transp.offset = var->transp.length = 0;
+       } else if (var->bits_per_pixel > 16) {
+               struct pxafb_mode_info *mode;
+
+               mode = pxafb_getmode(inf, var);
+               if (!mode)
+                       return -EINVAL;
+
+               switch (mode->depth) {
+               case 18: /* RGB666 */
+                       var->transp.offset = var->transp.length     = 0;
+                       var->red.offset    = 12; var->red.length    = 6;
+                       var->green.offset  = 6;  var->green.length  = 6;
+                       var->blue.offset   = 0;  var->blue.length   = 6;
+                       break;
+               case 19: /* RGBT666 */
+                       var->transp.offset = 18; var->transp.length = 1;
+                       var->red.offset    = 12; var->red.length    = 6;
+                       var->green.offset  = 6;  var->green.length  = 6;
+                       var->blue.offset   = 0;  var->blue.length   = 6;
+                       break;
+               case 24: /* RGB888 */
+                       var->transp.offset = var->transp.length     = 0;
+                       var->red.offset    = 16; var->red.length    = 8;
+                       var->green.offset  = 8;  var->green.length  = 8;
+                       var->blue.offset   = 0;  var->blue.length   = 8;
+                       break;
+               case 25: /* RGBT888 */
+                       var->transp.offset = 24; var->transp.length = 1;
+                       var->red.offset    = 16; var->red.length    = 8;
+                       var->green.offset  = 8;  var->green.length  = 8;
+                       var->blue.offset   = 0;  var->blue.length   = 8;
+                       break;
+               default:
+                       return -EINVAL;
+               }
        } else {
                var->red.offset = var->green.offset = 0;
                var->blue.offset = var->transp.offset = 0;
@@ -376,7 +427,7 @@ static int pxafb_set_par(struct fb_info *info)
        struct pxafb_info *fbi = (struct pxafb_info *)info;
        struct fb_var_screeninfo *var = &info->var;
 
-       if (var->bits_per_pixel == 16)
+       if (var->bits_per_pixel >= 16)
                fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
        else if (!fbi->cmap_static)
                fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -391,7 +442,7 @@ static int pxafb_set_par(struct fb_info *info)
 
        fbi->fb.fix.line_length = var->xres_virtual *
                                  var->bits_per_pixel / 8;
-       if (var->bits_per_pixel == 16)
+       if (var->bits_per_pixel >= 16)
                fbi->palette_size = 0;
        else
                fbi->palette_size = var->bits_per_pixel == 1 ?
@@ -404,7 +455,7 @@ static int pxafb_set_par(struct fb_info *info)
         */
        pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
 
-       if (fbi->fb.var.bits_per_pixel == 16)
+       if (fbi->fb.var.bits_per_pixel >= 16)
                fb_dealloc_cmap(&fbi->fb.cmap);
        else
                fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
@@ -831,6 +882,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
                case 4:
                case 8:
                case 16:
+               case 24:
+               case 32:
                        break;
                default:
                        printk(KERN_ERR "%s: invalid bit depth %d\n",
@@ -968,6 +1021,11 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
 
        for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
                pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
+       /* 18 bit interface */
+       if (fbi->fb.var.bits_per_pixel > 16) {
+               pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT);
+               pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT);
+       }
        pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
        pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
        pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
index bbd22396841ae15d0eefcd235ffeccd9abdacb8b..daf018d0c60409cbaa4ad53bf6b181fd1e5bbcc7 100644 (file)
@@ -71,7 +71,8 @@ struct pxafb_mode_info {
 
        u_char          bpp;
        u_int           cmap_greyscale:1,
-                       unused:31;
+                       depth:8,
+                       unused:23;
 
        /* Parallel Mode Timing */
        u_char          hsync_len;