drm/bridge: dw-hdmi: move next_bridge lookup to attach time

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
Acked-by: Liu Ying <victor.liu@nxp.com>
Tested-by: Damon Ding <damon.ding@rock-chips.com> # rk3399
Link: https://patch.msgid.link/20260407-drm-lcdif-dbanc-v4-7-247a16e61ef9@bootlin.com
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
This commit is contained in:
Luca Ceresoli 2026-04-07 14:24:21 +02:00
parent 5316b7464c
commit 91938b4fdc

View File

@ -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);