|
@@ -789,11 +789,27 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
|
|
|
struct snd_kcontrol *kcontrol, int event)
|
|
|
{
|
|
|
struct snd_soc_codec *codec = w->codec;
|
|
|
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
|
|
|
|
|
|
switch (event) {
|
|
|
case SND_SOC_DAPM_PRE_PMU:
|
|
|
return configure_clock(codec);
|
|
|
|
|
|
+ case SND_SOC_DAPM_POST_PMU:
|
|
|
+ /*
|
|
|
+ * JACKDET won't run until we start the clock and it
|
|
|
+ * only reports deltas, make sure we notify the state
|
|
|
+ * up the stack on startup. Use a *very* generous
|
|
|
+ * timeout for paranoia, there's no urgency and we
|
|
|
+ * don't want false reports.
|
|
|
+ */
|
|
|
+ if (wm8994->jackdet && !wm8994->clk_has_run) {
|
|
|
+ schedule_delayed_work(&wm8994->jackdet_bootstrap,
|
|
|
+ msecs_to_jiffies(1000));
|
|
|
+ wm8994->clk_has_run = true;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
case SND_SOC_DAPM_POST_PMD:
|
|
|
configure_clock(codec);
|
|
|
break;
|
|
@@ -1632,7 +1648,8 @@ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event,
|
|
|
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
|
|
|
|
|
SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event,
|
|
|
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
|
|
|
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
|
|
|
+ SND_SOC_DAPM_PRE_PMD),
|
|
|
|
|
|
SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0),
|
|
|
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)
|
|
|
SND_JACK_MECHANICAL | SND_JACK_HEADSET |
|
|
|
wm8994->btn_mask);
|
|
|
|
|
|
+ /* Since we only report deltas force an update, ensures we
|
|
|
+ * avoid bootstrapping issues with the core. */
|
|
|
+ snd_soc_jack_report(wm8994->micdet[0].jack, 0, 0);
|
|
|
+
|
|
|
pm_runtime_put(codec->dev);
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
+static void wm1811_jackdet_bootstrap(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct wm8994_priv *wm8994 = container_of(work,
|
|
|
+ struct wm8994_priv,
|
|
|
+ jackdet_bootstrap.work);
|
|
|
+ wm1811_jackdet_irq(0, wm8994);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ
|
|
|
*
|
|
@@ -3582,6 +3611,10 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
|
|
|
* otherwise jump straight to microphone detection.
|
|
|
*/
|
|
|
if (wm8994->jackdet) {
|
|
|
+ /* Disable debounce for the initial detect */
|
|
|
+ snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
|
|
|
+ WM1811_JACKDET_DB, 0);
|
|
|
+
|
|
|
snd_soc_update_bits(codec, WM8958_MICBIAS2,
|
|
|
WM8958_MICB2_DISCH,
|
|
|
WM8958_MICB2_DISCH);
|
|
@@ -3706,6 +3739,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
|
|
|
|
|
|
mutex_init(&wm8994->accdet_lock);
|
|
|
INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
|
|
|
+ INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
|
|
|
+ wm1811_jackdet_bootstrap);
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
|
|
|
init_completion(&wm8994->fll_locked[i]);
|