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

Patrice CHOTARD patrice.chotard at foss.st.com
Fri Apr 22 09:53:37 CEST 2022


Hi Yannick


On 4/6/22 10:41, Yannick Fertre wrote:
> 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)

Reviewed-by: Patrice Chotard <patrice.chotard at foss.st.com>

Thanks
Patrice


More information about the U-Boot mailing list