@@ -133,6 +133,8 @@ struct mca_cluster {
133133 struct clk * clk_parent ;
134134 struct dma_chan * dma_chans [SNDRV_PCM_STREAM_LAST + 1 ];
135135
136+ bool clk_provider ;
137+
136138 bool port_clk_started [SNDRV_PCM_STREAM_LAST + 1 ];
137139 int port_clk_driver ; /* The cluster driving this cluster's port */
138140
@@ -256,11 +258,32 @@ static int mca_fe_trigger(struct snd_pcm_substream *substream, int cmd,
256258 return 0 ;
257259}
258260
261+ static int mca_fe_get_port (struct snd_pcm_substream * substream )
262+ {
263+ struct snd_soc_pcm_runtime * fe = snd_soc_substream_to_rtd (substream );
264+ struct snd_soc_pcm_runtime * be ;
265+ struct snd_soc_dpcm * dpcm ;
266+
267+ be = NULL ;
268+ for_each_dpcm_be (fe , substream -> stream , dpcm ) {
269+ be = dpcm -> be ;
270+ break ;
271+ }
272+
273+ if (!be )
274+ return - EINVAL ;
275+
276+ return mca_dai_to_cluster (snd_soc_rtd_to_cpu (be , 0 ))-> no ;
277+ }
278+
259279static int mca_fe_enable_clocks (struct mca_cluster * cl )
260280{
261281 struct mca_data * mca = cl -> host ;
262282 int ret ;
263283
284+ if (!cl -> clk_provider )
285+ return - EINVAL ;
286+
264287 ret = clk_prepare_enable (cl -> clk_parent );
265288 if (ret ) {
266289 dev_err (mca -> dev ,
@@ -334,7 +357,7 @@ static int mca_be_prepare(struct snd_pcm_substream *substream,
334357 int ret ;
335358
336359 if (cl -> port_clk_driver < 0 )
337- return - EINVAL ;
360+ return 0 ;
338361
339362 fe_cl = & mca -> clusters [cl -> port_clk_driver ];
340363
@@ -355,6 +378,44 @@ static int mca_be_prepare(struct snd_pcm_substream *substream,
355378 return 0 ;
356379}
357380
381+ static int mca_fe_prepare (struct snd_pcm_substream * substream ,
382+ struct snd_soc_dai * dai )
383+ {
384+ struct mca_cluster * cl = mca_dai_to_cluster (dai );
385+ struct mca_data * mca = cl -> host ;
386+
387+ if (cl -> clk_provider )
388+ return 0 ;
389+
390+ if (!mca_fe_clocks_in_use (cl )) {
391+ int port = mca_fe_get_port (substream );
392+ writel_relaxed (port + 6 + 1 ,
393+ cl -> base + REG_SYNCGEN_MCLK_SEL );
394+ mca_modify (cl , REG_SYNCGEN_STATUS , SYNCGEN_STATUS_EN ,
395+ SYNCGEN_STATUS_EN );
396+ }
397+ cl -> clocks_in_use [substream -> stream ] = true;
398+
399+ return 0 ;
400+ }
401+
402+ static int mca_fe_hw_free (struct snd_pcm_substream * substream ,
403+ struct snd_soc_dai * dai )
404+ {
405+ struct mca_cluster * cl = mca_dai_to_cluster (dai );
406+
407+ if (cl -> clk_provider )
408+ return 0 ;
409+
410+ cl -> clocks_in_use [substream -> stream ] = false;
411+ if (mca_fe_clocks_in_use (cl ))
412+ return 0 ;
413+
414+ mca_modify (cl , REG_SYNCGEN_STATUS , SYNCGEN_STATUS_EN , 0 );
415+
416+ return 0 ;
417+ }
418+
358419static unsigned int mca_crop_mask (unsigned int mask , int nchans )
359420{
360421 while (hweight32 (mask ) > nchans )
@@ -480,9 +541,18 @@ static int mca_fe_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
480541 u32 serdes_conf = 0 ;
481542 u32 bitstart ;
482543
483- if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK ) !=
484- SND_SOC_DAIFMT_BP_FP )
544+ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK ) {
545+ case SND_SOC_DAIFMT_BP_FP :
546+ cl -> clk_provider = true;
547+ break ;
548+
549+ case SND_SOC_DAIFMT_BC_FC :
550+ cl -> clk_provider = false;
551+ break ;
552+
553+ default :
485554 goto err ;
555+ }
486556
487557 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK ) {
488558 case SND_SOC_DAIFMT_I2S :
@@ -539,24 +609,6 @@ static int mca_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
539609 return 0 ;
540610}
541611
542- static int mca_fe_get_port (struct snd_pcm_substream * substream )
543- {
544- struct snd_soc_pcm_runtime * fe = snd_soc_substream_to_rtd (substream );
545- struct snd_soc_pcm_runtime * be ;
546- struct snd_soc_dpcm * dpcm ;
547-
548- be = NULL ;
549- for_each_dpcm_be (fe , substream -> stream , dpcm ) {
550- be = dpcm -> be ;
551- break ;
552- }
553-
554- if (!be )
555- return - EINVAL ;
556-
557- return mca_dai_to_cluster (snd_soc_rtd_to_cpu (be , 0 ))-> no ;
558- }
559-
560612static int mca_fe_hw_params (struct snd_pcm_substream * substream ,
561613 struct snd_pcm_hw_params * params ,
562614 struct snd_soc_dai * dai )
@@ -681,6 +733,8 @@ static const struct snd_soc_dai_ops mca_fe_ops = {
681733 .set_tdm_slot = mca_fe_set_tdm_slot ,
682734 .hw_params = mca_fe_hw_params ,
683735 .trigger = mca_fe_trigger ,
736+ .prepare = mca_fe_prepare ,
737+ .hw_free = mca_fe_hw_free ,
684738};
685739
686740/*
@@ -734,6 +788,9 @@ static int mca_be_startup(struct snd_pcm_substream *substream,
734788 PORT_ENABLES_TX_DATA );
735789 }
736790
791+ if (!fe_cl -> clk_provider )
792+ return 0 ;
793+
737794 if (mca_be_clk_started (cl )) {
738795 /*
739796 * Port is already started in the other direction.
@@ -763,7 +820,10 @@ static int mca_be_startup(struct snd_pcm_substream *substream,
763820static void mca_be_shutdown (struct snd_pcm_substream * substream ,
764821 struct snd_soc_dai * dai )
765822{
823+ struct snd_soc_pcm_runtime * be = snd_soc_substream_to_rtd (substream );
824+ struct snd_soc_pcm_runtime * fe = mca_be_get_fe (be , substream -> stream );
766825 struct mca_cluster * cl = mca_dai_to_cluster (dai );
826+ struct mca_cluster * fe_cl ;
767827 struct mca_data * mca = cl -> host ;
768828
769829 if (cl -> clocks_in_use [substream -> stream ] &&
@@ -786,11 +846,18 @@ static void mca_be_shutdown(struct snd_pcm_substream *substream,
786846 mca_fe_disable_clocks (fe_cl );
787847 }
788848
849+ if (!fe )
850+ return ;
851+ fe_cl = mca_dai_to_cluster (snd_soc_rtd_to_cpu (fe , 0 ));
852+
789853 if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK ) {
790854 mca_modify (cl , REG_PORT_ENABLES , PORT_ENABLES_TX_DATA , 0 );
791855 writel_relaxed (0 , cl -> base + REG_PORT_DATA_SEL );
792856 }
793857
858+ if (!fe_cl -> clk_provider )
859+ return ;
860+
794861 cl -> port_clk_started [substream -> stream ] = false;
795862 if (!mca_be_clk_started (cl )) {
796863 /*
0 commit comments