]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ASoC: ak4104: add regulator consumer support
authorDaniel Mack <zonque@gmail.com>
Thu, 27 Mar 2014 20:42:15 +0000 (21:42 +0100)
committerMark Brown <broonie@linaro.org>
Wed, 23 Apr 2014 12:20:07 +0000 (13:20 +0100)
The AK4104 has only one power supply, called VDD. Enable it as long as
the codec is in use.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
sound/soc/codecs/ak4104.c

index 10adf25d4c14f36e64d383d8be3a967387ce1726..1fd7f72b2a62a05f99567e02e634328f65bc5fce 100644 (file)
 
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/soc.h>
-#include <sound/initval.h>
 #include <linux/spi/spi.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
 #include <sound/asoundef.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
 
 /* AK4104 registers addresses */
 #define AK4104_REG_CONTROL1            0x00
@@ -47,6 +48,7 @@
 
 struct ak4104_private {
        struct regmap *regmap;
+       struct regulator *regulator;
 };
 
 static const struct snd_soc_dapm_widget ak4104_dapm_widgets[] = {
@@ -174,20 +176,30 @@ static int ak4104_probe(struct snd_soc_codec *codec)
        struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
+       ret = regulator_enable(ak4104->regulator);
+       if (ret < 0) {
+               dev_err(codec->dev, "Unable to enable regulator: %d\n", ret);
+               return ret;
+       }
+
        /* set power-up and non-reset bits */
        ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
                                 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
                                 AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
        if (ret < 0)
-               return ret;
+               goto exit_disable_regulator;
 
        /* enable transmitter */
        ret = regmap_update_bits(ak4104->regmap, AK4104_REG_TX,
                                 AK4104_TX_TXE, AK4104_TX_TXE);
        if (ret < 0)
-               return ret;
+               goto exit_disable_regulator;
 
        return 0;
+
+exit_disable_regulator:
+       regulator_disable(ak4104->regulator);
+       return ret;
 }
 
 static int ak4104_remove(struct snd_soc_codec *codec)
@@ -196,13 +208,42 @@ static int ak4104_remove(struct snd_soc_codec *codec)
 
        regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1,
                           AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
+       regulator_disable(ak4104->regulator);
 
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int ak4104_soc_suspend(struct snd_soc_codec *codec)
+{
+       struct ak4104_private *priv = snd_soc_codec_get_drvdata(codec);
+
+       regulator_disable(priv->regulator);
+
+       return 0;
+}
+
+static int ak4104_soc_resume(struct snd_soc_codec *codec)
+{
+       struct ak4104_private *priv = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       ret = regulator_enable(priv->regulator);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+#else
+#define ak4104_soc_suspend     NULL
+#define ak4104_soc_resume      NULL
+#endif /* CONFIG_PM */
+
 static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
-       .probe =        ak4104_probe,
-       .remove =       ak4104_remove,
+       .probe = ak4104_probe,
+       .remove = ak4104_remove,
+       .suspend = ak4104_soc_suspend,
+       .resume = ak4104_soc_resume,
 
        .dapm_widgets = ak4104_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(ak4104_dapm_widgets),
@@ -239,6 +280,13 @@ static int ak4104_spi_probe(struct spi_device *spi)
        if (ak4104 == NULL)
                return -ENOMEM;
 
+       ak4104->regulator = devm_regulator_get(&spi->dev, "vdd");
+       if (IS_ERR(ak4104->regulator)) {
+               ret = PTR_ERR(ak4104->regulator);
+               dev_err(&spi->dev, "Unable to get Vdd regulator: %d\n", ret);
+               return ret;
+       }
+
        ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
        if (IS_ERR(ak4104->regmap)) {
                ret = PTR_ERR(ak4104->regmap);