From c4e97a6379969d3ee5564ba651a5213468437b65 Mon Sep 17 00:00:00 2001 From: Huang Jiachai Date: Mon, 31 Jul 2017 19:53:15 +0800 Subject: [PATCH] drm/rockchip: get connector in bridge mode Change-Id: I08535f5c2d83783dc86ae641daeb530dedec36e6 Signed-off-by: Huang Jiachai --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 70 +++++++++++++++++++++ drivers/gpu/drm/rockchip/rockchip_lvds.c | 1 + include/drm/drm_crtc.h | 2 + 3 files changed, 73 insertions(+) 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; -- 2.34.1