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 <[email protected]> > --- > > 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 <[email protected]> Thanks Patrice

