Merge branch 'sh-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / include / linux / amba / clcd.h
index 2e51121..e82e3ee 100644 (file)
@@ -53,6 +53,7 @@
 #define CNTL_LCDBPP8           (3 << 1)
 #define CNTL_LCDBPP16          (4 << 1)
 #define CNTL_LCDBPP16_565      (6 << 1)
+#define CNTL_LCDBPP16_444      (7 << 1)
 #define CNTL_LCDBPP24          (5 << 1)
 #define CNTL_LCDBW             (1 << 4)
 #define CNTL_LCDTFT            (1 << 5)
 #define CNTL_LDMAFIFOTIME      (1 << 15)
 #define CNTL_WATERMARK         (1 << 16)
 
+enum {
+       /* individual formats */
+       CLCD_CAP_RGB444         = (1 << 0),
+       CLCD_CAP_RGB5551        = (1 << 1),
+       CLCD_CAP_RGB565         = (1 << 2),
+       CLCD_CAP_RGB888         = (1 << 3),
+       CLCD_CAP_BGR444         = (1 << 4),
+       CLCD_CAP_BGR5551        = (1 << 5),
+       CLCD_CAP_BGR565         = (1 << 6),
+       CLCD_CAP_BGR888         = (1 << 7),
+
+       /* connection layouts */
+       CLCD_CAP_444            = CLCD_CAP_RGB444 | CLCD_CAP_BGR444,
+       CLCD_CAP_5551           = CLCD_CAP_RGB5551 | CLCD_CAP_BGR5551,
+       CLCD_CAP_565            = CLCD_CAP_RGB565 | CLCD_CAP_BGR565,
+       CLCD_CAP_888            = CLCD_CAP_RGB888 | CLCD_CAP_BGR888,
+
+       /* red/blue ordering */
+       CLCD_CAP_RGB            = CLCD_CAP_RGB444 | CLCD_CAP_RGB5551 |
+                                 CLCD_CAP_RGB565 | CLCD_CAP_RGB888,
+       CLCD_CAP_BGR            = CLCD_CAP_BGR444 | CLCD_CAP_BGR5551 |
+                                 CLCD_CAP_BGR565 | CLCD_CAP_BGR888,
+
+       CLCD_CAP_ALL            = CLCD_CAP_BGR | CLCD_CAP_RGB,
+};
+
 struct clcd_panel {
        struct fb_videomode     mode;
        signed short            width;  /* width in mm */
@@ -73,6 +100,7 @@ struct clcd_panel {
        u32                     tim2;
        u32                     tim3;
        u32                     cntl;
+       u32                     caps;
        unsigned int            bpp:8,
                                fixedtimings:1,
                                grayscale:1;
@@ -96,6 +124,11 @@ struct clcd_fb;
 struct clcd_board {
        const char *name;
 
+       /*
+        * Optional.  Hardware capability flags.
+        */
+       u32     caps;
+
        /*
         * Optional.  Check whether the var structure is acceptable
         * for this display.
@@ -103,7 +136,7 @@ struct clcd_board {
        int     (*check)(struct clcd_fb *fb, struct fb_var_screeninfo *var);
 
        /*
-        * Compulsary.  Decode fb->fb.var into regs->*.  In the case of
+        * Compulsory.  Decode fb->fb.var into regs->*.  In the case of
         * fixed timing, set regs->* to the register values required.
         */
        void    (*decode)(struct clcd_fb *fb, struct clcd_regs *regs);
@@ -155,34 +188,35 @@ struct clcd_fb {
 
 static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
 {
+       struct fb_var_screeninfo *var = &fb->fb.var;
        u32 val, cpl;
 
        /*
         * Program the CLCD controller registers and start the CLCD
         */
-       val = ((fb->fb.var.xres / 16) - 1) << 2;
-       val |= (fb->fb.var.hsync_len - 1) << 8;
-       val |= (fb->fb.var.right_margin - 1) << 16;
-       val |= (fb->fb.var.left_margin - 1) << 24;
+       val = ((var->xres / 16) - 1) << 2;
+       val |= (var->hsync_len - 1) << 8;
+       val |= (var->right_margin - 1) << 16;
+       val |= (var->left_margin - 1) << 24;
        regs->tim0 = val;
 
-       val = fb->fb.var.yres;
+       val = var->yres;
        if (fb->panel->cntl & CNTL_LCDDUAL)
                val /= 2;
        val -= 1;
-       val |= (fb->fb.var.vsync_len - 1) << 10;
-       val |= fb->fb.var.lower_margin << 16;
-       val |= fb->fb.var.upper_margin << 24;
+       val |= (var->vsync_len - 1) << 10;
+       val |= var->lower_margin << 16;
+       val |= var->upper_margin << 24;
        regs->tim1 = val;
 
        val = fb->panel->tim2;
-       val |= fb->fb.var.sync & FB_SYNC_HOR_HIGH_ACT  ? 0 : TIM2_IHS;
-       val |= fb->fb.var.sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
+       val |= var->sync & FB_SYNC_HOR_HIGH_ACT  ? 0 : TIM2_IHS;
+       val |= var->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
 
-       cpl = fb->fb.var.xres_virtual;
+       cpl = var->xres_virtual;
        if (fb->panel->cntl & CNTL_LCDTFT)        /* TFT */
                /* / 1 */;
-       else if (!fb->fb.var.grayscale)           /* STN color */
+       else if (!var->grayscale)                 /* STN color */
                cpl = cpl * 8 / 3;
        else if (fb->panel->cntl & CNTL_LCDMONO8) /* STN monochrome, 8bit */
                cpl /= 8;
@@ -194,10 +228,22 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
        regs->tim3 = fb->panel->tim3;
 
        val = fb->panel->cntl;
-       if (fb->fb.var.grayscale)
+       if (var->grayscale)
                val |= CNTL_LCDBW;
 
-       switch (fb->fb.var.bits_per_pixel) {
+       if (fb->panel->caps && fb->board->caps &&
+           var->bits_per_pixel >= 16) {
+               /*
+                * if board and panel supply capabilities, we can support
+                * changing BGR/RGB depending on supplied parameters
+                */
+               if (var->red.offset == 0)
+                       val &= ~CNTL_BGR;
+               else
+                       val |= CNTL_BGR;
+       }
+
+       switch (var->bits_per_pixel) {
        case 1:
                val |= CNTL_LCDBPP1;
                break;
@@ -217,10 +263,12 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
                 * custom external wiring.
                 */
                if (amba_part(fb->dev) == 0x110 ||
-                   fb->fb.var.green.length == 5)
+                   var->green.length == 5)
                        val |= CNTL_LCDBPP16;
-               else
+               else if (var->green.length == 6)
                        val |= CNTL_LCDBPP16_565;
+               else
+                       val |= CNTL_LCDBPP16_444;
                break;
        case 32:
                val |= CNTL_LCDBPP24;
@@ -228,7 +276,7 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
        }
 
        regs->cntl = val;
-       regs->pixclock = fb->fb.var.pixclock;
+       regs->pixclock = var->pixclock;
 }
 
 static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)