[PATCH 3/6] ASoC: tlv320aic31xx: Register regulator notifier from the I2C probe

From: Chancel Liu

Date: Sun Sep 13 2026 - 06:16:47 EST


From: Chancel Liu <chancel.liu@xxxxxxx>

aic31xx registers its regulator disable notifiers from the ASoC
component probe, but the associated devres cleanup is tied to the
underlying I2C device.

The notifiers are only mishandled when the sound card is unregistered
and re-registered while the I2C 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 aic31xx_i2c_probe() so it runs once
per I2C device bind, right after the supplies are requested there.

Signed-off-by: Chancel Liu <chancel.liu@xxxxxxx>
---
sound/soc/codecs/tlv320aic31xx.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 43bcbc5449e1..b0df6e6435e7 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1366,27 +1366,12 @@ static int aic31xx_set_jack(struct snd_soc_component *component,
static int aic31xx_codec_probe(struct snd_soc_component *component)
{
struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
- int i, ret;
+ int ret;

dev_dbg(aic31xx->dev, "## %s\n", __func__);

aic31xx->component = component;

- for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) {
- aic31xx->disable_nb[i].nb.notifier_call =
- aic31xx_regulator_event;
- aic31xx->disable_nb[i].aic31xx = aic31xx;
- ret = devm_regulator_register_notifier(
- aic31xx->supplies[i].consumer,
- &aic31xx->disable_nb[i].nb);
- if (ret) {
- dev_err(component->dev,
- "Failed to request regulator notifier: %d\n",
- ret);
- return ret;
- }
- }
-
regcache_cache_only(aic31xx->regmap, true);
regcache_mark_dirty(aic31xx->regmap);

@@ -1791,6 +1776,19 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c)
if (ret)
return dev_err_probe(aic31xx->dev, ret, "Failed to request supplies\n");

+ for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) {
+ aic31xx->disable_nb[i].nb.notifier_call = aic31xx_regulator_event;
+ aic31xx->disable_nb[i].aic31xx = aic31xx;
+ ret = devm_regulator_register_notifier(aic31xx->supplies[i].consumer,
+ &aic31xx->disable_nb[i].nb);
+ if (ret) {
+ dev_err(aic31xx->dev,
+ "Failed to request regulator notifier: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
aic31xx_configure_ocmv(aic31xx);

if (aic31xx->irq > 0) {
--
2.50.1