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 >
signature.asc
Description: PGP signature