From: "Jernej Škrabec" <jernej.skrabec@gmail.com>
To: wens@kernel.org
Cc: samuel@sholland.org, mripard@kernel.org,
maarten.lankhorst@linux.intel.com, tzimmermann@suse.de,
airlied@gmail.com, simona@ffwll.ch, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org, mturquette@baylibre.com,
sboyd@kernel.org, dri-devel@lists.freedesktop.org,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-clk@vger.kernel.org
Subject: Re: [PATCH 5/7] drm/sun4i: Add planes driver
Date: Thu, 25 Dec 2025 20:16:56 +0100 [thread overview]
Message-ID: <2040104.PYKUYFuaPT@jernej-laptop> (raw)
In-Reply-To: <CAGb2v65e2a_f+UEDu-Wk3bWvgHt24erjk+iLWgMAQwB-mzcnaA@mail.gmail.com>
Dne četrtek, 25. december 2025 ob 10:37:06 Srednjeevropski standardni čas je Chen-Yu Tsai napisal(a):
> On Thu, Dec 25, 2025 at 5:29 PM Chen-Yu Tsai <wens@kernel.org> wrote:
> >
> > On Sat, Nov 15, 2025 at 10:14 PM Jernej Skrabec
> > <jernej.skrabec@gmail.com> wrote:
> > >
> > > This driver serves just as planes sharing manager, needed for Display
> > > Engine 3.3 and newer.
> > >
> > > Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
> > > ---
> > > drivers/gpu/drm/sun4i/Kconfig | 8 +
> > > drivers/gpu/drm/sun4i/Makefile | 1 +
> > > drivers/gpu/drm/sun4i/sun50i_planes.c | 205 ++++++++++++++++++++++++++
> > > drivers/gpu/drm/sun4i/sun50i_planes.h | 43 ++++++
> > > 4 files changed, 257 insertions(+)
> > > create mode 100644 drivers/gpu/drm/sun4i/sun50i_planes.c
> > > create mode 100644 drivers/gpu/drm/sun4i/sun50i_planes.h
> > >
> > > diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
> > > index b56ba00aabca..946dd7606094 100644
> > > --- a/drivers/gpu/drm/sun4i/Kconfig
> > > +++ b/drivers/gpu/drm/sun4i/Kconfig
> > > @@ -85,4 +85,12 @@ config DRM_SUN8I_TCON_TOP
> > > TCON TOP is responsible for configuring display pipeline for
> > > HDMI, TVE and LCD.
> > >
> > > +config DRM_SUN50I_PLANES
> > > + tristate
> > > + default DRM_SUN4I if DRM_SUN8I_MIXER!=n
> > > + help
> > > + Chose this option if you have an Allwinner Soc with the
> > > + Display Engine 3.3 or newer. Planes are shared resource
> > > + between multiple mixers.
> > > +
> > > endif
> > > diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> > > index bad7497a0d11..03f002abef15 100644
> > > --- a/drivers/gpu/drm/sun4i/Makefile
> > > +++ b/drivers/gpu/drm/sun4i/Makefile
> > > @@ -38,3 +38,4 @@ obj-$(CONFIG_DRM_SUN6I_DSI) += sun6i_mipi_dsi.o
> > > obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i-drm-hdmi.o
> > > obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
> > > obj-$(CONFIG_DRM_SUN8I_TCON_TOP) += sun8i_tcon_top.o
> > > +obj-$(CONFIG_DRM_SUN50I_PLANES) += sun50i_planes.o
> >
> > I don't think you can have this as a separate module:
> >
> > a. You are using sun8i_vi_layer_init_one() and sun8i_ui_layer_init_one()
> > from the sun8i-mixer module, and neither of them are exported symbols.
> >
> > b. You export sun50i_planes_setup() for sun8i-mixer to call, which ends
> > up becoming a circular dependency.
> >
> > The easiest solution would be to just fold this into the sun8i-mixer module.
I mimicked tcon-top module, but yeah, it's much less of a hassle to fold it
into sun8i-mixer.
> >
> >
> > > diff --git a/drivers/gpu/drm/sun4i/sun50i_planes.c b/drivers/gpu/drm/sun4i/sun50i_planes.c
> > > new file mode 100644
> > > index 000000000000..a99c01122990
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/sun4i/sun50i_planes.c
> > > @@ -0,0 +1,205 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +/* Copyright (c) 2025 Jernej Skrabec <jernej.skrabec@gmail.com> */
> > > +
> > > +#include <linux/device.h>
> > > +#include <linux/io.h>
> > > +#include <linux/mfd/syscon.h>
> > > +#include <linux/module.h>
> > > +#include <linux/of.h>
> > > +#include <linux/of_graph.h>
> > > +#include <linux/platform_device.h>
> > > +
> > > +#include "sun50i_planes.h"
> > > +#include "sun8i_ui_layer.h"
> > > +#include "sun8i_vi_layer.h"
> > > +
> > > +static bool sun50i_planes_node_is_planes(struct device_node *node)
> > > +{
> > > + return !!of_match_node(sun50i_planes_of_table, node);
> > > +}
> > > +
> > > +struct drm_plane **
> > > +sun50i_planes_setup(struct device *dev, struct drm_device *drm,
> > > + unsigned int mixer)
> > > +{
> > > + struct sun50i_planes *planes = dev_get_drvdata(dev);
> > > + const struct sun50i_planes_quirks *quirks;
> > > + struct drm_plane **drm_planes;
> > > + const struct default_map *map;
> > > + unsigned int i;
> > > +
> > > + if (!sun50i_planes_node_is_planes(dev->of_node)) {
> > > + dev_err(dev, "Device is not planes driver!\n");
> > > + return NULL;
> > > + }
> > > +
> > > + if (!planes) {
> > > + dev_err(dev, "Planes driver is not loaded yet!\n");
> > > + return NULL;
> > > + }
> > > +
> > > + if (mixer > 1) {
> > > + dev_err(dev, "Mixer index is too high!\n");
> > > + return NULL;
> > > + }
> > > +
> > > + quirks = planes->quirks;
> > > + map = &quirks->def_map[mixer];
> > > +
> > > + drm_planes = devm_kcalloc(drm->dev, map->num_ch + 1,
> >
> > Just a note: it seems we are missing the sentinel in sun8i_layers_init().
Why do you think so? Current mainline code has mixer->cfg->vi_num +
mixer->cfg->ui_num + 1.
> >
> > > + sizeof(*drm_planes), GFP_KERNEL);
> > > + if (!drm_planes)
> > > + return ERR_PTR(-ENOMEM);
> > > +
> > > + for (i = 0; i < map->num_ch; i++) {
> > > + unsigned int phy_ch = map->map[i];
> > > + struct sun8i_layer *layer;
> > > + enum drm_plane_type type;
> > > +
> > > + if ((i == 0 && map->num_ch == 1) || i == 1)
> > > + type = DRM_PLANE_TYPE_PRIMARY;
> > > + else
> > > + type = DRM_PLANE_TYPE_OVERLAY;
> > > +
> > > + if (phy_ch < UI_PLANE_OFFSET)
> > > + layer = sun8i_vi_layer_init_one(drm, type, planes->regs,
> > > + i, phy_ch, map->num_ch,
> > > + &quirks->cfg);
> > > + else
> > > + layer = sun8i_ui_layer_init_one(drm, type, planes->regs,
> > > + i, phy_ch, map->num_ch,
> > > + &quirks->cfg);
> > > +
> > > + if (IS_ERR(layer)) {
> > > + dev_err(drm->dev,
> > > + "Couldn't initialize DRM plane\n");
> > > + return ERR_CAST(layer);
> > > + }
> > > +
> > > + drm_planes[i] = &layer->plane;
> > > + }
> > > +
> > > + return drm_planes;
> > > +}
> > > +EXPORT_SYMBOL(sun50i_planes_setup);
> > > +
> > > +static void sun50i_planes_init_mapping(struct sun50i_planes *planes)
> > > +{
> > > + const struct sun50i_planes_quirks *quirks = planes->quirks;
> > > + unsigned int i, j;
> > > + u32 mapping;
> > > +
> > > + mapping = 0;
> > > + for (j = 0; j < MAX_DISP; j++)
> > > + for (i = 0; i < quirks->def_map[j].num_ch; i++) {
> > > + unsigned int ch = quirks->def_map[j].map[i];
> > > +
> > > + if (ch < UI_PLANE_OFFSET)
> > > + mapping |= j << (ch * 2);
> > > + else
> > > + mapping |= j << ((ch - UI_PLANE_OFFSET) * 2 + 16);
> > > + }
> > > + regmap_write(planes->mapping, SUNXI_DE33_DE_CHN2CORE_MUX_REG, mapping);
> > > +
> > > + for (j = 0; j < MAX_DISP; j++) {
> > > + mapping = 0;
> > > + for (i = 0; i < quirks->def_map[j].num_ch; i++) {
> > > + unsigned int ch = quirks->def_map[j].map[i];
> > > +
> > > + if (ch >= UI_PLANE_OFFSET)
> > > + ch += 2;
> > > +
> > > + mapping |= ch << (i * 4);
> > > + }
> > > + regmap_write(planes->mapping, SUNXI_DE33_DE_PORT02CHN_MUX_REG + j * 4, mapping);
> > > + }
> > > +}
> > > +
> > > +static const struct regmap_config sun50i_planes_regmap_config = {
> > > + .name = "planes",
> > > + .reg_bits = 32,
> > > + .val_bits = 32,
> > > + .reg_stride = 4,
> > > + .max_register = 0x17fffc,
> > > +};
> > > +
> > > +static int sun50i_planes_probe(struct platform_device *pdev)
> > > +{
> > > + struct device *dev = &pdev->dev;
> > > + struct sun50i_planes *planes;
> > > + void __iomem *regs;
> > > +
> > > + planes = devm_kzalloc(dev, sizeof(*planes), GFP_KERNEL);
> > > + if (!planes)
> > > + return -ENOMEM;
> > > +
> > > + planes->quirks = of_device_get_match_data(&pdev->dev);
> > > + if (!planes->quirks)
> > > + return dev_err_probe(dev, -EINVAL, "Unable to get quirks\n");
> > > +
> > > + planes->mapping = syscon_regmap_lookup_by_phandle(dev->of_node,
> > > + "allwinner,plane-mapping");
> > > + if (IS_ERR(planes->mapping))
> > > + return dev_err_probe(dev, PTR_ERR(planes->mapping),
> > > + "Unable to get mapping\n");
> > > +
> > > + regs = devm_platform_ioremap_resource(pdev, 0);
> > > + if (IS_ERR(regs))
> > > + return PTR_ERR(regs);
> > > +
> > > + planes->regs = devm_regmap_init_mmio(dev, regs, &sun50i_planes_regmap_config);
> > > + if (IS_ERR(planes->regs))
> > > + return PTR_ERR(planes->regs);
> > > +
> > > + dev_set_drvdata(dev, planes);
> > > +
> > > + sun50i_planes_init_mapping(planes);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static const struct sun50i_planes_quirks sun50i_h616_planes_quirks = {
> > > + .def_map = {
> > > + {
> > > + .map = {0, 6, 7},
> > > + .num_ch = 3,
> > > + },
> > > + {
> > > + .map = {1, 2, 8},
> > > + .num_ch = 3,
> > > + },
> > > + },
> > > + .cfg = {
> > > + .de_type = SUN8I_MIXER_DE33,
> > > + /*
> > > + * TODO: All planes support scaling, but driver needs
> > > + * improvements to properly support it.
> > > + */
> > > + .scaler_mask = 0,
> > > + .scanline_yuv = 4096,
> > > + },
> > > +};
> > > +
> > > +/* sun4i_drv uses this list to check if a device node is a plane */
>
> I didn't see any usage of this in patch 7. Is this part of another
> series?
>
> Maybe just export sun50i_planes_node_is_planes() instead?
It's not needed if driver is folder into sun8i-mixer module. Looks like this
is remnant of tcon-top concept...
>
> > > +const struct of_device_id sun50i_planes_of_table[] = {
> > > + {
> > > + .compatible = "allwinner,sun50i-h616-de33-planes",
> > > + .data = &sun50i_h616_planes_quirks
> > > + },
> > > + { }
> > > +};
> > > +MODULE_DEVICE_TABLE(of, sun50i_planes_of_table);
> > > +EXPORT_SYMBOL(sun50i_planes_of_table);
> > > +
> > > +static struct platform_driver sun50i_planes_platform_driver = {
> > > + .probe = sun50i_planes_probe,
> > > + .driver = {
> > > + .name = "sun50i-planes",
> > > + .of_match_table = sun50i_planes_of_table,
> > > + },
> > > +};
> > > +module_platform_driver(sun50i_planes_platform_driver);
> > > +
> > > +MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@gmail.com>");
> > > +MODULE_DESCRIPTION("Allwinner DE33 planes driver");
> > > +MODULE_LICENSE("GPL");
> > > diff --git a/drivers/gpu/drm/sun4i/sun50i_planes.h b/drivers/gpu/drm/sun4i/sun50i_planes.h
> > > new file mode 100644
> > > index 000000000000..446feaeb03fc
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/sun4i/sun50i_planes.h
> > > @@ -0,0 +1,43 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +/* Copyright (c) 2025 Jernej Skrabec <jernej.skrabec@gmail.com> */
> > > +
> > > +#ifndef _SUN50I_PLANES_H_
> > > +#define _SUN50I_PLANES_H_
> > > +
> > > +#include <drm/drm_device.h>
> > > +#include <linux/regmap.h>
> >
> > I think you could move these two to the .c file, and just use forward
> > declarations here.
Ok.
Best regards,
Jernej
> >
> > The rest looks OK.
> >
> >
> > > +
> > > +#include "sun8i_mixer.h"
> > > +
> > > +/* mapping registers, located in clock register space */
> > > +#define SUNXI_DE33_DE_CHN2CORE_MUX_REG 0x24
> > > +#define SUNXI_DE33_DE_PORT02CHN_MUX_REG 0x28
> > > +#define SUNXI_DE33_DE_PORT12CHN_MUX_REG 0x2c
> > > +
> > > +#define MAX_DISP 2
> > > +#define MAX_CHANNELS 8
> > > +#define UI_PLANE_OFFSET 6
> > > +
> > > +struct default_map {
> > > + unsigned int map[MAX_CHANNELS];
> > > + unsigned int num_ch;
> > > +};
> > > +
> > > +struct sun50i_planes_quirks {
> > > + struct default_map def_map[MAX_DISP];
> > > + struct sun8i_layer_cfg cfg;
> > > +};
> > > +
> > > +struct sun50i_planes {
> > > + struct regmap *regs;
> > > + struct regmap *mapping;
> > > + const struct sun50i_planes_quirks *quirks;
> > > +};
> > > +
> > > +extern const struct of_device_id sun50i_planes_of_table[];
> > > +
> > > +struct drm_plane **
> > > +sun50i_planes_setup(struct device *dev, struct drm_device *drm,
> > > + unsigned int mixer);
> > > +
> > > +#endif /* _SUN50I_PLANES_H_ */
> > > --
> > > 2.51.2
> > >
> > >
>
next prev parent reply other threads:[~2025-12-25 19:17 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-15 14:13 [PATCH 0/7] drm/sun4i: update DE33 support Jernej Skrabec
2025-11-15 14:13 ` [PATCH 1/7] drm/sun4i: Add support for DE33 CSC Jernej Skrabec
2025-12-25 8:22 ` Chen-Yu Tsai
2025-11-15 14:13 ` [PATCH 2/7] drm/sun4i: vi_layer: Limit formats for DE33 Jernej Skrabec
2025-11-15 14:40 ` Chen-Yu Tsai
2025-11-15 14:47 ` Jernej Škrabec
2025-11-15 14:13 ` [PATCH 3/7] clk: sunxi-ng: de2: Export register regmap " Jernej Skrabec
2025-11-15 17:37 ` Chen-Yu Tsai
2025-11-15 14:13 ` [PATCH 4/7] dt-bindings: display: allwinner: Add DE33 planes Jernej Skrabec
2025-11-16 11:29 ` Krzysztof Kozlowski
2025-11-16 11:44 ` Jernej Škrabec
2025-11-16 11:49 ` Krzysztof Kozlowski
2025-11-16 12:10 ` Jernej Škrabec
2025-11-15 14:13 ` [PATCH 5/7] drm/sun4i: Add planes driver Jernej Skrabec
2025-12-25 9:29 ` Chen-Yu Tsai
2025-12-25 9:37 ` Chen-Yu Tsai
2025-12-25 19:16 ` Jernej Škrabec [this message]
2025-12-25 19:30 ` Chen-Yu Tsai
2025-12-25 19:34 ` Jernej Škrabec
2025-11-15 14:13 ` [PATCH 6/7] dt-bindings: display: allwinner: Update H616 DE33 binding Jernej Skrabec
2025-11-16 11:33 ` Krzysztof Kozlowski
2025-11-16 11:33 ` Krzysztof Kozlowski
2025-11-16 12:00 ` Jernej Škrabec
2025-11-16 12:07 ` Chen-Yu Tsai
2025-11-15 14:13 ` [PATCH 7/7] drm/sun4i: switch DE33 to new bindings Jernej Skrabec
2025-12-25 9:49 ` Chen-Yu Tsai
2025-12-25 19:20 ` Jernej Škrabec
2026-02-14 20:55 ` Jernej Škrabec
2026-02-15 7:13 ` Chen-Yu Tsai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2040104.PYKUYFuaPT@jernej-laptop \
--to=jernej.skrabec@gmail.com \
--cc=airlied@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sunxi@lists.linux.dev \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=mturquette@baylibre.com \
--cc=robh@kernel.org \
--cc=samuel@sholland.org \
--cc=sboyd@kernel.org \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
--cc=wens@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.