]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ALSA: hda/tas2781: clear cali_data.total_sz when calibration read fails
authorPhilipp Oster <philippdev5396@outlook.de>
Mon, 20 Jul 2026 09:41:51 +0000 (11:41 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 20 Jul 2026 18:49:04 +0000 (20:49 +0200)
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 <philippdev5396@outlook.de>
Link: https://patch.msgid.link/20260720-tas2781-calfix-v1-1-3a5fa6ad90bc@outlook.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/hda/codecs/side-codecs/tas2781_hda_i2c.c

index 69a22fdfeedb7ee22ea801c55a85937b17434550..624db967f17bcede4998d96269a752d879130303 100644 (file)
@@ -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;
        }