[PATCH 3/5] ASoC: tas2783-sdw: use the BIOS speaker ID in the firmware name
From: Matthew Schwartz
Date: Fri Oct 16 2026 - 19:25:32 EST
Some boards have TAS2783 firmware in linux-firmware named
SSID-SPKID-LINK-0xUID.bin, with a speaker ID ahead of the link ID (the
HP 8EA1 has its amps on link 0 and ships 8EA1-{0,1}-0-0x*.bin). The
driver only builds the three-field SSID-LINK-0xUID name, so these boards
never load firmware. On the ASUS ROG Xbox Ally X20 (SSID 1954) the BIOS
provides the speaker ID in a 4-byte SPEAKER_ID EFI variable, and only
the four-field 1954-*-*-0x*.bin files exist.
Read SPEAKER_ID once and request the four-field name first when it is
present. Boards without the variable keep the current names, and the
unprefixed three-field name is still tried if the four-field file is
missing.
Signed-off-by: Matthew Schwartz <matthew.schwartz@xxxxxxxxx>
---
sound/soc/codecs/tas2783-sdw.c | 42 +++++++++++++++++++++++++++++++---
1 file changed, 39 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c
index a57230e01f755..db234c54aa2ac 100644
--- a/sound/soc/codecs/tas2783-sdw.c
+++ b/sound/soc/codecs/tas2783-sdw.c
@@ -46,6 +46,8 @@
#define TAS2783_PROBE_TIMEOUT 5000
#define TAS2783_CALI_GUID EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, \
0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92)
+#define TAS2783_SPKID_GUID EFI_GUID(0xaa61eaaf, 0x6e83, 0x7523, 0xb0, \
+ 0xd0, 0x7d, 0xf7, 0x4b, 0xb2, 0x4a, 0x81)
static const u32 tas2783_cali_reg[] = {
TAS2783_CAL_R0,
@@ -104,6 +106,11 @@ struct tas2783_prv {
bool fw_dl_success;
/* use fallback fw name */
bool fw_use_fallback;
+#if IS_ENABLED(CONFIG_PCI)
+ /* UEFI speaker ID, read once */
+ int spk_id;
+ bool spk_id_read;
+#endif
};
static const struct reg_default tas2783_reg_default[] = {
@@ -1156,6 +1163,26 @@ static const struct dev_pm_ops tas2783_sdca_pm = {
RUNTIME_PM_OPS(tas2783_sdca_dev_suspend, tas2783_sdca_dev_resume, NULL)
};
+#if IS_ENABLED(CONFIG_PCI)
+/* BIOS speaker ID that selects the SSID-SPKID-LINK-UID firmware name */
+static int tas2783_get_spk_id(void)
+{
+ efi_guid_t guid = TAS2783_SPKID_GUID;
+ unsigned long size = sizeof(u32);
+ efi_status_t status;
+ u32 spk_id = 0;
+
+ if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
+ return -ENOENT;
+
+ status = efi.get_variable(L"SPEAKER_ID", &guid, NULL, &size, &spk_id);
+ if (status != EFI_SUCCESS)
+ return -ENOENT;
+
+ return spk_id;
+}
+#endif
+
static void tas_generate_fw_name(struct sdw_slave *slave, char *name, size_t size)
{
struct sdw_bus *bus = slave->bus;
@@ -1170,9 +1197,18 @@ static void tas_generate_fw_name(struct sdw_slave *slave, char *name, size_t siz
for (; dev; dev = dev->parent) {
if (dev->bus == &pci_bus_type) {
pci = to_pci_dev(dev);
- scnprintf(name, size, "%04X-%1X-%s%1X.bin",
- pci->subsystem_device, bus->link_id,
- fw_uid_prefix, unique_id);
+ if (!tas_dev->spk_id_read) {
+ tas_dev->spk_id = tas2783_get_spk_id();
+ tas_dev->spk_id_read = true;
+ }
+ if (tas_dev->spk_id >= 0 && !tas_dev->fw_use_fallback)
+ scnprintf(name, size, "%04X-%X-%1X-0x%1X.bin",
+ pci->subsystem_device, tas_dev->spk_id,
+ bus->link_id, unique_id);
+ else
+ scnprintf(name, size, "%04X-%1X-%s%1X.bin",
+ pci->subsystem_device, bus->link_id,
+ fw_uid_prefix, unique_id);
pci_found = true;
break;
}
--
2.56.0