From: Philipp Oster Date: Mon, 20 Jul 2026 09:41:51 +0000 (+0200) Subject: ALSA: hda/tas2781: clear cali_data.total_sz when calibration read fails X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b6016332b8899a9775addf9b630b0a53a849c8ed;p=thirdparty%2Fkernel%2Flinux.git ALSA: hda/tas2781: clear cali_data.total_sz when calibration read fails tas2563_save_calibration() assigns cali_data.total_sz before it reads the per-device calibration data from EFI, but its error paths return without clearing it again. cali_data.cali_reg_array is left all zero, because the function returns before the register addresses are assigned. On the first playback tasdev_load_calibrated_data() does if (!data || !cali_data->total_sz) return; which passes, since total_sz is still non-zero. It then issues five 4-byte bulk writes to p->r0_reg, p->r0_low_reg, p->invr0_reg, p->pow_reg and p->tlimit_reg, all of which are 0. Register 0 decodes to book 0 / page 0 / register 0x00, so the auto-incrementing block write zeroes registers 0x00 to 0x03. Register 0x03 is PB_CFG1, which holds AMP_LEVEL, so the amplifier gain is set to its minimum and the speaker stays silent. This is reproducible on a Lenovo Yoga 7 14ARB7 (two TAS2563 on I2C, ACPI INT8866) whose factory calibration was never written to UEFI, so the EFI read fails with EFI_NOT_FOUND. The two woofers driven by the amplifiers are silent while the tweeters driven directly by the ALC287 play. Reading the amplifier registers over i2c shows PWR_CTL = 0x00 (active) and the TDM slots correctly programmed by the RCA profile, but PB_CFG1 = 0x00. With this change PB_CFG1 keeps its power-on default of 0x20 and both woofers play. tas2781_save_calibration() in tas2781_hda.c already clears total_sz on failure; do the same for the TAS2563 variant. Signed-off-by: Philipp Oster Link: https://patch.msgid.link/20260720-tas2781-calfix-v1-1-3a5fa6ad90bc@outlook.de Signed-off-by: Takashi Iwai --- diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c index 69a22fdfeedb..624db967f17b 100644 --- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c +++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c @@ -354,6 +354,7 @@ static int tas2563_save_calibration(struct tas2781_hda *h) if (ret < 0 || ret >= sizeof(var8) - 1) { dev_err(p->dev, "%s: Read %s failed\n", __func__, var8); + cd->total_sz = 0; return -EINVAL; } /* @@ -371,6 +372,7 @@ static int tas2563_save_calibration(struct tas2781_hda *h) dev_warn(p->dev, "Dev %d: Caldat[%d] read failed %ld\n", i, j, status); + cd->total_sz = 0; return -EINVAL; } bedata = cpu_to_be32(*(uint32_t *)&data[offset]); @@ -382,6 +384,7 @@ static int tas2563_save_calibration(struct tas2781_hda *h) if (cd->total_sz != offset) { dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) mismatch\n", __func__, cd->total_sz, offset); + cd->total_sz = 0; return -EINVAL; }