ASoC: cs4271: add regulator consumer support

The cs4271 has three power domains: vd, vl and va.
Enable them all, as long as the codec is in use.

While at it, factored out the reset code into its own function.

Signed-off-by: Pascal Huerst <pascal.huerst@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Pascal Huerst 2016-02-16 16:19:06 +01:00 committed by Mark Brown
parent 92e963f50f
commit 9a397f4736
2 changed files with 68 additions and 8 deletions

View File

@ -33,12 +33,19 @@ Optional properties:
Note that this is not needed in case the clocks are stable
throughout the entire runtime of the codec.
- vd-supply: Digital power
- vl-supply: Logic power
- va-supply: Analog Power
Examples:
codec_i2c: cs4271@10 {
compatible = "cirrus,cs4271";
reg = <0x10>;
reset-gpio = <&gpio 23 0>;
vd-supply = <&vdd_3v3_reg>;
vl-supply = <&vdd_3v3_reg>;
va-supply = <&vdd_3v3_reg>;
};
codec_spi: cs4271@0 {

View File

@ -26,6 +26,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/tlv.h>
@ -157,6 +158,10 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg)
return reg == CS4271_CHIPID;
}
static const char * const supply_names[] = {
"vd", "vl", "va"
};
struct cs4271_private {
unsigned int mclk;
bool master;
@ -170,6 +175,7 @@ struct cs4271_private {
int gpio_disable;
/* enable soft reset workaround */
bool enable_soft_reset;
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
};
static const struct snd_soc_dapm_widget cs4271_dapm_widgets[] = {
@ -487,6 +493,20 @@ static struct snd_soc_dai_driver cs4271_dai = {
.symmetric_rates = 1,
};
static int cs4271_reset(struct snd_soc_codec *codec)
{
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
if (gpio_is_valid(cs4271->gpio_nreset)) {
gpio_set_value(cs4271->gpio_nreset, 0);
mdelay(1);
gpio_set_value(cs4271->gpio_nreset, 1);
mdelay(1);
}
return 0;
}
#ifdef CONFIG_PM
static int cs4271_soc_suspend(struct snd_soc_codec *codec)
{
@ -499,6 +519,9 @@ static int cs4271_soc_suspend(struct snd_soc_codec *codec)
if (ret < 0)
return ret;
regcache_mark_dirty(cs4271->regmap);
regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies);
return 0;
}
@ -507,6 +530,16 @@ static int cs4271_soc_resume(struct snd_soc_codec *codec)
int ret;
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
ret = regulator_bulk_enable(ARRAY_SIZE(cs4271->supplies),
cs4271->supplies);
if (ret < 0) {
dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
return ret;
}
/* Do a proper reset after power up */
cs4271_reset(codec);
/* Restore codec state */
ret = regcache_sync(cs4271->regmap);
if (ret < 0)
@ -553,19 +586,24 @@ static int cs4271_codec_probe(struct snd_soc_codec *codec)
}
#endif
ret = regulator_bulk_enable(ARRAY_SIZE(cs4271->supplies),
cs4271->supplies);
if (ret < 0) {
dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
return ret;
}
if (cs4271plat) {
amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
cs4271->enable_soft_reset = cs4271plat->enable_soft_reset;
}
if (gpio_is_valid(cs4271->gpio_nreset)) {
/* Reset codec */
gpio_direction_output(cs4271->gpio_nreset, 0);
mdelay(1);
gpio_set_value(cs4271->gpio_nreset, 1);
/* Give the codec time to wake up */
mdelay(1);
}
/* Reset codec */
cs4271_reset(codec);
ret = regcache_sync(cs4271->regmap);
if (ret < 0)
return ret;
ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
@ -595,6 +633,9 @@ static int cs4271_codec_remove(struct snd_soc_codec *codec)
/* Set codec to the reset state */
gpio_set_value(cs4271->gpio_nreset, 0);
regcache_mark_dirty(cs4271->regmap);
regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies);
return 0;
};
@ -617,6 +658,7 @@ static int cs4271_common_probe(struct device *dev,
{
struct cs4271_platform_data *cs4271plat = dev->platform_data;
struct cs4271_private *cs4271;
int i, ret;
cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL);
if (!cs4271)
@ -638,6 +680,17 @@ static int cs4271_common_probe(struct device *dev,
return ret;
}
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
cs4271->supplies[i].supply = supply_names[i];
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs4271->supplies),
cs4271->supplies);
if (ret < 0) {
dev_err(dev, "Failed to get regulators: %d\n", ret);
return ret;
}
*c = cs4271;
return 0;
}