In order to support panels described either via graph links or via a subnode (e.g. "panel@0"), this driver uses low-level deprecated functions to find the next bridge. The resulting logic is complex and duplicates code already present in the DRM bridge core. Switch to the new APIs in DRM bridge core that allow to do the same in a much cleaner way. Note there are two slight changes in the new logic intended to improve the final result: * the old code looks for a subnode with any name except "port" or "ports", while the new code uses the node passed as a parameter * the old code looks for a subnode first and falls back to a graph link, while the new code uses the reverse order because graph links are the recommended device tree representation now The first change makes the code more robust by avoiding the risk of using an unrelated node which is not describing a panel and not names "port" or "ports". The second change is not expected to expose regressions because, in the cases where both a subnode and a graph link are used to describe a panel, the graph link should point to the subnode itself, such as in arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts As a further cleanup, use a temporary variable to assign dsi->out_bridge only on success. This avoids the risk of leaving a non-NULL value in dsi->out_bridge when samsung_dsim_host_attach() fails. Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx> Signed-off-by: Luca Ceresoli <luca.ceresoli@xxxxxxxxxxx> --- This patch was added in v6. --- drivers/gpu/drm/bridge/samsung-dsim.c | 55 ++++++----------------------------- 1 file changed, 9 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index f8b4fb8357659018ec0db65374ee5d05330639ae..bbd0a4f5a3f52b61bf48f10d6e8ca741bffa5e46 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1704,55 +1704,16 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host, const struct samsung_dsim_plat_data *pdata = dsi->plat_data; struct device *dev = dsi->dev; struct device_node *np = dev->of_node; - struct device_node *remote; - struct drm_panel *panel; + struct drm_bridge *out_bridge; int ret; - /* - * Devices can also be child nodes when we also control that device - * through the upstream device (ie, MIPI-DCS for a MIPI-DSI device). - * - * Lookup for a child node of the given parent that isn't either port - * or ports. - */ - for_each_available_child_of_node(np, remote) { - if (of_node_name_eq(remote, "port") || - of_node_name_eq(remote, "ports")) - continue; + out_bridge = devm_drm_of_get_bridge(dev, np, 1, 0); + if (IS_ERR(out_bridge) && PTR_ERR(out_bridge) != -EPROBE_DEFER) + out_bridge = devm_drm_of_get_bridge_by_node(dev, device->dev.of_node); - goto of_find_panel_or_bridge; - } - - /* - * of_graph_get_remote_node() produces a noisy error message if port - * node isn't found and the absence of the port is a legit case here, - * so at first we silently check whether graph presents in the - * device-tree node. - */ - if (!of_graph_is_present(np)) - return -ENODEV; - - remote = of_graph_get_remote_node(np, 1, 0); - -of_find_panel_or_bridge: - if (!remote) - return -ENODEV; - - panel = of_drm_find_panel(remote); - if (!IS_ERR(panel)) { - dsi->out_bridge = devm_drm_panel_bridge_add(dev, panel); - } else { - dsi->out_bridge = of_drm_find_bridge(remote); - if (!dsi->out_bridge) - dsi->out_bridge = ERR_PTR(-EINVAL); - } - - of_node_put(remote); - - if (IS_ERR(dsi->out_bridge)) { - ret = PTR_ERR(dsi->out_bridge); - DRM_DEV_ERROR(dev, "failed to find the bridge: %d\n", ret); - return ret; + if (IS_ERR(out_bridge)) { + DRM_DEV_ERROR(dev, "failed to find the bridge: %ld\n", PTR_ERR(out_bridge)); + return PTR_ERR(out_bridge); } DRM_DEV_INFO(dev, "Attached %s device (lanes:%d bpp:%d mode-flags:0x%lx)\n", @@ -1784,6 +1745,8 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host, dsi->format = device->format; dsi->mode_flags = device->mode_flags; + dsi->out_bridge = out_bridge; + return 0; } -- 2.34.1