RE: [PATCH 2/3] ASoC: sdw_utils: skip endpoints of a peripheral that is not on the bus

"Liao, Bard" <[email protected]> Wed, 5 Aug 2026 01:12:55 +0000
Newsgroups org.kernel.vger.linux-sound,org.kernel.vger.linux-kernel
Message-ID <SJ2PR11MB84240C52AC5C4DB36B92AACCFFD32@SJ2PR11MB8424.namprd11.prod.outlook.com>

> -----Original Message-----
> From: Sergey Lebedev <[email protected]>
> Sent: Wednesday, August 5, 2026 7:00 AM
> To: Mark Brown <[email protected]>; Liam Girdwood
> <[email protected]>; Jaroslav Kysela <[email protected]>; Takashi Iwai
> <[email protected]>; Oder Chiou <[email protected]>; Bard Liao <yung-
> [email protected]>; Peter Ujfalusi <[email protected]>;
> Kai Vehmanen <[email protected]>; Ranjani Sridharan
> <[email protected]>; Pierre-Louis Bossart <pierre-
> [email protected]>; Daniel Baluta <[email protected]>; Vijendar
> Mukunda <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]
> 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 <[email protected]>
> ---
>  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)
> 
>