[PATCH 4/6] ASoC: tlv320aic3x: Register regulator notifier from the bus probe
From: Chancel Liu
Date: Sun Sep 13 2026 - 06:17:29 EST
From: Chancel Liu <chancel.liu@xxxxxxx>
aic3x registers its regulator disable notifiers from the ASoC component
probe, but the associated devres cleanup is tied to the underlying bus
device.
The notifiers are only mishandled when the sound card is unregistered
and re-registered while the bus device stays bound. On that path the
component probe runs again and re-registers the same notifier_block on
the still-registered regulator notifier chain and corrupts the chain.
Move the notifier registration to aic3x_probe(), the shared bus probe
helper called from the I2C and SPI probes, so it runs once per bus
device bind, right after the supplies are requested there.
Signed-off-by: Chancel Liu <chancel.liu@xxxxxxx>
---
sound/soc/codecs/tlv320aic3x.c | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index b38393a8130f..405c60ec1448 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1627,24 +1627,9 @@ static int aic3x_init(struct snd_soc_component *component)
static int aic3x_component_probe(struct snd_soc_component *component)
{
struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component);
- int ret, i;
aic3x->component = component;
- for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
- aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
- aic3x->disable_nb[i].aic3x = aic3x;
- ret = devm_regulator_register_notifier(
- aic3x->supplies[i].consumer,
- &aic3x->disable_nb[i].nb);
- if (ret) {
- dev_err(component->dev,
- "Failed to request regulator notifier: %d\n",
- ret);
- return ret;
- }
- }
-
regcache_mark_dirty(aic3x->regmap);
aic3x_init(component);
@@ -1845,6 +1830,19 @@ int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver
if (ret)
return dev_err_probe(dev, ret, "Failed to request supplies\n");
+ for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
+ aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
+ aic3x->disable_nb[i].aic3x = aic3x;
+ ret = devm_regulator_register_notifier(aic3x->supplies[i].consumer,
+ &aic3x->disable_nb[i].nb);
+ if (ret) {
+ dev_err(dev,
+ "Failed to request regulator notifier: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
aic3x_configure_ocmv(dev, aic3x);
ret = devm_snd_soc_register_component(dev, &soc_component_dev_aic3x, &aic3x_dai, 1);
--
2.50.1