[alsa-devel] [PATCH] ASoC: wm8994: codec driver should manage its own MCLK
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@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) {
On Thu, Mar 03, 2016 at 02:45:35PM +0800, Zidan Wang wrote:
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.
Not sure the desired sequence here, would be neater to use runtime pm?
@@ -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);
Probe defer?
@@ -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]);
Return value? You probably should refer to wm8962 or wm8960.
On Thu, Mar 03, 2016 at 02:45:35PM +0800, Zidan Wang wrote:
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;}
This is unconditionally enabling both mclks but the device has a wide range of options with what it can do with clocks, it doesn't need to use both.
participants (3)
-
Mark Brown
-
Nicolin Chen
-
Zidan Wang