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) > >