diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index a079dd8eb7e1..f3a6e739e800 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1033,10 +1033,37 @@ static int sof_ipc4_init_output_audio_fmt(struct snd_sof_dev *sdev, struct sof_ipc4_available_audio_format *available_fmt, int input_audio_format_index) { + struct sof_ipc4_audio_format *out_fmt; + u32 out_rate, out_channels, out_valid_bits; + bool single_format = true; int i; - /* pick the only available output format */ - if (available_fmt->num_output_formats == 1) + if (!available_fmt->num_output_formats) + return -EINVAL; + + out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt; + out_rate = out_fmt->sampling_frequency; + out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(out_fmt->fmt_cfg); + out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); + + /* check if all output formats in topology are the same */ + for (i = 1; i < available_fmt->num_output_formats; i++) { + u32 _out_rate, _out_channels, _out_valid_bits; + + out_fmt = &available_fmt->output_pin_fmts[i].audio_fmt; + _out_rate = out_fmt->sampling_frequency; + _out_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(out_fmt->fmt_cfg); + _out_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(out_fmt->fmt_cfg); + + if (_out_rate != out_rate || _out_channels != out_channels || + _out_valid_bits != out_valid_bits) { + single_format = false; + break; + } + } + + /* pick the first format if there's only one available or if all formats are the same */ + if (single_format) i = 0; else i = input_audio_format_index; @@ -1522,6 +1549,11 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, &copier_data->base_config, available_fmt, ret); + if (output_fmt_index < 0) { + dev_err(sdev->dev, "No output formats in topology for copier %s", + swidget->widget->name); + return output_fmt_index; + } /* * Set the output format. Current topology defines pin 0 input and output formats in pairs. @@ -1700,7 +1732,11 @@ static int sof_ipc4_prepare_gain_module(struct snd_sof_widget *swidget, if (ret < 0) return ret; - sof_ipc4_init_output_audio_fmt(sdev, &gain->base_config, available_fmt, ret); + ret = sof_ipc4_init_output_audio_fmt(sdev, &gain->base_config, available_fmt, ret); + if (ret < 0) { + dev_err(sdev->dev, "No output formats for %s", swidget->widget->name); + return ret; + } /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &gain->base_config); @@ -1726,7 +1762,11 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget, if (ret < 0) return ret; - sof_ipc4_init_output_audio_fmt(sdev, &mixer->base_config, available_fmt, ret); + ret = sof_ipc4_init_output_audio_fmt(sdev, &mixer->base_config, available_fmt, ret); + if (ret < 0) { + dev_err(sdev->dev, "No output formats for %s", swidget->widget->name); + return ret; + } /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &mixer->base_config); @@ -1753,7 +1793,11 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, if (ret < 0) return ret; - sof_ipc4_init_output_audio_fmt(sdev, &src->base_config, available_fmt, ret); + ret = sof_ipc4_init_output_audio_fmt(sdev, &src->base_config, available_fmt, ret); + if (ret < 0) { + dev_err(sdev->dev, "No output formats for %s", swidget->widget->name); + return ret; + } /* update pipeline memory usage */ sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &src->base_config); @@ -1864,6 +1908,7 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, if (ret < 0) return ret; + /* No need to check the return value. Some processing modules do not have output pins */ output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, &process->base_config, available_fmt, ret);