diff mbox series

[1/3] drm/mxsfb: use bus_format to determine pixel RGB component order

Message ID 20190102170247.8208-2-a.fatoum@pengutronix.de (mailing list archive)
State New, archived
Headers show
Series drm/mxsfb: support swapped RGB lanes | expand

Commit Message

Ahmad Fatoum Jan. 2, 2019, 5:02 p.m. UTC
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.fatoum@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(-)

Comments

Ahmad Fatoum Jan. 2, 2019, 5:14 p.m. UTC | #1
On 2/1/19 18:02, Ahmad Fatoum wrote:

> -	reg &= ~CTRL_BUS_WIDTH_MASK;
> +	ctrl &= ~CTRL_BUS_WIDTH_MASK;
>  	switch (bus_format) {

>  	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);

Should the default case explicitly set a value for ctrl?
So far, the appropriate bits stay at zero after the &= ~CTRL_BUS_WIDTH_MASK
which is STMLCDIF_16BIT.

Or maybe skip the LCDC_CTRL register write altogether if dev_err is reached?
diff mbox series

Patch

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__ */