From 21a5adffad463344e9aca6ee697f45a079cb3ef5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 26 May 2026 13:57:47 +0300 Subject: [PATCH 1/2] ASoC: SOF: ipc4-topology: Validate the number of in/out formats for src/asrc SRC and ASRC modules must have at least one input and on one output formats to be usable. Do a sanity check during setup type and fail if either the number of input or output formats are 0. Signed-off-by: Peter Ujfalusi Link: https://patch.msgid.link/20260526105748.26149-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 76812d8fb567..f5623cff0554 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1092,6 +1092,15 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget) if (ret) goto err; + if (!src->available_fmt.num_input_formats || + !src->available_fmt.num_output_formats) { + dev_err(scomp->dev, + "Invalid number of formats: input: %d, output: %d\n", + src->available_fmt.num_input_formats, + src->available_fmt.num_output_formats); + goto err; + } + ret = sof_update_ipc_object(scomp, &src->data, SOF_SRC_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*src), 1); if (ret) { @@ -1135,6 +1144,15 @@ static int sof_ipc4_widget_setup_comp_asrc(struct snd_sof_widget *swidget) if (ret) goto err; + if (!asrc->available_fmt.num_input_formats || + !asrc->available_fmt.num_output_formats) { + dev_err(scomp->dev, + "Invalid number of formats: input: %d, output: %d\n", + asrc->available_fmt.num_input_formats, + asrc->available_fmt.num_output_formats); + goto err; + } + ret = sof_update_ipc_object(scomp, &asrc->data, SOF_ASRC_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*asrc), 1); if (ret) { From 3c3ce66b65c42d6bfe1de9ca72e3510b5101fa3c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 26 May 2026 13:57:48 +0300 Subject: [PATCH 2/2] ASoC: SOF: ipc4-topology: Allow the use of multiple formats for src output The SRC module can only change the rate, it keeps the format and channels intact, but this does not mean the num_output_formats must be 0: The SRC module can support different formats/channels, we just need to check if the output format lists the correct combination of out rate and the input format/channels. Change the logic to prioritize the sink_rate of the module as target rate, then the rate of the FE in case of capture or in case of playback check the single rate specified in the output formats. Signed-off-by: Peter Ujfalusi Reviewed-by: Seppo Ingalsuo Reviewed-by: Bard Liao Reviewed-by: Kai Vehmanen Link: https://patch.msgid.link/20260526105748.26149-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 46 +++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f5623cff0554..c36452622aae 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2628,16 +2628,6 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, if (input_fmt_index < 0) return input_fmt_index; - /* - * For playback, the SRC sink rate will be configured based on the requested output - * format, which is restricted to only deal with DAI's with a single format for now. - */ - if (dir == SNDRV_PCM_STREAM_PLAYBACK && available_fmt->num_output_formats > 1) { - dev_err(sdev->dev, "Invalid number of output formats: %d for SRC %s\n", - available_fmt->num_output_formats, swidget->widget->name); - return -EINVAL; - } - /* * SRC does not perform format conversion, so the output channels and valid bit depth must * be the same as that of the input. @@ -2647,12 +2637,36 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg); out_ref_type = sof_ipc4_fmt_cfg_to_type(in_audio_fmt->fmt_cfg); - /* - * For capture, the SRC module should convert the rate to match the rate requested by the - * PCM hw_params. Set the reference params based on the fe_params unconditionally as it - * will be ignored for playback anyway. - */ - out_ref_rate = params_rate(fe_params); + if (src->data.sink_rate) { + /* Use the sink rate as reference */ + out_ref_rate = src->data.sink_rate; + } else if (dir == SNDRV_PCM_STREAM_CAPTURE) { + /* + * Use the fe rate as reference for capture if the sink rate is + * not set since we need to convert to the rate the PCM device + * is openned with + */ + out_ref_rate = params_rate(fe_params); + } else { + /* + * Otherwise try to guess what the rate should be: + * The output formats must have single rate specified if the + * sink rate is not set for an SRC in playback path. + */ + int i; + + out_audio_fmt = &available_fmt->output_pin_fmts[0].audio_fmt; + out_ref_rate = out_audio_fmt->sampling_frequency; + for (i = 1; i < available_fmt->num_output_formats; i++) { + out_audio_fmt = &available_fmt->output_pin_fmts[i].audio_fmt; + if (out_ref_rate != out_audio_fmt->sampling_frequency) { + dev_err(sdev->dev, + "Cannot determine the output rate for SRC: %s\n", + swidget->widget->name); + return -EINVAL; + } + } + } output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, &src->data.base_config,