Skip to content

Commit

Permalink
ASoC: cs4271: add regulator consumer support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pascal Huerst authored and Mark Brown committed Feb 26, 2016
1 parent 92e963f commit 9a397f4
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 8 deletions.
7 changes: 7 additions & 0 deletions Documentation/devicetree/bindings/sound/cs4271.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
69 changes: 61 additions & 8 deletions sound/soc/codecs/cs4271.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand All @@ -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[] = {
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
}

Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
};

Expand All @@ -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)
Expand All @@ -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;
}
Expand Down

0 comments on commit 9a397f4

Please sign in to comment.