video: ARM CLCD: support pads connected in reverse order
authorLinus Walleij <linus.walleij@linaro.org>
Thu, 16 Jun 2016 09:36:15 +0000 (11:36 +0200)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Thu, 11 Aug 2016 14:54:53 +0000 (17:54 +0300)
There are CLCDs connected with the pads in BGR rather than RGB
order. It really doesn't matter since the CLCD has a flag and
a bit to switch the position of the RGB and BGR components.
This is needed to put something logical into the
arm,pl11x,tft-r0g0b0-pads property of the device tree on the
Nomadik which will then be <16 8 0>.

Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/video/fbdev/amba-clcd.c
include/linux/amba/clcd.h

index 5bd20e8..080e8a2 100644 (file)
@@ -675,6 +675,7 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
        } panels[] = {
                { 0x110, 1,  7, 13, CLCD_CAP_5551 },
                { 0x110, 0,  8, 16, CLCD_CAP_888 },
+               { 0x110, 16, 8, 0,  CLCD_CAP_888 },
                { 0x111, 4, 14, 20, CLCD_CAP_444 },
                { 0x111, 3, 11, 19, CLCD_CAP_444 | CLCD_CAP_5551 },
                { 0x111, 3, 10, 19, CLCD_CAP_444 | CLCD_CAP_5551 |
@@ -702,6 +703,13 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
                        fb->panel->caps = panels[i].caps;
        }
 
+       /*
+        * If we actually physically connected the R lines to B and
+        * vice versa
+        */
+       if (r0 != 0 && b0 == 0)
+               fb->panel->bgr_connection = true;
+
        return fb->panel->caps ? 0 : -EINVAL;
 }
 
index e64c1cc..8b64ec0 100644 (file)
@@ -108,6 +108,12 @@ struct clcd_panel {
                                grayscale:1;
        unsigned int            connector;
        struct backlight_device *backlight;
+       /*
+        * If the B/R lines are switched between the CLCD
+        * and the panel we need to know this and not try to
+        * compensate with the BGR bit in the control register.
+        */
+       bool                    bgr_connection;
 };
 
 struct clcd_regs {
@@ -234,16 +240,22 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
        if (var->grayscale)
                val |= CNTL_LCDBW;
 
-       if (fb->panel->caps && fb->board->caps &&
-           var->bits_per_pixel >= 16) {
+       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
+                * changing BGR/RGB depending on supplied parameters. Here
+                * we switch to what the framebuffer is providing if need
+                * be, so if the framebuffer is BGR but the display connection
+                * is RGB (first case) we switch it around. Vice versa mutatis
+                * mutandis if the framebuffer is RGB but the display connection
+                * is BGR, we flip it around.
                 */
                if (var->red.offset == 0)
                        val &= ~CNTL_BGR;
                else
                        val |= CNTL_BGR;
+               if (fb->panel->bgr_connection)
+                       val ^= CNTL_BGR;
        }
 
        switch (var->bits_per_pixel) {