@@ -727,6 +727,58 @@ static int sof_ipc4_pcm_dai_link_fixup_rate(struct snd_sof_dev *sdev,
727727 return 0 ;
728728}
729729
730+ static int sof_ipc4_pcm_dai_link_fixup_channels (struct snd_sof_dev * sdev ,
731+ struct snd_pcm_hw_params * params ,
732+ struct sof_ipc4_copier * ipc4_copier )
733+ {
734+ struct sof_ipc4_pin_format * pin_fmts = ipc4_copier -> available_fmt .input_pin_fmts ;
735+ struct snd_interval * channels = hw_param_interval (params , SNDRV_PCM_HW_PARAM_CHANNELS );
736+ int num_input_formats = ipc4_copier -> available_fmt .num_input_formats ;
737+ unsigned int fe_channels = params_channels (params );
738+ bool fe_be_match = false;
739+ bool single_be_channels = true;
740+ unsigned int be_channels , val ;
741+ int i ;
742+
743+ if (WARN_ON_ONCE (!num_input_formats ))
744+ return - EINVAL ;
745+
746+ /*
747+ * Copier does not change channels, so we
748+ * need to only consider the input pin information.
749+ */
750+ be_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT (pin_fmts [0 ].audio_fmt .fmt_cfg );
751+ for (i = 0 ; i < num_input_formats ; i ++ ) {
752+ val = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT (pin_fmts [i ].audio_fmt .fmt_cfg );
753+
754+ if (val != be_channels )
755+ single_be_channels = false;
756+
757+ if (val == fe_channels ) {
758+ fe_be_match = true;
759+ break ;
760+ }
761+ }
762+
763+ /*
764+ * If channels is different than FE channels, topology must contain a
765+ * module which can change the number of channels. But we do require
766+ * topology to define a single channels in the DAI copier config in
767+ * this case (FE channels may be variable).
768+ */
769+ if (!fe_be_match ) {
770+ if (!single_be_channels ) {
771+ dev_err (sdev -> dev , "Unable to select channels for DAI link\n" );
772+ return - EINVAL ;
773+ }
774+
775+ channels -> min = be_channels ;
776+ channels -> max = be_channels ;
777+ }
778+
779+ return 0 ;
780+ }
781+
730782static int sof_ipc4_pcm_dai_link_fixup (struct snd_soc_pcm_runtime * rtd ,
731783 struct snd_pcm_hw_params * params )
732784{
@@ -790,6 +842,10 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
790842 if (ret )
791843 return ret ;
792844
845+ ret = sof_ipc4_pcm_dai_link_fixup_channels (sdev , params , ipc4_copier );
846+ if (ret )
847+ return ret ;
848+
793849 if (single_bitdepth ) {
794850 snd_mask_none (fmt );
795851 valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH (ipc4_fmt -> fmt_cfg );
0 commit comments