lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <c7929aa2-93d4-40d5-aa6f-d554729f4bee@linux.dev>
Date: Fri, 2 Jan 2026 11:16:57 -0800
From: Matthew Schwartz <matthew.schwartz@...ux.dev>
To: Antheas Kapenekakis <lkml@...heas.dev>
Cc: Baojun Xu <baojun.xu@...com>, Shenghao Ding <shenghao-ding@...com>,
 linux-sound@...r.kernel.org,
 "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>, tiwai@...e.de
Subject: Re: [BUG] hda/tas2781: ASUS ROG Xbox Ally X audio issues with default
 firmware

On 1/2/26 9:12 AM, Antheas Kapenekakis wrote:
> On Tue, 30 Dec 2025 at 22:44, Matthew Schwartz
> <matthew.schwartz@...ux.dev> wrote:
>>
>>
>>
>>> On Dec 8, 2025, at 8:00 PM, Matthew Schwartz <matthew.schwartz@...ux.dev> wrote:
>>>
>> - snip
>>> 2.52.0
>>
>> After reading the TI E2E forums, it seems these calibration tuning configurations are only meant to be used during a calibration process.
> 
> A source would be good here, a link or two

Sorry about that, here is where I read about the differences between the two configs:
https://e2e.ti.com/support/audio-group/audio/f/audio-forum/1558310/tas2563-what-is-the-difference-between-tuning-and-calibration-configuration-in-exported-smartamp-binary

It's about a different amplifier model, but I assume the same applies to tas2781 given the naming structure is the same for the configurations.

> 
>> Instead, something else I found that works is not overriding the firmware file calibration data with the UEFI calibration data:
> 
> I did not look into the source code, do you have any reference in the
> ACPI TAS code that r0_buf is prefilled with UEFI data?

>From what I understand, I think the current flow goes like this:

1. During driver init, tas2781_save_calibration() reads UEFI calibration data into the cali_data memory buffer and sets is_user_space_calidata=true: https://github.com/torvalds/linux/blob/master/sound/hda/codecs/side-codecs/tas2781_hda.c#L162-L173

2. When switching to a DSP config, tasdevice_select_tuningprm_cfg() calls tasdevice_load_data() which writes the firmware configuration, including any calibration values embedded in that config: https://github.com/torvalds/linux/blob/master/sound/soc/codecs/tas2781-fmwlib.c#L2510

3. Immediately after, tasdev_load_calibrated_data() writes the UEFI calibration data from step 1, overwriting the values just set in step 2: https://github.com/torvalds/linux/blob/9b043680446067358913edc2e9dd71bf8ffae208/sound/soc/codecs/tas2781-fmwlib.c#L2392-L2428 + https://github.com/torvalds/linux/blob/master/sound/soc/codecs/tas2781-fmwlib.c#L2519

I confirmed this this by inserting some debug logs around tasdev_load_calibrated_data:

