The LCDIF controller v4, like the one included in the i.MX6UL,
can be configured to accept other RGB pixel formats. Extend
the driver to configure the controller to do so.

Signed-off-by: Ahmad Fatoum <a.fat...@pengutronix.de>
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 41 +++++++++++++++++++++++++-----
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  6 +++++
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 17 +++++++++++++
 3 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 24b1f0c1432e..1b5b1fddd691 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -97,29 +97,56 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private 
*mxsfb)
        struct drm_crtc *crtc = &mxsfb->pipe.crtc;
        struct drm_device *drm = crtc->dev;
        u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
-       u32 reg;
+       u32 ctrl, pattern;
 
-       reg = readl(mxsfb->base + LCDC_CTRL);
+       ctrl = readl(mxsfb->base + LCDC_CTRL);
 
        if (mxsfb->connector.display_info.num_bus_formats)
                bus_format = mxsfb->connector.display_info.bus_formats[0];
 
-       reg &= ~CTRL_BUS_WIDTH_MASK;
+       ctrl &= ~CTRL_BUS_WIDTH_MASK;
        switch (bus_format) {
        case MEDIA_BUS_FMT_RGB565_1X16:
-               reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT);
+               ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT);
+               pattern = CTRL2_PATTERN_RGB;
                break;
        case MEDIA_BUS_FMT_RGB666_1X18:
-               reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_18BIT);
+               ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_18BIT);
+               pattern = CTRL2_PATTERN_RGB;
                break;
        case MEDIA_BUS_FMT_RGB888_1X24:
-               reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
+               ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
+               pattern = CTRL2_PATTERN_RGB;
+               break;
+       case MEDIA_BUS_FMT_BGR888_1X24:
+               ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
+               pattern = CTRL2_PATTERN_BGR;
+               break;
+       case MEDIA_BUS_FMT_RBG888_1X24:
+               ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
+               pattern = CTRL2_PATTERN_RBG;
+               break;
+       case MEDIA_BUS_FMT_GBR888_1X24:
+               ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
+               pattern = CTRL2_PATTERN_GBR;
                break;
        default:
+               pattern = CTRL2_PATTERN_RGB;
                dev_err(drm->dev, "Unknown media bus format %d\n", bus_format);
                break;
        }
-       writel(reg, mxsfb->base + LCDC_CTRL);
+       writel(ctrl, mxsfb->base + LCDC_CTRL);
+
+       if (mxsfb_is_v4(mxsfb)) {
+               u32 ctrl2 = readl(mxsfb->base + LCDC_V4_CTRL2);
+               ctrl2 &= ~CTRL2_PATTERN_MASK;
+               ctrl2 |= CTRL2_SET_PATTERN(pattern);
+               writel(ctrl2, mxsfb->base + LCDC_V4_CTRL2);
+       } else if (pattern != CTRL2_PATTERN_RGB) {
+               /* RGB is default, so only warn for other patterns */
+               dev_err(drm->dev, "Unsupported media bus format %d\n",
+                       bus_format);
+       }
 }
 
 static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 5d0883fc805b..89fa2076acaf 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -16,6 +16,8 @@
 #ifndef __MXSFB_DRV_H__
 #define __MXSFB_DRV_H__
 
+#include <linux/types.h>
+
 struct mxsfb_devdata {
        unsigned int     transfer_count;
        unsigned int     cur_buf;
@@ -50,5 +52,9 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb);
 void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb);
 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
                               struct drm_plane_state *state);
+static inline bool mxsfb_is_v4(const struct mxsfb_drm_private *mxsfb)
+{
+       return mxsfb->devdata->ipversion == 4;
+}
 
 #endif /* __MXSFB_DRV_H__ */
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 66a6ba9ec533..c5f4dea80093 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -22,6 +22,7 @@
 
 #define LCDC_CTRL                      0x00
 #define LCDC_CTRL1                     0x10
+#define LCDC_V4_CTRL2                  0x20
 #define LCDC_V3_TRANSFER_COUNT         0x20
 #define LCDC_V4_TRANSFER_COUNT         0x30
 #define LCDC_V4_CUR_BUF                        0x40
@@ -59,6 +60,15 @@
 #define CTRL1_CUR_FRAME_DONE_IRQ_EN    (1 << 13)
 #define CTRL1_CUR_FRAME_DONE_IRQ       (1 << 9)
 
+#define CTRL2_EVEN_LINE_PATTERN_MASK   (0x7 << 12)
+#define CTRL2_ODD_LINE_PATTERN_MASK    (0x7 << 16)
+#define CTRL2_PATTERN_MASK             (CTRL2_ODD_LINE_PATTERN_MASK |\
+                                        CTRL2_EVEN_LINE_PATTERN_MASK)
+#define CTRL2_SET_EVEN_LINE_PATTERN(x) (((x) & 0x7) << 12)
+#define CTRL2_SET_ODD_LINE_PATTERN(x)  (((x) & 0x7) << 16)
+#define CTRL2_SET_PATTERN(x)           (CTRL2_SET_EVEN_LINE_PATTERN(x) |\
+                                        CTRL2_SET_ODD_LINE_PATTERN(x))
+
 #define TRANSFER_COUNT_SET_VCOUNT(x)   (((x) & 0xffff) << 16)
 #define TRANSFER_COUNT_GET_VCOUNT(x)   (((x) >> 16) & 0xffff)
 #define TRANSFER_COUNT_SET_HCOUNT(x)   ((x) & 0xffff)
@@ -112,4 +122,11 @@
 #define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT        (1 << 6)
 #define MXSFB_SYNC_DOTCLK_FALLING_ACT  (1 << 7) /* negative edge sampling */
 
+#define CTRL2_PATTERN_RGB              0x0
+#define CTRL2_PATTERN_RBG              0x1
+#define CTRL2_PATTERN_GBR              0x2
+#define CTRL2_PATTERN_GRB              0x3
+#define CTRL2_PATTERN_BRG              0x4
+#define CTRL2_PATTERN_BGR              0x5
+
 #endif /* __MXSFB_REGS_H__ */
-- 
2.19.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to