From: Matthew Schwartz <matthew.schwartz@linux.dev>
To: broonie@kernel.org
Cc: Matthew Schwartz <matthew.schwartz@linux.dev>,
Liam Girdwood <lgirdwood@gmail.com>,
Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
Vijendar Mukunda <Vijendar.Mukunda@amd.com>,
Venkata Prasad Potturu <venkataprasad.potturu@amd.com>,
Cezary Rojewski <cezary.rojewski@intel.com>,
Peter Ujfalusi <peter.ujfalusi@linux.intel.com>,
Bard Liao <yung-chuan.liao@linux.intel.com>,
Kai Vehmanen <kai.vehmanen@linux.intel.com>,
Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>,
linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 4/5] ASoC: sdw_utils: honor empty DisCo port lists when creating DAI links
Date: Fri, 16 Oct 2026 16:24:14 -0700 [thread overview]
Message-ID: <20261016232416.2628603-5-matthew.schwartz@linux.dev> (raw)
In-Reply-To: <20261016232416.2628603-1-matthew.schwartz@linux.dev>
The codec_info tables give each DAI a fixed direction, so a TAS2783
always gets an amp feedback capture link. The ASUS ROG Xbox Ally X20
BIOS declares mipi-sdw-source-port-list as 0 for both of its TAS2783s,
so the capture port has no DisCo properties and every open of the
SmartAmp capture PCM fails in sdw_program_slave_port_params() with
-EINVAL. The PCM is probed at session start, which logs a burst of
transport errors on every boot, and the same failure is reported on the
ASUS ProArt PX13.
Store the effective direction in each endpoint and drop a direction
when the peripheral declares an empty port list for it. A missing port
list keeps the table direction, so platforms that do not describe their
ports are unaffected.
Signed-off-by: Matthew Schwartz <matthew.schwartz@linux.dev>
---
include/sound/soc_sdw_utils.h | 1 +
sound/soc/amd/acp/acp-sdw-legacy-mach.c | 2 +-
sound/soc/amd/acp/acp-sdw-sof-mach.c | 2 +-
sound/soc/intel/boards/sof_sdw.c | 2 +-
sound/soc/sdw_utils/soc_sdw_utils.c | 36 ++++++++++++++++++++++---
5 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h
index 418466438ea1c..8e247a457a7c6 100644
--- a/include/sound/soc_sdw_utils.h
+++ b/include/sound/soc_sdw_utils.h
@@ -114,6 +114,7 @@ struct asoc_sdw_endpoint {
const char *codec_name;
const char *name_prefix;
bool include_sidecar;
+ bool direction[2]; /* dai_info direction limited by the DisCo port lists */
struct asoc_sdw_codec_info *codec_info;
const struct asoc_sdw_dai_info *dai_info;
diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
index a8b62817b2344..d485cee42542c 100644
--- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
@@ -262,7 +262,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
return -ENOMEM;
list_for_each_entry(soc_end, &soc_dai->endpoints, list) {
- if (!soc_end->dai_info->direction[stream])
+ if (!soc_end->direction[stream])
continue;
/*
diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c
index ec3e1f5f1052c..87e495e601bcd 100644
--- a/sound/soc/amd/acp/acp-sdw-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c
@@ -177,7 +177,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
return -ENOMEM;
list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
- if (!sof_end->dai_info->direction[stream])
+ if (!sof_end->direction[stream])
continue;
int link_num = ffs(sof_end->link_mask) - 1;
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 72fe013fffe86..42c6c262cc80e 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -973,7 +973,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
return -ENOMEM;
list_for_each_entry(sof_end, &sof_dai->endpoints, list) {
- if (!sof_end->dai_info->direction[stream])
+ if (!sof_end->direction[stream])
continue;
if (cur_link != sof_end->link_mask) {
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 7a19de75f32b5..126ff1b2dc450 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -2407,6 +2407,32 @@ static int is_sdca_endpoint_present(struct device *dev,
return 0;
}
+/* A DisCo port list that is present but empty means the stream cannot run */
+static bool asoc_sdw_has_ports(struct device *dev,
+ const struct snd_soc_acpi_link_adr *adr_link,
+ int adr_index, int stream)
+{
+ const char *prop = stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ "mipi-sdw-sink-port-list" : "mipi-sdw-source-port-list";
+ const char *sdw_codec_name;
+ struct device *sdw_dev;
+ u32 ports;
+ int ret;
+
+ 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;
+
+ ret = device_property_read_u32(sdw_dev, prop, &ports);
+ put_device(sdw_dev);
+
+ return ret || ports;
+}
+
int asoc_sdw_parse_sdw_endpoints(struct device *dev,
struct asoc_sdw_mc_private *ctx,
struct snd_soc_aux_dev *soc_aux,
@@ -2529,12 +2555,16 @@ int asoc_sdw_parse_sdw_endpoints(struct device *dev,
}
}
+ for_each_pcm_streams(stream)
+ soc_end->direction[stream] = dai_info->direction[stream] &&
+ asoc_sdw_has_ports(dev, adr_link, i, stream);
+
dev_dbg(dev,
"Add dev: %d, 0x%llx end: %d, dai: %d, %c/%c to %s: %d\n",
ffs(adr_link->mask) - 1, adr_dev->adr,
adr_end->num, dai_info->dai_type,
- dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-',
- dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-',
+ soc_end->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-',
+ soc_end->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-',
adr_end->aggregated ? "group" : "solo",
adr_end->group_id);
@@ -2555,7 +2585,7 @@ int asoc_sdw_parse_sdw_endpoints(struct device *dev,
return -EINVAL;
}
- if (dai_info->direction[stream]) {
+ if (soc_end->direction[stream]) {
num_dais += !soc_dai->num_devs[stream];
soc_dai->num_devs[stream]++;
soc_dai->link_mask[stream] |= adr_link->mask;
--
2.56.0
next prev parent reply other threads:[~2026-10-16 23:24 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 23:24 [PATCH 0/5] ASoC: support the ASUS ROG Xbox Ally X20 audio Matthew Schwartz
2026-10-16 23:24 ` [PATCH 1/5] ASoC: amd: acp-config: force SoundWire probe on ASUS RC74XA Matthew Schwartz
2026-10-16 23:24 ` [PATCH 2/5] ASoC: amd: acp: add ACP70 SoundWire machine entry for " Matthew Schwartz
2026-10-16 23:24 ` [PATCH 3/5] ASoC: tas2783-sdw: use the BIOS speaker ID in the firmware name Matthew Schwartz
2026-10-16 23:24 ` Matthew Schwartz [this message]
2026-10-16 23:24 ` [PATCH 5/5] ASoC: rt721-sdca: wait for PDEs to reach PS0 after powering them up Matthew Schwartz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261016232416.2628603-5-matthew.schwartz@linux.dev \
--to=matthew.schwartz@linux.dev \
--cc=Vijendar.Mukunda@amd.com \
--cc=broonie@kernel.org \
--cc=cezary.rojewski@intel.com \
--cc=kai.vehmanen@linux.intel.com \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=perex@perex.cz \
--cc=peter.ujfalusi@linux.intel.com \
--cc=pierre-louis.bossart@linux.dev \
--cc=tiwai@suse.com \
--cc=venkataprasad.potturu@amd.com \
--cc=yung-chuan.liao@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®