ASoC: SOF: ipc4-topology: Update the pipeline_params of prepared modules

If the module in path has been already prepared on a branch type of
topology, where the branching happens downstream:
A1--> A2 ---> B1 --> B2 ... B-branch
          |-> C1 --> C2 ... C-branch

In this case if B-branch is started then A1/A2 is prepared, but when
C-branch starts we still need to refine the parameters up to C1 to arrive
with a correct params to configure C1.

This branching can happen with copiers process modules.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Link: https://patch.msgid.link/20260730121729.18673-4-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Peter Ujfalusi
2026-07-30 15:17:29 +03:00
committed by Mark Brown
parent c599f0f521
commit 94648dc65e
2 changed files with 92 additions and 7 deletions

View File

@@ -2104,10 +2104,57 @@ static void sof_ipc4_host_config(struct snd_sof_dev *sdev, struct snd_sof_widget
}
static int
sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *fe_params,
struct snd_sof_platform_stream_params *platform_params,
struct snd_pcm_hw_params *pipeline_params, int dir)
sof_ipc4_copier_module_update_params(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *pipeline_params)
{
struct snd_soc_component *scomp = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc4_copier_data *copier_data;
struct sof_ipc4_copier *ipc4_copier;
switch (swidget->id) {
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
case snd_soc_dapm_buffer:
ipc4_copier = swidget->private;
copier_data = &ipc4_copier->data;
break;
case snd_soc_dapm_dai_in:
case snd_soc_dapm_dai_out:
{
struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
struct snd_sof_dai *dai;
if (pipeline->use_chain_dma)
return 0;
dai = swidget->private;
ipc4_copier = (struct sof_ipc4_copier *)dai->private;
copier_data = &ipc4_copier->data;
break;
}
default:
dev_err(sdev->dev, "unsupported type %d for copier %s",
swidget->id, swidget->widget->name);
return -EINVAL;
}
/* modify the input params for the next widget */
return sof_ipc4_update_hw_params(sdev, pipeline_params,
&copier_data->out_format,
BIT(SNDRV_PCM_HW_PARAM_FORMAT) |
BIT(SNDRV_PCM_HW_PARAM_CHANNELS) |
BIT(SNDRV_PCM_HW_PARAM_RATE));
}
static int
_sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *fe_params,
struct snd_sof_platform_stream_params *platform_params,
struct snd_pcm_hw_params *pipeline_params, int dir)
{
struct sof_ipc4_available_audio_format *available_fmt;
struct snd_soc_component *scomp = swidget->scomp;
@@ -2579,6 +2626,21 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
return 0;
}
static int
sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *fe_params,
struct snd_sof_platform_stream_params *platform_params,
struct snd_pcm_hw_params *pipeline_params, int dir)
{
if (swidget->prepared)
return sof_ipc4_copier_module_update_params(swidget,
pipeline_params);
return _sof_ipc4_prepare_copier_module(swidget, fe_params,
platform_params, pipeline_params,
dir);
}
static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *fe_params,
struct snd_sof_platform_stream_params *platform_params,
@@ -2592,6 +2654,10 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget,
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
int input_fmt_index, output_fmt_index;
/* This cannot happen */
if (unlikely(swidget->prepared))
return 0;
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
&gain->data.base_config,
pipeline_params,
@@ -2637,6 +2703,10 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
int input_fmt_index, output_fmt_index;
/* Already prepared, nothing to do */
if (swidget->prepared)
return 0;
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
&mixer->base_config,
pipeline_params,
@@ -2683,6 +2753,10 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
u32 out_ref_rate, out_ref_channels, out_ref_valid_bits, out_ref_type;
int output_fmt_index, input_fmt_index;
/* This cannot happen */
if (unlikely(swidget->prepared))
return 0;
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
&src->data.base_config,
pipeline_params,
@@ -2849,6 +2923,18 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
int ret;
if (available_fmt->num_input_formats) {
if (swidget->prepared) {
if (!available_fmt->num_output_formats)
return 0;
/* modify the pipeline params with the output format */
return sof_ipc4_update_hw_params(sdev, pipeline_params,
&process->output_format,
BIT(SNDRV_PCM_HW_PARAM_FORMAT) |
BIT(SNDRV_PCM_HW_PARAM_CHANNELS) |
BIT(SNDRV_PCM_HW_PARAM_RATE));
}
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
&process->base_config,
pipeline_params,

View File

@@ -502,9 +502,8 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
!sof_widget_in_same_direction(swidget, dir))
return 0;
/* skip widgets already prepared or aggregated DAI widgets*/
if (!widget_ops[widget->id].ipc_prepare || swidget->prepared ||
is_aggregated_dai(swidget))
/* skip widgets aggregated DAI widgets */
if (!widget_ops[widget->id].ipc_prepare || is_aggregated_dai(swidget))
goto sink_prepare;
/* prepare the source widget */