[PATCH v10 10/11] drm: sun4i: de33: mixer: add Display Engine 3.3 (DE33) support
Maxime Ripard
mripard at kernel.org
Wed May 14 15:07:30 UTC 2025
On Sun, May 11, 2025 at 10:31:19PM +1200, Ryan Walklin wrote:
> From: Jernej Skrabec <jernej.skrabec at gmail.com>
>
> The DE33 is a newer version of the Allwinner Display Engine IP block,
> found in the H616, H618, H700 and T507 SoCs. DE2 and DE3 are already
> supported by the mainline driver.
>
> Notable features (from the H616 datasheet and implemented):
> - 4096 x 2048 (4K) output support
>
> Other features (implemented but not in this patchset):
> - AFBC ARM Frame Buffer Compression support
> - YUV pipeline support
>
> The DE2 and DE3 engines have a blender register range within the
> mixer engine register map, whereas the DE33 separates this out into
> a separate display group, and adds a top register map.
>
> The DE33 also appears to remove the global double buffer control
> register, present in the DE2 and DE3.
>
> Extend the mixer to support the DE33.
>
> Signed-off-by: Jernej Skrabec <jernej.skrabec at gmail.com>
> Signed-off-by: Ryan Walklin <ryan at testtoast.com>
> Signed-off-by: Chris Morgan <macromorgan at hotmail.com>
>
> ---
> Changelog v4..v5:
> - Whitespace fixes
> - Correct strict mode warnings from checkpatch.pl
>
> Changelog v7..v8:
> - Add top/disp regmaps to mixer for DE33
> - Remove YUV-specific code
> - Remove use of global double buffer
> - Remove unneeded if/then parentheses and fix an alignment issue as suggested by checkpatch.pl
>
> Changelog v9..v10:
> - Use names from vendor BSP kernel for register blocks.
> ---
> drivers/gpu/drm/sun4i/sun8i_mixer.c | 82 +++++++++++++++++++++++++----
> drivers/gpu/drm/sun4i/sun8i_mixer.h | 22 ++++++--
> 2 files changed, 90 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> index cc4da11e2c10..0d4695132dae 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -318,8 +318,9 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine,
> regmap_write(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
> pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
>
> - regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
> - SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
> + if (mixer->cfg->de_type != sun8i_mixer_de33)
> + regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_DBUFF,
> + SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
> }
>
> static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
> @@ -368,25 +369,31 @@ static void sun8i_mixer_mode_set(struct sunxi_engine *engine,
> const struct drm_display_mode *mode)
> {
> struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
> + struct regmap *bld_regs;
> u32 bld_base, size, val;
> bool interlaced;
>
> bld_base = sun8i_blender_base(mixer);
> + bld_regs = sun8i_blender_regmap(mixer);
> interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
> size = SUN8I_MIXER_SIZE(mode->hdisplay, mode->vdisplay);
>
> DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n",
> mode->hdisplay, mode->vdisplay);
>
> - regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_SIZE, size);
> - regmap_write(engine->regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size);
> + if (mixer->cfg->de_type == sun8i_mixer_de33)
> + regmap_write(mixer->top_regs, SUN50I_MIXER_GLOBAL_SIZE, size);
> + else
> + regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_SIZE, size);
> +
> + regmap_write(bld_regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size);
>
> if (interlaced)
> val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
> else
> val = 0;
>
> - regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
> + regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
> SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, val);
>
> DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
> @@ -400,12 +407,29 @@ static const struct sunxi_engine_ops sun8i_engine_ops = {
> };
>
> static const struct regmap_config sun8i_mixer_regmap_config = {
> + .name = "layers",
> .reg_bits = 32,
> .val_bits = 32,
> .reg_stride = 4,
> .max_register = 0xffffc, /* guessed */
> };
>
> +static const struct regmap_config sun8i_top_regmap_config = {
> + .name = "top",
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x3c,
> +};
> +
> +static const struct regmap_config sun8i_disp_regmap_config = {
> + .name = "display",
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = 0x20000,
> +};
> +
> static int sun8i_mixer_of_get_id(struct device_node *node)
> {
> struct device_node *ep, *remote;
> @@ -428,33 +452,45 @@ static int sun8i_mixer_of_get_id(struct device_node *node)
>
> static void sun8i_mixer_init(struct sun8i_mixer *mixer)
> {
> + struct regmap *top_regs, *disp_regs;
> unsigned int base = sun8i_blender_base(mixer);
> int plane_cnt, i;
>
> + if (mixer->cfg->de_type == sun8i_mixer_de33) {
> + top_regs = mixer->top_regs;
> + disp_regs = mixer->disp_regs;
> + } else {
> + top_regs = mixer->engine.regs;
> + disp_regs = mixer->engine.regs;
> + }
> +
> /* Enable the mixer */
> - regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
> + regmap_write(top_regs, SUN8I_MIXER_GLOBAL_CTL,
> SUN8I_MIXER_GLOBAL_CTL_RT_EN);
>
> + if (mixer->cfg->de_type == sun8i_mixer_de33)
> + regmap_write(top_regs, SUN50I_MIXER_GLOBAL_CLK, 1);
> +
> /* Set background color to black */
> - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
> + regmap_write(disp_regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
> SUN8I_MIXER_BLEND_COLOR_BLACK);
>
> /*
> * Set fill color of bottom plane to black. Generally not needed
> * except when VI plane is at bottom (zpos = 0) and enabled.
> */
> - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
> + regmap_write(disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
> SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
> - regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
> + regmap_write(disp_regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
> SUN8I_MIXER_BLEND_COLOR_BLACK);
>
> plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
> for (i = 0; i < plane_cnt; i++)
> - regmap_write(mixer->engine.regs,
> + regmap_write(disp_regs,
> SUN8I_MIXER_BLEND_MODE(base, i),
> SUN8I_MIXER_BLEND_MODE_DEF);
>
> - regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
> + regmap_update_bits(disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
> SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
> }
>
> @@ -526,6 +562,30 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
> return PTR_ERR(mixer->engine.regs);
> }
>
> + if (mixer->cfg->de_type == sun8i_mixer_de33) {
> + regs = devm_platform_ioremap_resource_byname(pdev, "top");
> + if (IS_ERR(regs))
> + return PTR_ERR(regs);
> +
> + mixer->top_regs = devm_regmap_init_mmio(dev, regs,
> + &sun8i_top_regmap_config);
> + if (IS_ERR(mixer->top_regs)) {
> + dev_err(dev, "Couldn't create the top regmap\n");
> + return PTR_ERR(mixer->top_regs);
> + }
> +
> + regs = devm_platform_ioremap_resource_byname(pdev, "display");
> + if (IS_ERR(regs))
> + return PTR_ERR(regs);
> +
> + mixer->disp_regs = devm_regmap_init_mmio(dev, regs,
> + &sun8i_disp_regmap_config);
> + if (IS_ERR(mixer->disp_regs)) {
> + dev_err(dev, "Couldn't create the disp regmap\n");
> + return PTR_ERR(mixer->disp_regs);
> + }
> + }
> +
> mixer->reset = devm_reset_control_get(dev, NULL);
> if (IS_ERR(mixer->reset)) {
> dev_err(dev, "Couldn't get our reset line\n");
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> index 43c413052a22..d87d197610e1 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> @@ -21,6 +21,9 @@
> #define SUN8I_MIXER_GLOBAL_DBUFF 0x8
> #define SUN8I_MIXER_GLOBAL_SIZE 0xc
>
> +#define SUN50I_MIXER_GLOBAL_SIZE 0x8
> +#define SUN50I_MIXER_GLOBAL_CLK 0xc
> +
> #define SUN8I_MIXER_GLOBAL_CTL_RT_EN BIT(0)
>
> #define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE BIT(0)
> @@ -151,6 +154,12 @@ enum {
> CCSC_D1_MIXER0_LAYOUT,
> };
>
> +enum sun8i_mixer_type {
> + sun8i_mixer_de2,
> + sun8i_mixer_de3,
> + sun8i_mixer_de33,
> +};
enum variants typically have their name in upper-case.
With that fixed,
Acked-by: Maxime Ripard <mripard at kernel.org>
Maxime
> /**
> * struct sun8i_mixer_cfg - mixer HW configuration
> * @vi_num: number of VI channels
> @@ -171,8 +180,9 @@ struct sun8i_mixer_cfg {
> int scaler_mask;
> int ccsc;
> unsigned long mod_rate;
> - unsigned int is_de3 : 1;
> + unsigned int de_type;
> unsigned int scanline_yuv;
> + unsigned int map[6];
> };
>
> struct sun8i_mixer {
> @@ -184,6 +194,9 @@ struct sun8i_mixer {
>
> struct clk *bus_clk;
> struct clk *mod_clk;
> +
> + struct regmap *top_regs;
> + struct regmap *disp_regs;
> };
>
> enum {
> @@ -220,13 +233,16 @@ sun8i_blender_base(struct sun8i_mixer *mixer)
> static inline struct regmap *
> sun8i_blender_regmap(struct sun8i_mixer *mixer)
> {
> - return mixer->engine.regs;
> + return mixer->cfg->de_type == sun8i_mixer_de33 ?
> + mixer->disp_regs : mixer->engine.regs;
> }
>
> static inline u32
> sun8i_channel_base(struct sun8i_mixer *mixer, int channel)
> {
> - if (mixer->cfg->is_de3)
> + if (mixer->cfg->de_type == sun8i_mixer_de33)
> + return mixer->cfg->map[channel] * 0x20000 + DE2_CH_SIZE;
> + else if (mixer->cfg->de_type == sun8i_mixer_de3)
> return DE3_CH_BASE + channel * DE3_CH_SIZE;
> else
> return DE2_CH_BASE + channel * DE2_CH_SIZE;
> --
> 2.49.0
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20250514/6bc1fa84/attachment-0001.sig>
More information about the dri-devel
mailing list