On Sun, May 11, 2025 at 10:31:19PM +1200, Ryan Walklin wrote:
> From: Jernej Skrabec <jernej.skra...@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.skra...@gmail.com>
> Signed-off-by: Ryan Walklin <r...@testtoast.com>
> Signed-off-by: Chris Morgan <macromor...@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 <mrip...@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
> 

Attachment: signature.asc
Description: PGP signature

Reply via email to