From: Liviu Dudau <liviu.dudau@arm.com>
To: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: dri-devel@lists.freedesktop.org,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Luca Ceresoli <luca.ceresoli@bootlin.com>,
Kory Maincent <kory.maincent@bootlin.com>
Subject: Re: [PATCH] drm/arm/hdlcd: Attach the output bridge directly
Date: Fri, 23 Oct 2026 13:57:26 +0100 [thread overview]
Message-ID: <attZtvw4UKx2LD2q@e142607> (raw)
In-Reply-To: <20261020130009.2017776-1-m.szyprowski@samsung.com>
On Tue, Oct 20, 2026 at 03:00:07PM +0200, Marek Szyprowski wrote:
> Since commit d700fd0ff100 ("drm/bridge: tda998x: Remove component
> support") the TDA998x driver no longer registers itself as a component,
> so the HDLCD component master never gets bound and the display stays
> dead on Juno board.
>
> Drop the component framework and get the output bridge with
> devm_drm_of_get_bridge() at probe time, deferring until it becomes
> available. Create the encoder in the HDLCD driver, attach the bridge
> with DRM_BRIDGE_ATTACH_NO_CONNECTOR and use drm_bridge_connector for
> the connector, like tilcdc does since the TDA998x component support
> removal.
>
> This also makes HDLCD work with any DRM bridge, not only TDA998x.
>
> As a side effect, interlaced modes are no longer exposed on the HDMI
> connector. The connector created by TDA998x itself always allowed them,
> while drm_bridge_connector only allows them when all bridges in the
> chain set interlace_allowed, which TDA998x does not. HDLCD has no
> interlaced scanout support, so these modes were not usable anyway.
>
> Fixes: d700fd0ff100 ("drm/bridge: tda998x: Remove component support")
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Pushed to drm-misc-next.
Best regards,
Liviu
> ---
> This patch has been developed with LLM assistance, but the results has
> been tested on the real Juno R1 board (juno-r1-scmi.dtb) with HDMI
> monitor.
>
> Bst regards
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
> ---
> drivers/gpu/drm/arm/Kconfig | 4 +-
> drivers/gpu/drm/arm/hdlcd_drv.c | 85 +++++++++++++++------------------
> drivers/gpu/drm/arm/hdlcd_drv.h | 1 +
> 3 files changed, 42 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/gpu/drm/arm/Kconfig b/drivers/gpu/drm/arm/Kconfig
> index ed3ed617c688..6dcc063aa503 100644
> --- a/drivers/gpu/drm/arm/Kconfig
> +++ b/drivers/gpu/drm/arm/Kconfig
> @@ -9,7 +9,9 @@ config DRM_HDLCD
> select DRM_CLIENT_SELECTION
> select DRM_KMS_HELPER
> select DRM_GEM_DMA_HELPER
> - select DRM_BRIDGE # for TDA998x
> + select DRM_BRIDGE
> + select DRM_BRIDGE_CONNECTOR
> + select DRM_DISPLAY_HELPER
> help
> Choose this option if you have an ARM High Definition Colour LCD
> controller.
> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> index 81d45f2dd6a7..340b1bb38bf9 100644
> --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> @@ -13,17 +13,17 @@
> #include <linux/module.h>
> #include <linux/spinlock.h>
> #include <linux/clk.h>
> -#include <linux/component.h>
> #include <linux/console.h>
> #include <linux/dma-mapping.h>
> #include <linux/list.h>
> -#include <linux/of_graph.h>
> #include <linux/of_reserved_mem.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
>
> #include <drm/clients/drm_client_setup.h>
> #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_bridge.h>
> +#include <drm/drm_bridge_connector.h>
> #include <drm/drm_crtc.h>
> #include <drm/drm_debugfs.h>
> #include <drm/drm_drv.h>
> @@ -238,12 +238,43 @@ static const struct drm_driver hdlcd_driver = {
> .minor = 0,
> };
>
> -static int hdlcd_drm_bind(struct device *dev)
> +static int hdlcd_attach_bridge(struct drm_device *drm, struct drm_bridge *bridge)
> {
> + struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
> + struct drm_connector *connector;
> + int ret;
> +
> + ret = drmm_encoder_init(drm, &hdlcd->encoder, NULL,
> + DRM_MODE_ENCODER_NONE, NULL);
> + if (ret)
> + return ret;
> +
> + hdlcd->encoder.possible_crtcs = drm_crtc_mask(&hdlcd->crtc);
> +
> + ret = drm_bridge_attach(&hdlcd->encoder, bridge, NULL,
> + DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> + if (ret)
> + return ret;
> +
> + connector = drm_bridge_connector_init(drm, &hdlcd->encoder);
> +
> + return PTR_ERR_OR_ZERO(connector);
> +}
> +
> +static int hdlcd_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> struct drm_device *drm;
> struct hdlcd_drm_private *hdlcd;
> + struct drm_bridge *bridge;
> int ret;
>
> + /* there is only one output port inside each device, find its bridge */
> + bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> + if (IS_ERR(bridge))
> + return dev_err_probe(dev, PTR_ERR(bridge),
> + "failed to find output bridge\n");
> +
> hdlcd = devm_drm_dev_alloc(dev, &hdlcd_driver, typeof(*hdlcd), base);
> if (IS_ERR(hdlcd))
> return PTR_ERR(hdlcd);
> @@ -260,12 +291,9 @@ static int hdlcd_drm_bind(struct device *dev)
> if (ret)
> goto err_free;
>
> - /* Set the CRTC's port so that the encoder component can find it */
> - hdlcd->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);
> -
> - ret = component_bind_all(dev, drm);
> + ret = hdlcd_attach_bridge(drm, bridge);
> if (ret) {
> - DRM_ERROR("Failed to bind all components\n");
> + DRM_ERROR("failed to attach bridge\n");
> goto err_unload;
> }
>
> @@ -311,10 +339,7 @@ static int hdlcd_drm_bind(struct device *dev)
> pm_runtime_disable(drm->dev);
> err_pm_active:
> drm_atomic_helper_shutdown(drm);
> - component_unbind_all(dev, drm);
> err_unload:
> - of_node_put(hdlcd->crtc.port);
> - hdlcd->crtc.port = NULL;
> hdlcd_irq_uninstall(hdlcd);
> of_reserved_mem_device_release(drm->dev);
> err_free:
> @@ -322,16 +347,14 @@ static int hdlcd_drm_bind(struct device *dev)
> return ret;
> }
>
> -static void hdlcd_drm_unbind(struct device *dev)
> +static void hdlcd_remove(struct platform_device *pdev)
> {
> + struct device *dev = &pdev->dev;
> struct drm_device *drm = dev_get_drvdata(dev);
> struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
>
> drm_dev_unregister(drm);
> drm_kms_helper_poll_fini(drm);
> - component_unbind_all(dev, drm);
> - of_node_put(hdlcd->crtc.port);
> - hdlcd->crtc.port = NULL;
> pm_runtime_get_sync(dev);
> drm_atomic_helper_shutdown(drm);
> hdlcd_irq_uninstall(hdlcd);
> @@ -342,38 +365,6 @@ static void hdlcd_drm_unbind(struct device *dev)
> dev_set_drvdata(dev, NULL);
> }
>
> -static const struct component_master_ops hdlcd_master_ops = {
> - .bind = hdlcd_drm_bind,
> - .unbind = hdlcd_drm_unbind,
> -};
> -
> -static int compare_dev(struct device *dev, void *data)
> -{
> - return dev->of_node == data;
> -}
> -
> -static int hdlcd_probe(struct platform_device *pdev)
> -{
> - struct device_node *port;
> - struct component_match *match = NULL;
> -
> - /* there is only one output port inside each device, find it */
> - port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
> - if (!port)
> - return -ENODEV;
> -
> - drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
> - of_node_put(port);
> -
> - return component_master_add_with_match(&pdev->dev, &hdlcd_master_ops,
> - match);
> -}
> -
> -static void hdlcd_remove(struct platform_device *pdev)
> -{
> - component_master_del(&pdev->dev, &hdlcd_master_ops);
> -}
> -
> static void hdlcd_shutdown(struct platform_device *pdev)
> {
> drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.h b/drivers/gpu/drm/arm/hdlcd_drv.h
> index f1c1da2ac2db..6fb48727e54e 100644
> --- a/drivers/gpu/drm/arm/hdlcd_drv.h
> +++ b/drivers/gpu/drm/arm/hdlcd_drv.h
> @@ -11,6 +11,7 @@ struct hdlcd_drm_private {
> void __iomem *mmio;
> struct clk *clk;
> struct drm_crtc crtc;
> + struct drm_encoder encoder;
> struct drm_plane *plane;
> unsigned int irq;
> #ifdef CONFIG_DEBUG_FS
> --
> 2.43.0
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
prev parent reply other threads:[~2026-10-23 12:57 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20261020130022eucas1p2564adcaa74eea27cb4b88164b385b184@eucas1p2.samsung.com>
2026-10-20 13:00 ` [PATCH] drm/arm/hdlcd: Attach the output bridge directly Marek Szyprowski
2026-10-21 12:36 ` Liviu Dudau
2026-10-23 12:57 ` Liviu Dudau [this message]
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=attZtvw4UKx2LD2q@e142607 \
--to=liviu.dudau@arm.com \
--cc=airlied@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=kory.maincent@bootlin.com \
--cc=luca.ceresoli@bootlin.com \
--cc=m.szyprowski@samsung.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
/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.