From 87092e3ca4ff7b2c2d7723b3402fe2f74b249bc4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 6 Feb 2012 18:50:39 +0000 Subject: [PATCH] ASoC: wm8994: Bring WM8994 accessory detection up to date Make the mechanism used for WM8994 more like that for WM1811 and WM8958: provide the logic to distinguish between headphone and headset and hard code the reporting of sensible SND_JACK values. Should integration with other detection mechanisms be required we can add appropriate callbacks (though some integrations should be able to use the subsystem ones). Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 82 +++++++++++++++++++++++++++++---------- sound/soc/codecs/wm8994.h | 5 +-- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6a47c75119bd..8aed0e3c6131 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2946,8 +2946,6 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) * @codec: WM8994 codec * @jack: jack to report detection events on * @micbias: microphone bias to detect on - * @det: value to report for presence detection - * @shrt: value to report for short detection * * Enable microphone detection via IRQ on the WM8994. If GPIOs are * being used to bring out signals to the processor then only platform @@ -2958,43 +2956,63 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) * and micbias2_lvl platform data members. */ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, - int micbias, int det, int shrt) + int micbias) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); struct wm8994_micdet *micdet; struct wm8994 *control = wm8994->wm8994; - int reg; + int reg, ret; - if (control->type != WM8994) + if (control->type != WM8994) { + dev_warn(codec->dev, "Not a WM8994\n"); return -EINVAL; + } switch (micbias) { case 1: micdet = &wm8994->micdet[0]; + if (jack) + ret = snd_soc_dapm_force_enable_pin(&codec->dapm, + "MICBIAS1"); + else + ret = snd_soc_dapm_disable_pin(&codec->dapm, + "MICBIAS1"); break; case 2: micdet = &wm8994->micdet[1]; + if (jack) + ret = snd_soc_dapm_force_enable_pin(&codec->dapm, + "MICBIAS1"); + else + ret = snd_soc_dapm_disable_pin(&codec->dapm, + "MICBIAS1"); break; default: + dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias); return -EINVAL; - } + } - dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n", - micbias, det, shrt); + if (ret != 0) + dev_warn(codec->dev, "Failed to configure MICBIAS%d: %d\n", + micbias, ret); + + dev_dbg(codec->dev, "Configuring microphone detection on %d %p\n", + micbias, jack); /* Store the configuration */ micdet->jack = jack; - micdet->det = det; - micdet->shrt = shrt; + micdet->detecting = true; /* If either of the jacks is set up then enable detection */ if (wm8994->micdet[0].jack || wm8994->micdet[1].jack) reg = WM8994_MICD_ENA; - else + else reg = 0; snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); + snd_soc_dapm_sync(&codec->dapm); + return 0; } EXPORT_SYMBOL_GPL(wm8994_mic_detect); @@ -3020,20 +3038,42 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) dev_dbg(codec->dev, "Microphone status: %x\n", reg); report = 0; - if (reg & WM8994_MIC1_DET_STS) - report |= priv->micdet[0].det; - if (reg & WM8994_MIC1_SHRT_STS) - report |= priv->micdet[0].shrt; + if (reg & WM8994_MIC1_DET_STS) { + if (priv->micdet[0].detecting) + report = SND_JACK_HEADSET; + } + if (reg & WM8994_MIC1_SHRT_STS) { + if (priv->micdet[0].detecting) + report = SND_JACK_HEADPHONE; + else + report |= SND_JACK_BTN_0; + } + if (report) + priv->micdet[0].detecting = false; + else + priv->micdet[0].detecting = true; + snd_soc_jack_report(priv->micdet[0].jack, report, - priv->micdet[0].det | priv->micdet[0].shrt); + SND_JACK_HEADSET | SND_JACK_BTN_0); report = 0; - if (reg & WM8994_MIC2_DET_STS) - report |= priv->micdet[1].det; - if (reg & WM8994_MIC2_SHRT_STS) - report |= priv->micdet[1].shrt; + if (reg & WM8994_MIC2_DET_STS) { + if (priv->micdet[1].detecting) + report = SND_JACK_HEADSET; + } + if (reg & WM8994_MIC2_SHRT_STS) { + if (priv->micdet[1].detecting) + report = SND_JACK_HEADPHONE; + else + report |= SND_JACK_BTN_0; + } + if (report) + priv->micdet[1].detecting = false; + else + priv->micdet[1].detecting = true; + snd_soc_jack_report(priv->micdet[1].jack, report, - priv->micdet[1].det | priv->micdet[1].shrt); + SND_JACK_HEADSET | SND_JACK_BTN_0); return IRQ_HANDLED; } diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index c3a42474ab19..f996d14766d9 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -35,7 +35,7 @@ typedef void (*wm8958_micdet_cb)(u16 status, void *data); int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, - int micbias, int det, int shrt); + int micbias); int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, wm8958_micdet_cb cb, void *cb_data); @@ -46,8 +46,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec); struct wm8994_micdet { struct snd_soc_jack *jack; - int det; - int shrt; + bool detecting; }; /* codec private data */ -- 2.20.1