From: Myeonghun Pak <mhun512@gmail.com>
To: Liam Girdwood <lgirdwood@gmail.com>,
Mark Brown <broonie@kernel.org>, Jaroslav Kysela <perex@perex.cz>,
Takashi Iwai <tiwai@suse.com>
Cc: 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-kernel@vger.kernel.org, linux-tegra@vger.kernel.org,
stable@vger.kernel.org, Ijae Kim <ae878000@gmail.com>
Subject: [PATCH v4] ASoC: wm8962: Stop IRQ from requeuing mic_work on remove
Date: Sat, 17 Oct 2026 22:18:17 -0400 [thread overview]
Message-ID: <20261018021817.3859256-1-mhun512@gmail.com> (raw)
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 and disable detection in wm8962_mic_detect(),
wait for any handler that already read the old mask, and drain mic_work
before changing the jack pointer. When installing a new jack, unmask its
interrupts before enabling detection, preserving the existing hardware
sequence. Call this path from component remove while the component is
still valid, leaving 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 v4:
- Always disable microphone detection before draining the IRQ and work,
then unmask microphone interrupts before re-enabling detection for a
new jack, as requested by Charles Keepax.
- Keep the redundant Tegra card remove callback deletion; Charles
withdrew his initial objection in the follow-up review.
Changes in v3:
- Mask microphone interrupts, synchronize the IRQ and cancel mic_work
before replacing the jack pointer in wm8962_mic_detect().
- Use wm8962_mic_detect(component, NULL) from component remove and drop
the 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. Compile-tested both modified objects with GCC 15,
W=1, x86_64 and COMPILE_TEST=y. No hardware or runtime testing.
Review: https://lore.kernel.org/r/arY6GbRBjKxJDKVn@opensource.cirrus.com/
Follow-up: https://lore.kernel.org/r/arY%2FVSKn%2Fsq32sr0@opensource.cirrus.com/
sound/soc/codecs/wm8962.c | 36 +++++++++++++++++++++---------------
sound/soc/tegra/tegra_wm8962.c | 13 -------------
2 files changed, 21 insertions(+), 28 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 8a9598161b35..253b41fff8ab 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3230,21 +3230,29 @@
{
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;
+
+ /*
+ * Mask microphone events, then drain the IRQ and work before
+ * changing the jack.
+ */
+ snd_soc_component_update_bits(component, WM8962_INTERRUPT_STATUS_2_MASK,
+ mic_irq_mask, mic_irq_mask);
+ snd_soc_component_update_bits(component, WM8962_ADDITIONAL_CONTROL_4,
+ WM8962_MICDET_ENA, 0);
+ 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 +3600,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
index 31f9d9181595..a79d464b6a80 100644
--- 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;
-
- 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 @@
.owner = THIS_MODULE,
.dai_link = &tegra_wm8962_dai,
.num_links = 1,
- .remove = tegra_wm8962_remove,
.fully_routed = true,
};
base-commit: 238650ef6c7c7cca08e032527329424c9fbd70e5
--
2.53.0
reply other threads:[~2026-10-18 2:18 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=20261018021817.3859256-1-mhun512@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=stable@vger.kernel.org \
--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®