[alsa-devel] [PATCH] ASoC: wm8994: codec driver should manage its own MCLK

Zidan Wang zidan.wang at freescale.com
Thu Mar 3 07:45:35 CET 2016


codec driver should manage its own master clock, MCLK1 and MCLK2.
When bias_level change from standby to prepare, enable codec MCLK.
When bias_level change from prepare to standby, disable codec MCLK.

Signed-off-by: Zidan Wang <zidan.wang at freescale.com>
---
 drivers/mfd/wm8994-core.c        |  7 +++++++
 include/linux/mfd/wm8994/pdata.h |  3 +++
 sound/soc/codecs/wm8994.c        | 17 +++++++++++++++--
 3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 7eec619..ace2cea 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/err.h>
@@ -270,6 +271,7 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
 {
 	struct device_node *np = wm8994->dev->of_node;
 	struct wm8994_pdata *pdata = &wm8994->pdata;
+	char tmp[8];
 	int i;
 
 	if (!np)
@@ -310,6 +312,11 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
 	if (pdata->ldo[1].enable < 0)
 		pdata->ldo[1].enable = 0;
 
+	for (i = 0; i < WM8994_NUM_MCLK; i++) {
+		sprintf(tmp, "MCLK%d", i + 1);
+		pdata->mclk[i] = devm_clk_get(wm8994->dev, tmp);
+	}
+
 	return 0;
 }
 #else
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index 90c6052..657a828 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -18,6 +18,7 @@
 #define WM8994_NUM_LDO   2
 #define WM8994_NUM_GPIO 11
 #define WM8994_NUM_AIF   3
+#define WM8994_NUM_MCLK  2
 
 struct wm8994_ldo_pdata {
 	/** GPIOs to enable regulator, 0 or less if not available */
@@ -233,6 +234,8 @@ struct wm8994_pdata {
 	 * GPIO for the IRQ pin if host only supports edge triggering
 	 */
 	int irq_gpio;
+
+	struct clk *mclk[WM8994_NUM_MCLK];
 };
 
 #endif
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 2ccbb32..7379eae 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/gcd.h>
+#include <linux/clk.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
@@ -2474,6 +2475,8 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
 {
 	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	struct wm8994 *control = wm8994->wm8994;
+	struct wm8994_pdata *pdata = &control->pdata;
+	int i;
 
 	wm_hubs_set_bias_level(codec, level);
 
@@ -2495,8 +2498,13 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
 			break;
 		}
 
-		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY)
+		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) {
 			active_reference(codec);
+
+			for (i = 0; i < WM8994_NUM_MCLK; i++)
+				if (!IS_ERR(pdata->mclk[i]))
+					clk_prepare_enable(pdata->mclk[i]);
+		}
 		break;
 
 	case SND_SOC_BIAS_STANDBY:
@@ -2524,8 +2532,13 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
 					    WM8994_LINEOUT2_DISCH);
 		}
 
-		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE)
+		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) {
+			for (i = 0; i < WM8994_NUM_MCLK; i++)
+				if (!IS_ERR(pdata->mclk[i]))
+					clk_disable_unprepare(pdata->mclk[i]);
+
 			active_dereference(codec);
+		}
 
 		/* MICBIAS into bypass mode on newer devices */
 		switch (control->type) {
-- 
1.9.1



More information about the Alsa-devel mailing list