[PATCH v2 07/10] drm/bridge: dw-hdmi: move next_bridge lookup to attach time

Luca Ceresoli posted 10 patches 1 day, 14 hours ago
[PATCH v2 07/10] drm/bridge: dw-hdmi: move next_bridge lookup to attach time
Posted by Luca Ceresoli 1 day, 14 hours ago
This driver looks up the next_bridge at probe time and stores it in
hdmi->bridge.next_bridge, but only uses the stored value when attaching,
and only in the DRM_BRIDGE_ATTACH_NO_CONNECTOR case.

This will be problematic with an upcoming change, adding an hdmi-connector
using a device tree overlay when not present. That change is in turn
necessary to migrate the i.MX LCDIF driver to the bridge-connector.

The problem is that, adding the hdmi-connector via an overlay, devlink
considers hdmi-connector a consumer of the dw-hdmi device, generating a
chicken-egg problem:

 * hdmi-connector probe won't be tried until dw-hdmi is probed (devlink)
 * dw-hdmi probe will defer until it finds the next_bridge (the
   hdmi-connector wrapper bridge)

In preparation for those changes, move the next_bridge lookup from probe to
attach, when it is actually used. This allows dw-hdmi to probe, so that the
hdmi-connector can probe as well.

Also avoid storing the pointer in hdmi->bridge.next_bridge: the value is
computed when needed, thus a local variable is enough.

Finally, this also allows to slightly improve the code by not doing any DT
lookup in the !DRM_BRIDGE_ATTACH_NO_CONNECTOR case.

Tested-by: Martyn Welch <martyn.welch@collabora.com>
Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com> # TQMa8MPxL/MBa8MPxL
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>

---

Changes in v2:
- Fix returned error codes
- Added missing cleanup.h include
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 45 +++++++++++--------------------
 1 file changed, 16 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ab1a6a8783cd..f4a1ebb79716 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -6,6 +6,8 @@
  * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
  * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
  */
+
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -2914,9 +2916,20 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
 	if (WARN_ON((flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) && !hdmi->plat_data->output_port))
 		return -EINVAL;
 
-	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
-		return drm_bridge_attach(encoder, hdmi->bridge.next_bridge,
-					 bridge, flags);
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+		struct device_node *remote __free(device_node) =
+			of_graph_get_remote_node(hdmi->dev->of_node,
+						 hdmi->plat_data->output_port, -1);
+		if (!remote)
+			return -ENODEV;
+
+		struct drm_bridge *next_bridge __free(drm_bridge_put) =
+			of_drm_find_and_get_bridge(remote);
+		if (!next_bridge)
+			return -EPROBE_DEFER;
+
+		return drm_bridge_attach(encoder, next_bridge, bridge, flags);
+	}
 
 	return dw_hdmi_connector_create(hdmi);
 }
@@ -3307,28 +3320,6 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi)
  * Probe/remove API, used from platforms based on the DRM bridge API.
  */
 
-static int dw_hdmi_parse_dt(struct dw_hdmi *hdmi)
-{
-	struct device_node *remote;
-
-	if (!hdmi->plat_data->output_port)
-		return 0;
-
-
-	remote = of_graph_get_remote_node(hdmi->dev->of_node,
-					  hdmi->plat_data->output_port,
-					  -1);
-	if (!remote)
-		return -ENODEV;
-
-	hdmi->bridge.next_bridge = of_drm_find_and_get_bridge(remote);
-	of_node_put(remote);
-	if (!hdmi->bridge.next_bridge)
-		return -EPROBE_DEFER;
-
-	return 0;
-}
-
 bool dw_hdmi_bus_fmt_is_420(struct dw_hdmi *hdmi)
 {
 	return hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format);
@@ -3373,10 +3364,6 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
 	mutex_init(&hdmi->cec_notifier_mutex);
 	spin_lock_init(&hdmi->audio_lock);
 
-	ret = dw_hdmi_parse_dt(hdmi);
-	if (ret < 0)
-		return ERR_PTR(ret);
-
 	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
 	if (ddc_node) {
 		hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);

