From: Myeonghun Pak <mhun512@gmail.com>
To: Mark Brown <broonie@kernel.org>
Cc: Myeonghun Pak <mhun512@gmail.com>,
Liam Girdwood <lgirdwood@gmail.com>,
Charles Keepax <ckeepax@opensource.cirrus.com>,
Thierry Reding <thierry.reding@kernel.org>,
Jonathan Hunter <jonathanh@nvidia.com>,
patches@opensource.cirrus.com, linux-sound@vger.kernel.org,
linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org,
Ijae Kim <ae878000@gmail.com>, Jaroslav Kysela <perex@perex.cz>,
Takashi Iwai <tiwai@suse.com>
Subject: [PATCH v6] ASoC: wm8962: stop microphone work before component removal
Date: Tue, 10 Nov 2026 00:08:12 -0500 [thread overview]
Message-ID: <20261110-wm8962-v6-c78c17edd171@gmail.com> (raw)
The I2C-owned IRQ outlives the codec component. Cancelling mic_work during
component removal leaves its producer running, so another microphone event
can queue work for the old component and jack.
Mask microphone sources, synchronize the IRQ and drain mic_work before
changing the jack pointer, regardless of whether a jack was registered.
Disable microphone detection during cleanup only while holding an active
runtime-PM reference, because its control register is volatile. Keep
unrelated IRQ events available.
Run this cleanup unconditionally from codec removal and drop Tegra's late
card remove callback, which runs after component and PCM runtime teardown.
Fixes: 0512615db6db ("ASoC: wm8962: Convert interrupt handler to direct regmap usage")
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
No hardware testing.
Changes in v6:
- Mask microphone IRQs and drain the IRQ/work path even with no old jack.
- Run codec cleanup unconditionally from component removal.
- Retain the active runtime-PM guard and Tegra callback removal.
sound/soc/codecs/wm8962.c | 34 +++++++++++++++++++---------------
sound/soc/tegra/tegra_wm8962.c | 13 -------------
2 files changed, 19 insertions(+), 28 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3248,21 +3248,27 @@
{
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;
+ int mic_irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT;
+
+ snd_soc_component_update_bits(component, WM8962_INTERRUPT_STATUS_2_MASK,
+ mic_irq_mask, mic_irq_mask);
+ if (pm_runtime_get_if_active(component->dev) > 0) {
+ snd_soc_component_update_bits(component, WM8962_ADDITIONAL_CONTROL_4,
+ WM8962_MICDET_ENA, 0);
+ pm_runtime_put(component->dev);
+ }
+ if (wm8962->irq)
+ synchronize_irq(wm8962->irq);
+ cancel_delayed_work_sync(&wm8962->mic_work);
wm8962->jack = jack;
if (jack) {
- irq_mask = 0;
- enable = WM8962_MICDET_ENA;
- } else {
- irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT;
- enable = 0;
- }
-
- snd_soc_component_update_bits(component, WM8962_INTERRUPT_STATUS_2_MASK,
- WM8962_MICD_EINT | WM8962_MICSCD_EINT, irq_mask);
- snd_soc_component_update_bits(component, WM8962_ADDITIONAL_CONTROL_4,
- WM8962_MICDET_ENA, enable);
+ snd_soc_component_update_bits(component,
+ WM8962_INTERRUPT_STATUS_2_MASK,
+ mic_irq_mask, 0);
+ snd_soc_component_update_bits(component, WM8962_ADDITIONAL_CONTROL_4,
+ WM8962_MICDET_ENA, WM8962_MICDET_ENA);
+ }
/* Send an initial empty report */
snd_soc_jack_report(wm8962->jack, 0,
@@ -3592,9 +3598,7 @@
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
--- a/sound/soc/tegra/tegra_wm8962.c
+++ b/sound/soc/tegra/tegra_wm8962.c
@@ -97,18 +97,6 @@
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;
-
- snd_soc_component_set_jack(component, NULL, 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 @@
.owner = THIS_MODULE,
.dai_link = &tegra_wm8962_dai,
.num_links = 1,
- .remove = tegra_wm8962_remove,
.fully_routed = true,
};
reply other threads:[~2026-11-10 5:08 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110-wm8962-v6-c78c17edd171@gmail.com \
--to=mhun512@gmail.com \
--cc=ae878000@gmail.com \
--cc=broonie@kernel.org \
--cc=ckeepax@opensource.cirrus.com \
--cc=jonathanh@nvidia.com \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=patches@opensource.cirrus.com \
--cc=perex@perex.cz \
--cc=thierry.reding@kernel.org \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®