mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v6] ASoC: wm8962: stop microphone work before component removal
@ 2026-11-10  5:08 Myeonghun Pak
  0 siblings, 0 replies; only message in thread
From: Myeonghun Pak @ 2026-11-10  5:08 UTC (permalink / raw)
  To: Mark Brown
  Cc: Myeonghun Pak, Liam Girdwood, Charles Keepax, Thierry Reding,
	Jonathan Hunter, patches, linux-sound, linux-tegra, linux-kernel,
	Ijae Kim, Jaroslav Kysela, Takashi Iwai

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,
 };
 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-10  5:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-10  5:08 [PATCH v6] ASoC: wm8962: stop microphone work before component removal Myeonghun Pak

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®