From: Huang Jiachai <hjc@rock-chips.com>
Date: Mon, 31 Jul 2017 11:53:15 +0000 (+0800)
Subject: drm/rockchip: get connector in bridge mode
X-Git-Tag: release-20171130_firefly~4^2~35
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c4e97a6379969d3ee5564ba651a5213468437b65;p=firefly-linux-kernel-4.4.55.git

drm/rockchip: get connector in bridge mode

Change-Id: I08535f5c2d83783dc86ae641daeb530dedec36e6
Signed-off-by: Huang Jiachai <hjc@rock-chips.com>
---

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 76151586df6e..bc42cbc77bdb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -106,6 +106,74 @@ static struct drm_connector *find_connector_by_node(struct drm_device *drm_dev,
 	return NULL;
 }
 
+static
+struct drm_connector *find_connector_by_bridge(struct drm_device *drm_dev,
+					       struct device_node *node)
+{
+	struct device_node *np_encoder, *np_connector;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector = NULL;
+	struct device_node *port, *endpoint;
+	bool encoder_bridge = false;
+	bool found_connector = false;
+
+	np_encoder = of_graph_get_remote_port_parent(node);
+	if (!np_encoder || !of_device_is_available(np_encoder))
+		goto err_put_encoder;
+	drm_for_each_encoder(encoder, drm_dev) {
+		if (encoder->port == np_encoder && encoder->bridge) {
+			encoder_bridge = true;
+			break;
+		}
+	}
+	if (!encoder_bridge) {
+		dev_err(drm_dev->dev, "can't found encoder bridge!\n");
+		goto err_put_encoder;
+	}
+	port = of_graph_get_port_by_id(np_encoder, 1);
+	if (!port) {
+		dev_err(drm_dev->dev, "can't found port point!\n");
+		goto err_put_encoder;
+	}
+	for_each_child_of_node(port, endpoint) {
+		np_connector = of_graph_get_remote_port_parent(endpoint);
+		if (!np_connector) {
+			dev_err(drm_dev->dev,
+				"can't found connector node, please init!\n");
+			goto err_put_port;
+		}
+		if (!of_device_is_available(np_connector)) {
+			of_node_put(np_connector);
+			np_connector = NULL;
+			continue;
+		} else {
+			break;
+		}
+	}
+	if (!np_connector) {
+		dev_err(drm_dev->dev, "can't found available connector node!\n");
+		goto err_put_port;
+	}
+
+	drm_for_each_connector(connector, drm_dev) {
+		if (connector->port == np_connector) {
+			found_connector = true;
+			break;
+		}
+	}
+
+	if (!found_connector)
+		connector = NULL;
+
+	of_node_put(np_connector);
+err_put_port:
+	of_node_put(port);
+err_put_encoder:
+	of_node_put(np_encoder);
+
+	return connector;
+}
+
 void rockchip_free_loader_memory(struct drm_device *drm)
 {
 	struct rockchip_drm_private *private = drm->dev_private;
@@ -298,6 +366,8 @@ of_parse_display_resource(struct drm_device *drm_dev, struct device_node *route)
 
 	crtc = find_crtc_by_node(drm_dev, connect);
 	connector = find_connector_by_node(drm_dev, connect);
+	if (!connector)
+		connector = find_connector_by_bridge(drm_dev, connect);
 	if (!crtc || !connector) {
 		dev_warn(drm_dev->dev,
 			 "No available crtc or connector for display");
diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 4b4249114477..ad497552b5ea 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -821,6 +821,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
 	}
 
 	drm_encoder_helper_add(encoder, &rockchip_lvds_encoder_helper_funcs);
+	encoder->port = dev->of_node;
 
 	if (lvds->panel) {
 		connector = &lvds->connector;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 1b904d9d2808..5d7b55c1b911 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -722,6 +722,7 @@ struct drm_encoder_funcs {
 /**
  * struct drm_encoder - central DRM encoder structure
  * @dev: parent DRM device
+ * @port: OF node used by find encoder by node
  * @head: list management
  * @base: base KMS object
  * @name: encoder name
@@ -738,6 +739,7 @@ struct drm_encoder_funcs {
  */
 struct drm_encoder {
 	struct drm_device *dev;
+	struct device_node *port;
 	struct list_head head;
 
 	struct drm_mode_object base;