Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 99af79df authored by Mark Brown's avatar Mark Brown
Browse files

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: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 8cb8e83b
Loading
Loading
Loading
Loading
+36 −1
Original line number Original line Diff line number Diff line
@@ -789,11 +789,27 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
			 struct snd_kcontrol *kcontrol, int event)
			 struct snd_kcontrol *kcontrol, int event)
{
{
	struct snd_soc_codec *codec = w->codec;
	struct snd_soc_codec *codec = w->codec;
	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);


	switch (event) {
	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
	case SND_SOC_DAPM_PRE_PMU:
		return configure_clock(codec);
		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:
	case SND_SOC_DAPM_POST_PMD:
		configure_clock(codec);
		configure_clock(codec);
		break;
		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_PRE_PMU | SND_SOC_DAPM_POST_PMD),


SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event,
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("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 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 |
				    SND_JACK_MECHANICAL | SND_JACK_HEADSET |
				    wm8994->btn_mask);
				    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);
	pm_runtime_put(codec->dev);
	return IRQ_HANDLED;
	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
 * 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.
		 * otherwise jump straight to microphone detection.
		 */
		 */
		if (wm8994->jackdet) {
		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,
			snd_soc_update_bits(codec, WM8958_MICBIAS2,
					    WM8958_MICB2_DISCH,
					    WM8958_MICB2_DISCH,
					    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);
	mutex_init(&wm8994->accdet_lock);
	INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
	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++)
	for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
		init_completion(&wm8994->fll_locked[i]);
		init_completion(&wm8994->fll_locked[i]);
+2 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,7 @@ struct wm8994_priv {
	struct completion fll_locked[2];
	struct completion fll_locked[2];
	bool fll_locked_irq;
	bool fll_locked_irq;
	bool fll_byp;
	bool fll_byp;
	bool clk_has_run;


	int vmid_refcount;
	int vmid_refcount;
	int active_refcount;
	int active_refcount;
@@ -134,6 +135,7 @@ struct wm8994_priv {
	int btn_mask;
	int btn_mask;
	bool jackdet;
	bool jackdet;
	int jackdet_mode;
	int jackdet_mode;
	struct delayed_work jackdet_bootstrap;


	wm8958_micdet_cb jack_cb;
	wm8958_micdet_cb jack_cb;
	void *jack_cb_data;
	void *jack_cb_data;