[PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index
Sergey Lebedev <[email protected]> Tue, 04 Aug 2026 22:59:42 +0000
| Newsgroups | gmane.linux.sound,gmane.linux.kernel |
|---|---|
| Message-ID | <[email protected]> |
find_acpi_adr_device() assigns each amplifier a name prefix carrying an
index ("rt1320-1", "rt1320-2", or Left/Right) and advances that index
once per _ADR entry. Firmware that describes one physical part with two
_ADR entries therefore consumes two indices for one device.
The Microsoft Surface Pro 11 (Intel) does exactly that. Link 0 carries:
SWRA _ADR 0x000030025D132000 SDCA class 0
SWRB _ADR 0x000030025D132001 SDCA class 1
identical but for the class id: same link, same manufacturer, part and
version, same unique id 0. The part reports class 1, so SWRB is the one
that enumerates and SWRA never attaches on any boot or firmware version
tested.
Both still reach this function, so SWRA takes index 1 and the real
amplifier is named "rt1320-2". Its controls appear as "rt1320-2 OT23 L/R
Switch". The stock sof-soundwire UCM profile expects the first
amplifier, so it enables switches on a device that is not present, and
the speakers stay silent while everything else reports success.
Compare entries that differ only in class id and give the later one the
earlier one's name prefix, jumping past the amplifier-index increment so
a repeated description consumes one index rather than several.
Testing the peripheral's attach status instead does not work here, and
was tried: at machine-select time neither entry has attached yet, so a
status test finds both unattached, no amplifier is matched at all, and
the card falls back to the HDMI-only HDA machine driver. Comparing
addresses needs no runtime state.
Signed-off-by: Sergey Lebedev <[email protected]>
---
sound/soc/sof/intel/hda.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 4dbba9186..1d60a8caa 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -1245,6 +1245,22 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
((u64)(sdw_device->id.sdw_version & 0xF) << 44) |
((u64)(sdw_device->bus->link_id & 0xF) << 48);
+ /*
+ * Firmware may describe a single physical part with more than one _ADR
+ * entry, differing only in SDCA class id. Those entries are the same
+ * device: they must share a name prefix, and only the first of them may
+ * consume an amp index. Otherwise the part that actually enumerates is
+ * named as though it were the second amplifier, and UCM profiles
+ * written for the first one address a device that is not there.
+ */
+ for (j = 0; j < index; j++) {
+ if ((adr_dev[j].adr & ~SDW_CLASS_ID_MASK) ==
+ (adr_dev[index].adr & ~SDW_CLASS_ID_MASK)) {
+ adr_dev[index].name_prefix = adr_dev[j].name_prefix;
+ goto done_name_prefix;
+ }
+ }
+
if (!codec_info_list[i].is_amp) {
/* For non-amp codecs, get name_prefix from codec_info_list[] */
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s", name_prefix);
--
2.50.1 (Apple Git-155)