ASoC: rt5640: add master clock handling for rt5640
authorSugar Zhang <sugar.zhang@rock-chips.com>
Fri, 19 Feb 2016 05:03:19 +0000 (13:03 +0800)
committerSugar Zhang <sugar.zhang@rock-chips.com>
Fri, 19 Feb 2016 08:34:19 +0000 (16:34 +0800)
enable/disable master clock when codec is active or not.

Change-Id: Ia876abde08138c4f23ed5a1a684f6637c42d5e34
Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Documentation/devicetree/bindings/sound/rt5640.txt
sound/soc/codecs/rt5640.c
sound/soc/codecs/rt5640.h

index 9e62f6eb348f9499923dbcb473dad6ff22678bfa..57fe64643050a5e9f41072dd0d4ae0376f5d6958 100644 (file)
@@ -12,6 +12,9 @@ Required properties:
 
 Optional properties:
 
+- clocks: The phandle of the master clock to the CODEC
+- clock-names: Should be "mclk"
+
 - realtek,in1-differential
 - realtek,in2-differential
 - realtek,in3-differential
index f2beb1aa5763dfe99dc6de821f4c9367446773a7..09288233d3c4f3074ab2abc7c7d392ceb8430fe8 100644 (file)
@@ -1917,7 +1917,33 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 static int rt5640_set_bias_level(struct snd_soc_codec *codec,
                        enum snd_soc_bias_level level)
 {
+       struct rt5640_priv *rt5640 = 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(rt5640->mclk))
+                       break;
+
+               if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) {
+                       clk_disable_unprepare(rt5640->mclk);
+               } else {
+                       ret = clk_prepare_enable(rt5640->mclk);
+                       if (ret)
+                               return ret;
+               }
+               break;
+
        case SND_SOC_BIAS_STANDBY:
                if (SND_SOC_BIAS_OFF == snd_soc_codec_get_bias_level(codec)) {
                        snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
@@ -1986,6 +2012,11 @@ static int rt5640_probe(struct snd_soc_codec *codec)
        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
        struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
 
+       /* Check if MCLK provided */
+       rt5640->mclk = devm_clk_get(codec->dev, "mclk");
+       if (PTR_ERR(rt5640->mclk) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+
        rt5640->codec = codec;
 
        snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
index 3deb8babeabb691d37a314bb3ab19c84d5c9cd1f..084507d15c580d27213308d2d687bc3e3a1f72a3 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _RT5640_H
 #define _RT5640_H
 
+#include <linux/clk.h>
 #include <sound/rt5640.h>
 
 /* Info */
@@ -2083,6 +2084,7 @@ struct rt5640_priv {
        struct snd_soc_codec *codec;
        struct rt5640_platform_data pdata;
        struct regmap *regmap;
+       struct clk *mclk;
 
        int sysclk;
        int sysclk_src;