[PATCH] video: stm32: stm32_ltdc: support several hardware versions

Yannick Fertre yannick.fertre at foss.st.com
Wed Apr 6 10:41:35 CEST 2022


Register mapping & pixel formats depend on version of ltdc
display controller.

Signed-off-by: Yannick Fertre <yannick.fertre at foss.st.com>
---

 drivers/video/stm32/stm32_ltdc.c | 245 +++++++++++++++++++++++++++----
 1 file changed, 216 insertions(+), 29 deletions(-)

diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c
index e741e74739..60bfd2390d 100644
--- a/drivers/video/stm32/stm32_ltdc.c
+++ b/drivers/video/stm32/stm32_ltdc.c
@@ -25,8 +25,114 @@ struct stm32_ltdc_priv {
 	void __iomem *regs;
 	enum video_log2_bpp l2bpp;
 	u32 bg_col_argb;
+	const u32 *layer_regs;
+	const u32 *pix_fmt_hw;
 	u32 crop_x, crop_y, crop_w, crop_h;
 	u32 alpha;
+	u32 hw_version;
+};
+
+/* Layer register offsets */
+static const u32 layer_regs_a0[] = {
+	0x80,	/* L1 configuration 0 */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x84,	/* L1 control register */
+	0x88,	/* L1 window horizontal position configuration */
+	0x8c,	/* L1 window vertical position configuration */
+	0x90,	/* L1 color keying configuration */
+	0x94,	/* L1 pixel format configuration */
+	0x98,	/* L1 constant alpha configuration */
+	0x9c,	/* L1 default color configuration */
+	0xa0,	/* L1 blending factors configuration */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0xac,	/* L1 color frame buffer address */
+	0xb0,	/* L1 color frame buffer length */
+	0xb4,	/* L1 color frame buffer line number */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0xc4,	/* L1 CLUT write */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00	/* not available */
+};
+
+static const u32 layer_regs_a1[] = {
+	0x80,	/* L1 configuration 0 */
+	0x84,	/* L1 configuration 1 */
+	0x00,	/* L1 reload control */
+	0x88,	/* L1 control register */
+	0x8c,	/* L1 window horizontal position configuration */
+	0x90,	/* L1 window vertical position configuration */
+	0x94,	/* L1 color keying configuration */
+	0x98,	/* L1 pixel format configuration */
+	0x9c,	/* L1 constant alpha configuration */
+	0xa0,	/* L1 default color configuration */
+	0xa4,	/* L1 blending factors configuration */
+	0xa8,	/* L1 burst length configuration */
+	0x00,	/* not available */
+	0xac,	/* L1 color frame buffer address */
+	0xb0,	/* L1 color frame buffer length */
+	0xb4,	/* L1 color frame buffer line number */
+	0xb8,	/* L1 auxiliary frame buffer address 0 */
+	0xbc,	/* L1 auxiliary frame buffer address 1 */
+	0xc0,	/* L1 auxiliary frame buffer length */
+	0xc4,	/* L1 auxiliary frame buffer line number */
+	0xc8,	/* L1 CLUT write */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00,	/* not available */
+	0x00	/* not available */
+};
+
+static const u32 layer_regs_a2[] = {
+	0x100,	/* L1 configuration 0 */
+	0x104,	/* L1 configuration 1 */
+	0x108,	/* L1 reload control */
+	0x10c,	/* L1 control register */
+	0x110,	/* L1 window horizontal position configuration */
+	0x114,	/* L1 window vertical position configuration */
+	0x118,	/* L1 color keying configuration */
+	0x11c,	/* L1 pixel format configuration */
+	0x120,	/* L1 constant alpha configuration */
+	0x124,	/* L1 default color configuration */
+	0x128,	/* L1 blending factors configuration */
+	0x12c,	/* L1 burst length configuration */
+	0x130,	/* L1 planar configuration */
+	0x134,	/* L1 color frame buffer address */
+	0x138,	/* L1 color frame buffer length */
+	0x13c,	/* L1 color frame buffer line number */
+	0x140,	/* L1 auxiliary frame buffer address 0 */
+	0x144,	/* L1 auxiliary frame buffer address 1 */
+	0x148,	/* L1 auxiliary frame buffer length */
+	0x14c,	/* L1 auxiliary frame buffer line number */
+	0x150,	/* L1 CLUT write */
+	0x154,	/* not available */
+	0x158,	/* not available */
+	0x15c,	/* not available */
+	0x160,	/* not available */
+	0x164,	/* not available */
+	0x168,	/* not available */
+	0x16c,	/* L1 Conversion YCbCr RGB 0 */
+	0x170,	/* L1 Conversion YCbCr RGB 1 */
+	0x174,	/* L1 Flexible Pixel Format 0 */
+	0x178	/* L1 Flexible Pixel Format 1 */
 };
 
 /* LTDC main registers */
