From ccad2baaaf2b7be6d2a289179312a5da4f6537d4 Mon Sep 17 00:00:00 2001 From: Wojciech Jablonski Date: Thu, 21 May 2026 17:04:00 +0200 Subject: [PATCH] audio: asrc: fix runtime params validation IPC4 params do not provide a PCM sampling rate that is dynamically selected based on the mode (PULL/PUSH). Instead, the received params contain only a copy of the source rate already stored in ipc4_asrc_module_cfg. As a result, mode-dependent validation can trigger a bogus error. Fix this by splitting params validation into IPC protocol-specific functions. Signed-off-by: Wojciech Jablonski --- src/audio/asrc/asrc.c | 49 +++++--------------------------------- src/audio/asrc/asrc.h | 1 + src/audio/asrc/asrc_ipc3.c | 28 ++++++++++++++++++++++ src/audio/asrc/asrc_ipc4.c | 12 ++++++++++ 4 files changed, 47 insertions(+), 43 deletions(-) diff --git a/src/audio/asrc/asrc.c b/src/audio/asrc/asrc.c index e9c9e6e736d4..b070d3b1c251 100644 --- a/src/audio/asrc/asrc.c +++ b/src/audio/asrc/asrc.c @@ -336,47 +336,6 @@ static int asrc_set_config(struct processing_module *mod, uint32_t config_id, return -EINVAL; } -static int asrc_verify_params(struct processing_module *mod, - struct sof_ipc_stream_params *params) -{ - struct comp_data *cd = module_get_private_data(mod); - struct comp_dev *dev = mod->dev; - int ret; - - comp_dbg(dev, "entry"); - - /* check whether params->rate (received from driver) are equal - * to asrc->source_rate (PLAYBACK) or asrc->sink_rate (CAPTURE) set - * during creating src component in asrc_new(). - * src->source/sink_rate = 0 means that source/sink rate can vary. - */ - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { - if (asrc_get_source_rate(&cd->ipc_config) && - params->rate != asrc_get_source_rate(&cd->ipc_config)) { - comp_err(dev, "runtime stream pcm rate %u does not match rate %u fetched from ipc.", - params->rate, asrc_get_source_rate(&cd->ipc_config)); - return -EINVAL; - } - } else { - if (asrc_get_sink_rate(&cd->ipc_config) && - params->rate != asrc_get_sink_rate(&cd->ipc_config)) { - comp_err(dev, "runtime stream pcm rate %u does not match rate %u fetched from ipc.", - params->rate, asrc_get_sink_rate(&cd->ipc_config)); - return -EINVAL; - } - } - - /* update downstream (playback) or upstream (capture) buffer parameters - */ - ret = comp_verify_params(dev, BUFF_PARAMS_RATE, params); - if (ret < 0) { - comp_err(dev, "comp_verify_params() failed."); - return ret; - } - - return 0; -} - /* set component audio stream parameters */ static int asrc_params(struct processing_module *mod) { @@ -390,9 +349,13 @@ static int asrc_params(struct processing_module *mod) asrc_set_stream_params(cd, pcm_params); - err = asrc_verify_params(mod, pcm_params); + err = asrc_verify_stream_params(mod, pcm_params); + if (err < 0) + return -EINVAL; + + err = comp_verify_params(dev, BUFF_PARAMS_RATE, pcm_params); if (err < 0) { - comp_err(dev, "pcm params verification failed."); + comp_err(dev, "comp_verify_params() failed."); return -EINVAL; } diff --git a/src/audio/asrc/asrc.h b/src/audio/asrc/asrc.h index 1c86a2cf757e..4d7a902a0c9d 100644 --- a/src/audio/asrc/asrc.h +++ b/src/audio/asrc/asrc.h @@ -124,6 +124,7 @@ int asrc_dai_start_timestamp(struct comp_data *cd); int asrc_dai_stop_timestamp(struct comp_data *cd); void asrc_update_buffer_format(struct comp_buffer *buf_c, struct comp_data *cd); void asrc_set_stream_params(struct comp_data *cd, struct sof_ipc_stream_params *params); +int asrc_verify_stream_params(struct processing_module *mod, struct sof_ipc_stream_params *params); extern struct tr_ctx asrc_tr; /* Different UUID names for different build configurations... */ diff --git a/src/audio/asrc/asrc_ipc3.c b/src/audio/asrc/asrc_ipc3.c index ca917318d7e5..68a1a9297bfa 100644 --- a/src/audio/asrc/asrc_ipc3.c +++ b/src/audio/asrc/asrc_ipc3.c @@ -63,3 +63,31 @@ void asrc_set_stream_params(struct comp_data *cd, struct sof_ipc_stream_params * { /* IPC3 don't need to update audio stream format here. */ } + +int asrc_verify_stream_params(struct processing_module *mod, struct sof_ipc_stream_params *params) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + /* PCM sampling rate received in params is dynamically selected based on the mode + * (PULL/PUSH). Need to validate it against the initial fixed ASRC configuration + * src->source/sink_rate = 0 means that source/sink rate can vary. + */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + if (asrc_get_source_rate(&cd->ipc_config) && + params->rate != asrc_get_source_rate(&cd->ipc_config)) { + comp_err(dev, "runtime stream pcm rate %u does not match rate %u fetched from ipc.", + params->rate, asrc_get_source_rate(&cd->ipc_config)); + return -EINVAL; + } + } else { + if (asrc_get_sink_rate(&cd->ipc_config) && + params->rate != asrc_get_sink_rate(&cd->ipc_config)) { + comp_err(dev, "runtime stream pcm rate %u does not match rate %u fetched from ipc.", + params->rate, asrc_get_sink_rate(&cd->ipc_config)); + return -EINVAL; + } + } + + return 0; +} diff --git a/src/audio/asrc/asrc_ipc4.c b/src/audio/asrc/asrc_ipc4.c index 1047799f207b..039f8cfe7b78 100644 --- a/src/audio/asrc/asrc_ipc4.c +++ b/src/audio/asrc/asrc_ipc4.c @@ -75,3 +75,15 @@ void asrc_set_stream_params(struct comp_data *cd, struct sof_ipc_stream_params * { ipc4_base_module_cfg_to_stream_params(&cd->ipc_config.base, params); } + +int asrc_verify_stream_params(struct processing_module *mod, struct sof_ipc_stream_params *params) +{ + /* IPC4 params contain the same fixed sampling rate that is already stored in + * ipc4_asrc_module_cfg, rather than a PCM sampling rate that is dynamically selected + * based on the mode (PULL/PUSH) as in IPC3. For now leave the function empty. + */ + ARG_UNUSED(mod); + ARG_UNUSED(params); + + return 0; +}