[PATCH] drm: of: Properly try all possible cases for bridge/panel detection
Paul Kocialkowski
paul.kocialkowski at bootlin.com
Wed Mar 9 14:32:00 UTC 2022
While bridge/panel detection was initially relying on the usual
port/ports-based of graph detection, it was recently changed to
perform the lookup on any child node that is not port/ports
instead when such a node is available, with no fallback on the
usual way.
This results in breaking detection when a child node is present
but does not contain any panel or bridge node, even when the
usual port/ports-based of graph is there.
In order to support both situations properly, this commit reworks
the logic to try both options and not just one of the two: it will
only return -EPROBE_DEFER when both have failed.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski at bootlin.com>
Fixes: 80253168dbfd ("drm: of: Lookup if child node has panel or bridge")
---
drivers/gpu/drm/drm_of.c | 93 +++++++++++++++++++++-------------------
1 file changed, 49 insertions(+), 44 deletions(-)
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 9d90cd75c457..67f1b7dfc892 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -219,6 +219,35 @@ int drm_of_encoder_active_endpoint(struct device_node *node,
}
EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint);
+static int drm_of_find_remote_panel_or_bridge(struct device_node *remote,
+ struct drm_panel **panel,
+ struct drm_bridge **bridge)
+{
+ int ret = -EPROBE_DEFER;
+
+ if (panel) {
+ *panel = of_drm_find_panel(remote);
+ if (!IS_ERR(*panel))
+ ret = 0;
+ else
+ *panel = NULL;
+ }
+
+ /* No panel found yet, check for a bridge next. */
+ if (bridge) {
+ if (ret) {
+ *bridge = of_drm_find_bridge(remote);
+ if (*bridge)
+ ret = 0;
+ } else {
+ *bridge = NULL;
+ }
+
+ }
+
+ return ret;
+}
+
/**
* drm_of_find_panel_or_bridge - return connected panel or bridge device
* @np: device tree node containing encoder output ports
@@ -249,57 +278,33 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
if (panel)
*panel = NULL;
- /**
- * 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;
-
- goto of_find_panel_or_bridge;
+ /* Check for a graph on the device node first. */
+ if (of_graph_is_present(np)) {
+ remote = of_graph_get_remote_node(np, port, endpoint);
+ if (remote) {
+ ret = drm_of_find_remote_panel_or_bridge(remote, panel,
+ bridge);
+ of_node_put(remote);
+ }
}
- /*
- * 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, port, endpoint);
-
-of_find_panel_or_bridge:
- if (!remote)
- return -ENODEV;
+ /* Otherwise check for any child node other than port/ports. */
+ if (ret) {
+ for_each_available_child_of_node(np, remote) {
+ if (of_node_name_eq(remote, "port") ||
+ of_node_name_eq(remote, "ports"))
+ continue;
- if (panel) {
- *panel = of_drm_find_panel(remote);
- if (!IS_ERR(*panel))
- ret = 0;
- else
- *panel = NULL;
- }
+ ret = drm_of_find_remote_panel_or_bridge(remote, panel,
+ bridge);
+ of_node_put(remote);
- /* No panel found yet, check for a bridge next. */
- if (bridge) {
- if (ret) {
- *bridge = of_drm_find_bridge(remote);
- if (*bridge)
- ret = 0;
- } else {
- *bridge = NULL;
+ /* Stop at the first found occurrence. */
+ if (!ret)
+ break;
}
-
}
- of_node_put(remote);
return ret;
}
EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge);
--
2.35.1
More information about the dri-devel
mailing list