UPSTREAM: ASoC: rt5616: add the mclk for the codec driver
authorJacob Chen <jacob2.chen@rock-chips.com>
Fri, 15 Jul 2016 01:43:39 +0000 (09:43 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Mon, 18 Jul 2016 03:58:41 +0000 (11:58 +0800)
This patch adds the code to enable the clock to the CODEC driver
if it needs the clock enabled.

In some case, We need to claim the clock which is driving the codec
so that when we enable clock gating, we continue to clock the codec
when needed.

if mclk provided, to enable and disable the clock source.

Signed-off-by: Caesar Wang <wxt@rock-chips.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Bug: 27307957
Patchset: fetch the upstream ASoC for rk3036 kylin board.

(cherry picked from git.kernel.org broonie/sound.git for-next
 commit 76d3204eaa9364a662f0fe0f075dfe61e6bd14fe)
Signed-off-by: Caesar Wang <wxt@rock-chips.com>
Change-Id: Iaa1b07a1ff729f3b84c1e32cd0fdd0f36d9a8889
Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
sound/soc/codecs/rt5616.c

index d4bdf9f6f0af99c172c563b6b00925f20cdf1a6a..fdca63694b409e4ec061097a4fdb475a8c934237 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
@@ -144,6 +145,7 @@ struct rt5616_priv {
        struct snd_soc_codec *codec;
        struct delayed_work patch_work;
        struct regmap *regmap;
+       struct clk *mclk;
 
        int sysclk;
        int sysclk_src;
@@ -1159,7 +1161,34 @@ static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 static int rt5616_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
+       struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
        switch (level) {
+
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               /*
+                * SND_SOC_BIAS_PREPARE is called while preparing for a
+                * transition to ON or away from ON. If current bias_level
+                * is SND_SOC_BIAS_ON, then it is preparing for a transition
+                * away from ON. Disable the clock in that case, otherwise
+                * enable it.
+                */
+               if (IS_ERR(rt5616->mclk))
+                       break;
+
+               if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) {
+                       clk_disable_unprepare(rt5616->mclk);
+               } else {
+                       ret = clk_prepare_enable(rt5616->mclk);
+                       if (ret)
+                               return ret;
+               }
+               break;
+
        case SND_SOC_BIAS_STANDBY:
                if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
                        snd_soc_update_bits(codec, RT5616_PWR_ANLG1,
@@ -1198,6 +1227,11 @@ static int rt5616_probe(struct snd_soc_codec *codec)
 {
        struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
 
+       /* Check if MCLK provided */
+       rt5616->mclk = devm_clk_get(codec->dev, "mclk");
+       if (PTR_ERR(rt5616->mclk) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+
        rt5616->codec = codec;
 
        return 0;