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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.