diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-07-25 18:03:36 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-08-03 18:03:56 -0400 |
commit | 99af79dff5a609fe886d271bbc91e1a95eca3066 (patch) | |
tree | 204f77752d1f2a7939ad2ba58d9f8b32ff86d701 | |
parent | 8cb8e83bfa7cb63ad4b3c3b79410766da397124b (diff) |
ASoC: wm8994: Ensure we get a notification on startup for jackdet
Since jackdet only reports deltas it won't generate an interrupt on startup
when a jack is not present. This doesn't make a difference to userspace
but does mean we don't generate a notification via the internal notifier
chains. Fix that by scheduling a work to poll the chip after the clock is
enabled. Use an extremely large timeout since there's no urgency and we
don't want to report a false negative.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | sound/soc/codecs/wm8994.c | 37 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994.h | 2 |
2 files changed, 38 insertions, 1 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 1237c11c8c35..7bb0c2c824cc 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -789,11 +789,27 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, | |||
789 | struct snd_kcontrol *kcontrol, int event) | 789 | struct snd_kcontrol *kcontrol, int event) |
790 | { | 790 | { |
791 | struct snd_soc_codec *codec = w->codec; | 791 | struct snd_soc_codec *codec = w->codec; |
792 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
792 | 793 | ||
793 | switch (event) { | 794 | switch (event) { |
794 | case SND_SOC_DAPM_PRE_PMU: | 795 | case SND_SOC_DAPM_PRE_PMU: |
795 | return configure_clock(codec); | 796 | return configure_clock(codec); |
796 | 797 | ||
798 | case SND_SOC_DAPM_POST_PMU: | ||
799 | /* | ||
800 | * JACKDET won't run until we start the clock and it | ||
801 | * only reports deltas, make sure we notify the state | ||
802 | * up the stack on startup. Use a *very* generous | ||
803 | * timeout for paranoia, there's no urgency and we | ||
804 | * don't want false reports. | ||
805 | */ | ||
806 | if (wm8994->jackdet && !wm8994->clk_has_run) { | ||
807 | schedule_delayed_work(&wm8994->jackdet_bootstrap, | ||
808 | msecs_to_jiffies(1000)); | ||
809 | wm8994->clk_has_run = true; | ||
810 | } | ||
811 | break; | ||
812 | |||
797 | case SND_SOC_DAPM_POST_PMD: | 813 | case SND_SOC_DAPM_POST_PMD: |
798 | configure_clock(codec); | 814 | configure_clock(codec); |
799 | break; | 815 | break; |
@@ -1632,7 +1648,8 @@ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, | |||
1632 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 1648 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1633 | 1649 | ||
1634 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, | 1650 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, |
1635 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 1651 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1652 | SND_SOC_DAPM_PRE_PMD), | ||
1636 | 1653 | ||
1637 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), | 1654 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), |
1638 | SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), | 1655 | SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), |
@@ -3508,10 +3525,22 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
3508 | SND_JACK_MECHANICAL | SND_JACK_HEADSET | | 3525 | SND_JACK_MECHANICAL | SND_JACK_HEADSET | |
3509 | wm8994->btn_mask); | 3526 | wm8994->btn_mask); |
3510 | 3527 | ||
3528 | /* Since we only report deltas force an update, ensures we | ||
3529 | * avoid bootstrapping issues with the core. */ | ||
3530 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, 0); | ||
3531 | |||
3511 | pm_runtime_put(codec->dev); | 3532 | pm_runtime_put(codec->dev); |
3512 | return IRQ_HANDLED; | 3533 | return IRQ_HANDLED; |
3513 | } | 3534 | } |
3514 | 3535 | ||
3536 | static void wm1811_jackdet_bootstrap(struct work_struct *work) | ||
3537 | { | ||
3538 | struct wm8994_priv *wm8994 = container_of(work, | ||
3539 | struct wm8994_priv, | ||
3540 | jackdet_bootstrap.work); | ||
3541 | wm1811_jackdet_irq(0, wm8994); | ||
3542 | } | ||
3543 | |||
3515 | /** | 3544 | /** |
3516 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ | 3545 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ |
3517 | * | 3546 | * |
@@ -3582,6 +3611,10 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3582 | * otherwise jump straight to microphone detection. | 3611 | * otherwise jump straight to microphone detection. |
3583 | */ | 3612 | */ |
3584 | if (wm8994->jackdet) { | 3613 | if (wm8994->jackdet) { |
3614 | /* Disable debounce for the initial detect */ | ||
3615 | snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, | ||
3616 | WM1811_JACKDET_DB, 0); | ||
3617 | |||
3585 | snd_soc_update_bits(codec, WM8958_MICBIAS2, | 3618 | snd_soc_update_bits(codec, WM8958_MICBIAS2, |
3586 | WM8958_MICB2_DISCH, | 3619 | WM8958_MICB2_DISCH, |
3587 | WM8958_MICB2_DISCH); | 3620 | WM8958_MICB2_DISCH); |
@@ -3706,6 +3739,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3706 | 3739 | ||
3707 | mutex_init(&wm8994->accdet_lock); | 3740 | mutex_init(&wm8994->accdet_lock); |
3708 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); | 3741 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); |
3742 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, | ||
3743 | wm1811_jackdet_bootstrap); | ||
3709 | 3744 | ||
3710 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | 3745 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
3711 | init_completion(&wm8994->fll_locked[i]); | 3746 | init_completion(&wm8994->fll_locked[i]); |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index e6d8209b8f29..f142ec198db3 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -81,6 +81,7 @@ struct wm8994_priv { | |||
81 | struct completion fll_locked[2]; | 81 | struct completion fll_locked[2]; |
82 | bool fll_locked_irq; | 82 | bool fll_locked_irq; |
83 | bool fll_byp; | 83 | bool fll_byp; |
84 | bool clk_has_run; | ||
84 | 85 | ||
85 | int vmid_refcount; | 86 | int vmid_refcount; |
86 | int active_refcount; | 87 | int active_refcount; |
@@ -134,6 +135,7 @@ struct wm8994_priv { | |||
134 | int btn_mask; | 135 | int btn_mask; |
135 | bool jackdet; | 136 | bool jackdet; |
136 | int jackdet_mode; | 137 | int jackdet_mode; |
138 | struct delayed_work jackdet_bootstrap; | ||
137 | 139 | ||
138 | wm8958_micdet_cb jack_cb; | 140 | wm8958_micdet_cb jack_cb; |
139 | void *jack_cb_data; | 141 | void *jack_cb_data; |