Skip to content

Commit

Permalink
ASoC: SOF: sof-audio/ipc4-topology: ipc_refine_pipeline_params ops
Browse files Browse the repository at this point in the history
Not the correct way, I'm sure, but nothing comes to mind, yet.

Signed-off-by: Peter Ujfalusi <[email protected]>
  • Loading branch information
ujfalusi committed Jun 10, 2024
1 parent 0810f84 commit 2dfe3e6
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 12 deletions.
104 changes: 97 additions & 7 deletions sound/soc/sof/ipc4-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -2533,6 +2533,91 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
return 0;
}

static int
sof_ipc4_copier_module_refine_params(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *pipeline_params,
int dir)
{
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_src_module_refine_params(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *pipeline_params,
int dir)
{
struct snd_soc_component *scomp = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc4_src *src = swidget->private;
struct sof_ipc4_audio_format fmt = { 0 };

fmt.sampling_frequency = src->data.sink_rate;
/* modify the pipeline params with the output format */
return sof_ipc4_update_hw_params(sdev, pipeline_params, &fmt,
BIT(SNDRV_PCM_HW_PARAM_RATE));
}

static int
sof_ipc4_process_module_refine_params(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *pipeline_params,
int dir)
{
struct snd_soc_component *scomp = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc4_process *process = swidget->private;
struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt;

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));
}

static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
{
struct sof_ipc4_control_data *control_data;
Expand Down Expand Up @@ -3494,23 +3579,28 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY
[snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
aif_token_list, ARRAY_SIZE(aif_token_list),
NULL, sof_ipc4_prepare_copier_module,
sof_ipc4_unprepare_copier_module},
sof_ipc4_unprepare_copier_module,
sof_ipc4_copier_module_refine_params},
[snd_soc_dapm_aif_out] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
aif_token_list, ARRAY_SIZE(aif_token_list),
NULL, sof_ipc4_prepare_copier_module,
sof_ipc4_unprepare_copier_module},
sof_ipc4_unprepare_copier_module,
sof_ipc4_copier_module_refine_params},
[snd_soc_dapm_dai_in] = {sof_ipc4_widget_setup_comp_dai, sof_ipc4_widget_free_comp_dai,
dai_token_list, ARRAY_SIZE(dai_token_list), NULL,
sof_ipc4_prepare_copier_module,
sof_ipc4_unprepare_copier_module},
sof_ipc4_unprepare_copier_module,
sof_ipc4_copier_module_refine_params},
[snd_soc_dapm_dai_out] = {sof_ipc4_widget_setup_comp_dai, sof_ipc4_widget_free_comp_dai,
dai_token_list, ARRAY_SIZE(dai_token_list), NULL,
sof_ipc4_prepare_copier_module,
sof_ipc4_unprepare_copier_module},
sof_ipc4_unprepare_copier_module,
sof_ipc4_copier_module_refine_params},
[snd_soc_dapm_buffer] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
buffer_token_list, ARRAY_SIZE(buffer_token_list),
NULL, sof_ipc4_prepare_copier_module,
sof_ipc4_unprepare_copier_module},
sof_ipc4_unprepare_copier_module,
sof_ipc4_copier_module_refine_params},
[snd_soc_dapm_scheduler] = {sof_ipc4_widget_setup_comp_pipeline,
sof_ipc4_widget_free_comp_pipeline,
pipeline_token_list, ARRAY_SIZE(pipeline_token_list), NULL,
Expand All @@ -3526,12 +3616,12 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY
[snd_soc_dapm_src] = {sof_ipc4_widget_setup_comp_src, sof_ipc4_widget_free_comp_src,
src_token_list, ARRAY_SIZE(src_token_list),
NULL, sof_ipc4_prepare_src_module,
NULL},
NULL, sof_ipc4_src_module_refine_params},
[snd_soc_dapm_effect] = {sof_ipc4_widget_setup_comp_process,
sof_ipc4_widget_free_comp_process,
process_token_list, ARRAY_SIZE(process_token_list),
NULL, sof_ipc4_prepare_process_module,
NULL},
NULL, sof_ipc4_process_module_refine_params},
};

const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
Expand Down
19 changes: 14 additions & 5 deletions sound/soc/sof/sof-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
struct snd_sof_widget *swidget = widget->dobj.private;
const struct sof_ipc_tplg_widget_ops *widget_ops;
struct snd_soc_dapm_path *p;
int ret;
int ret = 0;

if (is_virtual_widget(sdev, widget, __func__))
return 0;
Expand All @@ -458,12 +458,21 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
if (!widget_ops)
return 0;

if (!swidget || !widget_ops[widget->id].ipc_prepare || swidget->prepared)
if (!swidget)
goto sink_prepare;

/* prepare the source widget */
ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params, platform_params,
pipeline_params, dir);
if (!swidget->prepared && widget_ops[widget->id].ipc_prepare) {
/* prepare the source widget */
ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params,
platform_params,
pipeline_params, dir);
} else if (swidget->prepared &&
widget_ops[widget->id].ipc_refine_pipeline_params) {
/* prepare the source widget */
ret = widget_ops[widget->id].ipc_refine_pipeline_params(swidget,
pipeline_params, dir);
}

if (ret < 0) {
dev_err(sdev->dev, "failed to prepare widget %s\n", widget->name);
return ret;
Expand Down
5 changes: 5 additions & 0 deletions sound/soc/sof/sof-audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ struct sof_ipc_tplg_control_ops {
* @bind_event: Function pointer for binding events to the widget
* @ipc_prepare: Optional op for preparing a widget for set up
* @ipc_unprepare: Optional op for unpreparing a widget
* @ipc_refine_pipeline_params: Optional op for updating the pipeline params
* based on the already prepared module's
* configuration
*/
struct sof_ipc_tplg_widget_ops {
int (*ipc_setup)(struct snd_sof_widget *swidget);
Expand All @@ -190,6 +193,8 @@ struct sof_ipc_tplg_widget_ops {
struct snd_sof_platform_stream_params *platform_params,
struct snd_pcm_hw_params *source_params, int dir);
void (*ipc_unprepare)(struct snd_sof_widget *swidget);
int (*ipc_refine_pipeline_params)(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *source_params, int dir);
};

/**
Expand Down

0 comments on commit 2dfe3e6

Please sign in to comment.