[PATCH] ASoC: rt1015: make control calibration failures observable

From: Pengpeng Hou

Date: Sun Aug 30 2026 - 10:21:40 EST


The bypass-boost control runs a hardware calibration while bypassing the
register cache. It ignores every register access and cache restore
failure, then publishes both the requested mode and calibration
completion.

Return failures from the complete calibration sequence, always restore
normal cache operation and unlock DAPM, and only publish the control
state after the calibration and final mode write both succeed. The mixer
control callback is an effective error consumer, independent of deferred
component resume.

Fixes: da145172b236 ("ASoC: rt1015: Fix DC calibration on bypass boost mode")
Signed-off-by: Pengpeng Hou <pengpeng@xxxxxxxxxxx>
---
sound/soc/codecs/rt1015.c | 81 +++++++++++++++++++++++++++++++++++++----------
1 file changed, 65 insertions(+), 16 deletions(-)

diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c
index ff0c08ff610e1..c6cb8d3ec0454 100644
--- a/sound/soc/codecs/rt1015.c
+++ b/sound/soc/codecs/rt1015.c
@@ -488,35 +488,72 @@ static int rt1015_bypass_boost_get(struct snd_kcontrol *kcontrol,
return 0;
}

-static void rt1015_calibrate(struct rt1015_priv *rt1015)
+static int rt1015_calibrate(struct rt1015_priv *rt1015)
{
struct snd_soc_component *component = rt1015->component;
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct regmap *regmap = rt1015->regmap;
+ int ret, sync_ret;

snd_soc_dapm_mutex_lock(dapm);
regcache_cache_bypass(regmap, true);

- regmap_write(regmap, RT1015_CLK_DET, 0x0000);
- regmap_write(regmap, RT1015_PWR4, 0x00B2);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0009);
+ ret = regmap_write(regmap, RT1015_CLK_DET, 0x0000);
+ if (ret)
+ goto restore_cache;
+
+ ret = regmap_write(regmap, RT1015_PWR4, 0x00B2);
+ if (ret)
+ goto restore_cache;
+
+ ret = regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0009);
+ if (ret)
+ goto restore_cache;
+
msleep(100);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000A);
+ ret = regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000A);
+ if (ret)
+ goto restore_cache;
+
msleep(100);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000C);
+ ret = regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000C);
+ if (ret)
+ goto restore_cache;
+
msleep(100);
- regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2028);
- regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0140);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000D);
+ ret = regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2028);
+ if (ret)
+ goto restore_cache;
+
+ ret = regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0140);
+ if (ret)
+ goto restore_cache;
+
+ ret = regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000D);
+ if (ret)
+ goto restore_cache;
+
msleep(300);
- regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0008);
- regmap_write(regmap, RT1015_SYS_RST1, 0x05F5);
- regmap_write(regmap, RT1015_CLK_DET, 0x8000);
+ ret = regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0008);
+ if (ret)
+ goto restore_cache;
+
+ ret = regmap_write(regmap, RT1015_SYS_RST1, 0x05F5);
+ if (ret)
+ goto restore_cache;
+
+ ret = regmap_write(regmap, RT1015_CLK_DET, 0x8000);
+
+restore_cache:

regcache_cache_bypass(regmap, false);
regcache_mark_dirty(regmap);
- regcache_sync(regmap);
+ sync_ret = regcache_sync(regmap);
+ if (!ret)
+ ret = sync_ret;
snd_soc_dapm_mutex_unlock(dapm);
+
+ return ret;
}

static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
@@ -525,6 +562,8 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt1015_priv *rt1015 =
snd_soc_component_get_drvdata(component);
+ int bypass_boost = rt1015->bypass_boost;
+ int ret;

if (rt1015->dac_is_used) {
dev_err(component->dev, "DAC is being used!\n");
@@ -534,13 +573,23 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol,
rt1015->bypass_boost = ucontrol->value.integer.value[0];
if (rt1015->bypass_boost == RT1015_Bypass_Boost &&
!rt1015->cali_done) {
- rt1015_calibrate(rt1015);
- rt1015->cali_done = 1;
+ ret = rt1015_calibrate(rt1015);
+ if (ret)
+ goto restore_boost;
+
+ ret = regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL,
+ 0x0010);
+ if (ret)
+ goto restore_boost;

- regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010);
+ rt1015->cali_done = 1;
}

return 0;
+
+restore_boost:
+ rt1015->bypass_boost = bypass_boost;
+ return ret;
}

static const char * const rt1015_dac_output_vol_select[] = {

base-commit: 32b4e6b134c62e14291206da331891e99e2fb63d
--
2.50.1