From 3f3274e653af3b2731434fd20e1c3fbce73613ed Mon Sep 17 00:00:00 2001 From: Robert Chiras Date: Thu, 21 Dec 2017 10:59:20 +0200 Subject: [PATCH] MLK-17275-1: drm/bridge: adv7511: Add support for OF_DYNAMIC When CONFIG_OF_DYNAMIC is used, and this driver is enabled in devicetree, but fails to probe a physical i2c client, it should disable it's remote endpoint, so that the DRM master device won't fail to bind the other available devices. Usually, the remote endpoint of this device is a DRM encoder. If a DRM encoder fails to bind, the DRM master device will also fail to bind. This is why, we should disable the encoder node dynamically in devicetree. Signed-off-by: Robert Chiras Reviewed-by: Laurentiu Palcu --- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 45 ++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 620434ef2a1e..82d3f7834cbc 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -9,7 +9,9 @@ #include #include #include +#include #include +#include #include #include @@ -1109,6 +1111,11 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) struct adv7511_link_config link_config; struct adv7511 *adv7511; struct device *dev = &i2c->dev; +#if IS_ENABLED(CONFIG_OF_DYNAMIC) + struct device_node *remote_node = NULL, *endpoint = NULL; + struct of_changeset ocs; + struct property *prop; +#endif unsigned int val; int ret; @@ -1249,6 +1256,44 @@ err_i2c_unregister_edid: i2c_unregister_device(adv7511->i2c_edid); uninit_regulators: adv7511_uninit_regulators(adv7511); +#if IS_ENABLED(CONFIG_OF_DYNAMIC) + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + if (endpoint) + remote_node = of_graph_get_remote_port_parent(endpoint); + + if (remote_node) { + int num_endpoints = 0; + + /* + * Remote node should have two endpoints (input and output: us) + * If remote node has more than two endpoints, probably that it + * has more outputs, so there is no need to disable it. + */ + endpoint = NULL; + while ((endpoint = of_graph_get_next_endpoint(remote_node, + endpoint))) + num_endpoints++; + + if (num_endpoints > 2) { + of_node_put(remote_node); + return ret; + } + + prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL); + prop->name = devm_kstrdup(dev, "status", GFP_KERNEL); + prop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL); + prop->length = 9; + of_changeset_init(&ocs); + of_changeset_update_property(&ocs, remote_node, prop); + ret = of_changeset_apply(&ocs); + if (!ret) + dev_warn(dev, + "Probe failed. Remote port '%s' disabled\n", + remote_node->full_name); + + of_node_put(remote_node); + }; +#endif return ret; } -- 2.17.1