[PATCH v6 11/26] drm/bridge: samsung-dsim: use devm_drm_of_get_bridge[_by_node] to find the out_bridge

Luca Ceresoli
2025-02-06T18:15:07Z

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@linaro.org>
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>

---

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