summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-09-28 16:50:15 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-10-15 11:51:32 +0900
commitc0cc3f1665256b7cfdc1d581f997dcea1af71405 (patch)
tree53f064b7140e727147a9251baaf4dac25541edd6
parentddffeb8c4d0331609ef2581d84de4d763607bd37 (diff)
downloadop-kernel-dev-c0cc3f1665256b7cfdc1d581f997dcea1af71405.zip
op-kernel-dev-c0cc3f1665256b7cfdc1d581f997dcea1af71405.tar.gz
ASoC: wm8994: Allow a delay between jack insertion and microphone detect
This can be used to provide some additional settling time to ensure that we don't start microphone detection while the microphone pin is connected to one of the headphone pins. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--include/linux/mfd/wm8994/pdata.h5
-rw-r--r--sound/soc/codecs/wm8994.c74
2 files changed, 60 insertions, 19 deletions
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index fc87be4..8e21a09 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -176,6 +176,11 @@ struct wm8994_pdata {
unsigned int lineout1fb:1;
unsigned int lineout2fb:1;
+ /* Delay between detecting a jack and starting microphone
+ * detect (specified in ms)
+ */
+ int micdet_delay;
+
/* IRQ for microphone detection if brought out directly as a
* signal.
*/
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 2b2dadc..07095a9 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -3470,11 +3470,46 @@ static void wm8958_default_micdet(u16 status, void *data)
}
}
+/* Deferred mic detection to allow for extra settling time */
+static void wm1811_mic_work(struct work_struct *work)
+{
+ struct wm8994_priv *wm8994 = container_of(work, struct wm8994_priv,
+ mic_work.work);
+ struct snd_soc_codec *codec = wm8994->hubs.codec;
+
+ pm_runtime_get_sync(codec->dev);
+
+ /* If required for an external cap force MICBIAS on */
+ if (wm8994->pdata->jd_ext_cap) {
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS2");
+ snd_soc_dapm_sync(&codec->dapm);
+ }
+
+ mutex_lock(&wm8994->accdet_lock);
+
+ dev_dbg(codec->dev, "Starting mic detection\n");
+
+ /*
+ * Start off measument of microphone impedence to find out
+ * what's actually there.
+ */
+ wm8994->mic_detecting = true;
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
+
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+ WM8958_MICD_ENA, WM8958_MICD_ENA);
+
+ mutex_unlock(&wm8994->accdet_lock);
+
+ pm_runtime_put(codec->dev);
+}
+
static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
{
struct wm8994_priv *wm8994 = data;
struct snd_soc_codec *codec = wm8994->hubs.codec;
- int reg;
+ int reg, delay;
bool present;
pm_runtime_get_sync(codec->dev);
@@ -3505,18 +3540,14 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
WM1811_JACKDET_DB, 0);
- /*
- * Start off measument of microphone impedence to find
- * out what's actually there.
- */
- wm8994->mic_detecting = true;
- wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
-
- snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
- WM8958_MICD_ENA, WM8958_MICD_ENA);
+ delay = wm8994->pdata->micdet_delay;
+ schedule_delayed_work(&wm8994->mic_work,
+ msecs_to_jiffies(delay));
} else {
dev_dbg(codec->dev, "Jack not detected\n");
+ cancel_delayed_work_sync(&wm8994->mic_work);
+
snd_soc_update_bits(codec, WM8958_MICBIAS2,
WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
@@ -3533,14 +3564,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
mutex_unlock(&wm8994->accdet_lock);
- /* If required for an external cap force MICBIAS on */
- if (wm8994->pdata->jd_ext_cap) {
- if (present)
- snd_soc_dapm_force_enable_pin(&codec->dapm,
- "MICBIAS2");
- else
- snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
- }
+ /* Turn off MICBIAS if it was on for an external cap */
+ if (wm8994->pdata->jd_ext_cap && !present)
+ snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
if (present)
snd_soc_jack_report(wm8994->micdet[0].jack,
@@ -3763,10 +3789,20 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
mutex_init(&wm8994->accdet_lock);
- INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
wm1811_jackdet_bootstrap);
+ switch (control->type) {
+ case WM8994:
+ INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
+ break;
+ case WM1811:
+ INIT_DELAYED_WORK(&wm8994->mic_work, wm1811_mic_work);
+ break;
+ default:
+ break;
+ }
+
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
init_completion(&wm8994->fll_locked[i]);
OpenPOWER on IntegriCloud