Skip to content

Commit 67bae5f

Browse files
paulkocialkowskimripard
authored andcommitted
drm: of: Properly try all possible cases for bridge/panel detection
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@bootlin.com> Fixes: 8025316 ("drm: of: Lookup if child node has panel or bridge") Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20220329132732.628474-1-paul.kocialkowski@bootlin.com
1 parent c42ee39 commit 67bae5f

1 file changed

Lines changed: 50 additions & 49 deletions

File tree

drivers/gpu/drm/drm_of.c

Lines changed: 50 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,29 @@ int drm_of_encoder_active_endpoint(struct device_node *node,
219219
}
220220
EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint);
221221

222+
static int find_panel_or_bridge(struct device_node *node,
223+
struct drm_panel **panel,
224+
struct drm_bridge **bridge)
225+
{
226+
if (panel) {
227+
*panel = of_drm_find_panel(node);
228+
if (!IS_ERR(*panel))
229+
return 0;
230+
231+
/* Clear the panel pointer in case of error. */
232+
*panel = NULL;
233+
}
234+
235+
/* No panel found yet, check for a bridge next. */
236+
if (bridge) {
237+
*bridge = of_drm_find_bridge(node);
238+
if (*bridge)
239+
return 0;
240+
}
241+
242+
return -EPROBE_DEFER;
243+
}
244+
222245
/**
223246
* drm_of_find_panel_or_bridge - return connected panel or bridge device
224247
* @np: device tree node containing encoder output ports
@@ -241,66 +264,44 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
241264
struct drm_panel **panel,
242265
struct drm_bridge **bridge)
243266
{
244-
int ret = -EPROBE_DEFER;
245-
struct device_node *remote;
267+
struct device_node *node;
268+
int ret;
246269

247270
if (!panel && !bridge)
248271
return -EINVAL;
272+
249273
if (panel)
250274
*panel = NULL;
251-
252-
/**
253-
* Devices can also be child nodes when we also control that device
254-
* through the upstream device (ie, MIPI-DCS for a MIPI-DSI device).
255-
*
256-
* Lookup for a child node of the given parent that isn't either port
257-
* or ports.
258-
*/
259-
for_each_available_child_of_node(np, remote) {
260-
if (of_node_name_eq(remote, "port") ||
261-
of_node_name_eq(remote, "ports"))
262-
continue;
263-
264-
goto of_find_panel_or_bridge;
275+
if (bridge)
276+
*bridge = NULL;
277+
278+
/* Check for a graph on the device node first. */
279+
if (of_graph_is_present(np)) {
280+
node = of_graph_get_remote_node(np, port, endpoint);
281+
if (node) {
282+
ret = find_panel_or_bridge(node, panel, bridge);
283+
of_node_put(node);
284+
285+
if (!ret)
286+
return 0;
287+
}
265288
}
266289

267-
/*
268-
* of_graph_get_remote_node() produces a noisy error message if port
269-
* node isn't found and the absence of the port is a legit case here,
270-
* so at first we silently check whether graph presents in the
271-
* device-tree node.
272-
*/
273-
if (!of_graph_is_present(np))
274-
return -ENODEV;
275-
276-
remote = of_graph_get_remote_node(np, port, endpoint);
277-
278-
of_find_panel_or_bridge:
279-
if (!remote)
280-
return -ENODEV;
290+
/* Otherwise check for any child node other than port/ports. */
291+
for_each_available_child_of_node(np, node) {
292+
if (of_node_name_eq(node, "port") ||
293+
of_node_name_eq(node, "ports"))
294+
continue;
281295

282-
if (panel) {
283-
*panel = of_drm_find_panel(remote);
284-
if (!IS_ERR(*panel))
285-
ret = 0;
286-
else
287-
*panel = NULL;
288-
}
289-
290-
/* No panel found yet, check for a bridge next. */
291-
if (bridge) {
292-
if (ret) {
293-
*bridge = of_drm_find_bridge(remote);
294-
if (*bridge)
295-
ret = 0;
296-
} else {
297-
*bridge = NULL;
298-
}
296+
ret = find_panel_or_bridge(node, panel, bridge);
297+
of_node_put(node);
299298

299+
/* Stop at the first found occurrence. */
300+
if (!ret)
301+
return 0;
300302
}
301303

302-
of_node_put(remote);
303-
return ret;
304+
return -EPROBE_DEFER;
304305
}
305306
EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge);
306307

0 commit comments

Comments
 (0)