* [PATCH v4 0/3] Add SoundWire port constraints into SDCA stream
@ 2026-11-09 17:26 Charles Keepax
2026-11-09 17:26 ` [PATCH v4 1/3] ASoC: SDCA: Move DAI constraint allocation Charles Keepax
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Charles Keepax @ 2026-11-09 17:26 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, linux-sound,
linux-kernel, patches
SDCA adds constraints onto the DAI based on the DisCo properties for the
Input/Output Terminal. As the SoundWire port for a Terminal can be
selected it is possible for the SoundWire port to support fewer options
than the Terminal. These patches add the SoundWire port properties into
the constraints for the DAI startup to cover these situations.
Changes since v3:
- Added defaults for the word length min/max
- Removed unused static_assert
Changes since v2:
- Add check for ending up with a zero mask for channels
- Switch to using SNDRV_PCM_HW_PARAM_FORMAT, rather than SAMPLE_BITS
Changes since v1:
- Move constraint allocation to DAI probe/remove
- Use BIT macro where appropriate
- Correct GENMASK usage
- Add missing array indexing
- Correct channel masking
- Reorder the priority of SDCA properties
- Handle the case of the word length not being specified
- Add a static_assert to check the constraint array is large enough for
the word length mask
Charles Keepax (3):
ASoC: SDCA: Move DAI constraint allocation
ASoC: SDCA: Factor out helper for creating mask of Cluster channels
ASoC: SDCA: Add port constraints into sdca_asoc_set_constraints()
include/sound/sdca_asoc.h | 9 +-
sound/soc/sdca/sdca_asoc.c | 246 +++++++++++++++++++++------
sound/soc/sdca/sdca_class_function.c | 6 +-
3 files changed, 206 insertions(+), 55 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v4 1/3] ASoC: SDCA: Move DAI constraint allocation
2026-11-09 17:26 [PATCH v4 0/3] Add SoundWire port constraints into SDCA stream Charles Keepax
@ 2026-11-09 17:26 ` Charles Keepax
2026-11-09 17:26 ` [PATCH v4 2/3] ASoC: SDCA: Factor out helper for creating mask of Cluster channels Charles Keepax
2026-11-09 17:26 ` [PATCH v4 3/3] ASoC: SDCA: Add port constraints into sdca_asoc_set_constraints() Charles Keepax
2 siblings, 0 replies; 4+ messages in thread
From: Charles Keepax @ 2026-11-09 17:26 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, linux-sound,
linux-kernel, patches
It isn't necessary to allocate memory for constraints every time a DAI
link is opened. It is faster to allocate them once when the DAI link
is probed, update the SDCA code to do so.
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v3.
include/sound/sdca_asoc.h | 5 +-
sound/soc/sdca/sdca_asoc.c | 75 +++++++++++++++++-----------
sound/soc/sdca/sdca_class_function.c | 3 +-
3 files changed, 52 insertions(+), 31 deletions(-)
diff --git a/include/sound/sdca_asoc.h b/include/sound/sdca_asoc.h
index 599a72f335153..236a441ec9d89 100644
--- a/include/sound/sdca_asoc.h
+++ b/include/sound/sdca_asoc.h
@@ -89,12 +89,13 @@ int sdca_asoc_populate_rate_format(struct device *dev,
struct sdca_entity *entity,
struct snd_soc_pcm_stream *stream);
+int sdca_asoc_alloc_constraints(struct snd_soc_dai *dai);
+int sdca_asoc_free_constraints(struct snd_soc_dai *dai);
int sdca_asoc_set_constraints(struct device *dev, struct regmap *regmap,
struct sdca_function_data *function,
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai);
-void sdca_asoc_free_constraints(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai);
+
int sdca_asoc_get_port(struct device *dev, struct regmap *regmap,
struct sdca_function_data *function,
struct snd_soc_dai *dai);
diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c
index ccc579f878ff1..b8bde56298706 100644
--- a/sound/soc/sdca/sdca_asoc.c
+++ b/sound/soc/sdca/sdca_asoc.c
@@ -1434,6 +1434,48 @@ int sdca_asoc_populate_component(struct device *dev,
}
EXPORT_SYMBOL_NS(sdca_asoc_populate_component, "SND_SOC_SDCA");
+struct sdca_asoc_constraints {
+ struct snd_pcm_hw_constraint_list channels;
+};
+
+/**
+ * sdca_asoc_alloc_constraints - allocate a constraint structure on the DAI
+ * @dai: Pointer to the ASoC DAI.
+ *
+ * Typically called from DAI probe().
+ *
+ * Return: Returns zero on success, and a negative error code on failure.
+ */
+int sdca_asoc_alloc_constraints(struct snd_soc_dai *dai)
+{
+ struct sdca_asoc_constraints *constraints;
+
+ constraints = kzalloc_obj(*constraints);
+ if (!constraints)
+ return -ENOMEM;
+
+ snd_soc_dai_set_priv(dai, constraints);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(sdca_asoc_alloc_constraints, "SND_SOC_SDCA");
+
+/**
+ * sdca_asoc_free_constraints - free constraint allocations
+ * @dai: Pointer to the ASoC DAI.
+ *
+ * Typically called from DAI remove().
+ *
+ * Return: Returns zero on success, and a negative error code on failure.
+ */
+int sdca_asoc_free_constraints(struct snd_soc_dai *dai)
+{
+ kfree(snd_soc_dai_to_priv(dai));
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(sdca_asoc_free_constraints, "SND_SOC_SDCA");
+
/**
* sdca_asoc_set_constraints - constrain channels available on a DAI
* @dev: Pointer to the device, used for error messages.
@@ -1455,8 +1497,8 @@ int sdca_asoc_set_constraints(struct device *dev, struct regmap *regmap,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
};
+ struct sdca_asoc_constraints *constraints = snd_soc_dai_to_priv(dai);
struct sdca_entity *entity = &function->entities[dai->id];
- struct snd_pcm_hw_constraint_list *constraint;
struct sdca_control_range *range;
struct sdca_control *control;
unsigned int channel_mask = 0;
@@ -1490,45 +1532,22 @@ int sdca_asoc_set_constraints(struct device *dev, struct regmap *regmap,
dev_dbg(dev, "%s: set channel constraint mask: %#x\n",
entity->label, channel_mask);
- constraint = kzalloc_obj(*constraint);
- if (!constraint)
- return -ENOMEM;
-
- constraint->count = ARRAY_SIZE(channel_list);
- constraint->list = channel_list;
- constraint->mask = channel_mask;
+ constraints->channels.count = ARRAY_SIZE(channel_list);
+ constraints->channels.list = channel_list;
+ constraints->channels.mask = channel_mask;
ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
- constraint);
+ &constraints->channels);
if (ret) {
dev_err(dev, "%s: failed to add constraint: %d\n", entity->label, ret);
- kfree(constraint);
return ret;
}
- snd_soc_dai_set_priv(dai, constraint);
-
return 0;
}
EXPORT_SYMBOL_NS(sdca_asoc_set_constraints, "SND_SOC_SDCA");
-/**
- * sdca_asoc_free_constraints - free constraint allocations
- * @substream: Pointer to the PCM substream.
- * @dai: Pointer to the ASoC DAI.
- *
- * Typically called from shutdown().
- */
-void sdca_asoc_free_constraints(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_hw_constraint_list *constraint = snd_soc_dai_to_priv(dai);
-
- kfree(constraint);
-}
-EXPORT_SYMBOL_NS(sdca_asoc_free_constraints, "SND_SOC_SDCA");
-
/**
* sdca_asoc_get_port - return SoundWire port for a DAI
* @dev: Pointer to the device, used for error messages.
diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c
index 13b70f0f0dbf7..6406c9d0f6119 100644
--- a/sound/soc/sdca/sdca_class_function.c
+++ b/sound/soc/sdca/sdca_class_function.c
@@ -184,8 +184,9 @@ static int class_function_sdw_set_stream(struct snd_soc_dai *dai, void *sdw_stre
}
static const struct snd_soc_dai_ops class_function_sdw_ops = {
+ .probe = sdca_asoc_alloc_constraints,
+ .remove = sdca_asoc_free_constraints,
.startup = class_function_startup,
- .shutdown = sdca_asoc_free_constraints,
.set_stream = class_function_sdw_set_stream,
.hw_params = class_function_sdw_add_peripheral,
.hw_free = class_function_sdw_remove_peripheral,
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v4 2/3] ASoC: SDCA: Factor out helper for creating mask of Cluster channels
2026-11-09 17:26 [PATCH v4 0/3] Add SoundWire port constraints into SDCA stream Charles Keepax
2026-11-09 17:26 ` [PATCH v4 1/3] ASoC: SDCA: Move DAI constraint allocation Charles Keepax
@ 2026-11-09 17:26 ` Charles Keepax
2026-11-09 17:26 ` [PATCH v4 3/3] ASoC: SDCA: Add port constraints into sdca_asoc_set_constraints() Charles Keepax
2 siblings, 0 replies; 4+ messages in thread
From: Charles Keepax @ 2026-11-09 17:26 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, linux-sound,
linux-kernel, patches
Factor out the code that builds a mask of the allowed channels from the
Cluster information. This is slightly cleaner and prepares for
additional constraints to be added to sdca_asoc_set_constraints().
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v3.
sound/soc/sdca/sdca_asoc.c | 64 +++++++++++++++++++++++---------------
1 file changed, 39 insertions(+), 25 deletions(-)
diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c
index b8bde56298706..be1b4c0075796 100644
--- a/sound/soc/sdca/sdca_asoc.c
+++ b/sound/soc/sdca/sdca_asoc.c
@@ -1476,6 +1476,37 @@ int sdca_asoc_free_constraints(struct snd_soc_dai *dai)
}
EXPORT_SYMBOL_NS(sdca_asoc_free_constraints, "SND_SOC_SDCA");
+static int get_cluster_mask(struct device *dev, struct sdca_function_data *function,
+ struct sdca_entity *entity, unsigned int *ch_mask)
+{
+ struct sdca_control_range *range;
+ struct sdca_control *control;
+ int i;
+
+ control = sdca_selector_find_control(dev, entity, SDCA_CTL_IT_CLUSTERINDEX);
+ if (!control)
+ return -EINVAL;
+
+ range = sdca_control_find_range(dev, entity, control, SDCA_CLUSTER_NCOLS, 0);
+ if (!range)
+ return -EINVAL;
+
+ *ch_mask = 0;
+
+ for (i = 0; i < range->rows; i++) {
+ int clusterid = sdca_range(range, SDCA_CLUSTER_CLUSTERID, i);
+ struct sdca_cluster *cluster;
+
+ cluster = sdca_id_find_cluster(dev, function, clusterid);
+ if (!cluster)
+ return -ENODEV;
+
+ *ch_mask |= BIT(cluster->num_channels - 1);
+ }
+
+ return 0;
+}
+
/**
* sdca_asoc_set_constraints - constrain channels available on a DAI
* @dev: Pointer to the device, used for error messages.
@@ -1499,42 +1530,25 @@ int sdca_asoc_set_constraints(struct device *dev, struct regmap *regmap,
};
struct sdca_asoc_constraints *constraints = snd_soc_dai_to_priv(dai);
struct sdca_entity *entity = &function->entities[dai->id];
- struct sdca_control_range *range;
- struct sdca_control *control;
- unsigned int channel_mask = 0;
- int i, ret;
+ unsigned int cluster_ch_mask;
+ int ret;
static_assert(ARRAY_SIZE(channel_list) == SDCA_MAX_CHANNEL_COUNT);
- static_assert(sizeof(channel_mask) * BITS_PER_BYTE >= SDCA_MAX_CHANNEL_COUNT);
+ static_assert(sizeof(cluster_ch_mask) * BITS_PER_BYTE >= SDCA_MAX_CHANNEL_COUNT);
if (entity->type != SDCA_ENTITY_TYPE_IT)
return 0;
- control = sdca_selector_find_control(dev, entity, SDCA_CTL_IT_CLUSTERINDEX);
- if (!control)
- return -EINVAL;
-
- range = sdca_control_find_range(dev, entity, control, SDCA_CLUSTER_NCOLS, 0);
- if (!range)
- return -EINVAL;
-
- for (i = 0; i < range->rows; i++) {
- int clusterid = sdca_range(range, SDCA_CLUSTER_CLUSTERID, i);
- struct sdca_cluster *cluster;
-
- cluster = sdca_id_find_cluster(dev, function, clusterid);
- if (!cluster)
- return -ENODEV;
-
- channel_mask |= (1 << (cluster->num_channels - 1));
- }
+ ret = get_cluster_mask(dev, function, entity, &cluster_ch_mask);
+ if (ret)
+ return ret;
dev_dbg(dev, "%s: set channel constraint mask: %#x\n",
- entity->label, channel_mask);
+ entity->label, cluster_ch_mask);
constraints->channels.count = ARRAY_SIZE(channel_list);
constraints->channels.list = channel_list;
- constraints->channels.mask = channel_mask;
+ constraints->channels.mask = cluster_ch_mask;
ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v4 3/3] ASoC: SDCA: Add port constraints into sdca_asoc_set_constraints()
2026-11-09 17:26 [PATCH v4 0/3] Add SoundWire port constraints into SDCA stream Charles Keepax
2026-11-09 17:26 ` [PATCH v4 1/3] ASoC: SDCA: Move DAI constraint allocation Charles Keepax
2026-11-09 17:26 ` [PATCH v4 2/3] ASoC: SDCA: Factor out helper for creating mask of Cluster channels Charles Keepax
@ 2026-11-09 17:26 ` Charles Keepax
2 siblings, 0 replies; 4+ messages in thread
From: Charles Keepax @ 2026-11-09 17:26 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, linux-sound,
linux-kernel, patches
Currently the SDCA code constrains the params based on the DisCo for
the SDCA Terminal used. However, it ignores the properties of the
SoundWire port, which in some cases may further constrain the allowed
params. Add additional constraints to apply these restrictions.
Some minor additional refactoring is required since port constraints
should be applied for both Input and Output Terminals, whereas
currently Cluster constraints are only handled for Input Terminals.
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
Changes since v3:
- Added defaults for the word length min/max
- Removed unused static_assert
Also regarding ch_min/ch_max one can't assume defaults locally for those
as 0/0 is a valid combo. I have a patch that adds defaults at the
soundwire end, I will upstream that likely tomorrow.
include/sound/sdca_asoc.h | 4 +-
sound/soc/sdca/sdca_asoc.c | 133 +++++++++++++++++++++++++--
sound/soc/sdca/sdca_class_function.c | 3 +-
3 files changed, 128 insertions(+), 12 deletions(-)
diff --git a/include/sound/sdca_asoc.h b/include/sound/sdca_asoc.h
index 236a441ec9d89..26740f69f2bee 100644
--- a/include/sound/sdca_asoc.h
+++ b/include/sound/sdca_asoc.h
@@ -12,6 +12,7 @@
struct device;
struct regmap;
+struct sdw_slave;
struct sdca_function_data;
struct sdca_pde_delay;
struct snd_ctl_elem_value;
@@ -91,7 +92,8 @@ int sdca_asoc_populate_rate_format(struct device *dev,
int sdca_asoc_alloc_constraints(struct snd_soc_dai *dai);
int sdca_asoc_free_constraints(struct snd_soc_dai *dai);
-int sdca_asoc_set_constraints(struct device *dev, struct regmap *regmap,
+int sdca_asoc_set_constraints(struct device *dev, struct sdw_slave *sdw,
+ struct regmap *regmap,
struct sdca_function_data *function,
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai);
diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c
index be1b4c0075796..37cd1f9f58bd1 100644
--- a/sound/soc/sdca/sdca_asoc.c
+++ b/sound/soc/sdca/sdca_asoc.c
@@ -13,11 +13,13 @@
#include <linux/delay.h>
#include <linux/dev_printk.h>
#include <linux/device.h>
+#include <linux/limits.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/overflow.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_registers.h>
#include <linux/string_helpers.h>
#include <linux/types.h>
@@ -1436,6 +1438,7 @@ EXPORT_SYMBOL_NS(sdca_asoc_populate_component, "SND_SOC_SDCA");
struct sdca_asoc_constraints {
struct snd_pcm_hw_constraint_list channels;
+ u64 width;
};
/**
@@ -1507,9 +1510,91 @@ static int get_cluster_mask(struct device *dev, struct sdca_function_data *funct
return 0;
}
+static u64 get_word_mask(unsigned int width)
+{
+ switch (width) {
+ case 8:
+ return SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8;
+ case 16:
+ return SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
+ SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE;
+ case 18:
+ return SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE |
+ SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_U18_3BE;
+ case 20:
+ return SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_U20_LE |
+ SNDRV_PCM_FMTBIT_S20_BE | SNDRV_PCM_FMTBIT_U20_BE |
+ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE |
+ SNDRV_PCM_FMTBIT_S20_3BE | SNDRV_PCM_FMTBIT_U20_3BE;
+ case 24:
+ return SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |
+ SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE |
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE |
+ SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_U24_3BE;
+ case 32:
+ return SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |
+ SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE;
+ default:
+ return 0;
+ }
+}
+
+static int get_port_masks(struct sdw_slave *sdw, unsigned int port,
+ struct snd_pcm_substream *substream,
+ u64 *word_mask, unsigned int *ch_mask)
+{
+ struct sdw_dpn_prop *prop;
+ unsigned int nprop;
+ int i, j;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ prop = sdw->prop.sink_dpn_prop;
+ nprop = hweight32(sdw->prop.sink_ports);
+ } else {
+ prop = sdw->prop.src_dpn_prop;
+ nprop = hweight32(sdw->prop.source_ports);
+ }
+
+ *word_mask = 0;
+ *ch_mask = 0;
+
+ for (i = 0; i < nprop; i++) {
+ if (prop[i].num != port)
+ continue;
+
+ if (prop[i].num_words) {
+ for (j = 0; j < prop[i].num_words; j++)
+ *word_mask |= get_word_mask(prop[i].words[j]);
+ } else {
+ unsigned int max = prop[i].max_word;
+
+ if (!max || max > 32)
+ max = 32;
+
+ for (j = MAX(1, prop[i].min_word); j <= max; j++)
+ *word_mask |= get_word_mask(j);
+ }
+
+ /* Only handle the number of channels for constraints. */
+ if (prop[i].num_ch_combinations) {
+ for (j = 0; j < prop[i].num_ch_combinations; j++)
+ *ch_mask |= BIT(hweight32(prop[i].ch_combinations[j]) - 1);
+ } else if (prop[i].num_channels) {
+ *ch_mask = GENMASK(prop[i].num_channels - 1, 0);
+ } else {
+ *ch_mask = GENMASK(prop[i].max_ch - prop[i].min_ch, 0);
+ }
+
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
/**
* sdca_asoc_set_constraints - constrain channels available on a DAI
* @dev: Pointer to the device, used for error messages.
+ * @sdw: Pointer to the SoundWire peripheral device.
* @regmap: Pointer to the Function register map.
* @function: Pointer to the Function information.
* @substream: Pointer to the PCM substream.
@@ -1519,7 +1604,8 @@ static int get_cluster_mask(struct device *dev, struct sdca_function_data *funct
*
* Return: Returns zero on success, and a negative error code on failure.
*/
-int sdca_asoc_set_constraints(struct device *dev, struct regmap *regmap,
+int sdca_asoc_set_constraints(struct device *dev, struct sdw_slave *sdw,
+ struct regmap *regmap,
struct sdca_function_data *function,
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
@@ -1530,31 +1616,58 @@ int sdca_asoc_set_constraints(struct device *dev, struct regmap *regmap,
};
struct sdca_asoc_constraints *constraints = snd_soc_dai_to_priv(dai);
struct sdca_entity *entity = &function->entities[dai->id];
- unsigned int cluster_ch_mask;
+ unsigned int port_ch_mask, cluster_ch_mask;
+ int port;
int ret;
static_assert(ARRAY_SIZE(channel_list) == SDCA_MAX_CHANNEL_COUNT);
static_assert(sizeof(cluster_ch_mask) * BITS_PER_BYTE >= SDCA_MAX_CHANNEL_COUNT);
- if (entity->type != SDCA_ENTITY_TYPE_IT)
- return 0;
+ /* FIXME: Currently only a single unshared port is supported */
+ port = sdca_asoc_get_port(dev, regmap, function, dai);
+ if (port < 0)
+ return port;
- ret = get_cluster_mask(dev, function, entity, &cluster_ch_mask);
- if (ret)
+ ret = get_port_masks(sdw, port, substream, &constraints->width, &port_ch_mask);
+ if (ret < 0) {
+ dev_err(dev, "%s: no properties for port %d\n", entity->label, port);
return ret;
+ }
- dev_dbg(dev, "%s: set channel constraint mask: %#x\n",
- entity->label, cluster_ch_mask);
+ /* FIXME: OTs should inherit cluster information */
+ if (entity->type == SDCA_ENTITY_TYPE_IT) {
+ ret = get_cluster_mask(dev, function, entity, &cluster_ch_mask);
+ if (ret)
+ return ret;
+ } else {
+ cluster_ch_mask = UINT_MAX;
+ }
constraints->channels.count = ARRAY_SIZE(channel_list);
constraints->channels.list = channel_list;
- constraints->channels.mask = cluster_ch_mask;
+ constraints->channels.mask = cluster_ch_mask & port_ch_mask;
+
+ if (!constraints->channels.mask || !constraints->width) {
+ dev_err(dev, "%s: no valid constraint masks channel: %#x,%#x width: %#llx\n",
+ entity->label, cluster_ch_mask, port_ch_mask, constraints->width);
+ return -EINVAL;
+ }
ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
&constraints->channels);
if (ret) {
- dev_err(dev, "%s: failed to add constraint: %d\n", entity->label, ret);
+ dev_err(dev, "%s: failed to add channel constraint: %d\n",
+ entity->label, ret);
+ return ret;
+ }
+
+ ret = snd_pcm_hw_constraint_mask64(substream->runtime,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ constraints->width);
+ if (ret) {
+ dev_err(dev, "%s: failed to add bit width constraint: %d\n",
+ entity->label, ret);
return ret;
}
diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c
index 6406c9d0f6119..abccc63640c68 100644
--- a/sound/soc/sdca/sdca_class_function.c
+++ b/sound/soc/sdca/sdca_class_function.c
@@ -121,8 +121,9 @@ static int class_function_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct class_function_drv *drv = snd_soc_component_get_drvdata(dai->component);
+ struct sdw_slave *sdw = dev_to_sdw_dev(drv->dev->parent);
- return sdca_asoc_set_constraints(drv->dev, drv->regmap, drv->function,
+ return sdca_asoc_set_constraints(drv->dev, sdw, drv->regmap, drv->function,
substream, dai);
}
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-09 17:26 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-09 17:26 [PATCH v4 0/3] Add SoundWire port constraints into SDCA stream Charles Keepax
2026-11-09 17:26 ` [PATCH v4 1/3] ASoC: SDCA: Move DAI constraint allocation Charles Keepax
2026-11-09 17:26 ` [PATCH v4 2/3] ASoC: SDCA: Factor out helper for creating mask of Cluster channels Charles Keepax
2026-11-09 17:26 ` [PATCH v4 3/3] ASoC: SDCA: Add port constraints into sdca_asoc_set_constraints() Charles Keepax
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®