Hi Chen-Yu,

Dne četrtek, 25. december 2025 ob 10:49:47 Srednjeevropski standardni čas je 
Chen-Yu Tsai napisal(a):
> On Sat, Nov 15, 2025 at 10:14 PM Jernej Skrabec
> <[email protected]> wrote:
> >
> > Now that everything is in place, switch DE33 to new bindings.
> >
> > Signed-off-by: Jernej Skrabec <[email protected]>
> > ---
> >  drivers/gpu/drm/sun4i/sun8i_mixer.c | 130 +++++++++++++++-------------
> >  drivers/gpu/drm/sun4i/sun8i_mixer.h |  10 +--
> >  2 files changed, 71 insertions(+), 69 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c 
> > b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> > index fde3b677e925..da213e54e653 100644
> > --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> > +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> > @@ -13,6 +13,7 @@
> >  #include <linux/of.h>
> >  #include <linux/of_device.h>
> >  #include <linux/of_graph.h>
> > +#include <linux/of_platform.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/reset.h>
> >
> > @@ -24,6 +25,7 @@
> >  #include <drm/drm_probe_helper.h>
> >
> >  #include "sun4i_drv.h"
> > +#include "sun50i_planes.h"
> >  #include "sun8i_mixer.h"
> >  #include "sun8i_ui_layer.h"
> >  #include "sun8i_vi_layer.h"
> > @@ -256,7 +258,6 @@ static void sun8i_mixer_commit(struct sunxi_engine 
> > *engine,
> >  {
> >         struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
> >         u32 bld_base = sun8i_blender_base(mixer);
> > -       struct regmap *bld_regs = sun8i_blender_regmap(mixer);
> >         struct drm_plane_state *plane_state;
> >         struct drm_plane *plane;
> >         u32 route = 0, pipe_en = 0;
> > @@ -293,16 +294,16 @@ static void sun8i_mixer_commit(struct sunxi_engine 
> > *engine,
> >                 route |= layer->index << 
> > SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
> >                 pipe_en |= SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
> >
> > -               regmap_write(bld_regs,
> > +               regmap_write(engine->regs,
> >                              SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos),
> >                              SUN8I_MIXER_COORD(x, y));
> > -               regmap_write(bld_regs,
> > +               regmap_write(engine->regs,
> >                              SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos),
> >                              SUN8I_MIXER_SIZE(w, h));
> >         }
> >
> > -       regmap_write(bld_regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), route);
> > -       regmap_write(bld_regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
> > +       regmap_write(engine->regs, SUN8I_MIXER_BLEND_ROUTE(bld_base), 
> > route);
> > +       regmap_write(engine->regs, SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
> >                      pipe_en | SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
> >
> >         if (mixer->cfg->de_type != SUN8I_MIXER_DE33)
> > @@ -317,7 +318,6 @@ static struct drm_plane **sun8i_layers_init(struct 
> > drm_device *drm,
> >         struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
> >         int plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num;
> >         enum drm_plane_type type;
> > -       unsigned int phy_index;
> >         int i;
> >
> >         planes = devm_kcalloc(drm->dev, plane_cnt, sizeof(*planes), 
> > GFP_KERNEL);
> > @@ -332,12 +332,8 @@ static struct drm_plane **sun8i_layers_init(struct 
> > drm_device *drm,
> >                 else
> >                         type = DRM_PLANE_TYPE_OVERLAY;
> >
> > -               phy_index = i;
> > -               if (mixer->cfg->de_type == SUN8I_MIXER_DE33)
> > -                       phy_index = mixer->cfg->map[i];
> > -
> >                 layer = sun8i_vi_layer_init_one(drm, type, 
> > mixer->engine.regs,
> > -                                               i, phy_index, plane_cnt,
> > +                                               i, i, plane_cnt,
> >                                                 &mixer->cfg->lay_cfg);
> >                 if (IS_ERR(layer)) {
> >                         dev_err(drm->dev,
> > @@ -357,12 +353,8 @@ static struct drm_plane **sun8i_layers_init(struct 
> > drm_device *drm,
> >                 else
> >                         type = DRM_PLANE_TYPE_OVERLAY;
> >
> > -               phy_index = index;
> > -               if (mixer->cfg->de_type == SUN8I_MIXER_DE33)
> > -                       phy_index = mixer->cfg->map[index];
> > -
> >                 layer = sun8i_ui_layer_init_one(drm, type, 
> > mixer->engine.regs,
> > -                                               index, phy_index, plane_cnt,
> > +                                               index, index, plane_cnt,
> >                                                 &mixer->cfg->lay_cfg);
> >                 if (IS_ERR(layer)) {
> >                         dev_err(drm->dev, "Couldn't initialize %s plane\n",
> > @@ -376,16 +368,25 @@ static struct drm_plane **sun8i_layers_init(struct 
> > drm_device *drm,
> >         return planes;
> >  }
> >
> > +static struct drm_plane **sun50i_layers_init(struct drm_device *drm,
> > +                                            struct sunxi_engine *engine)
> > +{
> > +       struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
> > +
> > +       if (IS_ENABLED(CONFIG_DRM_SUN50I_PLANES))
> > +               return sun50i_planes_setup(mixer->planes_dev, drm, 
> > engine->id);
> > +
> > +       return NULL;
> > +}
> > +
> >  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);
> >
> > @@ -397,14 +398,14 @@ static void sun8i_mixer_mode_set(struct sunxi_engine 
> > *engine,
> >         else
> >                 regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_SIZE, 
> > size);
> >
> > -       regmap_write(bld_regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size);
> > +       regmap_write(engine->regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), 
> > size);
> >
> >         if (interlaced)
> >                 val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
> >         else
> >                 val = 0;
> >
> > -       regmap_update_bits(bld_regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
> > +       regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base),
> >                            SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, val);
> >
> >         DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
> > @@ -417,8 +418,14 @@ static const struct sunxi_engine_ops sun8i_engine_ops 
> > = {
> >         .mode_set       = sun8i_mixer_mode_set,
> >  };
> >
> > +static const struct sunxi_engine_ops sun50i_engine_ops = {
> > +       .commit         = sun8i_mixer_commit,
> > +       .layers_init    = sun50i_layers_init,
> > +       .mode_set       = sun8i_mixer_mode_set,
> > +};
> > +
> >  static const struct regmap_config sun8i_mixer_regmap_config = {
> > -       .name           = "layers",
> > +       .name           = "display",
> >         .reg_bits       = 32,
> >         .val_bits       = 32,
> >         .reg_stride     = 4,
> > @@ -433,14 +440,6 @@ static const struct regmap_config 
> > sun8i_top_regmap_config = {
> >         .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;
> > @@ -463,17 +462,14 @@ 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);
> > +       struct regmap *top_regs;
> >         int plane_cnt, i;
> >
> > -       if (mixer->cfg->de_type == SUN8I_MIXER_DE33) {
> > +       if (mixer->cfg->de_type == SUN8I_MIXER_DE33)
> >                 top_regs = mixer->top_regs;
> > -               disp_regs = mixer->disp_regs;
> > -       } else {
> > +       else
> >                 top_regs = mixer->engine.regs;
> > -               disp_regs = mixer->engine.regs;
> > -       }
> >
> >         /* Enable the mixer */
> >         regmap_write(top_regs, SUN8I_MIXER_GLOBAL_CTL,
> > @@ -483,25 +479,25 @@ static void sun8i_mixer_init(struct sun8i_mixer 
> > *mixer)
> >                 regmap_write(top_regs, SUN50I_MIXER_GLOBAL_CLK, 1);
> >
> >         /* Set background color to black */
> > -       regmap_write(disp_regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
> > +       regmap_write(mixer->engine.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(disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
> > +       regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
> >                      SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
> > -       regmap_write(disp_regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
> > +       regmap_write(mixer->engine.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(disp_regs,
> > +               regmap_write(mixer->engine.regs,
> >                              SUN8I_MIXER_BLEND_MODE(base, i),
> >                              SUN8I_MIXER_BLEND_MODE_DEF);
> >
> > -       regmap_update_bits(disp_regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
> > +       regmap_update_bits(mixer->engine.regs, 
> > SUN8I_MIXER_BLEND_PIPE_CTL(base),
> >                            SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
> >  }
> >
> > @@ -532,7 +528,6 @@ static int sun8i_mixer_bind(struct device *dev, struct 
> > device *master,
> >         if (!mixer)
> >                 return -ENOMEM;
> >         dev_set_drvdata(dev, mixer);
> > -       mixer->engine.ops = &sun8i_engine_ops;
> >         mixer->engine.node = dev->of_node;
> >
> >         if (of_property_present(dev->of_node, "iommus")) {
> > @@ -562,6 +557,11 @@ static int sun8i_mixer_bind(struct device *dev, struct 
> > device *master,
> >         if (!mixer->cfg)
> >                 return -EINVAL;
> >
> > +       if (mixer->cfg->de_type == SUN8I_MIXER_DE33)
> > +               mixer->engine.ops = &sun50i_engine_ops;
> 
> You're missing an IS_ENABLED() clause here if you wanted to make the DE 3.3
> planes driver optional. Though as I mentioned in the other patch, splittig
> the two modules might not work.
> 
> > +       else
> > +               mixer->engine.ops = &sun8i_engine_ops;
> > +
> >         regs = devm_platform_ioremap_resource(pdev, 0);
> >         if (IS_ERR(regs))
> >                 return PTR_ERR(regs);
> > @@ -584,17 +584,6 @@ static int sun8i_mixer_bind(struct device *dev, struct 
> > device *master,
> >                         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);
> > @@ -634,6 +623,33 @@ static int sun8i_mixer_bind(struct device *dev, struct 
> > device *master,
> >
> >         clk_prepare_enable(mixer->mod_clk);
> >
> > +       if (mixer->cfg->de_type == SUN8I_MIXER_DE33) {
> > +               struct platform_device *pdev;
> > +               struct device_node *np;
> > +               void *data;
> > +
> > +               np = of_parse_phandle(dev->of_node, "allwinner,planes", 0);
> > +               if (!np) {
> > +                       ret = -ENODEV;
> > +                       goto err_disable_mod_clk;
> > +               }
> > +
> > +               pdev = of_find_device_by_node(np);
> 
> You need to add a matching put_device() in the unbind function.
> 
> Side note:
> 
> This bind function is using a lot of devm_ functions. These have the wrong
> lifetime. I think it would be better if we could move resource acquisition
> into the probe function.

Looking a bit more into this, this requires a bit more work. For example, clocks
can be provided by tcon-top, which are created only in bind callback. Basically,
whole sun4i-drm driver depends on devm_* calls in bind functions. This would
need careful analysis of all driver calls and then refactoring drivers one by 
one. 

IMO tcon-top driver needs to be refactored to plain clock driver without 
component
bind/unbind functions. Although this may cause slightly higher power consumption
if device doesn't have display but driver is loaded nevertheless.

What do you think?

Best regards,
Jernej



Reply via email to