From e47ac37c01bd9bd840dbbbc57a6dc1ba1e49ccc0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 25 Apr 2011 20:14:21 +0100 Subject: [PATCH] ASoC: Implement WM8962 DMIC support DMIC support is automatically disabled when none of the GPIOs are set up to bring out the DMICCLK and DMICDAT pins at startup. Note that there's no support for controlling DMIC routing except the power control so the board DAPM configuration will need to manage DMIC enable and disable if analogue mics (eg, a headset) also exist. Signed-off-by: Mark Brown Acked-by: Liam Girdwood --- sound/soc/codecs/wm8962.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 549018e46233..ec4417a5e669 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2468,6 +2468,7 @@ SND_SOC_DAPM_INPUT("IN3R"), SND_SOC_DAPM_INPUT("IN4L"), SND_SOC_DAPM_INPUT("IN4R"), SND_SOC_DAPM_INPUT("Beep"), +SND_SOC_DAPM_INPUT("DMICDAT"), SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0), @@ -2487,6 +2488,8 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0, SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0, mixinr, ARRAY_SIZE(mixinr)), +SND_SOC_DAPM_AIF_IN("DMIC", NULL, 0, WM8962_PWR_MGMT_1, 10, 0), + SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0), SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0), @@ -2564,13 +2567,17 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { { "MICBIAS", NULL, "SYSCLK" }, + { "DMIC", NULL, "DMICDAT" }, + { "ADCL", NULL, "SYSCLK" }, { "ADCL", NULL, "TOCLK" }, { "ADCL", NULL, "MIXINL" }, + { "ADCL", NULL, "DMIC" }, { "ADCR", NULL, "SYSCLK" }, { "ADCR", NULL, "TOCLK" }, { "ADCR", NULL, "MIXINR" }, + { "ADCR", NULL, "DMIC" }, { "STL", "Left", "ADCL" }, { "STL", "Right", "ADCR" }, @@ -3719,6 +3726,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) dev); u16 *reg_cache = codec->reg_cache; int i, trigger, irq_pol; + bool dmicclk, dmicdat; wm8962->codec = codec; INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work); @@ -3856,6 +3864,29 @@ static int wm8962_probe(struct snd_soc_codec *codec) wm8962_add_widgets(codec); + /* Save boards having to disable DMIC when not in use */ + dmicclk = false; + dmicdat = false; + for (i = 0; i < WM8962_MAX_GPIO; i++) { + switch (snd_soc_read(codec, WM8962_GPIO_BASE + i) + & WM8962_GP2_FN_MASK) { + case WM8962_GPIO_FN_DMICCLK: + dmicclk = true; + break; + case WM8962_GPIO_FN_DMICDAT: + dmicdat = true; + break; + default: + break; + } + } + if (!dmicclk || !dmicdat) { + dev_dbg(codec->dev, "DMIC not in use, disabling\n"); + snd_soc_dapm_nc_pin(&codec->dapm, "DMICDAT"); + } + if (dmicclk != dmicdat) + dev_warn(codec->dev, "DMIC GPIOs partially configured\n"); + wm8962_init_beep(codec); wm8962_init_gpio(codec); -- 2.11.0