summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 9bfb5b967d38..8b3ca1e83f26 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -36,6 +36,7 @@
#include "sun4i_rgb.h"
#include "sun4i_tcon.h"
#include "sun6i_mipi_dsi.h"
+#include "sun8i_tcon_top.h"
#include "sunxi_engine.h"
static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
@@ -908,6 +909,36 @@ static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv,
return ERR_PTR(-EINVAL);
}
+static bool sun4i_tcon_connected_to_tcon_top(struct device_node *node)
+{
+ struct device_node *remote;
+ bool ret = false;
+
+ remote = of_graph_get_remote_node(node, 0, -1);
+ if (remote) {
+ ret = !!of_match_node(sun8i_tcon_top_of_table, remote);
+ of_node_put(remote);
+ }
+
+ return ret;
+}
+
+static int sun4i_tcon_get_index(struct sun4i_drv *drv)
+{
+ struct list_head *pos;
+ int size = 0;
+
+ /*
+ * Because TCON is added to the list at the end of the probe
+ * (after this function is called), index of the current TCON
+ * will be same as current TCON list size.
+ */
+ list_for_each(pos, &drv->tcon_list)
+ ++size;
+
+ return size;
+}
+
/*
* On SoCs with the old display pipeline design (Display Engine 1.0),
* we assumed the TCON was always tied to just one backend. However
@@ -956,8 +987,24 @@ static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
* 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);
+ int id;
+
+ /*
+ * When pipeline has the same number of TCONs and engines which
+ * are represented by frontends/backends (DE1) or mixers (DE2),
+ * we match them by their respective IDs. However, if pipeline
+ * contains TCON TOP, chances are that there are either more
+ * TCONs than engines (R40) or TCONs with non-consecutive ids.
+ * (H6). In that case it's easier just use TCON index in list
+ * as an id. That means that on R40, any 2 TCONs can be enabled
+ * in DT out of 4 (there are 2 mixers). Due to the design of
+ * TCON TOP, remaining 2 TCONs can't be connected to anything
+ * anyway.
+ */
+ if (sun4i_tcon_connected_to_tcon_top(node))
+ id = sun4i_tcon_get_index(drv);
+ else
+ 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);