Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 83 additions & 14 deletions sound/soc/sof/ipc4-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,39 @@ sof_ipc4_get_input_pin_audio_fmt(struct snd_sof_widget *swidget, int pin_index)
return NULL;
}

static void
sof_ipc4_evaluate_params_change(struct sof_ipc4_available_audio_format *available_fmt)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ujfalusi @ranj063 I'm assuming we can inject this params data into the module creation IPC update when its ready ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with what the module creation IPC update does, but this is stored at widget creation time and can be used later when we create the messages.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a question for @ranj063

{
struct sof_ipc4_audio_format *fmt;
u32 in_rate, in_channels, in_valid_bits;
u32 out_rate, out_channels, out_valid_bits;
u32 changed_params = 0;
int i, j;

for (i = 0; i < available_fmt->num_input_formats; i++) {
fmt = &available_fmt->input_pin_fmts[i].audio_fmt;
in_rate = fmt->sampling_frequency;
in_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
in_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);

for (j = 0; j < available_fmt->num_output_formats; j++) {
fmt = &available_fmt->output_pin_fmts[j].audio_fmt;
out_rate = fmt->sampling_frequency;
out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg);
out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg);

if (in_rate != out_rate)
changed_params |= BIT(SNDRV_PCM_HW_PARAM_RATE);
if (in_channels != out_channels)
changed_params |= BIT(SNDRV_PCM_HW_PARAM_CHANNELS);
if (in_valid_bits != out_valid_bits)
changed_params |= BIT(SNDRV_PCM_HW_PARAM_FORMAT);
}
}

available_fmt->changed_params = changed_params;
}

/**
* sof_ipc4_get_audio_fmt - get available audio formats from swidget->tuples
* @scomp: pointer to pointer to SOC component
Expand Down Expand Up @@ -470,6 +503,8 @@ static int sof_ipc4_get_audio_fmt(struct snd_soc_component *scomp,
available_fmt->num_output_formats);
}

sof_ipc4_evaluate_params_change(available_fmt);

return 0;

err_out:
Expand Down Expand Up @@ -632,6 +667,9 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
if (ret)
goto free_copier;

/* Copier can only change format */
available_fmt->changed_params &= BIT(SNDRV_PCM_HW_PARAM_FORMAT);

/*
* This callback is used by host copier and module-to-module copier,
* and only host copier needs to set gtw_cfg.
Expand Down Expand Up @@ -756,6 +794,9 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget)
if (ret)
goto free_copier;

/* Copier can only change format */
available_fmt->changed_params &= BIT(SNDRV_PCM_HW_PARAM_FORMAT);

ret = sof_update_ipc_object(scomp, &node_type,
SOF_COPIER_TOKENS, swidget->tuples,
swidget->num_tuples, sizeof(node_type), 1);
Expand Down Expand Up @@ -2729,23 +2770,53 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
if (available_fmt->num_output_formats) {
struct sof_ipc4_audio_format *in_fmt;
struct sof_ipc4_pin_format *pin_fmt;
u32 out_ref_rate, out_ref_channels;
int out_ref_valid_bits, out_ref_type;
u32 ref_rate, ref_channels;
int ref_valid_bits, ref_type;

/*
* The process module can change parameters and their operation
* depends on the direction:
* Playback: typically they have single output format. This is
* to 'force' the conversion from input to output.
* Use the input format as reference since the single
* format is going to be picked.
* Capture: typically they have multiple output formats to
* convert from dai (input) to FE (output) parameters.
* Use the input format as base and replace the param
* which is changed by the module with the FE parameter
* Reason: we can have module which changes the
* parameters in path, we cannot use the full
* FE param set for the module output lookup.
*/
in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;

out_ref_rate = in_fmt->sampling_frequency;
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg);

ref_rate = in_fmt->sampling_frequency;
ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg);

if (dir == SNDRV_PCM_STREAM_CAPTURE) {
if (available_fmt->changed_params & BIT(SNDRV_PCM_HW_PARAM_RATE))
ref_rate = params_rate(fe_params);
if (available_fmt->changed_params & BIT(SNDRV_PCM_HW_PARAM_CHANNELS))
ref_channels = params_channels(fe_params);
if (available_fmt->changed_params & BIT(SNDRV_PCM_HW_PARAM_FORMAT)) {
ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params);
if (ref_valid_bits < 0)
return ref_valid_bits;

ref_type = sof_ipc4_get_sample_type(sdev, fe_params);
if (ref_type < 0)
return ref_type;
}
}
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
&process->base_config,
available_fmt,
out_ref_rate,
out_ref_channels,
out_ref_valid_bits,
out_ref_type);
ref_rate,
ref_channels,
ref_valid_bits,
ref_type);
if (output_fmt_index < 0)
return output_fmt_index;

Expand All @@ -2759,9 +2830,7 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
/* modify the pipeline params with the output format */
ret = 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));
available_fmt->changed_params);
if (ret)
return ret;
}
Expand Down
3 changes: 3 additions & 0 deletions sound/soc/sof/ipc4-topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,15 @@ struct sof_ipc4_pin_format {
* @input_pin_fmts: Available input pin formats
* @num_input_formats: Number of input pin formats
* @num_output_formats: Number of output pin formats
* @changed_params: Mask of changed params by the module instance between it's
* input and output formts (rate, channels, depth)
*/
struct sof_ipc4_available_audio_format {
struct sof_ipc4_pin_format *output_pin_fmts;
struct sof_ipc4_pin_format *input_pin_fmts;
u32 num_input_formats;
u32 num_output_formats;
u32 changed_params;
};

/**
Expand Down
Loading