1
0
Fork 0

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 <robert.chiras@nxp.com>
Reviewed-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
5.4-rM2-2.2.x-imx-squashed
Robert Chiras 2017-12-21 10:59:20 +02:00 committed by Dong Aisheng
parent 453cd42feb
commit 369b5f06ac
1 changed files with 45 additions and 0 deletions

View File

@ -9,7 +9,9 @@
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/slab.h>
#include <media/cec.h>
@ -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;
}