* [PATCH 0/3] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel)
@ 2026-08-04 22:59 Sergey Lebedev
2026-08-04 22:59 ` [PATCH 1/3] ASoC: rt1320: run the initialisation preset on the first hardware init Sergey Lebedev
` (3 more replies)
0 siblings, 4 replies; 15+ messages in thread
From: Sergey Lebedev @ 2026-08-04 22:59 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Oder Chiou, Bard Liao, Peter Ujfalusi, Kai Vehmanen,
Ranjani Sridharan, Pierre-Louis Bossart, Daniel Baluta,
Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
The Microsoft Surface Pro 11 for Business (Intel, Lunar Lake) has no working
audio under Linux: the speakers are silent, while everything reports success.
These three patches fix it, and the machine then works with the stock
sof-soundwire UCM profile and the shipped topologies - no board quirk, no new
match entry, no local configuration of any kind.
All three failures come from one firmware defect. The board carries a single
physical RT1320 amplifier on SoundWire link 0, and describes it twice:
SWRA _ADR 0x000030025D132000 SDCA class 0
SWRB _ADR 0x000030025D132001 SDCA class 1
Identical apart from the class id: same link, same manufacturer, part and
version, same unique id 0. The part reports class 1, so only SWRB ever
enumerates. SWRA stays UNATTACHED on every boot, on every firmware version we
have tested, including the November 2025 bundle. Both entries nonetheless reach
the machine-select and card-probe paths, and the phantom breaks each in a
different way.
1/3 rt1320: the amplifier's preset never runs, because the driver waits for
FUNCTION_NEEDS_INITIALIZATION and this part never sets it. rt712-sdca and
rt722-sdca already handle this by also running the preset on the first
hardware init; rt1320 is the odd one out. One line.
2/3 sdw_utils: DAI links get built for the phantom, and later fail to prepare
with -61, taking the whole link down rather than degrading it.
3/3 SOF/Intel hda: the phantom consumes an amplifier index, so the real part
is named "rt1320-2". The stock UCM profile addresses the first amplifier
and therefore enables switches on a device that is not there.
Only 1/3 is codec-specific. The other two are general: any firmware that
describes a peripheral twice, or describes one that never enumerates, hits them.
One thing worth raising, since a reviewer will reasonably ask. Before 2/3
existed we also hit a DAI link name collision: create_sdw_dailink() builds names
from link id and function type alone, so the phantom's SmartMic endpoint
produced a second "SDW0-Capture-SmartMic" and the card failed to register at all
with -EEXIST. With 2/3 applied the phantom's endpoints never reach the naming
code, so that collision is no longer reachable on this machine and we cannot
demonstrate it. The naming scheme is still not unique in general - a board with
two genuinely distinct codecs of the same function type on one link would hit
it - but we have no such board, so it is deliberately not part of this series.
Happy to send it separately if you would like it.
Testing. Developed and tested on a Surface Pro 11 for Business (Intel Core Ultra
7 268V), booting 7.1.0-rc7 built from thesofproject/linux topic/sof-dev at
7e9e0409c with these three patches and nothing else. Verified on that kernel:
- card registers as sof-soundwire, 4 playback + 1 capture devices
- no -EEXIST, no -61 link startup errors
- amplifier named rt1320-1, controls "rt1320-1 OT23 L/R Switch"
- rt1320_vc_preset runs, reporting RT1320_KR0_INT_READY=0x1f
- amp function status reads 0x41 (NEWLY_ATTACHED | FUNCTION_HAS_BEEN_RESET)
on every boot, confirming bit 5 is never set on this part
- speakers audible, internal microphone captures signal
- stock alsa-ucm-conf 1.2.15.3 and firmware-sof-signed 2025.12.2, with no
local UCM, PipeWire or WirePlumber configuration
checkpatch --strict is clean on all three.
Sergey Lebedev (3):
ASoC: rt1320: run the initialisation preset on the first hardware init
ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus
ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index
sound/soc/codecs/rt1320-sdw.c | 2 +-
sound/soc/sdw_utils/soc_sdw_utils.c | 46 +++++++++++++++++++++++++++++
sound/soc/sof/intel/hda.c | 16 ++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
base-commit: 7e9e0409cd57924c4099090879154300c07b8643
--
2.50.1 (Apple Git-155)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/3] ASoC: rt1320: run the initialisation preset on the first hardware init
2026-08-04 22:59 [PATCH 0/3] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
@ 2026-08-04 22:59 ` Sergey Lebedev
2026-08-04 22:59 ` [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus Sergey Lebedev
` (2 subsequent siblings)
3 siblings, 0 replies; 15+ messages in thread
From: Sergey Lebedev @ 2026-08-04 22:59 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Oder Chiou, Bard Liao, Peter Ujfalusi, Kai Vehmanen,
Ranjani Sridharan, Pierre-Louis Bossart, Daniel Baluta,
Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
rt1320_io_init() applies the vendor initialisation preset only when the
amplifier's SDCA function status has FUNCTION_NEEDS_INITIALIZATION set:
if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION)) {
Its two sibling drivers guard the same write differently, also running
the preset on the first hardware init:
rt712-sdca.c: if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) ||
(!rt712->first_hw_init)) {
rt722-sdca.c: if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) ||
(!rt722->first_hw_init)) {
On the Microsoft Surface Pro 11 (Intel) the RT1320 never sets that bit.
Its function status reads back 0x41 on every boot, cold or warm:
rt1320-sdca sdw:0:0:025d:1320:01: rt1320_io_init amp func_status=0x41
which is NEWLY_ATTACHED | FUNCTION_HAS_BEEN_RESET: the function reports
that it has been reset and does not consider itself in need of
initialisation. Bit 5 is never set, so the preset never runs,
rt1320_vc_preset() and the MCU patch load are skipped, and the amplifier
is left unprogrammed. rt712 and rt722 would have run it via their
first_hw_init fallback.
Add the same fallback. With it rt1320_vc_preset() executes and the
amplifier reports RT1320_KR0_INT_READY=0x1f where previously it did not.
Signed-off-by: Sergey Lebedev <lsa.uz@pm.me>
---
sound/soc/codecs/rt1320-sdw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c
index 13493b85f..d1f3b160a 100644
--- a/sound/soc/codecs/rt1320-sdw.c
+++ b/sound/soc/codecs/rt1320-sdw.c
@@ -1900,7 +1900,7 @@ static int rt1320_io_init(struct device *dev, struct sdw_slave *slave)
dev_dbg(dev, "%s amp func_status=0x%x\n", __func__, amp_func_status);
/* initialization write */
- if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION)) {
+ if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) || !rt1320->first_hw_init) {
switch (rt1320->dev_id) {
case RT1320_DEV_ID:
if (rt1320->version_id < RT1320_VC)
--
2.50.1 (Apple Git-155)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus
2026-08-04 22:59 [PATCH 0/3] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
2026-08-04 22:59 ` [PATCH 1/3] ASoC: rt1320: run the initialisation preset on the first hardware init Sergey Lebedev
@ 2026-08-04 22:59 ` Sergey Lebedev
2026-08-05 1:12 ` Liao, Bard
2026-08-04 22:59 ` [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index Sergey Lebedev
2026-08-30 8:45 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
3 siblings, 1 reply; 15+ messages in thread
From: Sergey Lebedev @ 2026-08-04 22:59 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Oder Chiou, Bard Liao, Peter Ujfalusi, Kai Vehmanen,
Ranjani Sridharan, Pierre-Louis Bossart, Daniel Baluta,
Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
asoc_sdw_parse_sdw_endpoints() builds DAI links for every endpoint of
every _ADR entry the firmware declares. If a declared peripheral never
enumerates, its links are still created and later fail to prepare, which
takes the whole link down rather than degrading it:
sof_sdw sof_sdw: ASoC: error at snd_soc_link_startup on
SDW0-Playback-SmartAmp: -61
The Microsoft Surface Pro 11 (Intel) declares one physical RT1320 twice,
as two _ADR entries on link 0 differing only in SDCA class id:
SWRA _ADR 0x000030025D132000 class 0
SWRB _ADR 0x000030025D132001 class 1
Same link, same manufacturer, part and version, same unique id 0. The
part reports class 1, so only SWRB enumerates. SWRA is a phantom and
stays UNATTACHED across every boot and every firmware version tested,
including the November 2025 bundle.
The existing is_sdca_endpoint_present() check cannot filter it out.
Setting aside that it is gated on a non-zero class id and the phantom is
the class-0 entry, the deeper problem is that the BIOS describes both
entries identically: each declares the same two SDCA functions, so the
check matches for either. Bus presence is what distinguishes them, so
test that.
The check is by nature a runtime one, and its correctness depends on the
peripheral having enumerated by the time the card probes. That holds
here: the real device is Attached and the phantom has no device number
at all whenever this runs. It is a weaker property than the surrounding
BIOS-driven checks, and a suggestion for something stronger would be
welcome, but the firmware offers nothing else to key on.
Signed-off-by: Sergey Lebedev <lsa.uz@pm.me>
---
sound/soc/sdw_utils/soc_sdw_utils.c | 46 +++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index d8db8fc53..12ca4bdd4 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -1909,6 +1909,46 @@ int asoc_sdw_get_dai_type(u32 type)
}
EXPORT_SYMBOL_NS(asoc_sdw_get_dai_type, "SND_SOC_SDW_UTILS");
+/*
+ * Some firmware describes one physical peripheral with two _ADR entries that
+ * differ only in SDCA class id, on the same link and with the same unique id.
+ * Only the entry whose class id matches the part ever enumerates; the other is
+ * a phantom. Building DAI links for it fails the whole link rather than
+ * degrading it, so the endpoints have to be skipped.
+ *
+ * This cannot be decided from the BIOS description: on the machine that
+ * prompted this, both entries declare an identical set of SDCA functions, so
+ * is_sdca_endpoint_present() below matches for either. Bus presence is the only
+ * thing that distinguishes them.
+ */
+static bool is_peripheral_attached(struct device *dev,
+ const struct snd_soc_acpi_link_adr *adr_link,
+ int adr_index)
+{
+ const char *sdw_codec_name;
+ struct device *sdw_dev;
+ struct sdw_slave *slave;
+ bool attached;
+
+ sdw_codec_name = _asoc_sdw_get_codec_name(dev, adr_link, adr_index);
+ if (!sdw_codec_name)
+ return true;
+
+ sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_codec_name);
+ if (!sdw_dev)
+ return true;
+
+ slave = dev_to_sdw_dev(sdw_dev);
+ attached = slave->status != SDW_SLAVE_UNATTACHED;
+ if (!attached)
+ dev_dbg(dev, "%s not present on the bus, skipping its endpoints\n",
+ sdw_codec_name);
+
+ put_device(sdw_dev);
+
+ return attached;
+}
+
/**
* is_sdca_endpoint_present - Check if an SDCA endpoint is present on the SDW peripheral
* @dev: Device pointer
@@ -2065,6 +2105,12 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
dai_info = &codec_info->dais[adr_end->num];
soc_dai = asoc_sdw_find_dailink(soc_dais, adr_end);
+ /* skip a peripheral that is not on the bus at all */
+ if (!is_peripheral_attached(dev, adr_link, i)) {
+ (*num_devs)--;
+ continue;
+ }
+
/*
* quirk should have higher priority than the sdca properties
* in the BIOS. We can't always check the DAI quirk because we
--
2.50.1 (Apple Git-155)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index
2026-08-04 22:59 [PATCH 0/3] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
2026-08-04 22:59 ` [PATCH 1/3] ASoC: rt1320: run the initialisation preset on the first hardware init Sergey Lebedev
2026-08-04 22:59 ` [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus Sergey Lebedev
@ 2026-08-04 22:59 ` Sergey Lebedev
2026-08-05 1:21 ` Liao, Bard
2026-08-05 8:33 ` Pierre-Louis Bossart
2026-08-30 8:45 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
3 siblings, 2 replies; 15+ messages in thread
From: Sergey Lebedev @ 2026-08-04 22:59 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Oder Chiou, Bard Liao, Peter Ujfalusi, Kai Vehmanen,
Ranjani Sridharan, Pierre-Louis Bossart, Daniel Baluta,
Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
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 <lsa.uz@pm.me>
---
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)
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus
2026-08-04 22:59 ` [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus Sergey Lebedev
@ 2026-08-05 1:12 ` Liao, Bard
2026-08-05 8:22 ` Pierre-Louis Bossart
0 siblings, 1 reply; 15+ messages in thread
From: Liao, Bard @ 2026-08-05 1:12 UTC (permalink / raw)
To: Sergey Lebedev, Mark Brown, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai, Oder Chiou, Bard Liao, Peter Ujfalusi,
Kai Vehmanen, Ranjani Sridharan, Pierre-Louis Bossart,
Daniel Baluta, Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
> -----Original Message-----
> From: Sergey Lebedev <lsa.uz@pm.me>
> Sent: Wednesday, August 5, 2026 7:00 AM
> To: Mark Brown <broonie@kernel.org>; Liam Girdwood
> <lgirdwood@gmail.com>; Jaroslav Kysela <perex@perex.cz>; Takashi Iwai
> <tiwai@suse.com>; Oder Chiou <oder_chiou@realtek.com>; Bard Liao <yung-
> chuan.liao@linux.intel.com>; Peter Ujfalusi <peter.ujfalusi@linux.intel.com>;
> Kai Vehmanen <kai.vehmanen@linux.intel.com>; Ranjani Sridharan
> <ranjani.sridharan@linux.intel.com>; Pierre-Louis Bossart <pierre-
> louis.bossart@linux.dev>; Daniel Baluta <daniel.baluta@nxp.com>; Vijendar
> Mukunda <Vijendar.Mukunda@amd.com>
> Cc: linux-sound@vger.kernel.org; sound-open-firmware@alsa-project.org;
> linux-kernel@vger.kernel.org
> Subject: [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is
> not on the bus
>
> asoc_sdw_parse_sdw_endpoints() builds DAI links for every endpoint of
> every _ADR entry the firmware declares. If a declared peripheral never
> enumerates, its links are still created and later fail to prepare, which
> takes the whole link down rather than degrading it:
>
> sof_sdw sof_sdw: ASoC: error at snd_soc_link_startup on
> SDW0-Playback-SmartAmp: -61
>
> The Microsoft Surface Pro 11 (Intel) declares one physical RT1320 twice,
> as two _ADR entries on link 0 differing only in SDCA class id:
>
> SWRA _ADR 0x000030025D132000 class 0
> SWRB _ADR 0x000030025D132001 class 1
>
> Same link, same manufacturer, part and version, same unique id 0. The
> part reports class 1, so only SWRB enumerates. SWRA is a phantom and
> stays UNATTACHED across every boot and every firmware version tested,
> including the November 2025 bundle.
Why not just remove SWRA from the BIOS?
>
> The existing is_sdca_endpoint_present() check cannot filter it out.
> Setting aside that it is gated on a non-zero class id and the phantom is
> the class-0 entry, the deeper problem is that the BIOS describes both
> entries identically: each declares the same two SDCA functions, so the
> check matches for either. Bus presence is what distinguishes them, so
> test that.
>
> The check is by nature a runtime one, and its correctness depends on the
> peripheral having enumerated by the time the card probes. That holds
> here: the real device is Attached and the phantom has no device number
> at all whenever this runs. It is a weaker property than the surrounding
> BIOS-driven checks, and a suggestion for something stronger would be
> welcome, but the firmware offers nothing else to key on.
>
> Signed-off-by: Sergey Lebedev <lsa.uz@pm.me>
> ---
> sound/soc/sdw_utils/soc_sdw_utils.c | 46
> +++++++++++++++++++++++++++++
> 1 file changed, 46 insertions(+)
>
> diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c
> b/sound/soc/sdw_utils/soc_sdw_utils.c
> index d8db8fc53..12ca4bdd4 100644
> --- a/sound/soc/sdw_utils/soc_sdw_utils.c
> +++ b/sound/soc/sdw_utils/soc_sdw_utils.c
> @@ -1909,6 +1909,46 @@ int asoc_sdw_get_dai_type(u32 type)
> }
> EXPORT_SYMBOL_NS(asoc_sdw_get_dai_type, "SND_SOC_SDW_UTILS");
>
> +/*
> + * Some firmware describes one physical peripheral with two _ADR entries
> that
> + * differ only in SDCA class id, on the same link and with the same unique id.
> + * Only the entry whose class id matches the part ever enumerates; the other
> is
> + * a phantom. Building DAI links for it fails the whole link rather than
> + * degrading it, so the endpoints have to be skipped.
> + *
> + * This cannot be decided from the BIOS description: on the machine that
> + * prompted this, both entries declare an identical set of SDCA functions, so
> + * is_sdca_endpoint_present() below matches for either. Bus presence is the
> only
> + * thing that distinguishes them.
> + */
> +static bool is_peripheral_attached(struct device *dev,
> + const struct snd_soc_acpi_link_adr
> *adr_link,
> + int adr_index)
> +{
> + const char *sdw_codec_name;
> + struct device *sdw_dev;
> + struct sdw_slave *slave;
> + bool attached;
> +
> + sdw_codec_name = _asoc_sdw_get_codec_name(dev, adr_link,
> adr_index);
> + if (!sdw_codec_name)
> + return true;
> +
> + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL,
> sdw_codec_name);
> + if (!sdw_dev)
> + return true;
> +
> + slave = dev_to_sdw_dev(sdw_dev);
> + attached = slave->status != SDW_SLAVE_UNATTACHED;
The status just means the current state. A Peripheral aka Slave on the
bus could be attached or unattached. We can't use the slave->status to
determine whether a Peripheral is physically on the bus or not.
Checking slave->dev_num_sticky may work. However, there is a timing
issue that the Peripheral could be attached after the check.
> + if (!attached)
> + dev_dbg(dev, "%s not present on the bus, skipping its
> endpoints\n",
> + sdw_codec_name);
> +
> + put_device(sdw_dev);
> +
> + return attached;
> +}
> +
> /**
> * is_sdca_endpoint_present - Check if an SDCA endpoint is present on the
> SDW peripheral
> * @dev: Device pointer
> @@ -2065,6 +2105,12 @@ int asoc_sdw_parse_sdw_endpoints(struct
> snd_soc_card *card,
> dai_info = &codec_info->dais[adr_end->num];
> soc_dai = asoc_sdw_find_dailink(soc_dais,
> adr_end);
>
> + /* skip a peripheral that is not on the bus at all
> */
> + if (!is_peripheral_attached(dev, adr_link, i)) {
> + (*num_devs)--;
> + continue;
> + }
> +
> /*
> * quirk should have higher priority than the
> sdca properties
> * in the BIOS. We can't always check the DAI
> quirk because we
> --
> 2.50.1 (Apple Git-155)
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index
2026-08-04 22:59 ` [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index Sergey Lebedev
@ 2026-08-05 1:21 ` Liao, Bard
2026-08-05 8:33 ` Pierre-Louis Bossart
1 sibling, 0 replies; 15+ messages in thread
From: Liao, Bard @ 2026-08-05 1:21 UTC (permalink / raw)
To: Sergey Lebedev, Mark Brown, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai, Oder Chiou, Bard Liao, Peter Ujfalusi,
Kai Vehmanen, Ranjani Sridharan, Pierre-Louis Bossart,
Daniel Baluta, Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
> -----Original Message-----
> From: Sergey Lebedev <lsa.uz@pm.me>
> Sent: Wednesday, August 5, 2026 7:00 AM
> To: Mark Brown <broonie@kernel.org>; Liam Girdwood
> <lgirdwood@gmail.com>; Jaroslav Kysela <perex@perex.cz>; Takashi Iwai
> <tiwai@suse.com>; Oder Chiou <oder_chiou@realtek.com>; Bard Liao <yung-
> chuan.liao@linux.intel.com>; Peter Ujfalusi <peter.ujfalusi@linux.intel.com>;
> Kai Vehmanen <kai.vehmanen@linux.intel.com>; Ranjani Sridharan
> <ranjani.sridharan@linux.intel.com>; Pierre-Louis Bossart <pierre-
> louis.bossart@linux.dev>; Daniel Baluta <daniel.baluta@nxp.com>; Vijendar
> Mukunda <Vijendar.Mukunda@amd.com>
> Cc: linux-sound@vger.kernel.org; sound-open-firmware@alsa-project.org;
> linux-kernel@vger.kernel.org
> Subject: [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one
> amp index
>
> 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 <lsa.uz@pm.me>
> ---
> 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.
> + */
Not sure if it is true. AFAIK, Realtek has a few codecs with the same
part ID and different class ID and they are different codecs.
In other words, IIUC, rt1320 class 0 and 1 are 2 different codecs.
> + 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)
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus
2026-08-05 1:12 ` Liao, Bard
@ 2026-08-05 8:22 ` Pierre-Louis Bossart
2026-08-05 13:28 ` Liao, Bard
0 siblings, 1 reply; 15+ messages in thread
From: Pierre-Louis Bossart @ 2026-08-05 8:22 UTC (permalink / raw)
To: Liao, Bard, Sergey Lebedev, Mark Brown, Liam Girdwood,
Jaroslav Kysela, Takashi Iwai, Oder Chiou, Bard Liao,
Peter Ujfalusi, Kai Vehmanen, Ranjani Sridharan, Daniel Baluta,
Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
>> asoc_sdw_parse_sdw_endpoints() builds DAI links for every endpoint of
>> every _ADR entry the firmware declares. If a declared peripheral never
>> enumerates, its links are still created and later fail to prepare, which
>> takes the whole link down rather than degrading it:
>>
>> sof_sdw sof_sdw: ASoC: error at snd_soc_link_startup on
>> SDW0-Playback-SmartAmp: -61
>>
>> The Microsoft Surface Pro 11 (Intel) declares one physical RT1320 twice,
>> as two _ADR entries on link 0 differing only in SDCA class id:
>>
>> SWRA _ADR 0x000030025D132000 class 0
>> SWRB _ADR 0x000030025D132001 class 1
>>
>> Same link, same manufacturer, part and version, same unique id 0. The
>> part reports class 1, so only SWRB enumerates. SWRA is a phantom and
>> stays UNATTACHED across every boot and every firmware version tested,
>> including the November 2025 bundle.
>
> Why not just remove SWRA from the BIOS?
Or add a quirk in drivers/soundwire/dmi-quirks.c to skip this SWRA
device entirely, this has been the direction so far to ignore 'ghost'
devices.
It's much safer IMHO than trying to detect if a device is physically
present or not.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index
2026-08-04 22:59 ` [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index Sergey Lebedev
2026-08-05 1:21 ` Liao, Bard
@ 2026-08-05 8:33 ` Pierre-Louis Bossart
1 sibling, 0 replies; 15+ messages in thread
From: Pierre-Louis Bossart @ 2026-08-05 8:33 UTC (permalink / raw)
To: Sergey Lebedev, Mark Brown, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai, Oder Chiou, Bard Liao, Peter Ujfalusi,
Kai Vehmanen, Ranjani Sridharan, Daniel Baluta, Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
On 8/5/26 00:59, Sergey Lebedev wrote:
> 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.
yeah but that means two methods to detect the presence of this ghost
device...
>
> Signed-off-by: Sergey Lebedev <lsa.uz@pm.me>
> ---
> 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;
> + }
> + }
> +
The DMI quirk removes the need for the two patches that detect the
presence of the ghost device through two different mechanisms.
Can you try with a DMI quirk and let us know if this is good enough?
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus
2026-08-05 8:22 ` Pierre-Louis Bossart
@ 2026-08-05 13:28 ` Liao, Bard
2026-08-30 8:44 ` Sergey Lebedev
0 siblings, 1 reply; 15+ messages in thread
From: Liao, Bard @ 2026-08-05 13:28 UTC (permalink / raw)
To: Pierre-Louis Bossart, Sergey Lebedev, Mark Brown, Liam Girdwood,
Jaroslav Kysela, Takashi Iwai, Oder Chiou, Bard Liao,
Peter Ujfalusi, Kai Vehmanen, Ranjani Sridharan, Daniel Baluta,
Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
> -----Original Message-----
> From: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
> Sent: Wednesday, August 5, 2026 4:23 PM
> To: Liao, Bard <bard.liao@intel.com>; Sergey Lebedev <lsa.uz@pm.me>; Mark
> Brown <broonie@kernel.org>; Liam Girdwood <lgirdwood@gmail.com>;
> Jaroslav Kysela <perex@perex.cz>; Takashi Iwai <tiwai@suse.com>; Oder Chiou
> <oder_chiou@realtek.com>; Bard Liao <yung-chuan.liao@linux.intel.com>;
> Peter Ujfalusi <peter.ujfalusi@linux.intel.com>; Kai Vehmanen
> <kai.vehmanen@linux.intel.com>; Ranjani Sridharan
> <ranjani.sridharan@linux.intel.com>; Daniel Baluta <daniel.baluta@nxp.com>;
> Vijendar Mukunda <Vijendar.Mukunda@amd.com>
> Cc: linux-sound@vger.kernel.org; sound-open-firmware@alsa-project.org;
> linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that
> is not on the bus
>
>
> >> asoc_sdw_parse_sdw_endpoints() builds DAI links for every endpoint of
> >> every _ADR entry the firmware declares. If a declared peripheral never
> >> enumerates, its links are still created and later fail to prepare, which
> >> takes the whole link down rather than degrading it:
> >>
> >> sof_sdw sof_sdw: ASoC: error at snd_soc_link_startup on
> >> SDW0-Playback-SmartAmp: -61
> >>
> >> The Microsoft Surface Pro 11 (Intel) declares one physical RT1320 twice,
> >> as two _ADR entries on link 0 differing only in SDCA class id:
> >>
> >> SWRA _ADR 0x000030025D132000 class 0
> >> SWRB _ADR 0x000030025D132001 class 1
> >>
> >> Same link, same manufacturer, part and version, same unique id 0. The
> >> part reports class 1, so only SWRB enumerates. SWRA is a phantom and
> >> stays UNATTACHED across every boot and every firmware version tested,
> >> including the November 2025 bundle.
> >
> > Why not just remove SWRA from the BIOS?
>
> Or add a quirk in drivers/soundwire/dmi-quirks.c to skip this SWRA
> device entirely, this has been the direction so far to ignore 'ghost'
> devices.
Not sure if it is the case, but it is possible that the SKU has different
rt1320 versions depending on when was the device manufactured.
Hope they use different SKU values with different rt1320 versions.
>
> It's much safer IMHO than trying to detect if a device is physically
> present or not.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus
2026-08-05 13:28 ` Liao, Bard
@ 2026-08-30 8:44 ` Sergey Lebedev
0 siblings, 0 replies; 15+ messages in thread
From: Sergey Lebedev @ 2026-08-30 8:44 UTC (permalink / raw)
To: Bard Liao, Pierre-Louis Bossart, Vinod Koul, Mark Brown,
Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Oder Chiou,
Bard Liao, Peter Ujfalusi, Kai Vehmanen, Daniel Baluta,
Vijendar Mukunda
Cc: linux-sound, sound-open-firmware, linux-kernel
Sorry for the long silence - I did not have access to the hardware until
now. Thank you both for the review; it changed the shape of the fix for
the better.
> > Why not just remove SWRA from the BIOS?
>
> Or add a quirk in drivers/soundwire/dmi-quirks.c to skip this SWRA
> device entirely, this has been the direction so far to ignore 'ghost'
> devices.
>
> It's much safer IMHO than trying to detect if a device is physically
> present or not.
Agreed, and it works. I have tested it on the machine and it is good
enough: one quirk replaces both 2/3 and 3/3, so v2 is two patches
instead of three, and nothing has to guess at runtime whether a device
is present.
With the ghost's _ADR remapped to zero, sdw_acpi_find_slaves() never
creates the peripheral:
# ls /sys/bus/soundwire/devices/
sdw-master-0-0
sdw:0:0:025d:1320:01 <- only the real one now
and everything downstream falls out:
- amplifier is named "rt1320-1", so the stock sof-soundwire UCM
profile addresses the device that is actually there
- no -EEXIST, no -61 link startup errors, card registers cleanly
- 4 playback + 1 capture, speakers audible, internal mic captures
- no local UCM, PipeWire or WirePlumber configuration
On the BIOS question: the firmware is Microsoft's, signed, and updated
through Windows Update. The defect is present in the current November
2025 bundle and on every unit shipped so far, so I have no way to have
SWRA removed at the source.
> Not sure if it is the case, but it is possible that the SKU has
> different rt1320 versions depending on when was the device
> manufactured. Hope they use different SKU values with different
> rt1320 versions.
Good point, and it is a real hazard: the remap keys on the full 64-bit
_ADR, whose version nibble is part of the match. A batch with a
different RT1320 version would not match - harmless - but if such a
batch ever reported class 0 as the real part, a name-keyed quirk would
remove the working device and leave the ghost.
v2 therefore matches on the product SKU rather than the product name,
following dell_sku_0A3E above it:
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU,
"Surface_Pro_11th_Edition_With_Intel_For_Business_2103")
That keeps the remap to the hardware it was verified on. If other SKUs
turn out to need it, they can be added as they are reported, which is
also how we would find out whether the versions do differ.
On the other review point, for completeness:
> Not sure if it is true. AFAIK, Realtek has a few codecs with the same
> part ID and different class ID and they are different codecs.
Understood - and it no longer matters, because the patch that assumed
otherwise is dropped in v2. The quirk claims nothing general about class
ids; it says only that on this SKU this specific _ADR is a ghost, which
is the one thing I have actually verified.
One correction I owe you, because I told you the opposite in the v1
cover letter. About the DAI link name collision I had written a fourth
patch for and then dropped, I said:
"With 2/3 applied the phantom's endpoints never reach the naming code,
so that collision is no longer reachable on this machine and we
cannot demonstrate it."
That was wrong. While testing v2 I had a boot where the quirk did not
take effect, and the machine failed exactly there:
sysfs: cannot create duplicate filename
'/devices/pci0000:00/0000:00:1f.3/sof_sdw/SDW0-Capture-SmartMic'
kobject_add_internal failed for SDW0-Capture-SmartMic with -EEXIST,
don't try to register things with the same name in the same directory
sof_sdw sof_sdw: probe with driver sof_sdw failed with error -12
So the collision is reachable, reproducible and fatal whenever a ghost
declaring a duplicate function reaches create_sdw_dailink(). The quirk
does not fix that; it only removes this particular ghost before the
naming code sees it. create_sdw_dailink() still builds names from link
id and function type alone, so any board with two peripherals of the
same function type on one link would hit it.
I have not included a fix in v2 - with the quirk applied I cannot
reproduce it on purpose any more, and I would rather not send an
untestable patch. If you would like it addressed, I am happy to send it
separately and to describe the failure in more detail.
Testing note for v2: verified on 7.0.0-30 (Ubuntu 26.04), with the quirk
backported, because that is the kernel this machine runs. The posted
patch is against thesofproject/linux topic/sof-dev; the table entry is
identical and the mechanism it relies on is unchanged between the two
trees - slave.c drops a peripheral whose overridden _ADR is zero in
both. 1/2 is byte-identical to v1's 1/3 and unchanged since it was
tested on 7.1.0-rc7.
v2 follows this message.
Thanks again,
Sergey
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel)
2026-08-04 22:59 [PATCH 0/3] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
` (2 preceding siblings ...)
2026-08-04 22:59 ` [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index Sergey Lebedev
@ 2026-08-30 8:45 ` Sergey Lebedev
2026-08-30 8:45 ` [PATCH v2 1/2] ASoC: rt1320: run the initialisation preset on the first hardware init Sergey Lebedev
` (3 more replies)
3 siblings, 4 replies; 15+ messages in thread
From: Sergey Lebedev @ 2026-08-30 8:45 UTC (permalink / raw)
To: Vinod Koul, Bard Liao, Pierre-Louis Bossart, Oder Chiou,
Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
Cc: linux-sound, linux-kernel
The Microsoft Surface Pro 11 for Business (Intel, Lunar Lake) has no working
audio under Linux: the speakers are silent while every layer reports success.
These two patches fix it, and the machine then works with the stock
sof-soundwire UCM profile and the shipped topologies - no board quirk, no new
match entry, no local configuration of any kind.
v1 was three patches: https://lore.kernel.org/linux-sound/20260804225853.31585-1-lsa.uz@pm.me/
Two of them are replaced here by a single DMI quirk, which is what Bard Liao
and Pierre-Louis Bossart asked for in review, and which is both smaller and
safer than what it replaces.
The board carries one physical RT1320 amplifier on SoundWire link 0 and
describes it twice:
SWRA _ADR 0x000030025D132000 SDCA class 0
SWRB _ADR 0x000030025D132001 SDCA class 1
Identical apart from the class id: same link, same manufacturer, part and
version, same unique id 0. The part reports class 1, so only SWRB ever
enumerates. SWRA stays UNATTACHED on every boot and on every firmware version
tested, including the November 2025 bundle, and the firmware is signed vendor
firmware we cannot have corrected at the source.
That ghost broke two things at once. It consumed an amplifier index, so the
real part was named "rt1320-2" and the stock UCM enabled switches on a device
that is not there; and its endpoints reached create_sdw_dailink(), which builds
DAI link names from link id and function type alone, so its SmartMic collided
with the real one and the card failed to register at all with -EEXIST.
v1 fixed those two symptoms in two places, each with its own way of noticing
the ghost. Removing the ghost at enumeration instead fixes both at once and
needs no runtime presence test:
1/2 rt1320: the amplifier's preset never runs, because the driver waits for
FUNCTION_NEEDS_INITIALIZATION and this part never sets it. rt712-sdca and
rt722-sdca already handle this by also running the preset on the first
hardware init; rt1320 is the odd one out. One line, unchanged from v1.
2/2 dmi-quirks: remap the ghost _ADR to zero so sdw_acpi_find_slaves() never
creates the peripheral, as ghost_realtek and global_ghost_adr already do.
Matched on DMI_PRODUCT_SKU, not the product name, so a later batch with a
different RT1320 version - and therefore a different _ADR - cannot be
caught by a remap it was never verified against.
Testing. Surface Pro 11 for Business (Intel Core Ultra 7 268V). Verified on the
machine's own kernel, 7.0.0-30 (Ubuntu 26.04), with 2/2 backported to that
tree: its dmi-quirks.c predates ghost_realtek, but the table entry is identical
and the mechanism is unchanged - slave.c drops a peripheral whose overridden
_ADR is zero in both trees. 1/2 is byte-identical to v1's 1/3, which was built
and booted on 7.1.0-rc7.
- /sys/bus/soundwire/devices/ shows only sdw:0:0:025d:1320:01; the class-0
ghost is gone
- amplifier named rt1320-1, controls "rt1320-1 OT23 L/R Switch"
- card registers as sof-soundwire, 4 playback + 1 capture
- no -EEXIST, no -61 link startup errors
- speakers audible, internal microphone captures signal
- stock alsa-ucm-conf and firmware-sof-signed, no local configuration
- Secure Boot enabled with module signature enforcement, no rejections
One thing the review process turned up that is worth recording. The v1 cover
letter said the DAI link name collision was "no longer reachable on this
machine and we cannot demonstrate it". That was wrong: during v2 testing a boot
where the quirk did not take effect reproduced it exactly, and it is fatal.
create_sdw_dailink()'s naming scheme is still not unique in general. This series
does not address that - it removes the ghost before the naming code sees it -
and I am happy to send a separate patch if you would like it fixed.
checkpatch --strict is clean on both.
Sergey Lebedev (2):
ASoC: rt1320: run the initialisation preset on the first hardware init
soundwire: dmi-quirks: drop the ghost RT1320 on the Surface Pro 11
(Intel)
drivers/soundwire/dmi-quirks.c | 28 ++++++++++++++++++++++++++++
sound/soc/codecs/rt1320-sdw.c | 2 +-
2 files changed, 29 insertions(+), 1 deletion(-)
base-commit: 7e9e0409cd57924c4099090879154300c07b8643
--
2.50.1 (Apple Git-155)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 1/2] ASoC: rt1320: run the initialisation preset on the first hardware init
2026-08-30 8:45 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
@ 2026-08-30 8:45 ` Sergey Lebedev
2026-08-30 8:45 ` [PATCH v2 2/2] soundwire: dmi-quirks: drop the ghost RT1320 on the Surface Pro 11 (Intel) Sergey Lebedev
` (2 subsequent siblings)
3 siblings, 0 replies; 15+ messages in thread
From: Sergey Lebedev @ 2026-08-30 8:45 UTC (permalink / raw)
To: Vinod Koul, Bard Liao, Pierre-Louis Bossart, Oder Chiou,
Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
Cc: linux-sound, linux-kernel
rt1320_io_init() applies the vendor initialisation preset only when the
amplifier's SDCA function status has FUNCTION_NEEDS_INITIALIZATION set:
if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION)) {
Its two sibling drivers guard the same write differently, also running
the preset on the first hardware init:
rt712-sdca.c: if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) ||
(!rt712->first_hw_init)) {
rt722-sdca.c: if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) ||
(!rt722->first_hw_init)) {
On the Microsoft Surface Pro 11 (Intel) the RT1320 never sets that bit.
Its function status reads back 0x41 on every boot, cold or warm:
rt1320-sdca sdw:0:0:025d:1320:01: rt1320_io_init amp func_status=0x41
which is NEWLY_ATTACHED | FUNCTION_HAS_BEEN_RESET: the function reports
that it has been reset and does not consider itself in need of
initialisation. Bit 5 is never set, so the preset never runs,
rt1320_vc_preset() and the MCU patch load are skipped, and the amplifier
is left unprogrammed. rt712 and rt722 would have run it via their
first_hw_init fallback.
Add the same fallback. With it rt1320_vc_preset() executes and the
amplifier reports RT1320_KR0_INT_READY=0x1f where previously it did not.
Signed-off-by: Sergey Lebedev <lsa.uz@pm.me>
---
v2: unchanged from v1's 1/3.
sound/soc/codecs/rt1320-sdw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c
index 13493b85f..d1f3b160a 100644
--- a/sound/soc/codecs/rt1320-sdw.c
+++ b/sound/soc/codecs/rt1320-sdw.c
@@ -1900,7 +1900,7 @@ static int rt1320_io_init(struct device *dev, struct sdw_slave *slave)
dev_dbg(dev, "%s amp func_status=0x%x\n", __func__, amp_func_status);
/* initialization write */
- if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION)) {
+ if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) || !rt1320->first_hw_init) {
switch (rt1320->dev_id) {
case RT1320_DEV_ID:
if (rt1320->version_id < RT1320_VC)
--
2.50.1 (Apple Git-155)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 2/2] soundwire: dmi-quirks: drop the ghost RT1320 on the Surface Pro 11 (Intel)
2026-08-30 8:45 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
2026-08-30 8:45 ` [PATCH v2 1/2] ASoC: rt1320: run the initialisation preset on the first hardware init Sergey Lebedev
@ 2026-08-30 8:45 ` Sergey Lebedev
2026-08-30 12:26 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft " Sergey Lebedev
2026-08-30 14:27 ` Mark Brown
3 siblings, 0 replies; 15+ messages in thread
From: Sergey Lebedev @ 2026-08-30 8:45 UTC (permalink / raw)
To: Vinod Koul, Bard Liao, Pierre-Louis Bossart, Oder Chiou,
Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai
Cc: linux-sound, linux-kernel
The Microsoft Surface Pro 11 for Business (Intel, Lunar Lake) carries a
single physical RT1320 amplifier on link 0 and describes it twice:
SWRA _ADR 0x000030025D132000 SDCA class 0
SWRB _ADR 0x000030025D132001 SDCA class 1
Identical apart from the class id: same link, same manufacturer, part and
version, same unique id 0. The part reports class 1, so only SWRB
enumerates. SWRA never attaches on any boot or firmware version tested,
including the November 2025 bundle.
The ghost is not harmless. It consumes an amplifier index in
find_acpi_adr_device(), so the real part is named "rt1320-2" and the stock
sof-soundwire UCM profile enables switches on a device that is not there.
Its endpoints also reach create_sdw_dailink(), which builds DAI link names
from link id and function type alone; the ghost declares the same SmartMic
function as the real part, so the card fails to register at all:
sysfs: cannot create duplicate filename
'.../sof_sdw/SDW0-Capture-SmartMic'
kobject_add_internal failed for SDW0-Capture-SmartMic with -EEXIST
sof_sdw sof_sdw: probe with driver sof_sdw failed with error -12
Remap its _ADR to zero so sdw_acpi_find_slaves() never creates the
peripheral, which is how ghost devices are handled already - see
ghost_realtek and global_ghost_adr in this file. Both failures then
disappear, because neither path is reached.
Matched on DMI_PRODUCT_SKU rather than the product name. A later batch of
the same model could carry a different RT1320 version, which would change
the _ADR; keying on the SKU keeps this remap to the hardware it was
verified on, and follows dell_sku_0A3E above.
Suggested-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Suggested-by: Bard Liao <bard.liao@intel.com>
Signed-off-by: Sergey Lebedev <lsa.uz@pm.me>
---
v2:
- new in v2. Replaces v1's 2/3 (sdw_utils runtime presence test) and 3/3
(SOF/Intel amp-index dedup) with a single remap at enumeration, per
Pierre-Louis Bossart's suggestion.
- matched on DMI_PRODUCT_SKU rather than the product name, per Bard Liao:
a later batch could carry a different RT1320 version and therefore a
different _ADR.
drivers/soundwire/dmi-quirks.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c
index d75037558..8b3c5c8d1 100644
--- a/drivers/soundwire/dmi-quirks.c
+++ b/drivers/soundwire/dmi-quirks.c
@@ -111,6 +111,25 @@ static const struct adr_remap ghost_realtek[] = {
{}
};
+/*
+ * The Microsoft Surface Pro 11 (Intel) describes its single physical RT1320
+ * amplifier twice on link 0, as two _ADR entries differing only in SDCA class
+ * id and sharing the same unique id. Only the class 1 entry enumerates; the
+ * class 0 entry is a ghost.
+ *
+ * Matched on the product SKU rather than the product name: a later batch of the
+ * same model could carry a different RT1320 version, which would change the
+ * _ADR. Keying on the SKU keeps this remap to the hardware it was verified on.
+ */
+static const struct adr_remap microsoft_sp11_intel[] = {
+ /* ghost rt1320 on link0 */
+ {
+ 0x000030025d132000ull,
+ 0x0000000000000000ull
+ },
+ {}
+};
+
static const struct dmi_system_id adr_remap_quirk_table[] = {
/* TGL devices */
{
@@ -207,6 +226,15 @@ static const struct dmi_system_id adr_remap_quirk_table[] = {
},
.driver_data = (void *)ghost_realtek,
},
+ /* LNL devices */
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU,
+ "Surface_Pro_11th_Edition_With_Intel_For_Business_2103")
+ },
+ .driver_data = (void *)microsoft_sp11_intel,
+ },
{}
};
--
2.50.1 (Apple Git-155)
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel)
2026-08-30 8:45 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
2026-08-30 8:45 ` [PATCH v2 1/2] ASoC: rt1320: run the initialisation preset on the first hardware init Sergey Lebedev
2026-08-30 8:45 ` [PATCH v2 2/2] soundwire: dmi-quirks: drop the ghost RT1320 on the Surface Pro 11 (Intel) Sergey Lebedev
@ 2026-08-30 12:26 ` Sergey Lebedev
2026-08-30 14:27 ` Mark Brown
3 siblings, 0 replies; 15+ messages in thread
From: Sergey Lebedev @ 2026-08-30 12:26 UTC (permalink / raw)
To: Vinod Koul, Bard Liao, Pierre-Louis Bossart, Oder Chiou,
Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Amaan Lalani
Cc: linux-sound, linux-kernel
Some context I should have gathered before v1, not after v2. None of it
needs action from you; it is here so nobody spends time twice.
1. An overlapping series is already on the list
-----------------------------------------------
Amaan Lalani sent this on 2026-08-28, two days before my v2:
[PATCH 0/2] ASoC: fix SoundWire enumeration on Surface Pro 11
https://lore.kernel.org/linux-sound/BY5PR02MB63701A05A58EF6B4D6CAAC31A0AC2@BY5PR02MB6370.namprd02.prod.outlook.com/
Same machine, and in substance the same two changes as my v1 2/3 and 3/3 -
the name-prefix reuse for _ADR entries differing only in class id, and an
is_peripheral_attached() test on SDW_SLAVE_UNATTACHED. So the review you
already gave me applies to it unchanged: it detects the ghost at runtime
rather than removing it at enumeration.
Their version is better than mine was in two respects worth keeping if that
approach is ever preferred: it hooks both asoc_sdw_count_sdw_endpoints() and
asoc_sdw_parse_sdw_endpoints() rather than only the parse path, and it
carries Fixes: tags.
2. There is a body of downstream work for this machine
------------------------------------------------------
André Gilerson has carried Surface Pro 11 Intel patches in a linux-surface
fork since February - audio, cameras, an IR sensor driver, touchpad, lid
wake, a suspend hang fix. People have been running them daily for months.
None of it has been submitted here.
https://github.com/linux-surface/linux-surface/pull/1990
His audio fix takes the traditional shape: a DMI-gated machine entry in
soc-acpi-intel-lnl-match.c naming the real peripheral outright, with
name_prefix "rt1320-1" and two endpoints. With such an entry matched, the
generic find_acpi_adr_device() path is never reached, so the ghost never
gets the chance to consume an amp index.
3. The part that is actually interesting: the generic path is better here
--------------------------------------------------------------------------
Measured on this machine today, with v2 applied, stock alsa-ucm-conf
1.2.15.3 and firmware-sof 2025.12.2, and no local configuration:
Components: 'HDA:80862820,80860101,00100000 cfg-amp:1
iec61937-pcm:7,6,5 spk:rt1320 mic:rt1320-1 cfg-mics:1'
Using function topologies instead intel/sof-ipc4-tplg/sof-lnl-dummy.tplg
loading topology 0: intel/sof-ipc4-tplg/sof-sdca-1amp-id2.tplg
loading topology 1: intel/sof-ipc4-tplg/sof-sdca-mic-id4.tplg
loading topology 2: intel/sof-ipc4-tplg/sof-hdmi-pcm5-id5.tplg
arecord -l: card 0: sofsoundwire, device 4: Microphone
With no machine entry, the generic path uses a *-dummy.tplg base, dispatches
the function topologies itself, and produces cfg-mics:1.
On the machine-entry branches the microphone is a recurring problem. Users
report the mic missing entirely on the 6.18 branch - sof-sdca-mic-id4.tplg
present in firmware but never requested - and the v7.0 commit fixes it by
switching to a dummy base and forcing "Playback-SmartAmp" /
"Capture-SmartMic" dailink names, which is the dispatcher's own behaviour
reimplemented by hand. Its commit message attributes the loss to the
monolithic base topology discarding the SmartMic function. Separately, the
missing cfg-mics breaks the UCM import outright on alsa-ucm-conf 1.2.16.
I have not run that branch here, so that comparison is their reports against
my measurements rather than one machine tested both ways. I have offered to
do exactly that on this device and will report the result.
If it holds, the general shape is worth more than this laptop: remove ghost
_ADRs at enumeration and let the generic path do its job, instead of adding
a match entry per model - which for this hardware appears to cost the
microphone. Surface Pro 12 (Panther Lake) is reported to have the same
firmware shape, so it would be the next test of that idea rather than the
next entry.
Thanks,
Sergey
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel)
2026-08-30 8:45 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
` (2 preceding siblings ...)
2026-08-30 12:26 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft " Sergey Lebedev
@ 2026-08-30 14:27 ` Mark Brown
3 siblings, 0 replies; 15+ messages in thread
From: Mark Brown @ 2026-08-30 14:27 UTC (permalink / raw)
To: Sergey Lebedev
Cc: Vinod Koul, Bard Liao, Pierre-Louis Bossart, Oder Chiou,
Liam Girdwood, Jaroslav Kysela, Takashi Iwai, linux-sound,
linux-kernel
[-- Attachment #1: Type: text/plain, Size: 712 bytes --]
On Sun, Aug 30, 2026 at 08:45:05AM +0000, Sergey Lebedev wrote:
> The Microsoft Surface Pro 11 for Business (Intel, Lunar Lake) has no working
> audio under Linux: the speakers are silent while every layer reports success.
> These two patches fix it, and the machine then works with the stock
> sof-soundwire UCM profile and the shipped topologies - no board quirk, no new
> match entry, no local configuration of any kind.
Please don't send new patches in reply to old patches or serieses, this
makes it harder for both people and tools to understand what is going
on - it can bury things in mailboxes and make it difficult to keep track
of what current patches are, both for the new patches and the old ones.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-08-30 14:27 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-04 22:59 [PATCH 0/3] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
2026-08-04 22:59 ` [PATCH 1/3] ASoC: rt1320: run the initialisation preset on the first hardware init Sergey Lebedev
2026-08-04 22:59 ` [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus Sergey Lebedev
2026-08-05 1:12 ` Liao, Bard
2026-08-05 8:22 ` Pierre-Louis Bossart
2026-08-05 13:28 ` Liao, Bard
2026-08-30 8:44 ` Sergey Lebedev
2026-08-04 22:59 ` [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index Sergey Lebedev
2026-08-05 1:21 ` Liao, Bard
2026-08-05 8:33 ` Pierre-Louis Bossart
2026-08-30 8:45 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft Surface Pro 11 (Intel) Sergey Lebedev
2026-08-30 8:45 ` [PATCH v2 1/2] ASoC: rt1320: run the initialisation preset on the first hardware init Sergey Lebedev
2026-08-30 8:45 ` [PATCH v2 2/2] soundwire: dmi-quirks: drop the ghost RT1320 on the Surface Pro 11 (Intel) Sergey Lebedev
2026-08-30 12:26 ` [PATCH v2 0/2] ASoC: fix audio on the Microsoft " Sergey Lebedev
2026-08-30 14:27 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®