sound/soc/codecs/rt1015.c | 81 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 16 deletions(-)
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@iscas.ac.cn>
---
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
On Sun, 30 Aug 2026 22:21:18 +0800, Pengpeng Hou wrote:
> ASoC: rt1015: make control calibration failures observable
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.4
Thanks!
[1/1] ASoC: rt1015: make control calibration failures observable
https://git.kernel.org/broonie/sound/c/98fe8aab04ce
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
© 2016 - 2026 Red Hat, Inc.