@@ -49,26 +155,32 @@ struct stm32_ltdc_priv {
 #define LTDC_CPSR	0x44	/* Current Position Status */
 #define LTDC_CDSR	0x48	/* Current Display Status */
 
-/* LTDC layer 1 registers */
-#define LTDC_L1LC1R	0x80	/* L1 Layer Configuration 1 */
-#define LTDC_L1LC2R	0x84	/* L1 Layer Configuration 2 */
-#define LTDC_L1CR	0x84	/* L1 Control */
-#define LTDC_L1WHPCR	0x88	/* L1 Window Hor Position Config */
-#define LTDC_L1WVPCR	0x8C	/* L1 Window Vert Position Config */
-#define LTDC_L1CKCR	0x90	/* L1 Color Keying Configuration */
-#define LTDC_L1PFCR	0x94	/* L1 Pixel Format Configuration */
-#define LTDC_L1CACR	0x98	/* L1 Constant Alpha Config */
-#define LTDC_L1DCCR	0x9C	/* L1 Default Color Configuration */
-#define LTDC_L1BFCR	0xA0	/* L1 Blend Factors Configuration */
-#define LTDC_L1FBBCR	0xA4	/* L1 FrameBuffer Bus Control */
-#define LTDC_L1AFBCR	0xA8	/* L1 AuxFB Control */
-#define LTDC_L1CFBAR	0xAC	/* L1 Color FrameBuffer Address */
-#define LTDC_L1CFBLR	0xB0	/* L1 Color FrameBuffer Length */
-#define LTDC_L1CFBLNR	0xB4	/* L1 Color FrameBuffer Line Nb */
-#define LTDC_L1AFBAR	0xB8	/* L1 AuxFB Address */
-#define LTDC_L1AFBLR	0xBC	/* L1 AuxFB Length */
-#define LTDC_L1AFBLNR	0xC0	/* L1 AuxFB Line Number */
-#define LTDC_L1CLUTWR	0xC4	/* L1 CLUT Write */
+/* Layer register offsets */
+#define LTDC_L1C0R	(priv->layer_regs[0])	/* L1 configuration 0 */
+#define LTDC_L1C1R	(priv->layer_regs[1])	/* L1 configuration 1 */
+#define LTDC_L1RCR	(priv->layer_regs[2])	/* L1 reload control */
+#define LTDC_L1CR	(priv->layer_regs[3])	/* L1 control register */
+#define LTDC_L1WHPCR	(priv->layer_regs[4])	/* L1 window horizontal position configuration */
+#define LTDC_L1WVPCR	(priv->layer_regs[5])	/* L1 window vertical position configuration */
+#define LTDC_L1CKCR	(priv->layer_regs[6])	/* L1 color keying configuration */
+#define LTDC_L1PFCR	(priv->layer_regs[7])	/* L1 pixel format configuration */
+#define LTDC_L1CACR	(priv->layer_regs[8])	/* L1 constant alpha configuration */
+#define LTDC_L1DCCR	(priv->layer_regs[9])	/* L1 default color configuration */
+#define LTDC_L1BFCR	(priv->layer_regs[10])	/* L1 blending factors configuration */
+#define LTDC_L1BLCR	(priv->layer_regs[11])	/* L1 burst length configuration */
+#define LTDC_L1PCR	(priv->layer_regs[12])	/* L1 planar configuration */
+#define LTDC_L1CFBAR	(priv->layer_regs[13])	/* L1 color frame buffer address */
+#define LTDC_L1CFBLR	(priv->layer_regs[14])	/* L1 color frame buffer length */
+#define LTDC_L1CFBLNR	(priv->layer_regs[15])	/* L1 color frame buffer line number */
+#define LTDC_L1AFBA0R	(priv->layer_regs[16])	/* L1 auxiliary frame buffer address 0 */
+#define LTDC_L1AFBA1R	(priv->layer_regs[17])	/* L1 auxiliary frame buffer address 1 */
+#define LTDC_L1AFBLR	(priv->layer_regs[18])	/* L1 auxiliary frame buffer length */
+#define LTDC_L1AFBLNR	(priv->layer_regs[19])	/* L1 auxiliary frame buffer line number */
+#define LTDC_L1CLUTWR	(priv->layer_regs[20])	/* L1 CLUT write */
+#define LTDC_L1CYR0R	(priv->layer_regs[27])	/* L1 Conversion YCbCr RGB 0 */
+#define LTDC_L1CYR1R	(priv->layer_regs[28])	/* L1 Conversion YCbCr RGB 1 */
+#define LTDC_L1FPF0R	(priv->layer_regs[29])	/* L1 Flexible Pixel Format 0 */
+#define LTDC_L1FPF1R	(priv->layer_regs[30])	/* L1 Flexible Pixel Format 1 */
 
 /* Bit definitions */
 #define SSCR_VSH	GENMASK(10, 0)	/* Vertical Synchronization Height */
@@ -144,15 +256,60 @@ struct stm32_ltdc_priv {
 #define BF2_1PAXCA	0x007		/* 1 - (Pixel Alpha x Constant Alpha) */
 #define BF2_1CA		0x005		/* 1 - Constant Alpha */
 
+#define NB_PF		8		/* Max nb of HW pixel format */
+
+#define HWVER_10200 0x010200
+#define HWVER_10300 0x010300
+#define HWVER_20101 0x020101
+#define HWVER_40100 0x040100
+
 enum stm32_ltdc_pix_fmt {
-	PF_ARGB8888 = 0,
-	PF_RGB888,
-	PF_RGB565,
-	PF_ARGB1555,
-	PF_ARGB4444,
-	PF_L8,
-	PF_AL44,
-	PF_AL88
+	PF_ARGB8888 = 0,	/* ARGB [32 bits] */
+	PF_ABGR8888,		/* ABGR [32 bits] */
+	PF_BGRA8888,		/* BGRA [32 bits] */
+	PF_RGBA8888,		/* RGBA [32 bits] */
+	PF_RGB888,		/* RGB [24 bits] */
+	PF_BGR565,		/* RGB [16 bits] */
+	PF_RGB565,		/* RGB [16 bits] */
+	PF_ARGB1555,		/* ARGB A:1 bit RGB:15 bits [16 bits] */
+	PF_ARGB4444,		/* ARGB A:4 bits R/G/B: 4 bits each [16 bits] */
+	PF_AL44,		/* Alpha:4 bits + indexed 4 bits [8 bits] */
+	PF_AL88,		/* Alpha:8 bits + indexed 8 bits [16 bits] */
+	PF_L8,			/* Indexed 8 bits [8 bits] */
+	PF_NONE
+};
+
+static const enum stm32_ltdc_pix_fmt pix_fmt_a0[NB_PF] = {
+	PF_ARGB8888,		/* 0x00 */
+	PF_RGB888,		/* 0x01 */
+	PF_RGB565,		/* 0x02 */
+	PF_ARGB1555,		/* 0x03 */
+	PF_ARGB4444,		/* 0x04 */
+	PF_L8,			/* 0x05 */
+	PF_AL44,		/* 0x06 */
+	PF_AL88			/* 0x07 */
+};
+
+static const enum stm32_ltdc_pix_fmt pix_fmt_a1[NB_PF] = {
+	PF_ARGB8888,		/* 0x00 */
+	PF_RGB888,		/* 0x01 */
+	PF_RGB565,		/* 0x02 */
+	PF_RGBA8888,		/* 0x03 */
+	PF_AL44,		/* 0x04 */
+	PF_L8,			/* 0x05 */
+	PF_ARGB1555,		/* 0x06 */
+	PF_ARGB4444		/* 0x07 */
+};
+
+static const enum stm32_ltdc_pix_fmt pix_fmt_a2[NB_PF] = {
+	PF_ARGB8888,		/* 0x00 */
+	PF_ABGR8888,		/* 0x01 */
+	PF_RGBA8888,		/* 0x02 */
+	PF_BGRA8888,		/* 0x03 */
+	PF_RGB565,		/* 0x04 */
+	PF_BGR565,		/* 0x05 */
+	PF_RGB888,		/* 0x06 */
+	PF_NONE			/* 0x07 (flexible pixel format) */
 };
 
 /* TODO add more color format support */
@@ -306,7 +463,16 @@ static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr)
 
 	/* Pixel format */
 	format = stm32_ltdc_get_pixel_format(priv->l2bpp);
-	clrsetbits_le32(regs + LTDC_L1PFCR, LXPFCR_PF, format);
+	for (val = 0; val < NB_PF; val++)
+		if (priv->pix_fmt_hw[val] == format)
+			break;
+
+	if (val >= NB_PF) {
+		log_err("invalid pixel format\n");
+		return;
+	}
+
+	clrsetbits_le32(regs + LTDC_L1PFCR, LXPFCR_PF, val);
 
 	/* Constant alpha value */
 	clrsetbits_le32(regs + LTDC_L1CACR, LXCACR_CONSTA, priv->alpha);
@@ -359,6 +525,27 @@ static int stm32_ltdc_probe(struct udevice *dev)
 		return ret;
 	}
 
+	priv->hw_version = readl(priv->regs + LTDC_IDR);
+	debug("%s: LTDC hardware 0x%x\n", __func__, priv->hw_version);
+
+	switch (priv->hw_version) {
+	case HWVER_10200:
+	case HWVER_10300:
+		priv->layer_regs = layer_regs_a0;
+		priv->pix_fmt_hw = pix_fmt_a0;
+		break;
+	case HWVER_20101:
+		priv->layer_regs = layer_regs_a1;
+		priv->pix_fmt_hw = pix_fmt_a1;
+		break;
+	case HWVER_40100:
+		priv->layer_regs = layer_regs_a2;
+		priv->pix_fmt_hw = pix_fmt_a2;
+		break;
+	default:
+		return -ENODEV;
+	}
+
 	ret = uclass_first_device_err(UCLASS_PANEL, &panel);
 	if (ret) {
 		if (ret != -ENODEV)
-- 
2.25.1



More information about the U-Boot mailing list