]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - sound/soc/codecs/wm8804.c
Merge remote-tracking branches 'asoc/topic/wm8804' and 'asoc/topic/wm9713' into asoc...
[karo-tx-linux.git] / sound / soc / codecs / wm8804.c
index 589455c3bfcd9b7ac430abe138169fa6b6606a1f..d96e5963ee352518eda188c74e1f46e8c04722e0 100644 (file)
@@ -63,6 +63,7 @@ struct wm8804_priv {
        struct regmap *regmap;
        struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
        struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
+       int mclk_div;
 };
 
 static int txsrc_get(struct snd_kcontrol *kcontrol,
@@ -318,7 +319,7 @@ static struct {
 
 #define FIXED_PLL_SIZE ((1ULL << 22) * 10)
 static int pll_factors(struct pll_div *pll_div, unsigned int target,
-                      unsigned int source)
+                      unsigned int source, unsigned int mclk_div)
 {
        u64 Kpart;
        unsigned long int K, Ndiv, Nmod, tmp;
@@ -330,7 +331,8 @@ static int pll_factors(struct pll_div *pll_div, unsigned int target,
         */
        for (i = 0; i < ARRAY_SIZE(post_table); i++) {
                tmp = target * post_table[i].div;
-               if (tmp >= 90000000 && tmp <= 100000000) {
+               if ((tmp >= 90000000 && tmp <= 100000000) &&
+                   (mclk_div == post_table[i].mclkdiv)) {
                        pll_div->freqmode = post_table[i].freqmode;
                        pll_div->mclkdiv = post_table[i].mclkdiv;
                        target *= post_table[i].div;
@@ -387,8 +389,12 @@ static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id,
        } else {
                int ret;
                struct pll_div pll_div;
+               struct wm8804_priv *wm8804;
 
-               ret = pll_factors(&pll_div, freq_out, freq_in);
+               wm8804 = snd_soc_codec_get_drvdata(codec);
+
+               ret = pll_factors(&pll_div, freq_out, freq_in,
+                                 wm8804->mclk_div);
                if (ret)
                        return ret;
 
@@ -452,6 +458,7 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
                             int div_id, int div)
 {
        struct snd_soc_codec *codec;
+       struct wm8804_priv *wm8804;
 
        codec = dai->codec;
        switch (div_id) {
@@ -459,6 +466,10 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
                snd_soc_update_bits(codec, WM8804_PLL5, 0x30,
                                    (div & 0x3) << 4);
                break;
+       case WM8804_MCLK_DIV:
+               wm8804 = snd_soc_codec_get_drvdata(codec);
+               wm8804->mclk_div = div;
+               break;
        default:
                dev_err(dai->dev, "Unknown clock divider: %d\n", div_id);
                return -EINVAL;
@@ -535,7 +546,6 @@ static int wm8804_remove(struct snd_soc_codec *codec)
        for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
                regulator_unregister_notifier(wm8804->supplies[i].consumer,
                                              &wm8804->disable_nb[i]);
-       regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
        return 0;
 }
 
@@ -549,7 +559,7 @@ static int wm8804_probe(struct snd_soc_codec *codec)
        for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
                wm8804->supplies[i].supply = wm8804_supply_names[i];
 
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
+       ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
                                 wm8804->supplies);
        if (ret) {
                dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
@@ -574,7 +584,7 @@ static int wm8804_probe(struct snd_soc_codec *codec)
                                    wm8804->supplies);
        if (ret) {
                dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_reg_get;
+               return ret;
        }
 
        id1 = snd_soc_read(codec, WM8804_RST_DEVID1);
@@ -619,8 +629,6 @@ static int wm8804_probe(struct snd_soc_codec *codec)
 
 err_reg_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
-err_reg_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
        return ret;
 }