| From 49d75597cc0116d54a98d1aecd36ae7c90bb4520 Mon Sep 17 00:00:00 2001 |
| From: Archit Taneja <architt@codeaurora.org> |
| Date: Wed, 11 Jan 2017 12:22:27 +0530 |
| Subject: [PATCH 001/255] drm/bridge: adv7511: Initialize regulators |
| |
| Maintain a table of regulator names expected by ADV7511 and ADV7533. |
| Use regulator_bulk_* api to configure these. |
| |
| Initialize and enable the regulators during probe itself. Controlling |
| these dynamically is left for later. |
| |
| Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| Signed-off-by: Archit Taneja <architt@codeaurora.org> |
| Link: http://patchwork.freedesktop.org/patch/msgid/1484117547-26417-3-git-send-email-architt@codeaurora.org |
| (cherry picked from commit 5b06ba2378e177fdb8f100adda6e55b205308202) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/gpu/drm/bridge/adv7511/adv7511.h | 4 + |
| drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 86 ++++++++++++++++++++++++--- |
| 2 files changed, 81 insertions(+), 9 deletions(-) |
| |
| --- a/drivers/gpu/drm/bridge/adv7511/adv7511.h |
| +++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h |
| @@ -12,6 +12,7 @@ |
| #include <linux/hdmi.h> |
| #include <linux/i2c.h> |
| #include <linux/regmap.h> |
| +#include <linux/regulator/consumer.h> |
| |
| #include <drm/drm_crtc_helper.h> |
| #include <drm/drm_mipi_dsi.h> |
| @@ -329,6 +330,9 @@ struct adv7511 { |
| |
| struct gpio_desc *gpio_pd; |
| |
| + struct regulator_bulk_data *supplies; |
| + unsigned int num_supplies; |
| + |
| /* ADV7533 DSI RX related params */ |
| struct device_node *host_node; |
| struct mipi_dsi_device *dsi; |
| --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c |
| +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c |
| @@ -839,6 +839,58 @@ static struct drm_bridge_funcs adv7511_b |
| * Probe & remove |
| */ |
| |
| +static const char * const adv7511_supply_names[] = { |
| + "avdd", |
| + "dvdd", |
| + "pvdd", |
| + "bgvdd", |
| + "dvdd-3v", |
| +}; |
| + |
| +static const char * const adv7533_supply_names[] = { |
| + "avdd", |
| + "dvdd", |
| + "pvdd", |
| + "a2vdd", |
| + "v3p3", |
| + "v1p2", |
| +}; |
| + |
| +static int adv7511_init_regulators(struct adv7511 *adv) |
| +{ |
| + struct device *dev = &adv->i2c_main->dev; |
| + const char * const *supply_names; |
| + unsigned int i; |
| + int ret; |
| + |
| + if (adv->type == ADV7511) { |
| + supply_names = adv7511_supply_names; |
| + adv->num_supplies = ARRAY_SIZE(adv7511_supply_names); |
| + } else { |
| + supply_names = adv7533_supply_names; |
| + adv->num_supplies = ARRAY_SIZE(adv7533_supply_names); |
| + } |
| + |
| + adv->supplies = devm_kcalloc(dev, adv->num_supplies, |
| + sizeof(*adv->supplies), GFP_KERNEL); |
| + if (!adv->supplies) |
| + return -ENOMEM; |
| + |
| + for (i = 0; i < adv->num_supplies; i++) |
| + adv->supplies[i].supply = supply_names[i]; |
| + |
| + ret = devm_regulator_bulk_get(dev, adv->num_supplies, adv->supplies); |
| + if (ret) |
| + return ret; |
| + |
| + return regulator_bulk_enable(adv->num_supplies, adv->supplies); |
| +} |
| + |
| +static void adv7511_uninit_regulators(struct adv7511 *adv) |
| +{ |
| + regulator_bulk_disable(adv->num_supplies, adv->supplies); |
| +} |
| + |
| static int adv7511_parse_dt(struct device_node *np, |
| struct adv7511_link_config *config) |
| { |
| @@ -939,6 +991,7 @@ static int adv7511_probe(struct i2c_clie |
| if (!adv7511) |
| return -ENOMEM; |
| |
| + adv7511->i2c_main = i2c; |
| adv7511->powered = false; |
| adv7511->status = connector_status_disconnected; |
| |
| @@ -956,13 +1009,21 @@ static int adv7511_probe(struct i2c_clie |
| if (ret) |
| return ret; |
| |
| + ret = adv7511_init_regulators(adv7511); |
| + if (ret) { |
| + dev_err(dev, "failed to init regulators\n"); |
| + return ret; |
| + } |
| + |
| /* |
| * The power down GPIO is optional. If present, toggle it from active to |
| * inactive to wake up the encoder. |
| */ |
| adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH); |
| - if (IS_ERR(adv7511->gpio_pd)) |
| - return PTR_ERR(adv7511->gpio_pd); |
| + if (IS_ERR(adv7511->gpio_pd)) { |
| + ret = PTR_ERR(adv7511->gpio_pd); |
| + goto uninit_regulators; |
| + } |
| |
| if (adv7511->gpio_pd) { |
| mdelay(5); |
| @@ -970,12 +1031,14 @@ static int adv7511_probe(struct i2c_clie |
| } |
| |
| adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config); |
| - if (IS_ERR(adv7511->regmap)) |
| - return PTR_ERR(adv7511->regmap); |
| + if (IS_ERR(adv7511->regmap)) { |
| + ret = PTR_ERR(adv7511->regmap); |
| + goto uninit_regulators; |
| + } |
| |
| ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val); |
| if (ret) |
| - return ret; |
| + goto uninit_regulators; |
| dev_dbg(dev, "Rev. %d\n", val); |
| |
| if (adv7511->type == ADV7511) |
| @@ -985,7 +1048,7 @@ static int adv7511_probe(struct i2c_clie |
| else |
| ret = adv7533_patch_registers(adv7511); |
| if (ret) |
| - return ret; |
| + goto uninit_regulators; |
| |
| regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr); |
| regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR, |
| @@ -995,10 +1058,11 @@ static int adv7511_probe(struct i2c_clie |
| |
| adv7511_packet_disable(adv7511, 0xffff); |
| |
| - adv7511->i2c_main = i2c; |
| adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1); |
| - if (!adv7511->i2c_edid) |
| - return -ENOMEM; |
| + if (!adv7511->i2c_edid) { |
| + ret = -ENOMEM; |
| + goto uninit_regulators; |
| + } |
| |
| if (adv7511->type == ADV7533) { |
| ret = adv7533_init_cec(adv7511); |
| @@ -1045,6 +1109,8 @@ err_unregister_cec: |
| adv7533_uninit_cec(adv7511); |
| err_i2c_unregister_edid: |
| i2c_unregister_device(adv7511->i2c_edid); |
| +uninit_regulators: |
| + adv7511_uninit_regulators(adv7511); |
| |
| return ret; |
| } |
| @@ -1058,6 +1124,8 @@ static int adv7511_remove(struct i2c_cli |
| adv7533_uninit_cec(adv7511); |
| } |
| |
| + adv7511_uninit_regulators(adv7511); |
| + |
| drm_bridge_remove(&adv7511->bridge); |
| |
| adv7511_audio_exit(adv7511); |