* function in fact searches the corresponding engine, and the ID is
  * requested via the get_id function of the engine.
  */
-static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
-                                                  struct device_node *node)
+static struct sunxi_engine *
+sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
+                               struct device_node *node)
 {
        struct device_node *port, *ep, *remote;
        struct sunxi_engine *engine;
                }
 
                /* keep looking through upstream ports */
-               engine = sun4i_tcon_find_engine(drv, remote);
+               engine = sun4i_tcon_find_engine_traverse(drv, remote);
                if (!IS_ERR(engine)) {
                        of_node_put(remote);
                        of_node_put(port);
        return ERR_PTR(-EINVAL);
 }
 
+/*
+ * The device tree binding says that the remote endpoint ID of any
+ * connection between components, up to and including the TCON, of
+ * the display pipeline should be equal to the actual ID of the local
+ * component. Thus we can look at any one of the input connections of
+ * the TCONs, and use that connection's remote endpoint ID as our own.
+ *
+ * Since the user of this function already finds the input port,
+ * the port is passed in directly without further checks.
+ */
+static int sun4i_tcon_of_get_id_from_port(struct device_node *port)
+{
+       struct device_node *ep;
+       int ret = -EINVAL;
+
+       /* try finding an upstream endpoint */
+       for_each_available_child_of_node(port, ep) {
+               struct device_node *remote;
+               u32 reg;
+
+               remote = of_graph_get_remote_endpoint(ep);
+               if (!remote)
+                       continue;
+
+               ret = of_property_read_u32(remote, "reg", ®);
+               if (ret)
+                       continue;
+
+               ret = reg;
+       }
+
+       return ret;
+}
+
+/*
+ * Once we know the TCON's id, we can look through the list of
+ * engines to find a matching one. We assume all engines have
+ * been probed and added to the list.
+ */
+static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv,
+                                                       int id)
+{
+       struct sunxi_engine *engine;
+
+       list_for_each_entry(engine, &drv->engine_list, list)
+               if (engine->id == id)
+                       return engine;
+
+       return ERR_PTR(-EINVAL);
+}
+
+/*
+ * On SoCs with the old display pipeline design (Display Engine 1.0),
+ * we assumed the TCON was always tied to just one backend. However
+ * this proved not to be the case. On the A31, the TCON can select
+ * either backend as its source. On the A20 (and likely on the A10),
+ * the backend can choose which TCON to output to.
+ *
+ * The device tree binding says that the remote endpoint ID of any
+ * connection between components, up to and including the TCON, of
+ * the display pipeline should be equal to the actual ID of the local
+ * component. Thus we should be able to look at any one of the input
+ * connections of the TCONs, and use that connection's remote endpoint
+ * ID as our own.
+ *
+ * However  the connections between the backend and TCON were assumed
+ * to be always singular, and their endpoit IDs were all incorrectly
+ * set to 0. This means for these old device trees, we cannot just look
+ * up the remote endpoint ID of a TCON input endpoint. TCON1 would be
+ * incorrectly identified as TCON0.
+ *
+ * This function first checks if the TCON node has 2 input endpoints.
+ * If so, then the device tree is a corrected version, and it will use
+ * sun4i_tcon_of_get_id() and sun4i_tcon_get_engine_by_id() from above
+ * to fetch the ID and engine directly. If not, then it is likely an
+ * old device trees, where the endpoint IDs were incorrect, but did not
+ * have endpoint connections between the backend and TCON across
+ * different display pipelines. It will fall back to the old method of
+ * traversing the  of_graph to try and find a matching engine by device
+ * node.
+ *
+ * In the case of single display pipeline device trees, either method
+ * works.
+ */
+static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
+                                                  struct device_node *node)
+{
+       struct device_node *port;
+       struct sunxi_engine *engine;
+
+       port = of_graph_get_port_by_id(node, 0);
+       if (!port)
+               return ERR_PTR(-EINVAL);
+
+       /*
+        * Is this a corrected device tree with cross pipeline
+        * connections between the backend and TCON?
+        */
+       if (of_get_child_count(port) > 1) {
+               /* Get our ID directly from an upstream endpoint */
+               int id = sun4i_tcon_of_get_id_from_port(port);
+
+               /* Get our engine by matching our ID */
+               engine = sun4i_tcon_get_engine_by_id(drv, id);
+
+               of_node_put(port);
+               return engine;
+       }
+
+       /* Fallback to old method by traversing input endpoints */
+       of_node_put(port);
+       return sun4i_tcon_find_engine_traverse(drv, node);
+}
+
 static int sun4i_tcon_bind(struct device *dev, struct device *master,
                           void *data)
 {