From 0ce5e4f55289798c092de17c86e785750f346b02 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 29 Apr 2025 10:22:52 +0300 Subject: [PATCH 1/2] ASoC: SOF: ipc4-topology: Propagate change caused by NHLT data for SSP We need to adjust the params based on the available and picked SSP blob in the similar way we do for DMIC. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/ipc4-topology.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 5a1f3b359f8a12..ea7b1918294292 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1805,6 +1805,12 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai dai_index); if (dev_type < 0) return dev_type; + + if (params_width(params) != bit_depth) { + format_change = true; + dev_dbg(sdev->dev, "SSP sample width change from %d to %d\n", + params_width(params), bit_depth); + } break; default: return 0; From 26f4500d5fdc0dbb35d8aef18f6d0c9decd52981 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 29 Apr 2025 09:38:56 +0300 Subject: [PATCH 2/2] ASoC: SOF: ipc4-topology: Improve playback dai copier in/out format selection The dai copier configuration for playback and capture needs to be separated because it is not correct to configure the dai copier as part of the input format selection for both direction. The input format is the dai format for capture, but it is not for playback, for playback the dai format is on the output side. Currently we configure and adjust the params based on the DAI supported formats when configuring the input side of the copier but right after the format has been adjusted we reset it for playback and loose this information. When using a nocodec passthrough topology (which is a bug) we have SSP blobs supporting 32bit only, copier supporting 16/24/32 bit then on playback the dai and copier will be incorrectly configured: host.copier.in: S16_LE host.copier.out: S16_LE dai.copier.in: S16_LE SSP.blob: S32_LE (we only have S32_LE blobs) dai.copier.out: S16_LE (the dai constraint is ignored) To handle such case the handling of capture and playback streams must be changed: The input format (no changes to previous implementation): for playback it is the pipeline_params for capture it is the adjusted fe_params The output format (no change for capture direction): for playback it is the adjusted fe_params for capture it is the fe_params with this change path format configuration will be correct: host.copier.in: S16_LE host.copier.out: S16_LE dai.copier.in: S16_LE SSP.blob: S32_LE (we only have S32_LE blobs) dai.copier.out: S32_LE Signed-off-by: Peter Ujfalusi --- sound/soc/sof/ipc4-topology.c | 72 +++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index ea7b1918294292..8041aac1d24ad0 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2175,28 +2175,32 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; - /* - * Use the fe_params as a base for the copier configuration. - * The ref_params might get updated to reflect what format is - * supported by the copier on the DAI side. - * - * In case of capture the ref_params returned will be used to - * find the input configuration of the copier. - */ - ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL); - if (!ref_params) - return -ENOMEM; - - ret = sof_ipc4_prepare_dai_copier(sdev, dai, ref_params, dir); - if (ret < 0) - return ret; + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + /* + * For playback the pipeline_params needs to be used to + * find the input configuration of the copier. + */ + ref_params = kmemdup(pipeline_params, sizeof(*ref_params), + GFP_KERNEL); + if (!ref_params) + return -ENOMEM; + } else { + /* + * For capture the adjusted fe_params needs to be used + * to find the input configuration of the copier. + * + * The params might be updated in + * sof_ipc4_prepare_dai_copier() to reflect the supported + * input formats by the copier/dai. + */ + ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL); + if (!ref_params) + return -ENOMEM; - /* - * For playback the pipeline_params needs to be used to find the - * input configuration of the copier. - */ - if (dir == SNDRV_PCM_STREAM_PLAYBACK) - memcpy(ref_params, pipeline_params, sizeof(*ref_params)); + ret = sof_ipc4_prepare_dai_copier(sdev, dai, ref_params, dir); + if (ret < 0) + return ret; + } break; } @@ -2251,15 +2255,33 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, } case snd_soc_dapm_aif_out: case snd_soc_dapm_dai_in: - out_ref_rate = params_rate(fe_params); - out_ref_channels = params_channels(fe_params); - ret = sof_ipc4_get_sample_type(sdev, fe_params); + /* + * For capture the fe_params needs to be used to find the output + * configuration of the copier. + * + * For playback the adjusted fe_params needs to be used + * to find the output configuration of the copier. + * + * The params might be updated in + * sof_ipc4_prepare_dai_copier() to reflect the supported + * output formats by the copier/dai. + */ + memcpy(ref_params, fe_params, sizeof(*ref_params)); + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + ret = sof_ipc4_prepare_dai_copier(sdev, dai, ref_params, dir); + if (ret < 0) + return ret; + } + + out_ref_rate = params_rate(ref_params); + out_ref_channels = params_channels(ref_params); + ret = sof_ipc4_get_sample_type(sdev, ref_params); if (ret < 0) return ret; out_ref_type = (u32)ret; if (!single_output_bitdepth) { - out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params); + out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, ref_params); if (out_ref_valid_bits < 0) return out_ref_valid_bits; }