These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / sound / soc / codecs / adau1701.c
index d4e219b..de53c0d 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/regmap.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 
 #define ADAU1701_FIRMWARE "adau1701.bin"
 
+static const char * const supply_names[] = {
+       "dvdd", "avdd"
+};
+
 struct adau1701 {
        int gpio_nreset;
        int gpio_pll_mode[2];
@@ -112,6 +117,7 @@ struct adau1701 {
        u8 pin_config[12];
 
        struct sigmadsp *sigmadsp;
+       struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
 };
 
 static const struct snd_kcontrol_new adau1701_controls[] = {
@@ -565,7 +571,6 @@ static int adau1701_set_bias_level(struct snd_soc_codec *codec,
                break;
        }
 
-       codec->dapm.bias_level = level;
        return 0;
 }
 
@@ -669,6 +674,13 @@ static int adau1701_probe(struct snd_soc_codec *codec)
        if (ret)
                return ret;
 
+       ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies),
+                                   adau1701->supplies);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
+               return ret;
+       }
+
        /*
         * Let the pll_clkdiv variable default to something that won't happen
         * at runtime. That way, we can postpone the firmware download from
@@ -680,7 +692,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
        /* initalize with pre-configured pll mode settings */
        ret = adau1701_reset(codec, adau1701->pll_clkdiv, 0);
        if (ret < 0)
-               return ret;
+               goto exit_regulators_disable;
 
        /* set up pin config */
        val = 0;
@@ -696,10 +708,60 @@ static int adau1701_probe(struct snd_soc_codec *codec)
        regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val);
 
        return 0;
+
+exit_regulators_disable:
+
+       regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies);
+       return ret;
 }
 
+static int adau1701_remove(struct snd_soc_codec *codec)
+{
+       struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
+
+       if (gpio_is_valid(adau1701->gpio_nreset))
+               gpio_set_value_cansleep(adau1701->gpio_nreset, 0);
+
+       regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int adau1701_suspend(struct snd_soc_codec *codec)
+{
+       struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
+
+       regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies),
+                              adau1701->supplies);
+
+       return 0;
+}
+
+static int adau1701_resume(struct snd_soc_codec *codec)
+{
+       struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+        ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies),
+                                   adau1701->supplies);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
+               return ret;
+       }
+
+       return adau1701_reset(codec, adau1701->pll_clkdiv, 0);
+}
+#else
+#define adau1701_resume        NULL
+#define adau1701_suspend       NULL
+#endif /* CONFIG_PM */
+
 static struct snd_soc_codec_driver adau1701_codec_drv = {
        .probe                  = adau1701_probe,
+       .remove                 = adau1701_remove,
+       .resume                 = adau1701_resume,
+       .suspend                = adau1701_suspend,
        .set_bias_level         = adau1701_set_bias_level,
        .idle_bias_off          = true,
 
@@ -730,32 +792,58 @@ static int adau1701_i2c_probe(struct i2c_client *client,
        struct device *dev = &client->dev;
        int gpio_nreset = -EINVAL;
        int gpio_pll_mode[2] = { -EINVAL, -EINVAL };
-       int ret;
+       int ret, i;
 
        adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL);
        if (!adau1701)
                return -ENOMEM;
 
+       for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+               adau1701->supplies[i].supply = supply_names[i];
+
+       ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(adau1701->supplies),
+                       adau1701->supplies);
+       if (ret < 0) {
+               dev_err(dev, "Failed to get regulators: %d\n", ret);
+               return ret;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies),
+                       adau1701->supplies);
+       if (ret < 0) {
+               dev_err(dev, "Failed to enable regulators: %d\n", ret);
+               return ret;
+       }
+
        adau1701->client = client;
        adau1701->regmap = devm_regmap_init(dev, NULL, client,
                                            &adau1701_regmap);
-       if (IS_ERR(adau1701->regmap))
-               return PTR_ERR(adau1701->regmap);
+       if (IS_ERR(adau1701->regmap)) {
+               ret = PTR_ERR(adau1701->regmap);
+               goto exit_regulators_disable;
+       }
+
 
        if (dev->of_node) {
                gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0);
-               if (gpio_nreset < 0 && gpio_nreset != -ENOENT)
-                       return gpio_nreset;
+               if (gpio_nreset < 0 && gpio_nreset != -ENOENT) {
+                       ret = gpio_nreset;
+                       goto exit_regulators_disable;
+               }
 
                gpio_pll_mode[0] = of_get_named_gpio(dev->of_node,
                                                   "adi,pll-mode-gpios", 0);
-               if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT)
-                       return gpio_pll_mode[0];
+               if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT) {
+                       ret = gpio_pll_mode[0];
+                       goto exit_regulators_disable;
+               }
 
                gpio_pll_mode[1] = of_get_named_gpio(dev->of_node,
                                                   "adi,pll-mode-gpios", 1);
-               if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT)
-                       return gpio_pll_mode[1];
+               if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT) {
+                       ret = gpio_pll_mode[1];
+                       goto exit_regulators_disable;
+               }
 
                of_property_read_u32(dev->of_node, "adi,pll-clkdiv",
                                     &adau1701->pll_clkdiv);
@@ -769,7 +857,7 @@ static int adau1701_i2c_probe(struct i2c_client *client,
                ret = devm_gpio_request_one(dev, gpio_nreset, GPIOF_OUT_INIT_LOW,
                                            "ADAU1701 Reset");
                if (ret < 0)
-                       return ret;
+                       goto exit_regulators_disable;
        }
 
        if (gpio_is_valid(gpio_pll_mode[0]) &&
@@ -778,13 +866,13 @@ static int adau1701_i2c_probe(struct i2c_client *client,
                                            GPIOF_OUT_INIT_LOW,
                                            "ADAU1701 PLL mode 0");
                if (ret < 0)
-                       return ret;
+                       goto exit_regulators_disable;
 
                ret = devm_gpio_request_one(dev, gpio_pll_mode[1],
                                            GPIOF_OUT_INIT_LOW,
                                            "ADAU1701 PLL mode 1");
                if (ret < 0)
-                       return ret;
+                       goto exit_regulators_disable;
        }
 
        adau1701->gpio_nreset = gpio_nreset;
@@ -795,11 +883,17 @@ static int adau1701_i2c_probe(struct i2c_client *client,
 
        adau1701->sigmadsp = devm_sigmadsp_init_i2c(client,
                &adau1701_sigmadsp_ops, ADAU1701_FIRMWARE);
-       if (IS_ERR(adau1701->sigmadsp))
-               return PTR_ERR(adau1701->sigmadsp);
+       if (IS_ERR(adau1701->sigmadsp)) {
+               ret = PTR_ERR(adau1701->sigmadsp);
+               goto exit_regulators_disable;
+       }
 
        ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv,
                        &adau1701_dai, 1);
+
+exit_regulators_disable:
+
+       regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies);
        return ret;
 }
 
@@ -821,7 +915,6 @@ MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id);
 static struct i2c_driver adau1701_i2c_driver = {
        .driver = {
                .name   = "adau1701",
-               .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(adau1701_dt_ids),
        },
        .probe          = adau1701_i2c_probe,