* [PATCH v3] ASoC: wm8962: Stop IRQ from requeuing mic_work on remove
@ 2026-09-24 22:05 mhun512
2026-09-25 9:08 ` Charles Keepax
0 siblings, 1 reply; 3+ messages in thread
From: mhun512 @ 2026-09-24 22:05 UTC (permalink / raw)
To: lgirdwood, broonie, perex, tiwai
Cc: ckeepax, patches, linux-sound, linux-kernel, stable, ae878000
The WM8962 IRQ remains registered to the I2C device when an ASoC card is
unbound. wm8962_remove() cancels mic_work, but a MICD or MICSCD interrupt
can queue it again before the component is destroyed. The work then
accesses the component and reports to the old jack.
Mask microphone interrupts in wm8962_mic_detect(), wait for a handler
that may already have read the mask, and drain mic_work before changing
the jack pointer. Install a new jack before unmasking the interrupts.
Call this path from wm8962_remove() while the component is still valid.
Leave the IRQ registered for FLL, FIFO and thermal events.
Tegra's card remove callback runs after ASoC removes the codec component
and PCM runtimes. Drop its redundant microphone cleanup.
Fixes: 0512615db6db ("ASoC: wm8962: Convert interrupt handler to
direct regmap usage")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
Changes in v3:
- Use the existing microphone interrupt mask in wm8962_mic_detect() to
stop new work, then synchronize the IRQ and cancel pending work before
changing the jack pointer.
- Call wm8962_mic_detect() from the codec remove callback and drop the
now-redundant Tegra card remove callback.
- Keep the IRQ registered for the other interrupt sources.
Changes in v2:
- Do not disable the IRQ from wm8962_i2c_remove(); card unbind does not
unbind the I2C client.
- Keep the devm IRQ on the I2C device for FLL, FIFO and thermal events.
Found by inspection; I do not have the hardware, so this is not runtime
tested. The modified codec and Tegra objects compile, and checkpatch
reports no errors or warnings.
sound/soc/codecs/wm8962.c | 29 ++++++++++++++---------------
sound/soc/tegra/tegra_wm8962.c | 13 -------------
2 files changed, 14 insertions(+), 28 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 8a9598161b35..7b09de65a009 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3230,21 +3230,22 @@ int wm8962_mic_detect(struct snd_soc_component
*component, struct snd_soc_jack *
{
struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
- int irq_mask, enable;
-
- wm8962->jack = jack;
- if (jack) {
- irq_mask = 0;
- enable = WM8962_MICDET_ENA;
- } else {
- irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT;
- enable = 0;
- }
+ int mic_irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT;
+ /* Mask microphone events, then drain the IRQ and work before
changing the jack. */
snd_soc_component_update_bits(component, WM8962_INTERRUPT_STATUS_2_MASK,
- WM8962_MICD_EINT | WM8962_MICSCD_EINT, irq_mask);
+ mic_irq_mask, mic_irq_mask);
snd_soc_component_update_bits(component, WM8962_ADDITIONAL_CONTROL_4,
- WM8962_MICDET_ENA, enable);
+ WM8962_MICDET_ENA, jack ? WM8962_MICDET_ENA : 0);
+ if (wm8962->irq)
+ synchronize_irq(wm8962->irq);
+ cancel_delayed_work_sync(&wm8962->mic_work);
+
+ wm8962->jack = jack;
+ if (jack)
+ snd_soc_component_update_bits(component,
+ WM8962_INTERRUPT_STATUS_2_MASK,
+ mic_irq_mask, 0);
/* Send an initial empty report */
snd_soc_jack_report(wm8962->jack, 0,
@@ -3592,9 +3593,7 @@ static int wm8962_probe(struct snd_soc_component
*component)
static void wm8962_remove(struct snd_soc_component *component)
{
- struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
-
- cancel_delayed_work_sync(&wm8962->mic_work);
+ wm8962_mic_detect(component, NULL);
wm8962_free_gpio(component);
wm8962_free_beep(component);
diff --git a/sound/soc/tegra/tegra_wm8962.c b/sound/soc/tegra/tegra_wm8962.c
index 31f9d9181595..a79d464b6a80 100644
--- a/sound/soc/tegra/tegra_wm8962.c
+++ b/sound/soc/tegra/tegra_wm8962.c
@@ -97,18 +97,6 @@ static int tegra_wm8962_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-static int tegra_wm8962_remove(struct snd_soc_card *card)
-{
- struct snd_soc_dai_link *link = &card->dai_link[0];
- struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card, link);
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- struct snd_soc_component *component = codec_dai->component;
-
- wm8962_mic_detect(component, NULL);
-
- return 0;
-}
-
SND_SOC_DAILINK_DEFS(wm8962_hifi,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8962")),
@@ -129,7 +117,6 @@ static struct snd_soc_card snd_soc_tegra_wm8962 = {
.owner = THIS_MODULE,
.dai_link = &tegra_wm8962_dai,
.num_links = 1,
- .remove = tegra_wm8962_remove,
.fully_routed = true,
};
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH v3] ASoC: wm8962: Stop IRQ from requeuing mic_work on remove
2026-09-24 22:05 [PATCH v3] ASoC: wm8962: Stop IRQ from requeuing mic_work on remove mhun512
@ 2026-09-25 9:08 ` Charles Keepax
2026-09-25 9:31 ` Charles Keepax
0 siblings, 1 reply; 3+ messages in thread
From: Charles Keepax @ 2026-09-25 9:08 UTC (permalink / raw)
To: mhun512
Cc: lgirdwood, broonie, perex, tiwai, patches, linux-sound,
linux-kernel, stable, ae878000
On Thu, Sep 24, 2026 at 03:05:41PM -0700, mhun512@gmail.com wrote:
> diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
> index 8a9598161b35..7b09de65a009 100644
> --- a/sound/soc/codecs/wm8962.c
> +++ b/sound/soc/codecs/wm8962.c
> @@ -3230,21 +3230,22 @@ int wm8962_mic_detect(struct snd_soc_component
> *component, struct snd_soc_jack *
> {
> struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
> struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
> - int irq_mask, enable;
> -
> - wm8962->jack = jack;
> - if (jack) {
> - irq_mask = 0;
> - enable = WM8962_MICDET_ENA;
> - } else {
> - irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT;
> - enable = 0;
> - }
> + int mic_irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT;
>
> + /* Mask microphone events, then drain the IRQ and work before
> changing the jack. */
Your email client appears to be corrupting the patch here, this
won't apply.
> snd_soc_component_update_bits(component, WM8962_INTERRUPT_STATUS_2_MASK,
> - WM8962_MICD_EINT | WM8962_MICSCD_EINT, irq_mask);
> + mic_irq_mask, mic_irq_mask);
> snd_soc_component_update_bits(component, WM8962_ADDITIONAL_CONTROL_4,
> - WM8962_MICDET_ENA, enable);
> + WM8962_MICDET_ENA, jack ? WM8962_MICDET_ENA : 0);
I would be tempted to just always disable here.
> + if (wm8962->irq)
> + synchronize_irq(wm8962->irq);
> + cancel_delayed_work_sync(&wm8962->mic_work);
> +
> + wm8962->jack = jack;
> + if (jack)
> + snd_soc_component_update_bits(component,
> + WM8962_INTERRUPT_STATUS_2_MASK,
> + mic_irq_mask, 0);
And then enable here, if needed. The current patch changes from
enabling after the IRQ is unmasked to enabling whilst it is
masked. Since neither of us have hardware its probably better not
to change that sequencing.
>
> /* Send an initial empty report */
> snd_soc_jack_report(wm8962->jack, 0,
> @@ -3592,9 +3593,7 @@ static int wm8962_probe(struct snd_soc_component
> *component)
>
> static void wm8962_remove(struct snd_soc_component *component)
> {
> - struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
> -
> - cancel_delayed_work_sync(&wm8962->mic_work);
> + wm8962_mic_detect(component, NULL);
>
> wm8962_free_gpio(component);
> wm8962_free_beep(component);
> diff --git a/sound/soc/tegra/tegra_wm8962.c b/sound/soc/tegra/tegra_wm8962.c
> index 31f9d9181595..a79d464b6a80 100644
> --- a/sound/soc/tegra/tegra_wm8962.c
> +++ b/sound/soc/tegra/tegra_wm8962.c
> @@ -97,18 +97,6 @@ static int tegra_wm8962_init(struct snd_soc_pcm_runtime *rtd)
> return 0;
> }
>
> -static int tegra_wm8962_remove(struct snd_soc_card *card)
> -{
> - struct snd_soc_dai_link *link = &card->dai_link[0];
> - struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card, link);
> - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
> - struct snd_soc_component *component = codec_dai->component;
> -
> - wm8962_mic_detect(component, NULL);
> -
> - return 0;
> -}
I don't think you should remove this. It is possible to remove
the machine driver but not the codec driver, and in that case you
still want the mic_detect disabled.
Thanks,
Charles
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH v3] ASoC: wm8962: Stop IRQ from requeuing mic_work on remove
2026-09-25 9:08 ` Charles Keepax
@ 2026-09-25 9:31 ` Charles Keepax
0 siblings, 0 replies; 3+ messages in thread
From: Charles Keepax @ 2026-09-25 9:31 UTC (permalink / raw)
To: mhun512
Cc: lgirdwood, broonie, perex, tiwai, patches, linux-sound,
linux-kernel, stable, ae878000
On Fri, Sep 25, 2026 at 10:08:41AM +0100, Charles Keepax wrote:
> On Thu, Sep 24, 2026 at 03:05:41PM -0700, mhun512@gmail.com wrote:
> > /* Send an initial empty report */
> > snd_soc_jack_report(wm8962->jack, 0,
> > @@ -3592,9 +3593,7 @@ static int wm8962_probe(struct snd_soc_component
> > *component)
> >
> > static void wm8962_remove(struct snd_soc_component *component)
> > {
> > - struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
> > -
> > - cancel_delayed_work_sync(&wm8962->mic_work);
> > + wm8962_mic_detect(component, NULL);
> >
> > wm8962_free_gpio(component);
> > wm8962_free_beep(component);
> > diff --git a/sound/soc/tegra/tegra_wm8962.c b/sound/soc/tegra/tegra_wm8962.c
> > index 31f9d9181595..a79d464b6a80 100644
> > --- a/sound/soc/tegra/tegra_wm8962.c
> > +++ b/sound/soc/tegra/tegra_wm8962.c
> > @@ -97,18 +97,6 @@ static int tegra_wm8962_init(struct snd_soc_pcm_runtime *rtd)
> > return 0;
> > }
> >
> > -static int tegra_wm8962_remove(struct snd_soc_card *card)
> > -{
> > - struct snd_soc_dai_link *link = &card->dai_link[0];
> > - struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card, link);
> > - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
> > - struct snd_soc_component *component = codec_dai->component;
> > -
> > - wm8962_mic_detect(component, NULL);
> > -
> > - return 0;
> > -}
>
> I don't think you should remove this. It is possible to remove
> the machine driver but not the codec driver, and in that case you
> still want the mic_detect disabled.
Sorry mistake on my part, as we are doing wm8962_mic_detect in
component remove, not bus remove you probably can drop this.
Thanks,
Charles
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-25 9:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-24 22:05 [PATCH v3] ASoC: wm8962: Stop IRQ from requeuing mic_work on remove mhun512
2026-09-25 9:08 ` Charles Keepax
2026-09-25 9:31 ` Charles Keepax
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®