From: Matthew Schwartz <matthew.schwartz@linux.dev>
To: Antheas Kapenekakis <lkml@antheas.dev>
Cc: Baojun Xu <baojun.xu@ti.com>,
Shenghao Ding <shenghao-ding@ti.com>,
linux-sound@vger.kernel.org,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
tiwai@suse.de
Subject: Re: [BUG] hda/tas2781: ASUS ROG Xbox Ally X audio issues with default firmware
Date: Fri, 2 Jan 2026 11:16:57 -0800 [thread overview]
Message-ID: <c7929aa2-93d4-40d5-aa6f-d554729f4bee@linux.dev> (raw)
In-Reply-To: <CAGwozwEJRDq96ZUQv+8H5fiXBVQ2jFvvuK48WpDqZ0eQ_NB+NA@mail.gmail.com>
On 1/2/26 9:12 AM, Antheas Kapenekakis wrote:
> On Tue, 30 Dec 2025 at 22:44, Matthew Schwartz
> <matthew.schwartz@linux.dev> wrote:
>>
>>
>>
>>> On Dec 8, 2025, at 8:00 PM, Matthew Schwartz <matthew.schwartz@linux.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>
>>
>
next prev parent reply other threads:[~2026-01-02 19:17 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-04 1:47 [BUG] hda/tas2781: ASUS ROG Xbox Ally X audio issues with default firmware Matthew Schwartz
2025-12-04 21:28 ` Antheas Kapenekakis
2025-12-08 21:37 ` Matthew Schwartz
2025-12-09 4:00 ` Matthew Schwartz
2025-12-30 20:43 ` Matthew Schwartz
2026-01-02 17:12 ` Antheas Kapenekakis
2026-01-02 19:16 ` Matthew Schwartz [this message]
2026-01-02 23:13 ` Antheas Kapenekakis
2026-01-03 0:31 ` Matthew Schwartz
2026-01-03 11:48 ` Antheas Kapenekakis
2026-01-04 8:58 ` [EXTERNAL] " Xu, Baojun
2026-01-04 9:29 ` Matthew Schwartz
2026-01-07 8:31 ` Takashi Iwai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c7929aa2-93d4-40d5-aa6f-d554729f4bee@linux.dev \
--to=matthew.schwartz@linux.dev \
--cc=baojun.xu@ti.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=lkml@antheas.dev \
--cc=shenghao-ding@ti.com \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.