summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/sun4i/sun4i_tcon.c
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2016-04-11 12:16:33 +0200
committerMaxime Ripard <maxime.ripard@free-electrons.com>2016-08-22 15:34:18 +0200
commit894f5a9f4b4aaf154fce121d80199a2e2146d6d1 (patch)
tree8600f72ea7a22ec8a62fa1ad4a24317a8a0fe23c /drivers/gpu/drm/sun4i/sun4i_tcon.c
parenta8444c7ee2c02b567731a6edcd5d328f85aac1b1 (diff)
drm/sun4i: Add bridge support
Our RGB bus can be either connected to a bridge or a panel. While the panel support was already there, the bridge was not. Fix that. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun4i_tcon.c')
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index d2f7489d29a5..2145ecf2cf5d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -432,6 +432,40 @@ struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
}
+struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node)
+{
+ struct device_node *port, *remote, *child;
+ struct device_node *end_node = NULL;
+
+ /* Inputs are listed first, then outputs */
+ port = of_graph_get_port_by_id(node, 1);
+
+ /*
+ * Our first output is the RGB interface where the panel will
+ * be connected.
+ */
+ for_each_child_of_node(port, child) {
+ u32 reg;
+
+ of_property_read_u32(child, "reg", &reg);
+ if (reg == 0)
+ end_node = child;
+ }
+
+ if (!end_node) {
+ DRM_DEBUG_DRIVER("Missing bridge endpoint\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ remote = of_graph_get_remote_port_parent(end_node);
+ if (!remote) {
+ DRM_DEBUG_DRIVER("Enable to parse remote node\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return of_drm_find_bridge(remote) ?: ERR_PTR(-EPROBE_DEFER);
+}
+
static int sun4i_tcon_bind(struct device *dev, struct device *master,
void *data)
{
@@ -514,19 +548,22 @@ static struct component_ops sun4i_tcon_ops = {
static int sun4i_tcon_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
+ struct drm_bridge *bridge;
struct drm_panel *panel;
/*
- * The panel is not ready.
+ * Neither the bridge or the panel is ready.
* Defer the probe.
*/
panel = sun4i_tcon_find_panel(node);
+ bridge = sun4i_tcon_find_bridge(node);
/*
* If we don't have a panel endpoint, just go on
*/
- if (PTR_ERR(panel) == -EPROBE_DEFER) {
- DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
+ if ((PTR_ERR(panel) == -EPROBE_DEFER) &&
+ (PTR_ERR(bridge) == -EPROBE_DEFER)) {
+ DRM_DEBUG_DRIVER("Still waiting for our panel/bridge. Deferring...\n");
return -EPROBE_DEFER;
}