[    3.908963] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tas2781_apply_calib: dspbin_typ=2, ndev=2, Setting is_user_space_calidata=true
[    6.215164] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdevice_tuning_switch: state=0, cur_prog=0, cur_conf=0, profile_cfg_id=0
[    6.215169] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdevice_tuning_switch: fw_state=3, is_user_space_calidata=1
[    6.215171] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdevice_select_tuningprm_cfg: Loading config[0] name='configuration_RC73_Veco_ISLR100_Tuning Mode_48 KHz_s2_0' nr_blk=8
[    6.365075] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev=0, is_user_space_calidata=1, cal_fmw=0000000000000000
[    6.365081] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: Loading user-space calibration for dev 0
[    6.365668] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 BEFORE r0_reg=0x000ce4: 408f5c29
[    6.366039] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 BEFORE invr0_reg=0x000cf4: 0fdc788c
[    6.366411] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 BEFORE r0_low_reg=0x000cfc: 0f7e9100
[    6.366889] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 BEFORE pow_reg=0x000ae0: 009b5281
[    6.367378] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 BEFORE tlimit_reg=0x000d70: 25800000
[    6.367380] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing calibration: r0_reg=0x000ce4 data=3c5f7222
[    6.367831] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing r0_low_reg=0x000cfc data=2e9b9aac
[    6.368168] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing invr0_reg=0x000cf4 data=10f615d5
[    6.368511] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing pow_reg=0x000ae0 data=0096915d
[    6.368963] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing tlimit_reg=0x000d70 data=25800000
[    6.369414] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev=1, is_user_space_calidata=1, cal_fmw=0000000000000000
[    6.369415] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: Loading user-space calibration for dev 1
[    6.370005] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 BEFORE r0_reg=0x000ce4: 40cccccd
[    6.370374] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 BEFORE invr0_reg=0x000cf4: 0fcd6e9e
[    6.370750] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 BEFORE r0_low_reg=0x000cfc: 0f8d4fdf
[    6.371233] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 BEFORE pow_reg=0x000ae0: 009b9c58
[    6.371716] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 BEFORE tlimit_reg=0x000d70: 25800000
[    6.371718] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing calibration: r0_reg=0x000ce4 data=3c90e72d
[    6.372173] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing r0_low_reg=0x000cfc data=2ec1c8ff
[    6.372514] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing invr0_reg=0x000cf4 data=10e83c28
[    6.372853] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing pow_reg=0x000ae0 data=0096cefc
[    6.373305] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing tlimit_reg=0x000d70 data=25800000

where it loads the UEFI calibration over top of the firmware calibration.

> 
> It could be that there is a specific priority, where UEFI data is
> supposed to be loaded after the firmware code, replacing the
> calibration data from the file, or that is what is done in Windows.
> But here it is done the other way. In that case, it might be more
> appropriate to set a dummy var such as bool uefi_calib that becomes 1
> when loading calibration from UEFI, and skip loading from the fw file
> if available.
> 
> But links, etc. Here, this would affect all TAS devices too, so it is
> more major.

Yes, was really hoping to get TI's feedback before potentially sending it out, as it would be a major change and the documentation on this is scarce. I could also be misunderstanding the calibration data load flow, but this is just from poking at this issue from every angle I can think of. 

Happy new year,
Matt

> 
> Happy new year,
> Antheas
> 
>> diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
>> index 78fd0a5dc6f2..1e768e6187da 100644
>> --- a/sound/soc/codecs/tas2781-fmwlib.c
>> +++ b/sound/soc/codecs/tas2781-fmwlib.c
>> @@ -2377,6 +2377,7 @@ static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i)
>>         unsigned char *data = cali_data->data;
>>         struct tasdevice_calibration *cal;
>>         int k = i * (cali_data->cali_dat_sz_per_dev + 1);
>> +       unsigned char r0_buf[4];
>>         int rc;
>>
>>         /* Load the calibrated data from cal bin file */
>> @@ -2389,6 +2390,20 @@ static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i)
>>         }
>>         if (!priv->is_user_space_calidata)
>>                 return;
>> +
>> +       /*
>> +        * Check if the DSP config already set the calibration registers.
>> +        * Some tuning configs contain their own calibration data which should
>> +        * not be overwritten by user space calibration data.
>> +        */
>> +       rc = tasdevice_dev_bulk_read(priv, i, p->r0_reg, r0_buf, 4);
>> +       if (rc >= 0 && (r0_buf[0] | r0_buf[1] | r0_buf[2] | r0_buf[3])) {
>> +               dev_dbg(priv->dev,
>> +                       "%s: dev %d r0_reg already set by config, skipping calibration\n",
>> +                       __func__, i);
>> +               return;
>> +       }
>> +
>>         /* load calibrated data from user space */
>>         if (data[k] != i) {
>>                 dev_err(priv->dev, "%s: no cal-data for dev %d from usr-spc\n",
>>
>> Is this more suitable to be upstreamed?
>>
>> Thanks,
>> Matt
>> <snip>
>>
> 


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