hda/tas2781: ASUS ROG Xbox Ally X audio issues with default firmware
Subsystems (3)
Hello,
I have an ASUS ROG Xbox Ally X which uses hda/tas2781 for the speaker amplifiers. I am splitting this out into a new thread based on the suggestion from [1] to fix the remaining issues with the device's audio separately.
I built a kernel from tags/sound-6.19-rc1 in tiwai/sound and included [2], which seemed potentially relevant to the issue that I describe below.
By default, my system loads /usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zst. With this firmware file, any sound above the 70% volume limit range starts to become distorted and frequently drop out from either one or both speakers. I've included an alsa-info.sh report with this default firmware at [3].
If I run sudo mv /usr/lib/firmware/ti/audio/tas2781/TAS2XXX13841.bin.zst /usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zst and force the other firmware file for Xbox Ally models, my speakers work up to 100% without any of the drop outs I experience on the default firmware. I've included an alsa-info.sh report with this renamed firmware at [4].
I took an acpidump at [5] and extracted the dsdt table at [6]. Please let me know if there's any additional information I can provide from the device to further debug the sound issues with the default selected firmware.
Thanks,
Matt
[1]: https://lore.kernel.org/linux-sound/[email protected]/
[2]: https://lore.kernel.org/all/[email protected]/
[3]: https://alsa-project.org/db/?f=840337cab11f6aa70cf48b15d55ac45e4027ff41
[4]: https://alsa-project.org/db/?f=6e482f72765d89520ea171f15641228bcadefcf0
[5]: https://gist.githubusercontent.com/matte-schwartz/d7ff3c857b45cca197f3d3adc16df0bc/raw/2e3267b8d1a9d619ecd8157e4da426be756b6497/acpidump.txt
[6]: https://gist.githubusercontent.com/matte-schwartz/4042dcd3779c3738af60536a9d4050d6/raw/5227717c6d40a2dc4012b95f7fefc6cd50ba784d/dsdt.dsl
Quoted 16 lines · Matthew Schwartz
Hello,
I have an ASUS ROG Xbox Ally X which uses hda/tas2781 for the speaker amplifiers. I am splitting this out into a new thread based on the suggestion from [1] to fix the remaining issues with the device's audio separately.
I built a kernel from tags/sound-6.19-rc1 in tiwai/sound and included [2], which seemed potentially relevant to the issue that I describe below.
By default, my system loads
/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zst. With this firmware file, any sound above the 70% volume limit range starts to become distorted and frequently drop out from either one or both speakers. I've included analsa-info.shreport with this default firmware at [3].If I run sudo mv
/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13841.bin.zst/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zstand force the other firmware file for Xbox Ally models, my speakers work up to 100% without any of the drop outs I experience on the default firmware. I've included analsa-info.shreport with this renamed firmware at [4].I took an acpidump at [5] and extracted the dsdt table at [6]. Please let me know if there's any additional information I can provide from the device to further debug the sound issues with the default selected firmware.
Thanks,
Matt
Quoted 7 lines
[1]: https://lore.kernel.org/linux-sound/[email protected]/
[2]: https://lore.kernel.org/all/[email protected]/
[3]: https://alsa-project.org/db/?f=840337cab11f6aa70cf48b15d55ac45e4027ff41
[4]: https://alsa-project.org/db/?f=6e482f72765d89520ea171f15641228bcadefcf0
[5]: https://gist.githubusercontent.com/matte-schwartz/d7ff3c857b45cca197f3d3adc16df0bc/raw/2e3267b8d1a9d619ecd8157e4da426be756b6497/acpidump.txt
[6]: https://gist.githubusercontent.com/matte-schwartz/4042dcd3779c3738af60536a9d4050d6/raw/5227717c6d40a2dc4012b95f7fefc6cd50ba784d/dsdt.dsl
Related to this I have a follow up patch that fixes the audio jack on the Xbox Allies which regressed with the initial quirk applied. But it did not seem to help here. I will send it soon-
Antheas
Quoted 9 lines · Matthew Schwartz
Hello,
I have an ASUS ROG Xbox Ally X which uses hda/tas2781 for the speaker amplifiers. I am splitting this out into a new thread based on the suggestion from [1] to fix the remaining issues with the device's audio separately.
I built a kernel from tags/sound-6.19-rc1 in tiwai/sound and included [2], which seemed potentially relevant to the issue that I describe below.
By default, my system loads
/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zst. With this firmware file, any sound above the 70% volume limit range starts to become distorted and frequently drop out from either one or both speakers. I've included analsa-info.shreport with this default firmware at [3].If I run sudo mv
/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13841.bin.zst/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zstand force the other firmware file for Xbox Ally models, my speakers work up to 100% without any of the drop outs I experience on the default firmware. I've included analsa-info.shreport with this renamed firmware at [4].
Hmm, I did just boot into Windows to confirm which firmware blob loads, and it looks like Windows also uses TAS2XXX13840 for my unit. So the driver doesn't appear to be loading the wrong firmware on Linux...
Quoted 12 lines
I took an acpidump at [5] and extracted the dsdt table at [6]. Please let me know if there's any additional information I can provide from the device to further debug the sound issues with the default selected firmware.
Thanks,
Matt[1]: https://lore.kernel.org/linux-sound/[email protected]/
[2]: https://lore.kernel.org/all/[email protected]/
[3]: https://alsa-project.org/db/?f=840337cab11f6aa70cf48b15d55ac45e4027ff41
[4]: https://alsa-project.org/db/?f=6e482f72765d89520ea171f15641228bcadefcf0
[5]: https://gist.githubusercontent.com/matte-schwartz/d7ff3c857b45cca197f3d3adc16df0bc/raw/2e3267b8d1a9d619ecd8157e4da426be756b6497/acpidump.txt
[6]: https://gist.githubusercontent.com/matte-schwartz/4042dcd3779c3738af60536a9d4050d6/raw/5227717c6d40a2dc4012b95f7fefc6cd50ba784d/dsdt.dsl
Quoted 5 lines · Matthew Schwartz
Quoted 4 lines · Matthew Schwartz
Hello,
I have an ASUS ROG Xbox Ally X which uses hda/tas2781 for the speaker amplifiers. I am splitting this out into a new thread based on the suggestion from [1] to fix the remaining issues with the device's audio separately.
Quoted 7 lines
Quoted 5 lines
I built a kernel from tags/sound-6.19-rc1 in tiwai/sound and included [2], which seemed potentially relevant to the issue that I describe below.
By default, my system loads
/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zst. With this firmware file, any sound above the 70% volume limit range starts to become distorted and frequently drop out from either one or both speakers. I've included analsa-info.shreport with this default firmware at [3].If I run sudo mv
/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13841.bin.zst/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zstand force the other firmware file for Xbox Ally models, my speakers work up to 100% without any of the drop outs I experience on the default firmware. I've included analsa-info.shreport with this renamed firmware at [4].Hmm, I did just boot into Windows to confirm which firmware blob loads, and it looks like Windows also uses TAS2XXX13840 for my unit. So the driver doesn't appear to be loading the wrong firmware on Linux...
Ok, I started looking into the issue a bit more closely after confirming the same firmware loads and works fine on Windows.
I noticed in tas2781_hda_i2c that there is a block of code that refers to multiple confs in the DSP firmware, but it's set to 0 as of ec1de5c214e ("ALSA: hda/tas2781: select program 0, conf 0 by default")
With a debug patch to try and shine some more light on the ROG Xbox Ally X's audio firmware:
sound/hda/codecs/side-codecs/tas2781_hda_i2c.c +7 -0
@@ -461,6 +463,9 @@ static void tasdevice_dspfw_init(void *context)"TAS2XXX%04X.bin" , lower_16_bits(codec->core.subsystem_id)); } +dev_info (tas_priv->dev,"%s: loading DSP firmware %s (speaker_id=%d, subsys_id=0x%04x)\n" , + __func__, tas_priv->coef_binaryname, tas_priv->speaker_id, +lower_16_bits (codec->core.subsystem_id)); ret =tasdevice_dsp_parser (tas_priv);if (ret) { dev_err(tas_priv->dev, "dspfw load %s error\n",
@@ -480,6 +485,10 @@ static void tasdevice_dspfw_init(void *context)if (tas_priv->fmw->nr_configurations >0 ) tas_priv->cur_conf =0 ; +dev_info (tas_priv->dev,"%s: DSP loaded - nr_programs=%d nr_configurations=%d cur_prog=%d cur_conf=%d\n" , + __func__, tas_priv->fmw->nr_programs, tas_priv->fmw->nr_configurations, + tas_priv->cur_prog, tas_priv->cur_conf); +/* Init common setting for different audio profiles */ if (tas_priv->rcabin.init_profile_id >=0 ) tasdevice_select_cfg_blk(tas_priv,
sound/soc/codecs/tas2781-fmwlib.c +2 -0
@@ -614,6 +614,8 @@ static int fw_parse_configuration_data_kernel( goto out; }memcpy (config->name, &data[offset],64 ); +dev_info (tas_priv->dev,"%s: Config[%u] name='%.64s'\n" , + __func__, i, config->name);/*skip extra 16 bytes*/ offset +=80 ;
Signature · 12 lines
2.52.0 I could see there are two configurations in TAS2XXX13840: [ 4.347832] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdevice_dspfw_init: loading DSP firmware TAS2XXX13840.bin (speaker_id=0, subsys_id=0x1384) [ 4.348238] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: fw_parse_configuration_data_kernel: Config[0] name='configuration_RC73_Veco_ISLR100_Tuning Mode_48 KHz_s2_0' [ 4.348240] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: fw_parse_configuration_data_kernel: Config[1] name='calibration_Tuning Mode_48 KHz_s2_0' [ 5.747560] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdevice_dspfw_init: DSP loaded - nr_programs=1 nr_configurations=2 cur_prog=0 cur_conf=0 With "configuration_RC73_Veco_ISLR100_Tuning Mode_48 KHz_s2_0", the default, I can hear the audio glitching I described in my original report. If I change the code to load "calibration_Tuning Mode_48 KHz_s2_0" instead:
sound/hda/codecs/side-codecs/tas2781_hda_i2c.c +1 -1
@@ -481,7 +481,7 @@ static void tasdevice_dspfw_init(void *context)if (tas_priv->fmw->nr_programs >0 ) tas_priv->cur_prog =0 ;if (tas_priv->fmw->nr_configurations >0 ) - tas_priv->cur_conf =0 ; + tas_priv->cur_conf =1 ; dev_info(tas_priv->dev, "%s: DSP loaded - nr_programs=%d nr_configurations=%d cur_prog=%d cur_conf=%d\n", __func__, tas_priv->fmw->nr_programs, tas_priv->fmw->nr_configurations,
Signature · 3 lines
2.52.0 then audio works perfectly up to 100% volume without any of the same issues as the other configuration, and without renaming the firmware blobs.
Quoted 14 lines
Quoted 13 lines
I took an acpidump at [5] and extracted the dsdt table at [6]. Please let me know if there's any additional information I can provide from the device to further debug the sound issues with the default selected firmware.
Thanks,
Matt[1]: https://lore.kernel.org/linux-sound/[email protected]/
[2]: https://lore.kernel.org/all/[email protected]/
[3]: https://alsa-project.org/db/?f=840337cab11f6aa70cf48b15d55ac45e4027ff41
[4]: https://alsa-project.org/db/?f=6e482f72765d89520ea171f15641228bcadefcf0
[5]: https://gist.githubusercontent.com/matte-schwartz/d7ff3c857b45cca197f3d3adc16df0bc/raw/2e3267b8d1a9d619ecd8157e4da426be756b6497/acpidump.txt
[6]: https://gist.githubusercontent.com/matte-schwartz/4042dcd3779c3738af60536a9d4050d6/raw/5227717c6d40a2dc4012b95f7fefc6cd50ba784d/dsdt.dsl
Quoted 91 lines · Matthew Schwartz
Quoted 5 lines · Matthew Schwartz
Quoted 4 lines · Matthew Schwartz
Hello,
I have an ASUS ROG Xbox Ally X which uses hda/tas2781 for the speaker amplifiers. I am splitting this out into a new thread based on the suggestion from [1] to fix the remaining issues with the device's audio separately.
Quoted 7 lines
Quoted 5 lines
I built a kernel from tags/sound-6.19-rc1 in tiwai/sound and included [2], which seemed potentially relevant to the issue that I describe below.
By default, my system loads
/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zst. With this firmware file, any sound above the 70% volume limit range starts to become distorted and frequently drop out from either one or both speakers. I've included analsa-info.shreport with this default firmware at [3].If I run sudo mv
/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13841.bin.zst/usr/lib/firmware/ti/audio/tas2781/TAS2XXX13840.bin.zstand force the other firmware file for Xbox Ally models, my speakers work up to 100% without any of the drop outs I experience on the default firmware. I've included analsa-info.shreport with this renamed firmware at [4].Hmm, I did just boot into Windows to confirm which firmware blob loads, and it looks like Windows also uses TAS2XXX13840 for my unit. So the driver doesn't appear to be loading the wrong firmware on Linux...
Ok, I started looking into the issue a bit more closely after confirming the same firmware loads and works fine on Windows.
I noticed in
tas2781_hda_i2cthat there is a block of code that refers to multiple confs in the DSP firmware, but it's set to 0 as ofec1de5c214e("ALSA: hda/tas2781: select program 0, conf 0 by default")With a debug patch to try and shine some more light on the ROG Xbox Ally X's audio firmware:
sound/hda/codecs/side-codecs/tas2781_hda_i2c.c +7
-0@@ -461,6 +463,9 @@ static void tasdevice_dspfw_init(void *context)"TAS2XXX%04X.bin" , lower_16_bits(codec->core.subsystem_id)); } +dev_info (tas_priv->dev,"%s: loading DSP firmware %s (speaker_id=%d, subsys_id=0x%04x)\n" , + __func__, tas_priv->coef_binaryname, tas_priv->speaker_id, +lower_16_bits (codec->core.subsystem_id)); ret =tasdevice_dsp_parser (tas_priv);if (ret) { dev_err(tas_priv->dev, "dspfw load %s error\n",@@ -480,6 +485,10 @@ static void tasdevice_dspfw_init(void *context)if (tas_priv->fmw->nr_configurations >0 ) tas_priv->cur_conf =0 ; +dev_info (tas_priv->dev,"%s: DSP loaded - nr_programs=%d nr_configurations=%d cur_prog=%d cur_conf=%d\n" , + __func__, tas_priv->fmw->nr_programs, tas_priv->fmw->nr_configurations, + tas_priv->cur_prog, tas_priv->cur_conf); +/* Init common setting for different audio profiles */ if (tas_priv->rcabin.init_profile_id >=0 ) tasdevice_select_cfg_blk(tas_priv,sound/soc/codecs/tas2781-fmwlib.c +2
-0@@ -614,6 +614,8 @@ static int fw_parse_configuration_data_kernel( goto out; }memcpy (config->name, &data[offset],64 ); +dev_info (tas_priv->dev,"%s: Config[%u] name='%.64s'\n" , + __func__, i, config->name);/*skip extra 16 bytes*/ offset +=80 ;Signature · 12 lines
2.52.0 I could see there are two configurations in TAS2XXX13840: [ 4.347832] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdevice_dspfw_init: loading DSP firmware TAS2XXX13840.bin (speaker_id=0, subsys_id=0x1384) [ 4.348238] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: fw_parse_configuration_data_kernel: Config[0] name='configuration_RC73_Veco_ISLR100_Tuning Mode_48 KHz_s2_0' [ 4.348240] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: fw_parse_configuration_data_kernel: Config[1] name='calibration_Tuning Mode_48 KHz_s2_0' [ 5.747560] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdevice_dspfw_init: DSP loaded - nr_programs=1 nr_configurations=2 cur_prog=0 cur_conf=0 With "configuration_RC73_Veco_ISLR100_Tuning Mode_48 KHz_s2_0", the default, I can hear the audio glitching I described in my original report. If I change the code to load "calibration_Tuning Mode_48 KHz_s2_0" instead:sound/hda/codecs/side-codecs/tas2781_hda_i2c.c +1
-1@@ -481,7 +481,7 @@ static void tasdevice_dspfw_init(void *context)if (tas_priv->fmw->nr_programs >0 ) tas_priv->cur_prog =0 ;if (tas_priv->fmw->nr_configurations >0 ) - tas_priv->cur_conf =0 ; + tas_priv->cur_conf =1 ; dev_info(tas_priv->dev, "%s: DSP loaded - nr_programs=%d nr_configurations=%d cur_prog=%d cur_conf=%d\n", __func__, tas_priv->fmw->nr_programs, tas_priv->fmw->nr_configurations,Signature · 1 line
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.
Instead, something else I found that works is not overriding the firmware file calibration data with the UEFI calibration data:
sound/soc/codecs/tas2781-fmwlib.c +15 -0
@@ -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
Quoted 16 lines
then audio works perfectly up to 100% volume without any of the same issues as the other configuration, and without renaming the firmware blobs.
Quoted 13 lines
Quoted 13 lines
I took an acpidump at [5] and extracted the dsdt table at [6]. Please let me know if there's any additional information I can provide from the device to further debug the sound issues with the default selected firmware.
Thanks,
Matt[1]: https://lore.kernel.org/linux-sound/[email protected]/
[2]: https://lore.kernel.org/all/[email protected]/
[3]: https://alsa-project.org/db/?f=840337cab11f6aa70cf48b15d55ac45e4027ff41
[4]: https://alsa-project.org/db/?f=6e482f72765d89520ea171f15641228bcadefcf0
[5]: https://gist.githubusercontent.com/matte-schwartz/d7ff3c857b45cca197f3d3adc16df0bc/raw/2e3267b8d1a9d619ecd8157e4da426be756b6497/acpidump.txt
[6]: https://gist.githubusercontent.com/matte-schwartz/4042dcd3779c3738af60536a9d4050d6/raw/5227717c6d40a2dc4012b95f7fefc6cd50ba784d/dsdt.dsl
Quoted 9 lines · Matthew Schwartz
Quoted 5 lines · Matthew Schwartz
- snip
Quoted 1 line
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
Quoted 1 line
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?
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.
Happy new year,
Antheas
Quoted 40 lines
sound/soc/codecs/tas2781-fmwlib.c +15
-0@@ -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>
Quoted 5 lines · Antheas Kapenekakis
Quoted 3 lines · Matthew Schwartz
Quoted 8 lines
Quoted 6 lines
Quoted 2 lines · Matthew Schwartz
- snip
Quoted 1 line
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.
Quoted 5 lines
Quoted 2 lines
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_bufis 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.
Quoted 11 lines
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_calibthat 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
Quoted 45 lines
Happy new year,
AntheasQuoted 40 lines
sound/soc/codecs/tas2781-fmwlib.c +15
-0@@ -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>
Quoted 10 lines · Matthew Schwartz
Quoted 8 lines · Antheas Kapenekakis
Quoted 6 lines · Matthew Schwartz
Quoted 5 lines · Matthew Schwartz
- snip
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
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
This link describes "calibration" configurations that are used in the calibration procedure. It is not clear to me that it refers to the calibration parameters exported by UEFI or in the configuration itself to be used alongside a configuration. I would tend toward this being irrelevant.
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Instead, something else I found that works is not overriding the firmware file calibration data with the UEFI calibration data:
I misunderstood what you meant by this before. I thought you meant that the firmware overrode the UEFI data, not the other way around. Surely, using the dummy data in the firmware file is better than using incorrect data from UEFI. However, the manufacturer calibrated data from the factory floor for each specific unit is in UEFI, so that is what should be used.
Quoted 5 lines
Quoted 2 lines
I did not look into the source code, do you have any reference in the ACPI TAS code that
r0_bufis prefilled with UEFI data?From what I understand, I think the current flow goes like this:
Quoted 7 lines
1. During driver init,
tas2781_save_calibration()reads UEFI calibration data into thecali_datamemory buffer and sets is_user_space_calidata=true: https://github.com/torvalds/linux/blob/master/sound/hda/codecs/side-codecs/tas2781_hda.c#L162-L1732. When switching to a DSP config,
tasdevice_select_tuningprm_cfg()callstasdevice_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#L25103. 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#L2519I confirmed this this by inserting some debug logs around
tasdev_load_calibrated_data:
I went through the code. It loads the UEFI data, sets is_user_space_calidata=1, then if the data is available it loads it. This is correct.
To me this seems like the calibration data for amp 1 is written to both amp 1 and amp 2, and for your firmware this breaks amp2.
In tasdev_load_calibrated_data(), an i index is provided, but cali_data is nested under priv. So only one calibration set is supported. This means that amp 2 gets amp 1 calibrations.
Perhaps there is a "SmartAmpCalibrationData2" that should be read instead for amp 2 instead, can you dump the EFI variables and check?
In that case, a minor refactor to move cali_data and is_user_space_calidata from priv to priv->tasdevice[i] and then use the proper efi var would fix this.
Antheas
Quoted 69 lines
[ 3.908963] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tas2781_apply_calib: dspbin_typ=2, ndev=2, Setting is_user_space_calidata=true<snip>
where it loads the UEFI calibration over top of the firmware calibration.
Quoted 11 lines
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_calibthat 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,
MattQuoted 45 lines
Happy new year,
AntheasQuoted 40 lines
sound/soc/codecs/tas2781-fmwlib.c +15
-0@@ -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>
Quoted 50 lines · Antheas Kapenekakis
Quoted 10 lines · Matthew Schwartz
Quoted 8 lines · Antheas Kapenekakis
Quoted 6 lines · Matthew Schwartz
Quoted 5 lines · Matthew Schwartz
- snip
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
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-binaryThis link describes "calibration" configurations that are used in the calibration procedure. It is not clear to me that it refers to the calibration parameters exported by UEFI or in the configuration itself to be used alongside a configuration. I would tend toward this being irrelevant.
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Instead, something else I found that works is not overriding the firmware file calibration data with the UEFI calibration data:
I misunderstood what you meant by this before. I thought you meant that the firmware overrode the UEFI data, not the other way around. Surely, using the dummy data in the firmware file is better than using incorrect data from UEFI. However, the manufacturer calibrated data from the factory floor for each specific unit is in UEFI, so that is what should be used.
Quoted 11 lines
Quoted 2 lines
I did not look into the source code, do you have any reference in the ACPI TAS code that
r0_bufis 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 thecali_datamemory buffer and sets is_user_space_calidata=true: https://github.com/torvalds/linux/blob/master/sound/hda/codecs/side-codecs/tas2781_hda.c#L162-L1732. When switching to a DSP config,
tasdevice_select_tuningprm_cfg()callstasdevice_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#L25103. 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
Quoted 8 lines
Quoted 1 line
I confirmed this this by inserting some debug logs around
tasdev_load_calibrated_data:I went through the code. It loads the UEFI data, sets is_user_space_calidata=1, then if the data is available it loads it. This is correct.
To me this seems like the calibration data for amp 1 is written to both amp 1 and amp 2, and for your firmware this breaks amp2.
If this were the case, shouldn't my debug logs have the same data being written to dev 0 and dev 1?
[ 6.367380] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing calibration: r0_reg=0x000ce4 data=3c5f7222 [ 6.371718] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing calibration: r0_reg=0x000ce4 data=3c90e72d
Quoted 7 lines
In
tasdev_load_calibrated_data(), an i index is provided, butcali_datais nested under priv. So only one calibration set is supported. This means that amp 2 gets amp 1 calibrations.Perhaps there is a "SmartAmpCalibrationData2" that should be read instead for amp 2 instead, can you dump the EFI variables and check?
(128)(deck@steamdeck ~)$ ls /sys/firmware/efi/efivars/
AmdAcpiVar-79941ecd-ed36-49d0-8124-e4c31ac75cd4 BugCheckProgress-ba57e015-65b3-4c3c-b274-659192f699e3 MemoryOverwriteRequestControl-e20939be-32d4-41be-a150-897f85d49829 AmdMemMcsrTimeStamp-ba0fc662-3edc-4038-8060-5a980d46d09f BuiltAsSecuredCorePC-77fa9abd-0359-4d32-bd60-28f4e78f784b MemoryOverwriteRequestControlLock-bb983ccf-151d-40e1-a07b-4a17be168292 AMD_PBS_SETUP-a339d746-f678-49b3-9fc7-54ce0f9df226 CALI_DATA-1f52d2a1-bb3a-457d-bc09-43a3f4310a92 MFG0-91b89306-5bac-4ae0-aab3-207ec12e989b AMD_RAID-fe26a894-d199-47d4-8afa-070e3d54ba86 ChainedLoaderDevicePartUUID-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f MonotonicCounter-01368881-c4ad-4b1d-b631-d57a8ec8db6b AmdSetup-3a997502-647a-4c82-998e-52ef9486a247 ChainLoaderEntryFlags-399abb9b-4bee-4a18-ab5b-45c6e0e8c716 MyasusAutoInstall-607005d5-3f75-4b2e-98f0-85ba66797a3e AMITCGPPIVAR-a8a2093b-fefa-43c1-8e62-ce526847265e CloudRecoverySupport-607005d5-3f75-4b2e-98f0-85ba66797a3e OA30-91b89306-5bac-4ae0-aab3-207ec12e989b AodCoreInfo-5ed15dc0-edef-4161-9151-6014c4cc630c CNFG-91b89306-5bac-4ae0-aab3-207ec12e989b OfflineUniqueIDEKPubCRC-eaec226f-c9a3-477a-a826-ddc716cdc0e3 AodCoreInfoTemp-5ed15dc0-edef-4161-9151-6014c4cc630c ConIn-8be4df61-93ca-11d2-aa0d-00e098032b8c OfflineUniqueIDEKPub-eaec226f-c9a3-477a-a826-ddc716cdc0e3 AodSetupStx-5ed15dc0-edef-4161-9151-6014c4cc630c ConInDev-8be4df61-93ca-11d2-aa0d-00e098032b8c OsIndicationsSupported-8be4df61-93ca-11d2-aa0d-00e098032b8c ArmouryCrateStaticField-607005d5-3f75-4b2e-98f0-85ba66797a3e ConOut-8be4df61-93ca-11d2-aa0d-00e098032b8c PK-8be4df61-93ca-11d2-aa0d-00e098032b8c AsusClearPspNvram-6aae2279-b4d8-4cf9-aa2a-3607fdb4ccee ConOutDev-8be4df61-93ca-11d2-aa0d-00e098032b8c PKDefault-8be4df61-93ca-11d2-aa0d-00e098032b8c AsusEDID-607005d5-3f75-4b2e-98f0-85ba66797a3e CurrentPolicy-77fa9abd-0359-4d32-bd60-28f4e78f784b PlatformLang-8be4df61-93ca-11d2-aa0d-00e098032b8c AsusGpnvVersion-607005d5-3f75-4b2e-98f0-85ba66797a3e db-d719b2cb-3d3a-4596-a3bc-dad00e67656f PlatformLangCodes-8be4df61-93ca-11d2-aa0d-00e098032b8c AsusManufactureVersion-607005d5-3f75-4b2e-98f0-85ba66797a3e dbDefault-8be4df61-93ca-11d2-aa0d-00e098032b8c SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c AsusMcuPwrSaving-68ebf80b-5a73-415c-a363-045837cd9168 dbt-d719b2cb-3d3a-4596-a3bc-dad00e67656f SetupMode-8be4df61-93ca-11d2-aa0d-00e098032b8c AsusPostLogoSound-607005d5-3f75-4b2e-98f0-85ba66797a3e dbtDefault-8be4df61-93ca-11d2-aa0d-00e098032b8c SIDSUPPORT-7d3dceee-cbce-4ea7-8709-6e552f1edbde AsusVariable-607005d5-3f75-4b2e-98f0-85ba66797a3e dbx-d719b2cb-3d3a-4596-a3bc-dad00e67656f SignatureSupport-8be4df61-93ca-11d2-aa0d-00e098032b8c AuditMode-8be4df61-93ca-11d2-aa0d-00e098032b8c dbxDefault-8be4df61-93ca-11d2-aa0d-00e098032b8c SmbiosEntryPointTable-4b3082a3-80c6-4d7e-9cd0-583917265df1 AuthVarPreBootPhase-7b59104a-c00d-4158-87ff-f04d6396a915 DefaultBootOrder-45cf35f6-0d6e-4d04-856a-0370a5b16f53 SmbiosEntryPointTableF000-4b3082a3-80c6-4d7e-9cd0-583917265df1 BitLockerStatus-607005d5-3f75-4b2e-98f0-85ba66797a3e DeployedMode-8be4df61-93ca-11d2-aa0d-00e098032b8c SmbiosScratchBuffer-4b3082a3-80c6-4d7e-9cd0-583917265df1 Boot0000-8be4df61-93ca-11d2-aa0d-00e098032b8c DeploymentModeNv-97e8965f-c761-4f48-b6e4-9ffa9cb2a2d6 SmbiosV3EntryPointTable-4b3082a3-80c6-4d7e-9cd0-583917265df1 Boot0001-8be4df61-93ca-11d2-aa0d-00e098032b8c _DMI-91b89306-5bac-4ae0-aab3-207ec12e989b SmmSupervisorVersion-d4adfc6f-2f58-4bcf-a887-05efb47d4299 Boot0002-8be4df61-93ca-11d2-aa0d-00e098032b8c EnableDIPM-a44da20b-add4-4ddf-bd44-2084a225e120 SPIROMSIZE-4175b27b-b5ed-41e9-b532-45f3d1d61bef Boot0003-8be4df61-93ca-11d2-aa0d-00e098032b8c EnableHIPM-a44da20b-add4-4ddf-bd44-2084a225e120 Timeout-8be4df61-93ca-11d2-aa0d-00e098032b8c Boot0004-8be4df61-93ca-11d2-aa0d-00e098032b8c ErrOut-8be4df61-93ca-11d2-aa0d-00e098032b8c TouchPanelDeviceInfo-8ee681db-b7a9-4684-b3cb-58ae37096492 Boot0005-8be4df61-93ca-11d2-aa0d-00e098032b8c FastBootOption-b540a530-6978-4da7-91cb-7207d764d262 TPMPERBIOSFLAGS-7d3dceee-cbce-4ea7-8709-6e552f1edbde Boot0009-8be4df61-93ca-11d2-aa0d-00e098032b8c GAMING_CNFG-91b89306-5bac-4ae0-aab3-207ec12e989b TpmServFlags-7d3dceee-cbce-4ea7-8709-6e552f1edbde Boot000A-8be4df61-93ca-11d2-aa0d-00e098032b8c HiiDB-1b838190-4625-4ead-abc9-cd5e6af18fe0 UmaCarveOutDefault-0e5ce58d-e59b-4f93-904a-6ef2b97a41d7 Boot000B-8be4df61-93ca-11d2-aa0d-00e098032b8c HwErrRecSupport-8be4df61-93ca-11d2-aa0d-00e098032b8c UmaCarveOutIndexDefault-cfff9da9-99ad-4e94-9ffd-02306b427b1f Boot000C-8be4df61-93ca-11d2-aa0d-00e098032b8c KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c UnlockIDCopy-eaec226f-c9a3-477a-a826-ddc716cdc0e3 Boot000D-8be4df61-93ca-11d2-aa0d-00e098032b8c KEKDefault-8be4df61-93ca-11d2-aa0d-00e098032b8c VendorKeys-8be4df61-93ca-11d2-aa0d-00e098032b8c Boot000E-8be4df61-93ca-11d2-aa0d-00e098032b8c LanguageControl-74265840-9434-409e-9846-92d21e5daa65 WifiSetup-ec87d643-eba4-4bb5-a1e5-3f3e36b20da9 BootCurrent-8be4df61-93ca-11d2-aa0d-00e098032b8c LastBoot-b540a530-6978-4da7-91cb-7207d764d262 WifiSetupRecentConnectInfo-beca2d18-062a-47bd-b998-7f5befd4c523 BootOptionSupport-8be4df61-93ca-11d2-aa0d-00e098032b8c LastBootFailed-b540a530-6978-4da7-91cb-7207d764d262 WIIM-beca2d18-062a-47bd-b998-7f5befd4c523 BootOrder-8be4df61-93ca-11d2-aa0d-00e098032b8c LoaderDevicePartUUID-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f WriteOnceStatus-4b3082a3-80c6-4d7e-9cd0-583917265df1 BugCheckCode-ba57e015-65b3-4c3c-b274-659192f699e3 LoaderInfo-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f BugCheckParameter1-ba57e015-65b3-4c3c-b274-659192f699e3 MaximumTableSize-4b3082a3-80c6-4d7e-9cd0-583917265df1
There's only one EFI var that seems to be for calibration data:
xxd /sys/firmware/efi/efivars/CALI_DATA-1f52d2a1-bb3a-457d-bc09-43a3f4310a92:
00000000: 0700 0000 dd0a 0000 0300 0000 7e4a 9d68 ............~J.h 00000010: 0000 0000 2272 5f3c d515 f610 ac9a 9b2e ...."r_<........ 00000020: 5d91 9600 0000 8025 0100 0000 2de7 903c ]......%....-..< 00000030: 283c e810 ffc8 c12e fcce 9600 0000 8025 (<.............% 00000040: 8000 0000 0000 1964 0000 1974 0000 197c .......d...t...| 00000050: 0000 1560 0000 1a70 eb7f b12b ...`...p...+
Quoted 77 lines
In that case, a minor refactor to move
cali_dataandis_user_space_calidatafrom priv to priv->tasdevice[i] and then use the proper efi var would fix this.Antheas
Quoted 69 lines
[ 3.908963] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tas2781_apply_calib: dspbin_typ=2, ndev=2, Setting is_user_space_calidata=true<snip>
where it loads the UEFI calibration over top of the firmware calibration.
Quoted 11 lines
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_calibthat 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,
MattQuoted 45 lines
Happy new year,
AntheasQuoted 40 lines
sound/soc/codecs/tas2781-fmwlib.c +15
-0@@ -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>
Quoted 79 lines · Matthew Schwartz
Quoted 50 lines · Antheas Kapenekakis
Quoted 10 lines · Matthew Schwartz
Quoted 8 lines · Antheas Kapenekakis
Quoted 6 lines · Matthew Schwartz
Quoted 5 lines · Matthew Schwartz
- snip
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
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-binaryThis link describes "calibration" configurations that are used in the calibration procedure. It is not clear to me that it refers to the calibration parameters exported by UEFI or in the configuration itself to be used alongside a configuration. I would tend toward this being irrelevant.
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Instead, something else I found that works is not overriding the firmware file calibration data with the UEFI calibration data:
I misunderstood what you meant by this before. I thought you meant that the firmware overrode the UEFI data, not the other way around. Surely, using the dummy data in the firmware file is better than using incorrect data from UEFI. However, the manufacturer calibrated data from the factory floor for each specific unit is in UEFI, so that is what should be used.
Quoted 11 lines
Quoted 2 lines
I did not look into the source code, do you have any reference in the ACPI TAS code that
r0_bufis 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 thecali_datamemory buffer and sets is_user_space_calidata=true: https://github.com/torvalds/linux/blob/master/sound/hda/codecs/side-codecs/tas2781_hda.c#L162-L1732. When switching to a DSP config,
tasdevice_select_tuningprm_cfg()callstasdevice_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#L25103. 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#L2519Quoted 8 lines
Quoted 1 line
I confirmed this this by inserting some debug logs around
tasdev_load_calibrated_data:I went through the code. It loads the UEFI data, sets is_user_space_calidata=1, then if the data is available it loads it. This is correct.
To me this seems like the calibration data for amp 1 is written to both amp 1 and amp 2, and for your firmware this breaks amp2.
If this were the case, shouldn't my debug logs have the same data being written to dev 0 and dev 1?
[ 6.367380] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing calibration: r0_reg=0x000ce4 data=3c5f7222 [ 6.371718] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing calibration: r0_reg=0x000ce4 data=3c90e72dQuoted 7 lines
In
tasdev_load_calibrated_data(), an i index is provided, butcali_datais nested under priv. So only one calibration set is supported. This means that amp 2 gets amp 1 calibrations.Perhaps there is a "SmartAmpCalibrationData2" that should be read instead for amp 2 instead, can you dump the EFI variables and check?
(128)(deck@steamdeck ~)$ ls
/sys/firmware/efi/efivars/
AmdAcpiVar-79941ecd-ed36-49d0-8124-e4c31ac75cd4 BugCheckProgress-ba57e015-65b3-4c3c-b274-659192f699e3 MemoryOverwriteRequestControl-e20939be-32d4-41be-a150-897f85d49829
<snip>
There's only one EFI var that seems to be for calibration data:
Quoted 8 lines
xxd
/sys/firmware/efi/efivars/CALI_DATA-1f52d2a1-bb3a-457d-bc09-43a3f4310a92:00000000: 0700 0000 dd0a 0000 0300 0000 7e4a 9d68 ............~J.h 00000010: 0000 0000 2272 5f3c d515 f610 ac9a 9b2e ...."r_<........ 00000020: 5d91 9600 0000 8025 0100 0000 2de7 903c ]......%....-..< 00000030: 283c e810 ffc8 c12e fcce 9600 0000 8025 (<.............% 00000040: 8000 0000 0000 1964 0000 1974 0000 197c .......d...t...| 00000050: 0000 1560 0000 1a70 eb7f b12b ...`...p...+
I reviewed the loader for CALI_DATA, it supports multiple device calibration data and indexes it currently. In addition, it has two versions with CRC checks that pass, so one of those versions loads the data correctly.
So everything looks technically correct
Here is your data from the first amp reordered:
r0_reg=0x000ce4 408f5c29
r0_reg=0x000ce4 3c5f7222 invr0_reg=0x000cf4 0fdc788c
invr0_reg=0x000cf4 10f615d5
r0_low_reg=0x000cfc 0f7e9100
r0_low_reg=0x000cfc 2e9b9aac
pow_reg=0x000ae0 009b5281
pow_reg=0x000ae0 0096915d
tlimit_reg=0x000d70 25800000
tlimit_reg=0x000d70 25800000
And the second amp:
r0_reg=0x000ce4 40cccccd
r0_reg=0x000ce4 3c90e72d invr0_reg=0x000cf4 0fcd6e9e
invr0_reg=0x000cf4 10e83c28
r0_low_reg=0x000cfc 0f8d4fdf
r0_low_reg=0x000cfc 2ec1c8ff
pow_reg=0x000ae0 009b9c58
pow_reg=0x000ae0 0096cefc
tlimit_reg=0x000d70 25800000
tlimit_reg=0x000d70 25800000
There is a large deviation in r0, invr0, and r0_low in both of them. Unfortunately, I do not have my Xbox Ally non-X to check to see if it's incorrect. This hints to me that the registers get incorrect data loaded, so there might be a mistake in the UEFI parser.
Here is a breakdown of your efivar
0700 0000 # This is not supposed to be here / Might have been thrown out by kernel if v2 loads
dd0a 0000 # 2781, is v2 protocol
0300 0000 # Data-Group-Sum / How many nodes
7e4a 9d68 # Timestamp
# First amplifier data
0000 0000
2272 5f3c # r0
d515 f610 # invr0
ac9a 9b2e # r0_low
5d91 9600 # pow
0000 8025 # tlimit
# Second amplifier data
0100 0000
2de7 903c # r0
283c e810 # invr0
ffc8 c12e # r0_low
fcce 9600 # pow
0000 8025 # tlimit
8000 0000 # Calibration data / Derivation logic in TASDEVICE_REG 0000 1964 # r0 addr
0000 1974 # invr0 addr
0000 197c # r0_low addr
0000 1560 # pow addr
0000 1a70 # tlimit addr
eb7f b12b # CRC32
Specifically for the 0x80, cali_reg addresses get stored into r0/invr0... iff p->dspbin_typ == TASDEV_BASIC.
I suspect the problem here is that the UEFI override for the first three values tries to change different registers and not r0, invr0 and r0_low. The pow, tlimit look correct.
But, due to p->dspbin_typ != TASDEV_BASIC, cali_reg ends up being thrown out and the UEFI values end up corrupting the r0, invr0 and r0_low default addresses. and not 00, 19, 64/74/7c
Antheas
Quoted 79 lines
Quoted 77 lines
In that case, a minor refactor to move
cali_dataandis_user_space_calidatafrom priv to priv->tasdevice[i] and then use the proper efi var would fix this.Antheas
Quoted 69 lines
[ 3.908963] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tas2781_apply_calib: dspbin_typ=2, ndev=2, Setting is_user_space_calidata=true<snip>
where it loads the UEFI calibration over top of the firmware calibration.
Quoted 11 lines
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_calibthat 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,
MattQuoted 45 lines
Happy new year,
AntheasQuoted 40 lines
sound/soc/codecs/tas2781-fmwlib.c +15
-0@@ -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>
Xu, Baojun
maintainerHi Antheas,
It may known issue which relative with calibration result.
Could you try to remove calibration result apply, and check if the problem still exist? For example, mask below line (line number is 494) in tasdevice_dspfw_init() from tas2781-hda-i2c.c:
hda_priv->save_calibration(tas_hda);
Best Regards
Jim
________________________________________
From: Antheas Kapenekakis <[email protected]>
Sent: 03 January 2026 19:48
To: Matthew Schwartz
Cc: Xu, Baojun; Ding, Shenghao; [email protected]; [email protected]; [email protected]
Subject: [EXTERNAL] Re: [BUG] hda/tas2781: ASUS ROG Xbox Ally X audio issues with default firmware
On Sat, 3 Jan 2026 at 02: 31, Matthew Schwartz <matthew. schwartz@ linux. dev> wrote: > > On 1/2/26 3: 13 PM, Antheas Kapenekakis wrote: > > On Fri, 2 Jan 2026 at 21: 17, Matthew Schwartz > > <matthew. schwartz@ linux. dev> ZjQcmQRYFpfptBannerStart
This message was sent from outside of Texas Instruments.
Do not click links or open attachments unless you recognize the source of this email and know the content is safe.
<https://us-phishalarm-ewt.proofpoint.com/EWT/v1/G3vK!tDdkczlnnYRTxMpLVz-pN5EZOCpqg7wGjyDRBvMeAZFuWZXBJlfNUQdJ4vR2DLvmO1o91tMvcFY2CkFWEO4UIBOBJ80exLz0o0fjR_qbdsgA4aHVUaeJh-oUWg$>
Report Suspicious
ZjQcmQRYFpfptBannerEnd
Quoted 79 lines · Matthew Schwartz
Quoted 50 lines · Antheas Kapenekakis
Quoted 10 lines · Matthew Schwartz
Quoted 8 lines · Antheas Kapenekakis
Quoted 6 lines · Matthew Schwartz
Quoted 5 lines · Matthew Schwartz
- snip
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
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-binaryThis link describes "calibration" configurations that are used in the calibration procedure. It is not clear to me that it refers to the calibration parameters exported by UEFI or in the configuration itself to be used alongside a configuration. I would tend toward this being irrelevant.
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Instead, something else I found that works is not overriding the firmware file calibration data with the UEFI calibration data:
I misunderstood what you meant by this before. I thought you meant that the firmware overrode the UEFI data, not the other way around. Surely, using the dummy data in the firmware file is better than using incorrect data from UEFI. However, the manufacturer calibrated data from the factory floor for each specific unit is in UEFI, so that is what should be used.
Quoted 11 lines
Quoted 2 lines
I did not look into the source code, do you have any reference in the ACPI TAS code that
r0_bufis 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 thecali_datamemory buffer and sets is_user_space_calidata=true: https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/master/sound/hda/codecs/side-codecs/tas2781_hda.c*L162-L173__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyA1aQnWHw$2. When switching to a DSP config,
tasdevice_select_tuningprm_cfg()callstasdevice_load_data()which writes the firmware configuration, including any calibration values embedded in that config: https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/master/sound/soc/codecs/tas2781-fmwlib.c*L2510__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyDJTrchbQ$3. Immediately after,
tasdev_load_calibrated_data()writes the UEFI calibration data from step 1, overwriting the values just set in step 2: https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/9b043680446067358913edc2e9dd71bf8ffae208/sound/soc/codecs/tas2781-fmwlib.c*L2392-L2428__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyBeYnGr_w$ + https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/master/sound/soc/codecs/tas2781-fmwlib.c*L2519__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyBz8-7Z6g$Quoted 8 lines
Quoted 1 line
I confirmed this this by inserting some debug logs around
tasdev_load_calibrated_data:I went through the code. It loads the UEFI data, sets is_user_space_calidata=1, then if the data is available it loads it. This is correct.
To me this seems like the calibration data for amp 1 is written to both amp 1 and amp 2, and for your firmware this breaks amp2.
If this were the case, shouldn't my debug logs have the same data being written to dev 0 and dev 1?
[ 6.367380] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing calibration: r0_reg=0x000ce4 data=3c5f7222 [ 6.371718] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing calibration: r0_reg=0x000ce4 data=3c90e72dQuoted 7 lines
In
tasdev_load_calibrated_data(), an i index is provided, butcali_datais nested under priv. So only one calibration set is supported. This means that amp 2 gets amp 1 calibrations.Perhaps there is a "SmartAmpCalibrationData2" that should be read instead for amp 2 instead, can you dump the EFI variables and check?
(128)(deck@steamdeck ~)$ ls
/sys/firmware/efi/efivars/
AmdAcpiVar-79941ecd-ed36-49d0-8124-e4c31ac75cd4 BugCheckProgress-ba57e015-65b3-4c3c-b274-659192f699e3 MemoryOverwriteRequestControl-e20939be-32d4-41be-a150-897f85d49829
<snip>
There's only one EFI var that seems to be for calibration data:
Quoted 8 lines
xxd
/sys/firmware/efi/efivars/CALI_DATA-1f52d2a1-bb3a-457d-bc09-43a3f4310a92:00000000: 0700 0000 dd0a 0000 0300 0000 7e4a 9d68 ............~J.h 00000010: 0000 0000 2272 5f3c d515 f610 ac9a 9b2e ...."r_<........ 00000020: 5d91 9600 0000 8025 0100 0000 2de7 903c ]......%....-..< 00000030: 283c e810 ffc8 c12e fcce 9600 0000 8025 (<.............% 00000040: 8000 0000 0000 1964 0000 1974 0000 197c .......d...t...| 00000050: 0000 1560 0000 1a70 eb7f b12b ...`...p...+
I reviewed the loader for CALI_DATA, it supports multiple device calibration data and indexes it currently. In addition, it has two versions with CRC checks that pass, so one of those versions loads the data correctly.
So everything looks technically correct
Here is your data from the first amp reordered:
r0_reg=0x000ce4 408f5c29
r0_reg=0x000ce4 3c5f7222 invr0_reg=0x000cf4 0fdc788c
invr0_reg=0x000cf4 10f615d5
r0_low_reg=0x000cfc 0f7e9100
r0_low_reg=0x000cfc 2e9b9aac
pow_reg=0x000ae0 009b5281
pow_reg=0x000ae0 0096915d
tlimit_reg=0x000d70 25800000
tlimit_reg=0x000d70 25800000
And the second amp:
r0_reg=0x000ce4 40cccccd
r0_reg=0x000ce4 3c90e72d invr0_reg=0x000cf4 0fcd6e9e
invr0_reg=0x000cf4 10e83c28
r0_low_reg=0x000cfc 0f8d4fdf
r0_low_reg=0x000cfc 2ec1c8ff
pow_reg=0x000ae0 009b9c58
pow_reg=0x000ae0 0096cefc
tlimit_reg=0x000d70 25800000
tlimit_reg=0x000d70 25800000
There is a large deviation in r0, invr0, and r0_low in both of them. Unfortunately, I do not have my Xbox Ally non-X to check to see if it's incorrect. This hints to me that the registers get incorrect data loaded, so there might be a mistake in the UEFI parser.
Here is a breakdown of your efivar
0700 0000 # This is not supposed to be here / Might have been thrown out by kernel if v2 loads
dd0a 0000 # 2781, is v2 protocol
0300 0000 # Data-Group-Sum / How many nodes
7e4a 9d68 # Timestamp
# First amplifier data
0000 0000
2272 5f3c # r0
d515 f610 # invr0
ac9a 9b2e # r0_low
5d91 9600 # pow
0000 8025 # tlimit
# Second amplifier data
0100 0000
2de7 903c # r0
283c e810 # invr0
ffc8 c12e # r0_low
fcce 9600 # pow
0000 8025 # tlimit
8000 0000 # Calibration data / Derivation logic in TASDEVICE_REG 0000 1964 # r0 addr
0000 1974 # invr0 addr
0000 197c # r0_low addr
0000 1560 # pow addr
0000 1a70 # tlimit addr
eb7f b12b # CRC32
Specifically for the 0x80, cali_reg addresses get stored into r0/invr0... iff p->dspbin_typ == TASDEV_BASIC.
I suspect the problem here is that the UEFI override for the first three values tries to change different registers and not r0, invr0 and r0_low. The pow, tlimit look correct.
But, due to p->dspbin_typ != TASDEV_BASIC, cali_reg ends up being thrown out and the UEFI values end up corrupting the r0, invr0 and r0_low default addresses. and not 00, 19, 64/74/7c
Antheas
Quoted 79 lines
Quoted 77 lines
In that case, a minor refactor to move
cali_dataandis_user_space_calidatafrom priv to priv->tasdevice[i] and then use the proper efi var would fix this.Antheas
Quoted 69 lines
[ 3.908963] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tas2781_apply_calib: dspbin_typ=2, ndev=2, Setting is_user_space_calidata=true<snip>
where it loads the UEFI calibration over top of the firmware calibration.
Quoted 11 lines
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_calibthat 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,
MattQuoted 45 lines
Happy new year,
AntheasQuoted 40 lines
sound/soc/codecs/tas2781-fmwlib.c +15
-0@@ -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>
Quoted 10 lines · Baojun
Hi Antheas,
It may known issue which relative with calibration result.
Could you try to remove calibration result apply, and check if the problem still exist? For example, mask below line (line number is 494) intasdevice_dspfw_init()fromtas2781-hda-i2c.c:
hda_priv->save_calibration(tas_hda);Best Regards
Jim
Hi Jim,
Thanks for the reply. Antheas does not have hardware affected by this issue, but I can confirm that this fixes the problem on my own device.
Matt
Quoted 270 lines
________________________________________
From: Antheas Kapenekakis <[email protected]>
Sent: 03 January 2026 19:48
To: Matthew Schwartz
Cc: Xu, Baojun; Ding, Shenghao; [email protected]; [email protected]; [email protected]
Subject: [EXTERNAL] Re: [BUG] hda/tas2781: ASUS ROG Xbox Ally X audio issues with default firmwareOn Sat, 3 Jan 2026 at 02: 31, Matthew Schwartz <matthew. schwartz@ linux. dev> wrote: > > On 1/2/26 3: 13 PM, Antheas Kapenekakis wrote: > > On Fri, 2 Jan 2026 at 21: 17, Matthew Schwartz > > <matthew. schwartz@ linux. dev> ZjQcmQRYFpfptBannerStart
This message was sent from outside of Texas Instruments.
Do not click links or open attachments unless you recognize the source of this email and know the content is safe.
<https://us-phishalarm-ewt.proofpoint.com/EWT/v1/G3vK!tDdkczlnnYRTxMpLVz-pN5EZOCpqg7wGjyDRBvMeAZFuWZXBJlfNUQdJ4vR2DLvmO1o91tMvcFY2CkFWEO4UIBOBJ80exLz0o0fjR_qbdsgA4aHVUaeJh-oUWg$>
Report SuspiciousZjQcmQRYFpfptBannerEnd
Quoted 79 lines · Matthew Schwartz
Quoted 50 lines · Antheas Kapenekakis
Quoted 10 lines · Matthew Schwartz
Quoted 8 lines · Antheas Kapenekakis
Quoted 6 lines · Matthew Schwartz
Quoted 5 lines · Matthew Schwartz
- snip
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
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-binaryThis link describes "calibration" configurations that are used in the calibration procedure. It is not clear to me that it refers to the calibration parameters exported by UEFI or in the configuration itself to be used alongside a configuration. I would tend toward this being irrelevant.
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Instead, something else I found that works is not overriding the firmware file calibration data with the UEFI calibration data:
I misunderstood what you meant by this before. I thought you meant that the firmware overrode the UEFI data, not the other way around. Surely, using the dummy data in the firmware file is better than using incorrect data from UEFI. However, the manufacturer calibrated data from the factory floor for each specific unit is in UEFI, so that is what should be used.
Quoted 11 lines
Quoted 2 lines
I did not look into the source code, do you have any reference in the ACPI TAS code that
r0_bufis 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 thecali_datamemory buffer and sets is_user_space_calidata=true: https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/master/sound/hda/codecs/side-codecs/tas2781_hda.c*L162-L173__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyA1aQnWHw$2. When switching to a DSP config,
tasdevice_select_tuningprm_cfg()callstasdevice_load_data()which writes the firmware configuration, including any calibration values embedded in that config: https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/master/sound/soc/codecs/tas2781-fmwlib.c*L2510__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyDJTrchbQ$3. Immediately after,
tasdev_load_calibrated_data()writes the UEFI calibration data from step 1, overwriting the values just set in step 2: https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/9b043680446067358913edc2e9dd71bf8ffae208/sound/soc/codecs/tas2781-fmwlib.c*L2392-L2428__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyBeYnGr_w$ + https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/master/sound/soc/codecs/tas2781-fmwlib.c*L2519__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyBz8-7Z6g$Quoted 8 lines
Quoted 1 line
I confirmed this this by inserting some debug logs around
tasdev_load_calibrated_data:I went through the code. It loads the UEFI data, sets is_user_space_calidata=1, then if the data is available it loads it. This is correct.
To me this seems like the calibration data for amp 1 is written to both amp 1 and amp 2, and for your firmware this breaks amp2.
If this were the case, shouldn't my debug logs have the same data being written to dev 0 and dev 1?
[ 6.367380] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing calibration: r0_reg=0x000ce4 data=3c5f7222 [ 6.371718] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing calibration: r0_reg=0x000ce4 data=3c90e72dQuoted 7 lines
In
tasdev_load_calibrated_data(), an i index is provided, butcali_datais nested under priv. So only one calibration set is supported. This means that amp 2 gets amp 1 calibrations.Perhaps there is a "SmartAmpCalibrationData2" that should be read instead for amp 2 instead, can you dump the EFI variables and check?
(128)(deck@steamdeck ~)$ ls
/sys/firmware/efi/efivars/
AmdAcpiVar-79941ecd-ed36-49d0-8124-e4c31ac75cd4 BugCheckProgress-ba57e015-65b3-4c3c-b274-659192f699e3 MemoryOverwriteRequestControl-e20939be-32d4-41be-a150-897f85d49829
<snip>
There's only one EFI var that seems to be for calibration data:Quoted 8 lines
xxd
/sys/firmware/efi/efivars/CALI_DATA-1f52d2a1-bb3a-457d-bc09-43a3f4310a92:00000000: 0700 0000 dd0a 0000 0300 0000 7e4a 9d68 ............~J.h 00000010: 0000 0000 2272 5f3c d515 f610 ac9a 9b2e ...."r_<........ 00000020: 5d91 9600 0000 8025 0100 0000 2de7 903c ]......%....-..< 00000030: 283c e810 ffc8 c12e fcce 9600 0000 8025 (<.............% 00000040: 8000 0000 0000 1964 0000 1974 0000 197c .......d...t...| 00000050: 0000 1560 0000 1a70 eb7f b12b ...`...p...+I reviewed the loader for
CALI_DATA, it supports multiple device calibration data and indexes it currently. In addition, it has two versions with CRC checks that pass, so one of those versions loads the data correctly.So everything looks technically correct
Here is your data from the first amp reordered:
r0_reg=0x000ce4 408f5c29 r0_reg=0x000ce4 3c5f7222invr0_reg=0x000cf4
0fdc788c
invr0_reg=0x000cf410f615d5
r0_low_reg=0x000cfc0f7e9100
r0_low_reg=0x000cfc2e9b9aac
pow_reg=0x000ae0009b5281
pow_reg=0x000ae00096915d
tlimit_reg=0x000d70 25800000
tlimit_reg=0x000d70 25800000And the second amp:
r0_reg=0x000ce4 40cccccd r0_reg=0x000ce4 3c90e72dinvr0_reg=0x000cf4
0fcd6e9e
invr0_reg=0x000cf410e83c28
r0_low_reg=0x000cfc0f8d4fdf
r0_low_reg=0x000cfc2ec1c8ff
pow_reg=0x000ae0009b9c58
pow_reg=0x000ae00096cefc
tlimit_reg=0x000d70 25800000
tlimit_reg=0x000d70 25800000There is a large deviation in r0, invr0, and
r0_lowin both of them. Unfortunately, I do not have my Xbox Ally non-X to check to see if it's incorrect. This hints to me that the registers get incorrect data loaded, so there might be a mistake in the UEFI parser.Here is a breakdown of your efivar
0700 0000 # This is not supposed to be here / Might have been thrown out by kernel if v2 loadsdd0a 0000 # 2781, is v2 protocol
0300 0000 # Data-Group-Sum / How many nodes
7e4a 9d68 # Timestamp# First amplifier data
0000 0000
2272 5f3c # r0
d515 f610 # invr0
ac9a 9b2e #r0_low
5d91 9600 # pow
0000 8025 # tlimit# Second amplifier data
0100 0000
2de7 903c # r0
283c e810 # invr0
ffc8 c12e #r0_low
fcce 9600 # pow
0000 8025 # tlimit8000 0000 # Calibration data / Derivation logic in
TASDEVICE_REG0000 1964 # r0 addr
0000 1974 # invr0 addr
0000 197c #r0_lowaddr
0000 1560 # pow addr
0000 1a70 # tlimit addreb7f b12b # CRC32
Specifically for the
0x80,cali_regaddresses get stored into r0/invr0... iffp->dspbin_typ==TASDEV_BASIC.I suspect the problem here is that the UEFI override for the first three values tries to change different registers and not r0, invr0 and
r0_low. The pow, tlimit look correct.But, due to
p->dspbin_typ!=TASDEV_BASIC,cali_regends up being thrown out and the UEFI values end up corrupting the r0, invr0 andr0_lowdefault addresses. and not 00, 19, 64/74/7cAntheas
Quoted 79 lines
Quoted 77 lines
In that case, a minor refactor to move
cali_dataandis_user_space_calidatafrom priv to priv->tasdevice[i] and then use the proper efi var would fix this.Antheas
Quoted 69 lines
[ 3.908963] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tas2781_apply_calib: dspbin_typ=2, ndev=2, Setting is_user_space_calidata=true<snip>
where it loads the UEFI calibration over top of the firmware calibration.
Quoted 11 lines
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_calibthat 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,
MattQuoted 45 lines
Happy new year,
AntheasQuoted 40 lines
sound/soc/codecs/tas2781-fmwlib.c +15
-0@@ -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>
Quoted 8 lines · Matthew Schwartz
Quoted 6 lines · Baojun
Hi Antheas,
It may known issue which relative with calibration result.
Could you try to remove calibration result apply, and check if the problem still exist? For example, mask below line (line number is 494) intasdevice_dspfw_init()fromtas2781-hda-i2c.c:
Quoted 8 lines
Quoted 4 lines
hda_priv->save_calibration(tas_hda);Best Regards
JimHi Jim,
Thanks for the reply. Antheas does not have hardware affected by this issue, but I can confirm that this fixes the problem on my own device.
Can anyone submit a proper fix patch? It's a regression, and the fix itself sounds trivial, as it seems.
thanks,
Takashi
Quoted 274 lines
Matt
Quoted 270 lines
________________________________________
From: Antheas Kapenekakis <[email protected]>
Sent: 03 January 2026 19:48
To: Matthew Schwartz
Cc: Xu, Baojun; Ding, Shenghao; [email protected]; [email protected]; [email protected]
Subject: [EXTERNAL] Re: [BUG] hda/tas2781: ASUS ROG Xbox Ally X audio issues with default firmwareOn Sat, 3 Jan 2026 at 02: 31, Matthew Schwartz <matthew. schwartz@ linux. dev> wrote: > > On 1/2/26 3: 13 PM, Antheas Kapenekakis wrote: > > On Fri, 2 Jan 2026 at 21: 17, Matthew Schwartz > > <matthew. schwartz@ linux. dev> ZjQcmQRYFpfptBannerStart
This message was sent from outside of Texas Instruments.
Do not click links or open attachments unless you recognize the source of this email and know the content is safe.
<https://us-phishalarm-ewt.proofpoint.com/EWT/v1/G3vK!tDdkczlnnYRTxMpLVz-pN5EZOCpqg7wGjyDRBvMeAZFuWZXBJlfNUQdJ4vR2DLvmO1o91tMvcFY2CkFWEO4UIBOBJ80exLz0o0fjR_qbdsgA4aHVUaeJh-oUWg$>
Report SuspiciousZjQcmQRYFpfptBannerEnd
Quoted 79 lines · Matthew Schwartz
Quoted 50 lines · Antheas Kapenekakis
Quoted 10 lines · Matthew Schwartz
Quoted 8 lines · Antheas Kapenekakis
Quoted 6 lines · Matthew Schwartz
Quoted 5 lines · Matthew Schwartz
- snip
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
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-binaryThis link describes "calibration" configurations that are used in the calibration procedure. It is not clear to me that it refers to the calibration parameters exported by UEFI or in the configuration itself to be used alongside a configuration. I would tend toward this being irrelevant.
Quoted 4 lines
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.
Quoted 2 lines
Quoted 2 lines
Instead, something else I found that works is not overriding the firmware file calibration data with the UEFI calibration data:
I misunderstood what you meant by this before. I thought you meant that the firmware overrode the UEFI data, not the other way around. Surely, using the dummy data in the firmware file is better than using incorrect data from UEFI. However, the manufacturer calibrated data from the factory floor for each specific unit is in UEFI, so that is what should be used.
Quoted 11 lines
Quoted 2 lines
I did not look into the source code, do you have any reference in the ACPI TAS code that
r0_bufis 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 thecali_datamemory buffer and sets is_user_space_calidata=true: https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/master/sound/hda/codecs/side-codecs/tas2781_hda.c*L162-L173__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyA1aQnWHw$2. When switching to a DSP config,
tasdevice_select_tuningprm_cfg()callstasdevice_load_data()which writes the firmware configuration, including any calibration values embedded in that config: https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/master/sound/soc/codecs/tas2781-fmwlib.c*L2510__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyDJTrchbQ$3. Immediately after,
tasdev_load_calibrated_data()writes the UEFI calibration data from step 1, overwriting the values just set in step 2: https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/9b043680446067358913edc2e9dd71bf8ffae208/sound/soc/codecs/tas2781-fmwlib.c*L2392-L2428__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyBeYnGr_w$ + https://urldefense.com/v3/__https://github.com/torvalds/linux/blob/master/sound/soc/codecs/tas2781-fmwlib.c*L2519__;Iw!!G3vK!U3mEJNuRpB9ZxVAGZZCyoMNqMnAl4M1N8YoxbHiMHIsF-13h4Wg_fbVfd008drQfvgstYyBz8-7Z6g$Quoted 8 lines
Quoted 1 line
I confirmed this this by inserting some debug logs around
tasdev_load_calibrated_data:I went through the code. It loads the UEFI data, sets is_user_space_calidata=1, then if the data is available it loads it. This is correct.
To me this seems like the calibration data for amp 1 is written to both amp 1 and amp 2, and for your firmware this breaks amp2.
If this were the case, shouldn't my debug logs have the same data being written to dev 0 and dev 1?
[ 6.367380] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 0 writing calibration: r0_reg=0x000ce4 data=3c5f7222 [ 6.371718] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tasdev_load_calibrated_data: dev 1 writing calibration: r0_reg=0x000ce4 data=3c90e72dQuoted 7 lines
In
tasdev_load_calibrated_data(), an i index is provided, butcali_datais nested under priv. So only one calibration set is supported. This means that amp 2 gets amp 1 calibrations.Perhaps there is a "SmartAmpCalibrationData2" that should be read instead for amp 2 instead, can you dump the EFI variables and check?
(128)(deck@steamdeck ~)$ ls
/sys/firmware/efi/efivars/
AmdAcpiVar-79941ecd-ed36-49d0-8124-e4c31ac75cd4 BugCheckProgress-ba57e015-65b3-4c3c-b274-659192f699e3 MemoryOverwriteRequestControl-e20939be-32d4-41be-a150-897f85d49829
<snip>
There's only one EFI var that seems to be for calibration data:Quoted 8 lines
xxd
/sys/firmware/efi/efivars/CALI_DATA-1f52d2a1-bb3a-457d-bc09-43a3f4310a92:00000000: 0700 0000 dd0a 0000 0300 0000 7e4a 9d68 ............~J.h 00000010: 0000 0000 2272 5f3c d515 f610 ac9a 9b2e ...."r_<........ 00000020: 5d91 9600 0000 8025 0100 0000 2de7 903c ]......%....-..< 00000030: 283c e810 ffc8 c12e fcce 9600 0000 8025 (<.............% 00000040: 8000 0000 0000 1964 0000 1974 0000 197c .......d...t...| 00000050: 0000 1560 0000 1a70 eb7f b12b ...`...p...+I reviewed the loader for
CALI_DATA, it supports multiple device calibration data and indexes it currently. In addition, it has two versions with CRC checks that pass, so one of those versions loads the data correctly.So everything looks technically correct
Here is your data from the first amp reordered:
r0_reg=0x000ce4 408f5c29 r0_reg=0x000ce4 3c5f7222invr0_reg=0x000cf4
0fdc788c
invr0_reg=0x000cf410f615d5
r0_low_reg=0x000cfc0f7e9100
r0_low_reg=0x000cfc2e9b9aac
pow_reg=0x000ae0009b5281
pow_reg=0x000ae00096915d
tlimit_reg=0x000d70 25800000
tlimit_reg=0x000d70 25800000And the second amp:
r0_reg=0x000ce4 40cccccd r0_reg=0x000ce4 3c90e72dinvr0_reg=0x000cf4
0fcd6e9e
invr0_reg=0x000cf410e83c28
r0_low_reg=0x000cfc0f8d4fdf
r0_low_reg=0x000cfc2ec1c8ff
pow_reg=0x000ae0009b9c58
pow_reg=0x000ae00096cefc
tlimit_reg=0x000d70 25800000
tlimit_reg=0x000d70 25800000There is a large deviation in r0, invr0, and
r0_lowin both of them. Unfortunately, I do not have my Xbox Ally non-X to check to see if it's incorrect. This hints to me that the registers get incorrect data loaded, so there might be a mistake in the UEFI parser.Here is a breakdown of your efivar
0700 0000 # This is not supposed to be here / Might have been thrown out by kernel if v2 loadsdd0a 0000 # 2781, is v2 protocol
0300 0000 # Data-Group-Sum / How many nodes
7e4a 9d68 # Timestamp# First amplifier data
0000 0000
2272 5f3c # r0
d515 f610 # invr0
ac9a 9b2e #r0_low
5d91 9600 # pow
0000 8025 # tlimit# Second amplifier data
0100 0000
2de7 903c # r0
283c e810 # invr0
ffc8 c12e #r0_low
fcce 9600 # pow
0000 8025 # tlimit8000 0000 # Calibration data / Derivation logic in
TASDEVICE_REG0000 1964 # r0 addr
0000 1974 # invr0 addr
0000 197c #r0_lowaddr
0000 1560 # pow addr
0000 1a70 # tlimit addreb7f b12b # CRC32
Specifically for the
0x80,cali_regaddresses get stored into r0/invr0... iffp->dspbin_typ==TASDEV_BASIC.I suspect the problem here is that the UEFI override for the first three values tries to change different registers and not r0, invr0 and
r0_low. The pow, tlimit look correct.But, due to
p->dspbin_typ!=TASDEV_BASIC,cali_regends up being thrown out and the UEFI values end up corrupting the r0, invr0 andr0_lowdefault addresses. and not 00, 19, 64/74/7cAntheas
Quoted 79 lines
Quoted 77 lines
In that case, a minor refactor to move
cali_dataandis_user_space_calidatafrom priv to priv->tasdevice[i] and then use the proper efi var would fix this.Antheas
Quoted 69 lines
[ 3.908963] tas2781-hda i2c-TXNW2781:00-tas2781-hda.0: tas2781_apply_calib: dspbin_typ=2, ndev=2, Setting is_user_space_calidata=true<snip>
where it loads the UEFI calibration over top of the firmware calibration.
Quoted 11 lines
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_calibthat 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,
MattQuoted 45 lines
Happy new year,
AntheasQuoted 40 lines
sound/soc/codecs/tas2781-fmwlib.c +15
-0@@ -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>