From: Chao Song chao.song@linux.intel.com
The copier output pin 0 format is set with module instance initialization, format for additional copier output pin should be set before the pin is used.
If a process module is connected to additional copier output pin, the copier output pin format should be set according to the corresponding input pin format of the process module.
Signed-off-by: Chao Song chao.song@linux.intel.com Co-developed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Bard Liao yung-chuan.liao@linux.intel.com Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Peter Ujfalusi peter.ujfalusi@linux.intel.com --- sound/soc/sof/ipc4-topology.c | 46 ++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-)
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index efd53e855601..962ec38b70cc 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -166,6 +166,37 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo } }
+static const struct sof_ipc4_audio_format * +sof_ipc4_get_input_pin_audio_fmt(struct snd_sof_widget *swidget, int pin_index) +{ + struct sof_ipc4_base_module_cfg_ext *base_cfg_ext; + struct sof_ipc4_process *process; + int i; + + if (swidget->id != snd_soc_dapm_effect) { + struct sof_ipc4_base_module_cfg *base = swidget->private; + + /* For non-process modules, base module config format is used for all input pins */ + return &base->audio_fmt; + } + + process = swidget->private; + base_cfg_ext = process->base_config_ext; + + /* + * If there are multiple input formats available for a pin, the first available format + * is chosen. + */ + for (i = 0; i < base_cfg_ext->num_input_pin_fmts; i++) { + struct sof_ipc4_pin_format *pin_format = &base_cfg_ext->pin_formats[i]; + + if (pin_format->pin_index == pin_index) + return &pin_format->audio_fmt; + } + + return NULL; +} + /** * sof_ipc4_get_audio_fmt - get available audio formats from swidget->tuples * @scomp: pointer to pointer to SOC component @@ -2049,9 +2080,9 @@ static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev, struct snd_sof_widget *sink_widget, int sink_id) { - struct sof_ipc4_base_module_cfg *sink_config = sink_widget->private; - struct sof_ipc4_base_module_cfg *src_config; struct sof_ipc4_copier_config_set_sink_format format; + struct sof_ipc4_base_module_cfg *src_config; + const struct sof_ipc4_audio_format *pin_fmt; struct sof_ipc4_fw_module *fw_module; struct sof_ipc4_msg msg = {{ 0 }}; u32 header, extension; @@ -2071,7 +2102,16 @@ static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev,
format.sink_id = sink_id; memcpy(&format.source_fmt, &src_config->audio_fmt, sizeof(format.source_fmt)); - memcpy(&format.sink_fmt, &sink_config->audio_fmt, sizeof(format.sink_fmt)); + + pin_fmt = sof_ipc4_get_input_pin_audio_fmt(sink_widget, sink_id); + if (!pin_fmt) { + dev_err(sdev->dev, "Unable to get pin %d format for %s", + sink_id, sink_widget->widget->name); + return -EINVAL; + } + + memcpy(&format.sink_fmt, pin_fmt, sizeof(format.sink_fmt)); + msg.data_size = sizeof(format); msg.data_ptr = &format;