Re: [PATCH] ASoC: tas2781: Add delay before block checksum retry to prevent deadlock
From: 李则良
Date: Fri Aug 14 2026 - 14:28:30 EST
dmesg on my laptop:
[ 4024.480031] snd_hda_codec_alc269 hdaudioC0D0: bound
i2c-TIAS2781:00 (ops tas2781_hda_comp_ops
[snd_hda_scodec_tas2781_i2c])
[ 4025.643145] tas2781-hda i2c-TIAS2781:00: tas2781_apply_calib: V1 CRC error
李则良 <lizeliang.linux@xxxxxxxxx> 于2026年8月15日周六 02:19写道:
>
> From 3ee77f811a91350caa56783b76251cd8218e2263 Mon Sep 17 00:00:00 2001
> From: Zeliang Li <lizeliang.linux@xxxxxxxxx>
> Date: Sat, 15 Aug 2026 01:52:57 +0800
> Subject: [PATCH] ASoC: tas2781: Add delay before block checksum retry to
> prevent deadlock
>
> During runtime resume from power-saving states, the tas2781 amplifier
> firmware block calibration checksum verification may occasionally fail
> due to transient instabilities on the I2C bus or the chip's internal
> power rails.
>
> When tasdev_block_chksum() detects a checksum mismatch, it correctly
> decrements block->nr_retry and returns -EAGAIN to trigger a
> re-transmission loop. However, because there is no delay introduced
> before repeating the loop, all available retry attempts are exhausted
> almost instantly (within microseconds) before the hardware can fully
> stabilize. This causes a permanent calibration failure, triggering
> "ERROR_PRAM_CRCCHK", and results in a silent speaker deadlock after
> pausing/resuming media on modern laptops.
>
> Fix this by adding a 2ms usleep_range() delay before initiating a
> checksum re-try loop, allowing the hardware sufficient time to
> stabilize.
>
> Signed-off-by: Zeliang Li <lizeliang.linux@xxxxxxxxx>
> ---
> sound/soc/codecs/tas2781-fmwlib.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/sound/soc/codecs/tas2781-fmwlib.c
> b/sound/soc/codecs/tas2781-fmwlib.c
> index dcbeb9618195..09cbee7a55dc 100644
> --- a/sound/soc/codecs/tas2781-fmwlib.c
> +++ b/sound/soc/codecs/tas2781-fmwlib.c
> @@ -1765,9 +1765,16 @@ static int tasdev_block_chksum(struct
> tasdevice_priv *tas_priv,
> ret = -EAGAIN;
> block->nr_retry--;
>
> - if (block->nr_retry <= 0)
> + if (block->nr_retry <= 0) {
> set_err_prg_cfg(block->type,
> &tas_priv->tasdevice[chn]);
> +
> + } else {
> + /* Give the chip and I2C bus time to stabilize before
> + * next re-transmission attempt.
> + */
> + usleep_range(2000, 2500);
> + }
> } else
> tas_priv->tasdevice[chn].err_code &= ~ERROR_PRAM_CRCCHK;
>
> --
> 2.53.0
>
> --
> KISS == Keep it simple,stupid~:-)
> http://lizeliang.org
--
KISS == Keep it simple,stupid~:-)
http://lizeliang.org