-- 
2.53.0
Re: [PATCH v2 07/10] drm/bridge: dw-hdmi: move next_bridge lookup to attach time
Posted by Damon Ding 1 day, 2 hours ago
On 3/31/2026 3:25 AM, Luca Ceresoli wrote:
> This driver looks up the next_bridge at probe time and stores it in
> hdmi->bridge.next_bridge, but only uses the stored value when attaching,
> and only in the DRM_BRIDGE_ATTACH_NO_CONNECTOR case.
> 
> This will be problematic with an upcoming change, adding an hdmi-connector
> using a device tree overlay when not present. That change is in turn
> necessary to migrate the i.MX LCDIF driver to the bridge-connector.
> 
> The problem is that, adding the hdmi-connector via an overlay, devlink
> considers hdmi-connector a consumer of the dw-hdmi device, generating a
> chicken-egg problem:
> 
>   * hdmi-connector probe won't be tried until dw-hdmi is probed (devlink)
>   * dw-hdmi probe will defer until it finds the next_bridge (the
>     hdmi-connector wrapper bridge)
> 
> In preparation for those changes, move the next_bridge lookup from probe to
> attach, when it is actually used. This allows dw-hdmi to probe, so that the
> hdmi-connector can probe as well.
> 
> Also avoid storing the pointer in hdmi->bridge.next_bridge: the value is
> computed when needed, thus a local variable is enough.
> 
> Finally, this also allows to slightly improve the code by not doing any DT
> lookup in the !DRM_BRIDGE_ATTACH_NO_CONNECTOR case.
> 
> Tested-by: Martyn Welch <martyn.welch@collabora.com>
> Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com> # TQMa8MPxL/MBa8MPxL
> Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
> 
> ---
> 
> Changes in v2:
> - Fix returned error codes
> - Added missing cleanup.h include
> ---
>   drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 45 +++++++++++--------------------
>   1 file changed, 16 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index ab1a6a8783cd..f4a1ebb79716 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -6,6 +6,8 @@
>    * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
>    * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
>    */
> +
> +#include <linux/cleanup.h>
>   #include <linux/clk.h>
>   #include <linux/delay.h>
>   #include <linux/err.h>
> @@ -2914,9 +2916,20 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
>   	if (WARN_ON((flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) && !hdmi->plat_data->output_port))
>   		return -EINVAL;
>   
> -	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
> -		return drm_bridge_attach(encoder, hdmi->bridge.next_bridge,
> -					 bridge, flags);
> +	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
> +		struct device_node *remote __free(device_node) =
> +			of_graph_get_remote_node(hdmi->dev->of_node,
> +						 hdmi->plat_data->output_port, -1);
> +		if (!remote)
> +			return -ENODEV;
> +
> +		struct drm_bridge *next_bridge __free(drm_bridge_put) =
> +			of_drm_find_and_get_bridge(remote);
> +		if (!next_bridge)
> +			return -EPROBE_DEFER;
> +
> +		return drm_bridge_attach(encoder, next_bridge, bridge, flags);
> +	}
>   
>   	return dw_hdmi_connector_create(hdmi);
>   }
> @@ -3307,28 +3320,6 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi)
>    * Probe/remove API, used from platforms based on the DRM bridge API.
>    */
>   
> -static int dw_hdmi_parse_dt(struct dw_hdmi *hdmi)
> -{
> -	struct device_node *remote;
> -
> -	if (!hdmi->plat_data->output_port)
> -		return 0;
> -
> -
> -	remote = of_graph_get_remote_node(hdmi->dev->of_node,
> -					  hdmi->plat_data->output_port,
> -					  -1);
> -	if (!remote)
> -		return -ENODEV;
> -
> -	hdmi->bridge.next_bridge = of_drm_find_and_get_bridge(remote);
> -	of_node_put(remote);
> -	if (!hdmi->bridge.next_bridge)
> -		return -EPROBE_DEFER;
> -
> -	return 0;
> -}
> -
>   bool dw_hdmi_bus_fmt_is_420(struct dw_hdmi *hdmi)
>   {
>   	return hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format);
> @@ -3373,10 +3364,6 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
>   	mutex_init(&hdmi->cec_notifier_mutex);
>   	spin_lock_init(&hdmi->audio_lock);
>   
> -	ret = dw_hdmi_parse_dt(hdmi);
> -	if (ret < 0)
> -		return ERR_PTR(ret);
> -
>   	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
>   	if (ddc_node) {
>   		hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
> 

Tested-by: Damon Ding <damon.ding@rock-chips.com> (on rk3399)

Best regards,
Damon