diff options
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/rt5677.c | 54 | ||||
-rw-r--r-- | sound/soc/codecs/rt5677.h | 1 |
2 files changed, 55 insertions, 0 deletions
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 4a0f3dfb2a47..d2c6abf38ad2 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/pm.h> +#include <linux/of_gpio.h> #include <linux/regmap.h> #include <linux/i2c.h> #include <linux/platform_device.h> @@ -3381,6 +3382,8 @@ static int rt5677_remove(struct snd_soc_codec *codec) struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); regmap_write(rt5677->regmap, RT5677_RESET, 0x10ec); + if (gpio_is_valid(rt5677->pow_ldo2)) + gpio_set_value_cansleep(rt5677->pow_ldo2, 0); return 0; } @@ -3392,6 +3395,8 @@ static int rt5677_suspend(struct snd_soc_codec *codec) regcache_cache_only(rt5677->regmap, true); regcache_mark_dirty(rt5677->regmap); + if (gpio_is_valid(rt5677->pow_ldo2)) + gpio_set_value_cansleep(rt5677->pow_ldo2, 0); return 0; } @@ -3400,6 +3405,10 @@ static int rt5677_resume(struct snd_soc_codec *codec) { struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); + if (gpio_is_valid(rt5677->pow_ldo2)) { + gpio_set_value_cansleep(rt5677->pow_ldo2, 1); + msleep(10); + } regcache_cache_only(rt5677->regmap, false); regcache_sync(rt5677->regmap); @@ -3558,6 +3567,24 @@ static const struct i2c_device_id rt5677_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); +static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np) +{ + rt5677->pow_ldo2 = of_get_named_gpio(np, + "realtek,pow-ldo2-gpio", 0); + + /* + * POW_LDO2 is optional (it may be statically tied on the board). + * -ENOENT means that the property doesn't exist, i.e. there is no + * GPIO, so is not an error. Any other error code means the property + * exists, but could not be parsed. + */ + if (!gpio_is_valid(rt5677->pow_ldo2) && + (rt5677->pow_ldo2 != -ENOENT)) + return rt5677->pow_ldo2; + + return 0; +} + static int rt5677_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -3576,6 +3603,33 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, if (pdata) rt5677->pdata = *pdata; + if (i2c->dev.of_node) { + ret = rt5677_parse_dt(rt5677, i2c->dev.of_node); + if (ret) { + dev_err(&i2c->dev, "Failed to parse device tree: %d\n", + ret); + return ret; + } + } else { + rt5677->pow_ldo2 = -EINVAL; + } + + if (gpio_is_valid(rt5677->pow_ldo2)) { + ret = devm_gpio_request_one(&i2c->dev, rt5677->pow_ldo2, + GPIOF_OUT_INIT_HIGH, + "RT5677 POW_LDO2"); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to request POW_LDO2 %d: %d\n", + rt5677->pow_ldo2, ret); + return ret; + } + /* Wait a while until I2C bus becomes available. The datasheet + * does not specify the exact we should wait but startup + * sequence mentiones at least a few milliseconds. + */ + msleep(10); + } + rt5677->regmap = devm_regmap_init_i2c(i2c, &rt5677_regmap); if (IS_ERR(rt5677->regmap)) { ret = PTR_ERR(rt5677->regmap); diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 1fe88727a063..d4eb6d5e6746 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h @@ -1554,6 +1554,7 @@ struct rt5677_priv { int pll_src; int pll_in; int pll_out; + int pow_ldo2; /* POW_LDO2 pin */ #ifdef CONFIG_GPIOLIB struct gpio_chip gpio_chip; #endif |