[PATCH 3/3] ASoC: SOF: Intel: wait and verifies the presence of SoundWire peripherals

From: Bard Liao

Date: Tue Sep 15 2026 - 09:54:02 EST


Wait and verifies the presence of SoundWire peripherals listed in the
ACPI table. This prevents the system from probing non-existent (ghost)
SoundWire devices.

Signed-off-by: Bard Liao <yung-chuan.liao@xxxxxxxxxxxxxxx>
Reviewed-by: Charles Keepax <ckeepax@xxxxxxxxxxxxxxxxxxxxx>
---
sound/soc/sof/intel/hda.c | 47 +++++++++++++++++++++++++++++++++++++--
1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 4dbba9186b29..e1815bfe358b 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -1304,6 +1304,8 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
return adr_dev;
}

+#define SDW_ENUM_TIMEOUT_MS 3000
+
static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *pdata = sdev->pdata;
@@ -1313,7 +1315,9 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
struct sdw_peripherals *peripherals;
struct snd_soc_acpi_mach *mach;
struct sof_intel_hda_dev *hdev;
+ struct sdw_slave *slave;
int link_index, link_num;
+ unsigned long time;
int amp_index = 1;
u32 link_mask = 0;
int i;
@@ -1415,14 +1419,53 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
if (!links)
return NULL;

+ /*
+ * Recalculate the link_mask as a link will be empty if all peripherals on the link are
+ * not enumerated
+ */
+ link_mask = 0;
/* Generate snd_soc_acpi_link_adr struct for each peripheral reported by the ACPI table */
for (i = 0; i < peripherals->num_peripherals; i++) {
+ slave = peripherals->array[i];
+
+ if (!slave->bus->is_present)
+ continue;
+
+ if (link_mask & BIT(slave->bus->link_id)) {
+ /*
+ * At least one peripheral is present on the link which means that this
+ * link has already been enumerated
+ */
+ goto skip_wait_link_enumeration;
+ }
+
+ if (sdw_show_ping_status(slave->bus, true) == 0) {
+ /* no peripherals attached on this link */
+ slave->bus->is_present = false;
+ continue;
+ }
+
+ time = wait_for_completion_timeout(&slave->bus->enumeration_complete,
+ msecs_to_jiffies(SDW_ENUM_TIMEOUT_MS));
+ if (!time) {
+ dev_warn(slave->bus->dev, "No peripheral is present\n");
+ slave->bus->is_present = false;
+ continue;
+ }
+
+skip_wait_link_enumeration:
+ /* Check if the SoundWire peripheral is present */
+ if (!slave->dev_num_sticky) {
+ dev_warn(&slave->dev, "SoundWire peripheral is not present\n");
+ continue;
+ }
/* link_index = the number of used links below the current link */
- link_index = hweight32(link_mask & (BIT(peripherals->array[i]->bus->link_id) - 1));
- links[link_index].adr_d = find_acpi_adr_device(sdev->dev, peripherals->array[i],
+ link_index = hweight32(link_mask & (BIT(slave->bus->link_id) - 1));
+ links[link_index].adr_d = find_acpi_adr_device(sdev->dev, slave,
&links[link_index], &amp_index);
if (!links[link_index].adr_d)
return NULL;
+ link_mask |= BIT(slave->bus->link_id);
}

mach->drv_name = "sof_sdw";
--
2.43.0