From: Patrice CHOTARD <patrice.chotard@foss.st.com>
To: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>,
Tom Rini <trini@konsulko.com>,
Kamil Lulko <kamil.lulko@gmail.com>,
Dillon Min <dillon.minfei@gmail.com>,
Patrick Delaunay <patrick.delaunay@foss.st.com>,
Anatolij Gustschin <ag.dev.uboot@gmail.com>,
Simon Glass <sjg@chromium.org>,
Sumit Garg <sumit.garg@kernel.org>
Cc: <u-boot@lists.denx.de>, <uboot-stm32@st-md-mailman.stormreply.com>
Subject: Re: [PATCH 5/8] video: stm32: ltdc: properly search the first available panel
Date: Mon, 25 Aug 2025 15:47:07 +0200 [thread overview]
Message-ID: <a268f0fb-8233-4a4c-ac96-5e2b263da43d@foss.st.com> (raw)
In-Reply-To: <20250820-master-v1-5-fc76f18ab2fd@foss.st.com>
On 8/20/25 18:17, Raphael Gallais-Pou wrote:
> Initially there was only one DSI bridge with one panel attached to this
> device. This explained the call to uclass_first_device_err(UCLASS_PANEL,
> ...) which worked fine at the time.
>
> Now that multiple bridges and panels, with different technologies, can
> be plugged onto the board this way to get the panel device is outdated.
>
> The lookup is done is two steps. First we cirle through the
typo /cirle/circle
With this typo fixed, you add my Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>
Thanks
> UCLASS_VIDEO_BRIDGE, and once we get one, we search through its
> endpoints until we get a UCLASS_PANEL device available.
>
> Signed-off-by: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
> ---
> drivers/video/stm32/stm32_ltdc.c | 136 +++++++++++++++++++++++++++++++++++----
> 1 file changed, 125 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c
> index d9ba5c4ef53558fe8b5565d47b022699d9e4ea0e..cdcfde678fb59ad884125e7c26f43710d76ba246 100644
> --- a/drivers/video/stm32/stm32_ltdc.c
> +++ b/drivers/video/stm32/stm32_ltdc.c
> @@ -17,6 +17,7 @@
> #include <video_bridge.h>
> #include <asm/io.h>
> #include <dm/device-internal.h>
> +#include <dm/uclass-internal.h>
> #include <dm/device_compat.h>
> #include <linux/bitops.h>
> #include <linux/printk.h>
> @@ -495,6 +496,101 @@ static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr)
> setbits_le32(priv->regs + LTDC_L1CR, LXCR_LEN);
> }
>
> +static int stm32_ltdc_get_remote_device(struct udevice *dev, ofnode ep_node,
> + enum uclass_id id, struct udevice **remote_dev)
> +{
> + u32 remote_phandle;
> + ofnode remote;
> + int ret = 0;
> +
> + ret = ofnode_read_u32(ep_node, "remote-endpoint", &remote_phandle);
> + if (ret) {
> + dev_err(dev, "%s(%s): Could not find remote-endpoint property\n",
> + __func__, dev_read_name(dev));
> + return ret;
> + }
> +
> + remote = ofnode_get_by_phandle(remote_phandle);
> + if (!ofnode_valid(remote))
> + return -EINVAL;
> +
> + while (ofnode_valid(remote)) {
> + remote = ofnode_get_parent(remote);
> + if (!ofnode_valid(remote)) {
> + dev_dbg(dev, "%s(%s): no uclass_id %d for remote-endpoint\n",
> + __func__, dev_read_name(dev), id);
> + continue;
> + }
> +
> + ret = uclass_find_device_by_ofnode(id, remote, remote_dev);
> + if (*remote_dev && !ret) {
> + ret = uclass_get_device_by_ofnode(id, remote, remote_dev);
> + if (ret)
> + dev_dbg(dev, "%s(%s): failed to get remote device %s\n",
> + __func__, dev_read_name(dev), dev_read_name(*remote_dev));
> + break;
> + }
> + };
> +
> + return ret;
> +}
> +
> +static int stm32_ltdc_get_panel(struct udevice *dev, struct udevice **panel)
> +{
> + ofnode ep_node, node, ports;
> + int ret = 0;
> +
> + if (!dev)
> + return -EINVAL;
> +
> + ports = ofnode_find_subnode(dev_ofnode(dev), "ports");
> + if (!ofnode_valid(ports)) {
> + dev_err(dev, "Remote bridge subnode\n");
> + return ret;
> + }
> +
> + for (node = ofnode_first_subnode(ports);
> + ofnode_valid(node);
> + node = dev_read_next_subnode(node)) {
> + ep_node = ofnode_first_subnode(node);
> + if (!ofnode_valid(ep_node))
> + continue;
> +
> + ret = stm32_ltdc_get_remote_device(dev, ep_node, UCLASS_PANEL, panel);
> + }
> +
> + /* Sanity check, we can get out of the loop without having a clean ofnode */
> + if (!(*panel))
> + ret = -EINVAL;
> + else
> + if (!ofnode_valid(dev_ofnode(*panel)))
> + ret = -EINVAL;
> +
> + return ret;
> +}
> +
> +static int stm32_ltdc_display_init(struct udevice *dev, ofnode *ep_node,
> + struct udevice **panel, struct udevice **bridge)
> +{
> + int ret;
> +
> + if (*panel)
> + return -EINVAL;
> +
> + if (IS_ENABLED(CONFIG_VIDEO_BRIDGE)) {
> + ret = stm32_ltdc_get_remote_device(dev, *ep_node, UCLASS_VIDEO_BRIDGE, bridge);
> + if (ret)
> + return ret;
> +
> + ret = stm32_ltdc_get_panel(*bridge, panel);
> + } else {
> + /* no bridge, search a panel from display controller node */
> + ret = stm32_ltdc_get_remote_device(dev, *ep_node, UCLASS_PANEL, panel);
> + }
> +
> + return ret;
> +}
> +
> #if IS_ENABLED(CONFIG_TARGET_STM32F469_DISCOVERY)
> static int stm32_ltdc_alloc_fb(struct udevice *dev)
> {
> @@ -532,6 +628,7 @@ static int stm32_ltdc_probe(struct udevice *dev)
> struct display_timing timings;
> struct clk pclk, bclk;
> struct reset_ctl rst;
> + ofnode node, port;
> ulong rate;
> int ret;
>
> @@ -568,7 +665,7 @@ static int stm32_ltdc_probe(struct udevice *dev)
> }
>
> priv->hw_version = readl(priv->regs + LTDC_IDR);
> - debug("%s: LTDC hardware 0x%x\n", __func__, priv->hw_version);
> + dev_dbg(dev, "%s: LTDC hardware 0x%x\n", __func__, priv->hw_version);
>
> switch (priv->hw_version) {
> case HWVER_10200:
> @@ -589,13 +686,35 @@ static int stm32_ltdc_probe(struct udevice *dev)
> return -ENODEV;
> }
>
> - ret = uclass_first_device_err(UCLASS_PANEL, &panel);
> - if (ret) {
> - if (ret != -ENODEV)
> - dev_err(dev, "panel device error %d\n", ret);
> - return ret;
> + /*
> + * Try all the ports until one working.
> + *
> + * This is done in two times. First is checks for the
> + * UCLASS_VIDEO_BRIDGE available, and then for this bridge
> + * it scans for a UCLASS_PANEL.
> + */
> +
> + port = dev_read_subnode(dev, "port");
> + if (!ofnode_valid(port)) {
> + dev_err(dev, "%s(%s): 'port' subnode not found\n",
> + __func__, dev_read_name(dev));
> + return -EINVAL;
> }
>
> + for (node = ofnode_first_subnode(port);
> + ofnode_valid(node);
> + node = dev_read_next_subnode(node)) {
> + ret = stm32_ltdc_display_init(dev, &node, &panel, &bridge);
> + if (ret)
> + dev_dbg(dev, "Device failed ret=%d\n", ret);
> + else
> + break;
> + }
> +
> + /* Sanity check */
> + if (ret)
> + return ret;
> +
> ret = panel_get_display_timing(panel, &timings);
> if (ret) {
> ret = ofnode_decode_display_timing(dev_ofnode(panel),
> @@ -624,11 +743,6 @@ static int stm32_ltdc_probe(struct udevice *dev)
> reset_deassert(&rst);
>
> if (IS_ENABLED(CONFIG_VIDEO_BRIDGE)) {
> - ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &bridge);
> - if (ret)
> - dev_dbg(dev,
> - "No video bridge, or no backlight on bridge\n");
> -
> if (bridge) {
> ret = video_bridge_attach(bridge);
> if (ret) {
>
next prev parent reply other threads:[~2025-08-25 13:49 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-20 16:17 [PATCH 0/8] Add display support for STM32MP25 Raphael Gallais-Pou
2025-08-20 16:17 ` [PATCH 1/8] ofnode: support panel-timings in ofnode_decode_display_timing Raphael Gallais-Pou
2025-08-25 7:48 ` Patrice CHOTARD
2025-08-20 16:17 ` [PATCH 2/8] video: simple_panel: add support for "panel-lvds" display Raphael Gallais-Pou
2025-08-25 7:49 ` Patrice CHOTARD
2025-08-20 16:17 ` [PATCH 3/8] video: stm32: STM32 driver support for LVDS Raphael Gallais-Pou
2025-08-25 9:42 ` Patrice CHOTARD
2025-08-25 14:50 ` Raphael Gallais-Pou
2025-08-20 16:17 ` [PATCH 4/8] video: stm32: ltdc: support new hardware version for STM32MP25 SoC Raphael Gallais-Pou
2025-08-25 9:48 ` Patrice CHOTARD
2025-08-20 16:17 ` [PATCH 5/8] video: stm32: ltdc: properly search the first available panel Raphael Gallais-Pou
2025-08-25 13:47 ` Patrice CHOTARD [this message]
2025-08-20 16:17 ` [PATCH 6/8] ARM: dts: stm32: use LTDC and LVDS nodes before relocation in stm32mp25-u-boot Raphael Gallais-Pou
2025-08-25 13:48 ` Patrice CHOTARD
2025-08-20 16:17 ` [PATCH 7/8] ARM: dts: stm32: remove panel property in stm32mp257f-ev1-u-boot Raphael Gallais-Pou
2025-08-25 13:54 ` Patrice CHOTARD
2025-08-26 12:00 ` Raphael Gallais-Pou
2025-08-20 16:17 ` [PATCH 8/8] configs: stm32mp25: enable LVDS display support Raphael Gallais-Pou
2025-08-25 13:49 ` Patrice CHOTARD
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=a268f0fb-8233-4a4c-ac96-5e2b263da43d@foss.st.com \
--to=patrice.chotard@foss.st.com \
--cc=ag.dev.uboot@gmail.com \
--cc=dillon.minfei@gmail.com \
--cc=kamil.lulko@gmail.com \
--cc=patrick.delaunay@foss.st.com \
--cc=raphael.gallais-pou@foss.st.com \
--cc=sjg@chromium.org \
--cc=sumit.garg@kernel.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
--cc=uboot-stm32@st-md-mailman.stormreply.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox