* [PATCH 1/4] ASoC: simple-card-utils: Add simple_util_remove_jack()
2026-09-13 10:24 [PATCH 0/4] ASoC: generic: Free jack GPIOs on card remove Chancel Liu
@ 2026-09-13 10:24 ` Chancel Liu
2026-09-13 10:25 ` [PATCH 2/4] ASoC: simple-card: Free jack GPIOs on card remove Chancel Liu
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Chancel Liu @ 2026-09-13 10:24 UTC (permalink / raw)
To: Mark Brown, Kuninori Morimoto, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-kernel
From: Chancel Liu <chancel.liu@nxp.com>
simple_util_init_jack() acquires a GPIO descriptor with
gpiod_get_optional() and hands it to snd_soc_jack_add_gpios(), which
additionally installs an IRQ handler, a PM notifier, a delayed work and
a sysfs export for it. simple-card-utils has no counterpart that
releases any of this again.
Add simple_util_remove_jack(), the counterpart of
simple_util_init_jack(). It releases the jack GPIO and everything
snd_soc_jack_add_gpios() installed for it via snd_soc_jack_free_gpios(),
and clears sjack->gpio.desc so the descriptor is not left dangling after
it has been put.
This gives the generic card drivers a card->remove() path to release the
jack when the card goes away. The devres cleanup alone is not enough:
it is tied to the platform device, so it does not run when the card is
unregistered and re-registered while the platform device stays bound -
for example when a codec component is unbound and bound again.
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
include/sound/simple_card_utils.h | 1 +
sound/soc/generic/simple-card-utils.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index bd8c3a033577..b0e00555092e 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -219,6 +219,7 @@ static inline int simple_util_parse_aux_devs(struct simple_util_priv *priv, char
int simple_util_init_jack(struct snd_soc_card *card,
struct simple_util_jack *sjack,
int is_hp, char *prefix, char *pin);
+void simple_util_remove_jack(struct simple_util_jack *sjack);
int simple_util_init_aux_jacks(struct snd_soc_card *card, char *prefix);
int simple_util_init_priv(struct simple_util_priv *priv,
struct link_info *li);
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 7df5253499cd..b91924d31c1a 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -825,6 +825,16 @@ int simple_util_init_jack(struct snd_soc_card *card,
}
EXPORT_SYMBOL_GPL(simple_util_init_jack);
+void simple_util_remove_jack(struct simple_util_jack *sjack)
+{
+ if (!sjack->gpio.desc)
+ return;
+
+ snd_soc_jack_free_gpios(&sjack->jack, 1, &sjack->gpio);
+ sjack->gpio.desc = NULL;
+}
+EXPORT_SYMBOL_GPL(simple_util_remove_jack);
+
int simple_util_init_aux_jacks(struct snd_soc_card *card, char *prefix)
{
struct simple_util_priv *priv = snd_soc_card_get_drvdata(card);
--
2.50.1
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 2/4] ASoC: simple-card: Free jack GPIOs on card remove
2026-09-13 10:24 [PATCH 0/4] ASoC: generic: Free jack GPIOs on card remove Chancel Liu
2026-09-13 10:24 ` [PATCH 1/4] ASoC: simple-card-utils: Add simple_util_remove_jack() Chancel Liu
@ 2026-09-13 10:25 ` Chancel Liu
2026-09-13 10:25 ` [PATCH 3/4] ASoC: audio-graph-card: " Chancel Liu
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Chancel Liu @ 2026-09-13 10:25 UTC (permalink / raw)
To: Mark Brown, Kuninori Morimoto, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-kernel
From: Chancel Liu <chancel.liu@nxp.com>
simple_soc_probe() sets up the headphone and microphone jacks, which
takes a reference on the jack detection GPIO and registers an IRQ, a PM
notifier, a delayed work and a sysfs export for it. simple-card has no
card->remove() callback, so none of this is released when the card is
torn down.
This goes unnoticed while the card is only torn down together with its
platform device, because the devres cleanup registered by
snd_soc_jack_add_gpios() is tied to that platform device. It becomes a
problem once the card alone is unregistered and registered again while
the platform device stays bound - for example when a codec component is
unbound and bound again. card->probe() then runs a second time and
gpiod_get_optional() fails with -EBUSY, because the descriptor is still
held by the previous bind. The card is not registered again and audio
stays broken until the platform device itself is unbound.
Add simple_soc_remove() as the counterpart of simple_soc_probe() and
release both jacks from there.
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
sound/soc/generic/simple-card.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 0a769c177149..b2fc91b8ab81 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -666,6 +666,16 @@ static int simple_soc_probe(struct snd_soc_card *card)
return simple_ret(priv, ret);
}
+static int simple_soc_remove(struct snd_soc_card *card)
+{
+ struct simple_util_priv *priv = snd_soc_card_get_drvdata(card);
+
+ simple_util_remove_jack(&priv->hp_jack);
+ simple_util_remove_jack(&priv->mic_jack);
+
+ return 0;
+}
+
static int simple_parse_of(struct simple_util_priv *priv)
{
struct snd_soc_card *card = simple_priv_to_card(priv);
@@ -754,6 +764,7 @@ static int simple_probe(struct platform_device *pdev)
card->owner = THIS_MODULE;
card->dev = dev;
card->probe = simple_soc_probe;
+ card->remove = simple_soc_remove;
card->driver_name = "simple-card";
return simple_parse_of(priv);
--
2.50.1
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 3/4] ASoC: audio-graph-card: Free jack GPIOs on card remove
2026-09-13 10:24 [PATCH 0/4] ASoC: generic: Free jack GPIOs on card remove Chancel Liu
2026-09-13 10:24 ` [PATCH 1/4] ASoC: simple-card-utils: Add simple_util_remove_jack() Chancel Liu
2026-09-13 10:25 ` [PATCH 2/4] ASoC: simple-card: Free jack GPIOs on card remove Chancel Liu
@ 2026-09-13 10:25 ` Chancel Liu
2026-09-14 0:29 ` Kuninori Morimoto
2026-09-13 10:25 ` [PATCH 4/4] ASoC: audio-graph-card2: " Chancel Liu
2026-09-15 16:36 ` [PATCH 0/4] ASoC: generic: " Mark Brown
4 siblings, 1 reply; 9+ messages in thread
From: Chancel Liu @ 2026-09-13 10:25 UTC (permalink / raw)
To: Mark Brown, Kuninori Morimoto, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-kernel
From: Chancel Liu <chancel.liu@nxp.com>
graph_util_card_probe() sets up the headphone and microphone jacks,
which takes a reference on the jack detection GPIO and registers an IRQ,
a PM notifier, a delayed work and a sysfs export for it. audio-graph-card
has no card->remove() callback, so none of this is released when the card
is torn down.
This goes unnoticed while the card is only torn down together with its
platform device, because the devres cleanup registered by
snd_soc_jack_add_gpios() is tied to that platform device. It becomes a
problem once the card alone is unregistered and registered again while
the platform device stays bound - for example when a codec component is
unbound and bound again. card->probe() then runs a second time and
gpiod_get_optional() fails with -EBUSY, because the descriptor is still
held by the previous bind. The card is not registered again and audio
stays broken until the platform device itself is unbound.
Add graph_util_card_remove() as the counterpart of
graph_util_card_probe() and hook it to card->remove. It lives in
simple-card-utils.c so that audio-graph-card2 can use it as well.
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
include/sound/simple_card_utils.h | 1 +
sound/soc/generic/audio-graph-card.c | 1 +
sound/soc/generic/simple-card-utils.c | 11 +++++++++++
3 files changed, 13 insertions(+)
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index b0e00555092e..68faec56970e 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -226,6 +226,7 @@ int simple_util_init_priv(struct simple_util_priv *priv,
void simple_util_remove(struct platform_device *pdev);
int graph_util_card_probe(struct snd_soc_card *card);
+int graph_util_card_remove(struct snd_soc_card *card);
int graph_util_is_ports0(struct device_node *port);
int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep,
struct snd_soc_dai_link_component *dlc, int *is_single_link);
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 0a8a6d891d1f..127c2e6b308e 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -629,6 +629,7 @@ static int graph_probe(struct platform_device *pdev)
card->dapm_widgets = graph_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(graph_dapm_widgets);
card->probe = graph_util_card_probe;
+ card->remove = graph_util_card_remove;
if (of_device_get_match_data(dev))
priv->dpcm_selectable = 1;
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index b91924d31c1a..de27163eeb0b 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -1028,6 +1028,17 @@ int graph_util_card_probe(struct snd_soc_card *card)
}
EXPORT_SYMBOL_GPL(graph_util_card_probe);
+int graph_util_card_remove(struct snd_soc_card *card)
+{
+ struct simple_util_priv *priv = snd_soc_card_get_drvdata(card);
+
+ simple_util_remove_jack(&priv->hp_jack);
+ simple_util_remove_jack(&priv->mic_jack);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(graph_util_card_remove);
+
int graph_util_is_ports0(struct device_node *np)
{
struct device_node *parent __free(device_node) = of_get_parent(np);
--
2.50.1
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH 3/4] ASoC: audio-graph-card: Free jack GPIOs on card remove
2026-09-13 10:25 ` [PATCH 3/4] ASoC: audio-graph-card: " Chancel Liu
@ 2026-09-14 0:29 ` Kuninori Morimoto
2026-09-15 2:46 ` Chancel Liu
0 siblings, 1 reply; 9+ messages in thread
From: Kuninori Morimoto @ 2026-09-14 0:29 UTC (permalink / raw)
To: Chancel Liu
Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-kernel
Hi Chancel
Thank you for the patch
> --- a/sound/soc/generic/audio-graph-card.c
> +++ b/sound/soc/generic/audio-graph-card.c
> @@ -629,6 +629,7 @@ static int graph_probe(struct platform_device *pdev)
> card->dapm_widgets = graph_dapm_widgets;
> card->num_dapm_widgets = ARRAY_SIZE(graph_dapm_widgets);
> card->probe = graph_util_card_probe;
> + card->remove = graph_util_card_remove;
Basically it looks good to me, but tegra_audio_graph_card is
using graph_util_card_probe(), too. Please care about this driver.
${LINUX}/sound/soc/tegra/tegra_audio_graph_card.c
Except above,
Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH 3/4] ASoC: audio-graph-card: Free jack GPIOs on card remove
2026-09-14 0:29 ` Kuninori Morimoto
@ 2026-09-15 2:46 ` Chancel Liu
2026-09-15 3:16 ` Kuninori Morimoto
0 siblings, 1 reply; 9+ messages in thread
From: Chancel Liu @ 2026-09-15 2:46 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-kernel
Hi Kuninori
Thank you for the review and the Ack.
> Hi Chancel
>
> Thank you for the patch
>
>> --- a/sound/soc/generic/audio-graph-card.c
>> +++ b/sound/soc/generic/audio-graph-card.c
>> @@ -629,6 +629,7 @@ static int graph_probe(struct platform_device *pdev)
>> card->dapm_widgets = graph_dapm_widgets;
>> card->num_dapm_widgets = ARRAY_SIZE(graph_dapm_widgets);
>> card->probe = graph_util_card_probe;
>> + card->remove = graph_util_card_remove;
>
> Basically it looks good to me, but tegra_audio_graph_card is
> using graph_util_card_probe(), too. Please care about this driver.
>
> ${LINUX}/sound/soc/tegra/tegra_audio_graph_card.c
>
> Except above,
>
> Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
>
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto
For this series I would like to keep the scope limited to the generic
cards. If this approach can be accepted, we can extend this fix to other
cards.
tegra_audio_graph_card has a slightly more complicated card->probe. It
also handles some clocks besides calling graph_util_card_probe(). So I
think this driver leaks both the clocks and the jack resources on card
unbind/rebind. I prefer a separate patch to fix tegra_audio_graph_card.
Regards,
Chancel Liu
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH 3/4] ASoC: audio-graph-card: Free jack GPIOs on card remove
2026-09-15 2:46 ` Chancel Liu
@ 2026-09-15 3:16 ` Kuninori Morimoto
0 siblings, 0 replies; 9+ messages in thread
From: Kuninori Morimoto @ 2026-09-15 3:16 UTC (permalink / raw)
To: Chancel Liu
Cc: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
linux-sound, linux-kernel
Hi Chancel
> For this series I would like to keep the scope limited to the generic
> cards. If this approach can be accepted, we can extend this fix to other
> cards.
>
> tegra_audio_graph_card has a slightly more complicated card->probe. It
> also handles some clocks besides calling graph_util_card_probe(). So I
> think this driver leaks both the clocks and the jack resources on card
> unbind/rebind. I prefer a separate patch to fix tegra_audio_graph_card.
OK. I have no big objection about it.
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/4] ASoC: audio-graph-card2: Free jack GPIOs on card remove
2026-09-13 10:24 [PATCH 0/4] ASoC: generic: Free jack GPIOs on card remove Chancel Liu
` (2 preceding siblings ...)
2026-09-13 10:25 ` [PATCH 3/4] ASoC: audio-graph-card: " Chancel Liu
@ 2026-09-13 10:25 ` Chancel Liu
2026-09-15 16:36 ` [PATCH 0/4] ASoC: generic: " Mark Brown
4 siblings, 0 replies; 9+ messages in thread
From: Chancel Liu @ 2026-09-13 10:25 UTC (permalink / raw)
To: Mark Brown, Kuninori Morimoto, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai
Cc: linux-sound, linux-kernel
From: Chancel Liu <chancel.liu@nxp.com>
audio-graph-card2 uses graph_util_card_probe() to set up the headphone
and microphone jacks, but never released them again, so the jack GPIO,
its IRQ, the PM notifier, the delayed work and the sysfs export stayed
claimed when the card was unbound. Re-binding the card alone - for
instance after a codec component is unbound and bound again - then made
graph_util_card_probe() fail with -EBUSY and the card was never
registered again.
Hook up the graph_util_card_remove() counterpart added for
audio-graph-card.
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
sound/soc/generic/audio-graph-card2.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c
index 9fb3d3df5cf6..e11bc8135cb0 100644
--- a/sound/soc/generic/audio-graph-card2.c
+++ b/sound/soc/generic/audio-graph-card2.c
@@ -1310,6 +1310,7 @@ int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev,
goto end;
card->probe = graph_util_card_probe;
+ card->remove = graph_util_card_remove;
card->owner = THIS_MODULE;
card->dev = dev;
--
2.50.1
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH 0/4] ASoC: generic: Free jack GPIOs on card remove
2026-09-13 10:24 [PATCH 0/4] ASoC: generic: Free jack GPIOs on card remove Chancel Liu
` (3 preceding siblings ...)
2026-09-13 10:25 ` [PATCH 4/4] ASoC: audio-graph-card2: " Chancel Liu
@ 2026-09-15 16:36 ` Mark Brown
4 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2026-09-15 16:36 UTC (permalink / raw)
To: Kuninori Morimoto, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Chancel Liu
Cc: linux-sound, linux-kernel
On Sun, 13 Sep 2026 19:24:58 +0900, Chancel Liu wrote:
> ASoC: generic: Free jack GPIOs on card remove
>
> From: Chancel Liu <chancel.liu@nxp.com>
>
> simple_util_init_jack() acquires a jack detection GPIO with
> gpiod_get_optional() and passes it to snd_soc_jack_add_gpios(), which
> also installs an IRQ handler, a PM notifier, a delayed work and a sysfs
> export for it. None of simple-card, audio-graph-card or
> audio-graph-card2 implements a card->remove() callback, so none of this
> is ever released.
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.4
Thanks!
[1/4] ASoC: simple-card-utils: Add simple_util_remove_jack()
https://git.kernel.org/broonie/sound/c/c7420dd9213d
[2/4] ASoC: simple-card: Free jack GPIOs on card remove
https://git.kernel.org/broonie/sound/c/b59a20808727
[3/4] ASoC: audio-graph-card: Free jack GPIOs on card remove
https://git.kernel.org/broonie/sound/c/698fdd31522c
[4/4] ASoC: audio-graph-card2: Free jack GPIOs on card remove
https://git.kernel.org/broonie/sound/c/df0afa439044
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 9+ messages in thread