From 2972adcc8488d050572d1a43c2ef6da9a6165951 Mon Sep 17 00:00:00 2001
From: Troy Kisky <troy.kisky@boundarydevices.com>
Date: Wed, 25 Jul 2018 17:20:39 -0700
Subject: [PATCH] fbpanel: add BGR24 support

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
---
 arch/arm/include/asm/mach-imx/fbpanel.h | 21 ++++++++++++
 arch/arm/mach-imx/fbpanel.c             | 44 +++++++++++++++++++------
 2 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/arch/arm/include/asm/mach-imx/fbpanel.h b/arch/arm/include/asm/mach-imx/fbpanel.h
index f5465c3c803..e9fc9042b24 100644
--- a/arch/arm/include/asm/mach-imx/fbpanel.h
+++ b/arch/arm/include/asm/mach-imx/fbpanel.h
@@ -66,6 +66,7 @@ void fbp_setup_display(const struct display_info_t *displays, int cnt);
 #define VD_INNOLUX_WVGA_M(_mode, _detect, _bus, _addr)	VDF_INNOLUX_WVGA(_mode, "INNOLUX-WVGA", RGB666, FBF_MODESTR, _detect, _bus, _addr)
 #define VD_OKAYA_480_272(_mode, _detect, _bus, _addr)	VDF_OKAYA_480_272(_mode, "okaya_480x272", RGB24, FBF_MODESTR, _detect, _bus, _addr)
 #define VD_QVGA(_mode, _detect, _bus, _addr)		VDF_QVGA(_mode, "qvga", RGB24, FBF_MODESTR, _detect, _bus, _addr)
+#define VD_DT035BTFT(_mode, _detect, _bus, _addr)	VDF_DT035BTFT(_mode, "DT035BTFT", BGR24, FBF_MODESTR, _detect, _bus, _addr)
 #define VD_AT035GT_07ET3(_mode, _detect, _bus, _addr)	VDF_AT035GT_07ET3(_mode, "AT035GT-07ET3", RGB24, FBF_MODESTR, _detect, _bus, _addr)
 #define VD_AMP1024_600(_mode, _detect, _bus, _addr)	VDF_AMP1024_600(_mode, "amp1024x600", RGB666, 0, _detect, _bus, _addr)
 #define VD_ND1024_600(_mode, _detect, _bus, _addr)	VDF_ND1024_600(_mode, "ND-070PCAP-1024x600", RGB24, 0, _detect, _bus, _addr)
@@ -562,6 +563,26 @@ void fbp_setup_display(const struct display_info_t *displays, int cnt);
 }
 
 /* tsc2004 */
+#define VDF_DT035BTFT(_mode, _name, _fmt, _flags, _detect, _bus, _addr) \
+{\
+	VD_HEADER(_mode, _fmt, _flags, _detect, _bus, _addr),\
+	.mode	= {\
+		.name           = _name,\
+		.refresh        = 60,\
+		.xres           = 320,\
+		.yres           = 240,\
+		.pixclock       = 1000000000000ULL/((320+40+18+30)*(240+10+9+3)*60),\
+		.left_margin    = 40,\
+		.right_margin   = 18,\
+		.upper_margin   = 10,\
+		.lower_margin   = 9,\
+		.hsync_len      = 30,\
+		.vsync_len      = 3,\
+		.sync           = FB_SYNC_EXT,\
+		.vmode          = FB_VMODE_NONINTERLACED\
+	}\
+}
+
 #define VDF_AT035GT_07ET3(_mode, _name, _fmt, _flags, _detect, _bus, _addr) \
 {\
 	VD_HEADER(_mode, _fmt, _flags, _detect, _bus, _addr),\
diff --git a/arch/arm/mach-imx/fbpanel.c b/arch/arm/mach-imx/fbpanel.c
index e134fff1ff2..742f33ca6ce 100644
--- a/arch/arm/mach-imx/fbpanel.c
+++ b/arch/arm/mach-imx/fbpanel.c
@@ -179,6 +179,7 @@ static unsigned get_fb_available_mask(const struct display_info_t *di, int cnt)
 
 	return mask;
 }
+static const char bgr24[] = "BGR24";
 static const char rgb24[] = "RGB24";
 static const char rgb565[] = "RGB565";
 static const char rgb666[] = "RGB666";
