]> www.infradead.org Git - users/hch/misc.git/commitdiff
ASoC: SOF: ipc4-pcm: Add fixup for channels
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Fri, 29 Aug 2025 10:53:03 +0000 (13:53 +0300)
committerMark Brown <broonie@kernel.org>
Fri, 29 Aug 2025 11:34:05 +0000 (13:34 +0200)
We can have modules in path which can change the number of channels and in
this case the BE params needs to be adjusted to configure the DAI according
to the copier configuration.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Message-ID: <20250829105305.31818-2-peter.ujfalusi@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc4-pcm.c

index 374dc10d10fd52c261267cae3729b76a479f1297..cb9a06792a47cda3388f289116719eda1fd7889d 100644 (file)
@@ -727,6 +727,58 @@ static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev,
        return 0;
 }
 
+static int sof_ipc4_pcm_dai_link_fixup_channels(struct snd_sof_dev *sdev,
+                                               struct snd_pcm_hw_params *params,
+                                               struct sof_ipc4_copier *ipc4_copier)
+{
+       struct sof_ipc4_pin_format *pin_fmts = ipc4_copier->available_fmt.input_pin_fmts;
+       struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+       int num_input_formats = ipc4_copier->available_fmt.num_input_formats;
+       unsigned int fe_channels = params_channels(params);
+       bool fe_be_match = false;
+       bool single_be_channels = true;
+       unsigned int be_channels, val;
+       int i;
+
+       if (WARN_ON_ONCE(!num_input_formats))
+               return -EINVAL;
+
+       /*
+        * Copier does not change channels, so we
+        * need to only consider the input pin information.
+        */
+       be_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(pin_fmts[0].audio_fmt.fmt_cfg);
+       for (i = 0; i < num_input_formats; i++) {
+               val = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(pin_fmts[i].audio_fmt.fmt_cfg);
+
+               if (val != be_channels)
+                       single_be_channels = false;
+
+               if (val == fe_channels) {
+                       fe_be_match = true;
+                       break;
+               }
+       }
+
+       /*
+        * If channels is different than FE channels, topology must contain a
+        * module which can change the number of channels. But we do require
+        * topology to define a single channels in the DAI copier config in
+        * this case (FE channels may be variable).
+        */
+       if (!fe_be_match) {
+               if (!single_be_channels) {
+                       dev_err(sdev->dev, "Unable to select channels for DAI link\n");
+                       return -EINVAL;
+               }
+
+               channels->min = be_channels;
+               channels->max = be_channels;
+       }
+
+       return 0;
+}
+
 static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
                                       struct snd_pcm_hw_params *params)
 {
@@ -790,6 +842,10 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
        if (ret)
                return ret;
 
+       ret = sof_ipc4_pcm_dai_link_fixup_channels(sdev, params, ipc4_copier);
+       if (ret)
+               return ret;
+
        if (single_bitdepth) {
                snd_mask_none(fmt);
                valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(ipc4_fmt->fmt_cfg);