The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [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
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ 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] 9+ 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
  2026-08-04 22:59 ` [PATCH 3/3] ASoC: SOF: Intel: hda: duplicate _ADR entries share one amp index Sergey Lebedev
  2 siblings, 0 replies; 9+ 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 related	[flat|nested] 9+ 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
  2 siblings, 1 reply; 9+ 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 related	[flat|nested] 9+ 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
  2 siblings, 2 replies; 9+ 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 related	[flat|nested] 9+ 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; 9+ 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@vger.kernel.org, sound-open-firmware@alsa-project.org,
	linux-kernel@vger.kernel.org



> -----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] 9+ 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; 9+ 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@vger.kernel.org, sound-open-firmware@alsa-project.org,
	linux-kernel@vger.kernel.org



> -----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] 9+ 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; 9+ 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@vger.kernel.org, sound-open-firmware@alsa-project.org,
	linux-kernel@vger.kernel.org


>> 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] 9+ 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; 9+ 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] 9+ 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
  0 siblings, 0 replies; 9+ 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@vger.kernel.org, sound-open-firmware@alsa-project.org,
	linux-kernel@vger.kernel.org



> -----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] 9+ messages in thread

end of thread, other threads:[~2026-08-05 13:28 UTC | newest]

Thread overview: 9+ 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-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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox