Merge remote-tracking branches 'asoc/topic/wm2200', 'asoc/topic/wm5100', 'asoc/topic...
[linux-2.6-block.git] / sound / soc / codecs / wm8731.c
index 098c143f44d653d99c33f36e02edde9eca6600d8..2245b6a32f3dc52da5b5f8ddf9393cf400172a7b 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/spi/spi.h>
 #include <linux/of_device.h>
 #include <linux/mutex.h>
+#include <linux/clk.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -45,6 +46,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
 /* codec private data */
 struct wm8731_priv {
        struct regmap *regmap;
+       struct clk *mclk;
        struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
        const struct snd_pcm_hw_constraint_list *constraints;
        unsigned int sysclk;
@@ -125,7 +127,7 @@ static int wm8731_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8731->deemph;
+       ucontrol->value.integer.value[0] = wm8731->deemph;
 
        return 0;
 }
@@ -135,7 +137,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
        int ret = 0;
 
        if (deemph > 1)
@@ -390,6 +392,8 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
        switch (clk_id) {
        case WM8731_SYSCLK_XTAL:
        case WM8731_SYSCLK_MCLK:
+               if (wm8731->mclk && clk_set_rate(wm8731->mclk, freq))
+                       return -EINVAL;
                wm8731->sysclk_type = clk_id;
                break;
        default:
@@ -491,6 +495,8 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
 
        switch (level) {
        case SND_SOC_BIAS_ON:
+               if (wm8731->mclk)
+                       clk_prepare_enable(wm8731->mclk);
                break;
        case SND_SOC_BIAS_PREPARE:
                break;
@@ -509,6 +515,8 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
                snd_soc_write(codec, WM8731_PWR, reg | 0x0040);
                break;
        case SND_SOC_BIAS_OFF:
+               if (wm8731->mclk)
+                       clk_disable_unprepare(wm8731->mclk);
                snd_soc_write(codec, WM8731_PWR, 0xffff);
                regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
                                       wm8731->supplies);
@@ -667,6 +675,19 @@ static int wm8731_spi_probe(struct spi_device *spi)
        if (wm8731 == NULL)
                return -ENOMEM;
 
+       wm8731->mclk = devm_clk_get(&spi->dev, "mclk");
+       if (IS_ERR(wm8731->mclk)) {
+               ret = PTR_ERR(wm8731->mclk);
+               if (ret == -ENOENT) {
+                       wm8731->mclk = NULL;
+                       dev_warn(&spi->dev, "Assuming static MCLK\n");
+               } else {
+                       dev_err(&spi->dev, "Failed to get MCLK: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
        mutex_init(&wm8731->lock);
 
        wm8731->regmap = devm_regmap_init_spi(spi, &wm8731_regmap);
@@ -718,6 +739,19 @@ static int wm8731_i2c_probe(struct i2c_client *i2c,
        if (wm8731 == NULL)
                return -ENOMEM;
 
+       wm8731->mclk = devm_clk_get(&i2c->dev, "mclk");
+       if (IS_ERR(wm8731->mclk)) {
+               ret = PTR_ERR(wm8731->mclk);
+               if (ret == -ENOENT) {
+                       wm8731->mclk = NULL;
+                       dev_warn(&i2c->dev, "Assuming static MCLK\n");
+               } else {
+                       dev_err(&i2c->dev, "Failed to get MCLK: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
        mutex_init(&wm8731->lock);
 
        wm8731->regmap = devm_regmap_init_i2c(i2c, &wm8731_regmap);