summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChen-Yu Tsai <wens@csie.org>2017-09-08 15:50:11 +0800
committerMaxime Ripard <maxime.ripard@free-electrons.com>2017-09-09 17:24:01 +0200
commit1469619d29d752759a2c9604a74091f92757830a (patch)
tree240da78970c002cf74673e7b9090a9e0a8230915 /drivers
parentda82b8785eebb2a97daa0164ccdfaa85361c237f (diff)
downloadlinux-1469619d29d752759a2c9604a74091f92757830a.tar.bz2
drm/sun4i: tcon: Check for multiple paths between TCONs and backends
The patch b317fa3ba11a ("drm/sun4i: tcon: Find matching display backend by device node matching") assumed a one-to-one mapping between TCONs and backends. This turned out wrong, as we found muxing controls in the TCON of the A31, and undocumented usage of the backend output selector of the A20. Make sun4i_tcon_find_engine() bail out if the current node has multiple input connections. Fixes: b317fa3ba11a ("drm/sun4i: tcon: Find matching display backend by device node matching") Signed-off-by: Chen-Yu Tsai <wens@csie.org> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Link: https://patchwork.freedesktop.org/patch/msgid/20170908075016.18657-4-wens@csie.org
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 36cf1a0acc65..79d8a0319e71 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -473,6 +473,20 @@ static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
if (!port)
return ERR_PTR(-EINVAL);
+ /*
+ * This only works if there is only one path from the TCON
+ * to any display engine. Otherwise the probe order of the
+ * TCONs and display engines is not guaranteed. They may
+ * either bind to the wrong one, or worse, bind to the same
+ * one if additional checks are not done.
+ *
+ * Bail out if there are multiple input connections.
+ */
+ if (of_get_available_child_count(port) != 1) {
+ of_node_put(port);
+ return ERR_PTR(-EINVAL);
+ }
+
for_each_available_child_of_node(port, ep) {
remote = of_graph_get_remote_port_parent(ep);
if (!remote)