@@ -215,6 +216,7 @@ static void setup_cmd_fb(unsigned fb, const struct display_info_t *di, char *buf
 	const char *mode_str = NULL;
 	int i;
 	int sz;
+	int interface_width;
 	const char *buf_start = buf;
 	const struct fb_videomode *mode;
 	const char * fmt;
@@ -262,19 +264,25 @@ static void setup_cmd_fb(unsigned fb, const struct display_info_t *di, char *buf
 		size -= sz;
 	}
 
-	if (di->pixfmt == IPU_PIX_FMT_RGB24)
+	interface_width = 18;
+	if (di->pixfmt == IPU_PIX_FMT_RGB24) {
 		fmt = rgb24;
-	else if (di->pixfmt == IPU_PIX_FMT_YUYV)
+		interface_width = 24;
+	} else if (di->pixfmt == IPU_PIX_FMT_BGR24) {
+		fmt = bgr24;
+		interface_width = 24;
+	} else if (di->pixfmt == IPU_PIX_FMT_YUYV) {
 		fmt = yuyv16;
-	else if (di->pixfmt == IPU_PIX_FMT_RGB565)
+	} else if (di->pixfmt == IPU_PIX_FMT_RGB565) {
 		fmt = rgb565;
-	else
+	} else {
 		fmt = rgb666;
+	}
 
 	if (di && (fb >= FB_LCD)) {
 #if defined(CONFIG_MX6SX) || defined(CONFIG_MX7D)
 		sz = snprintf(buf, size, "fdt set %s bus-width <%u>;", short_names[fb],
-				(di->pixfmt == IPU_PIX_FMT_RGB24) ? 24 : 18);
+				interface_width);
 
 #else
 		sz = snprintf(buf, size, "fdt set %s interface_pix_fmt %s;",
@@ -300,7 +308,7 @@ static void setup_cmd_fb(unsigned fb, const struct display_info_t *di, char *buf
 
 		sz = snprintf(buf, size, "fdt set %s fsl,data-width <%u>;",
 				ch_names[fb],
-				(di->pixfmt == IPU_PIX_FMT_RGB24) ? 24 : 18);
+				interface_width);
 		buf += sz;
 		size -= sz;
 
@@ -814,7 +822,8 @@ void fbp_enable_fb(struct display_info_t const *di, int enable)
 			 IOMUXC_GPR2_LVDS_CH1_MODE_MASK |
 			 IOMUXC_GPR2_SPLIT_MODE_EN_MASK);
 		tmp = 0;
-		if (di->pixfmt == IPU_PIX_FMT_RGB24)
+		if ((di->pixfmt == IPU_PIX_FMT_RGB24) ||
+				(di->pixfmt == IPU_PIX_FMT_BGR24))
 			tmp |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT;
 		if (di->fbflags & FBF_JEIDA)
 			tmp |= IOMUXC_GPR2_BIT_MAPPING_CH0_JEIDA;
@@ -845,7 +854,8 @@ void fbp_enable_fb(struct display_info_t const *di, int enable)
 			 IOMUXC_GPR2_LVDS_CH0_MODE_MASK |
 			 IOMUXC_GPR2_LVDS_CH1_MODE_MASK |
 			 IOMUXC_GPR2_SPLIT_MODE_EN_MASK);
-		if (di->pixfmt == IPU_PIX_FMT_RGB24)
+		if ((di->pixfmt == IPU_PIX_FMT_RGB24) ||
+				(di->pixfmt == IPU_PIX_FMT_BGR24))
 			reg |= IOMUXC_GPR2_DATA_WIDTH_CH1_24BIT;
 		if (di->fbflags & FBF_JEIDA)
 			reg |= IOMUXC_GPR2_BIT_MAPPING_CH1_JEIDA;
@@ -924,6 +934,7 @@ static const struct display_info_t * parse_mode(
 	int i;
 	struct display_info_t *di;
 	char *mode_str = g_mode_str[fb];
+	int pix_fmt = IPU_PIX_FMT_RGB24;
 
 	if (*p == '*') {
 		p++;
@@ -971,6 +982,11 @@ static const struct display_info_t * parse_mode(
 		p++;
 		c = *p;
 	}
+	if (c == 'b') {
+		pix_fmt = IPU_PIX_FMT_BGR24;
+		p++;
+		c = *p;
+	}
 	value = simple_strtoul(p, &endp, 10);
 	if (endp <= p) {
 		printf("expecting 18|24\n");
@@ -981,7 +997,7 @@ static const struct display_info_t * parse_mode(
 		return NULL;
 	}
 	p = endp;
-	di->pixfmt = (value == 24) ? IPU_PIX_FMT_RGB24 : IPU_PIX_FMT_RGB666;
+	di->pixfmt = (value == 24) ? pix_fmt : IPU_PIX_FMT_RGB666;
 	c = *p;
 
 	if (c == 'S') {
@@ -1120,6 +1136,7 @@ static void str_mode(char *p, int size, const struct display_info_t *di, unsigne
 {
 	int count;
 	int i;
+	int interface_width = 18;
 
 	if (prefer) {
 		*p++ = '*';
@@ -1151,7 +1168,14 @@ static void str_mode(char *p, int size, const struct display_info_t *di, unsigne
 		*p++ = 's';
 		size--;
 	}
-	count = snprintf(p, size, "%d", (di->pixfmt == IPU_PIX_FMT_RGB24) ? 24 : 18);
+	if ((di->pixfmt == IPU_PIX_FMT_RGB24) ||
+			(di->pixfmt == IPU_PIX_FMT_BGR24))
+		interface_width = 24;
+	if (di->pixfmt == IPU_PIX_FMT_BGR24) {
+		*p++ = 'b';
+		size--;
+	}
+	count = snprintf(p, size, "%d", interface_width);
 	if (size > count) {
 		p += count;
 		size -= count;
-- 
GitLab