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.

Signed-off-by: Luca Ceresoli <[email protected]>
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 41 +++++++++----------------------
 1 file changed, 12 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a668d66aeece..4ee865a1a6c8 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2914,9 +2914,18 @@ 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 -EPROBE_DEFER;
+
+               struct drm_bridge *next_bridge __free(drm_bridge_put) =
+                       of_drm_find_and_get_bridge(remote);
+
+               return drm_bridge_attach(encoder, next_bridge, bridge, flags);
+       }
 
        return dw_hdmi_connector_create(hdmi);
 }
@@ -3307,28 +3316,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 +3360,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

Reply via email to