@@ -125,6 +125,112 @@ static int ssp_context_restore(struct dai *dai)
125125 return 0 ;
126126}
127127
128+ static int ssp_mclk_prepare_enable (struct dai * dai )
129+ {
130+ struct ssp_pdata * ssp = dai_get_drvdata (dai );
131+ struct sof_ipc_dai_config * config = & ssp -> config ;
132+ int ret ;
133+
134+ if (ssp -> clk_active & SSP_CLK_MCLK_ACTIVE )
135+ return 0 ;
136+
137+ /* MCLK config */
138+ ret = mn_set_mclk (config -> ssp .mclk_id , config -> ssp .mclk_rate );
139+ if (ret < 0 )
140+ dai_err (dai , "ssp_mclk_prepare_enable(): invalid mclk_rate = %d for mclk_id = %d" ,
141+ config -> ssp .mclk_rate , config -> ssp .mclk_id );
142+ else
143+ ssp -> clk_active |= SSP_CLK_MCLK_ACTIVE ;
144+
145+ return ret ;
146+ }
147+
148+ static void ssp_mclk_disable_unprepare (struct dai * dai )
149+ {
150+ struct ssp_pdata * ssp = dai_get_drvdata (dai );
151+
152+ if (!(ssp -> clk_active & SSP_CLK_MCLK_ACTIVE ))
153+ return ;
154+
155+ mn_release_mclk (ssp -> config .ssp .mclk_id );
156+
157+ ssp -> clk_active &= ~SSP_CLK_MCLK_ACTIVE ;
158+ }
159+
160+ static int ssp_bclk_prepare_enable (struct dai * dai )
161+ {
162+ struct ssp_pdata * ssp = dai_get_drvdata (dai );
163+ struct sof_ipc_dai_config * config = & ssp -> config ;
164+ uint32_t sscr0 ;
165+ uint32_t mdiv ;
166+ bool need_ecs = false;
167+ int ret = 0 ;
168+
169+ if (ssp -> clk_active & SSP_CLK_BCLK_ACTIVE )
170+ return 0 ;
171+
172+ sscr0 = ssp_read (dai , SSCR0 );
173+
174+ #if CONFIG_INTEL_MN
175+ /* BCLK config */
176+ ret = mn_set_bclk (config -> dai_index , config -> ssp .bclk_rate ,
177+ & mdiv , & need_ecs );
178+ if (ret < 0 ) {
179+ dai_err (dai , "ssp_bclk_prepare_enable(): invalid bclk_rate = %d for dai_index = %d" ,
180+ config -> ssp .bclk_rate , config -> dai_index );
181+ goto out ;
182+ }
183+ #else
184+ if (ssp_freq [SSP_DEFAULT_IDX ].freq % config -> ssp .bclk_rate != 0 ) {
185+ dai_err (dai , "ssp_bclk_prepare_enable(): invalid bclk_rate = %d for dai_index = %d" ,
186+ config -> ssp .bclk_rate , config -> dai_index );
187+ ret = - EINVAL ;
188+ goto out ;
189+ }
190+
191+ mdiv = ssp_freq [SSP_DEFAULT_IDX ].freq / config -> ssp .bclk_rate ;
192+ #endif
193+
194+ if (need_ecs )
195+ sscr0 |= SSCR0_ECS ;
196+
197+ /* clock divisor is SCR + 1 */
198+ mdiv -= 1 ;
199+
200+ /* divisor must be within SCR range */
201+ if (mdiv > (SSCR0_SCR_MASK >> 8 )) {
202+ dai_err (dai , "ssp_bclk_prepare_enable(): divisor %d is not within SCR range" ,
203+ mdiv );
204+ ret = - EINVAL ;
205+ goto out ;
206+ }
207+
208+ /* set the SCR divisor */
209+ sscr0 &= ~SSCR0_SCR_MASK ;
210+ sscr0 |= SSCR0_SCR (mdiv );
211+
212+ ssp_write (dai , SSCR0 , sscr0 );
213+
214+ dai_info (dai , "ssp_bclk_prepare_enable(): sscr0 = 0x%08x" , sscr0 );
215+ out :
216+ if (!ret )
217+ ssp -> clk_active |= SSP_CLK_BCLK_ACTIVE ;
218+
219+ return ret ;
220+ }
221+
222+ static void ssp_bclk_disable_unprepare (struct dai * dai )
223+ {
224+ struct ssp_pdata * ssp = dai_get_drvdata (dai );
225+
226+ if (!(ssp -> clk_active & SSP_CLK_BCLK_ACTIVE ))
227+ return ;
228+ #if CONFIG_INTEL_MN
229+ mn_release_bclk (dai -> index );
230+ #endif
231+ ssp -> clk_active &= ~SSP_CLK_BCLK_ACTIVE ;
232+ }
233+
128234/* Digital Audio interface formatting */
129235static int ssp_set_config (struct dai * dai ,
130236 struct sof_ipc_dai_config * config )
@@ -619,75 +725,21 @@ static int ssp_set_config(struct dai *dai,
619725 */
620726static int ssp_pre_start (struct dai * dai )
621727{
622- struct ssp_pdata * ssp = dai_get_drvdata (dai );
623- struct sof_ipc_dai_config * config = & ssp -> config ;
624- uint32_t sscr0 ;
625- uint32_t mdiv ;
626- bool need_ecs = false;
627-
628- int ret = 0 ;
728+ int ret ;
629729
630730 dai_info (dai , "ssp_pre_start()" );
631731
632- /* SSP active means bclk already configured. */
633- if ( ssp -> state [ SOF_IPC_STREAM_PLAYBACK ] == COMP_STATE_ACTIVE ||
634- ssp -> state [ SOF_IPC_STREAM_CAPTURE ] == COMP_STATE_ACTIVE )
635- return 0 ;
732+ /*
733+ * We will test if mclk/bclk is configured in
734+ * ssp_mclk/bclk_prepare_enable/disable functions
735+ */
636736
637737 /* MCLK config */
638- ret = mn_set_mclk (config -> ssp .mclk_id , config -> ssp .mclk_rate );
639- if (ret < 0 ) {
640- dai_err (dai , "invalid mclk_rate = %d for mclk_id = %d" ,
641- config -> ssp .mclk_rate , config -> ssp .mclk_id );
642- goto out ;
643- }
644-
645- sscr0 = ssp_read (dai , SSCR0 );
738+ ret = ssp_mclk_prepare_enable (dai );
739+ if (ret < 0 )
740+ return ret ;
646741
647- #if CONFIG_INTEL_MN
648- /* BCLK config */
649- ret = mn_set_bclk (config -> dai_index , config -> ssp .bclk_rate ,
650- & mdiv , & need_ecs );
651- if (ret < 0 ) {
652- dai_err (dai , "invalid bclk_rate = %d for dai_index = %d" ,
653- config -> ssp .bclk_rate , config -> dai_index );
654- goto out ;
655- }
656- #else
657- if (ssp_freq [SSP_DEFAULT_IDX ].freq % config -> ssp .bclk_rate != 0 ) {
658- dai_err (dai , "invalid bclk_rate = %d for dai_index = %d" ,
659- config -> ssp .bclk_rate , config -> dai_index );
660- ret = - EINVAL ;
661- goto out ;
662- }
663-
664- mdiv = ssp_freq [SSP_DEFAULT_IDX ].freq / config -> ssp .bclk_rate ;
665- #endif
666-
667- if (need_ecs )
668- sscr0 |= SSCR0_ECS ;
669-
670- /* clock divisor is SCR + 1 */
671- mdiv -= 1 ;
672-
673- /* divisor must be within SCR range */
674- if (mdiv > (SSCR0_SCR_MASK >> 8 )) {
675- dai_err (dai , "ssp_pre_start(): divisor %d is not within SCR range" ,
676- mdiv );
677- ret = - EINVAL ;
678- goto out ;
679- }
680-
681- /* set the SCR divisor */
682- sscr0 &= ~SSCR0_SCR_MASK ;
683- sscr0 |= SSCR0_SCR (mdiv );
684-
685- ssp_write (dai , SSCR0 , sscr0 );
686-
687- dai_info (dai , "ssp_set_config(), sscr0 = 0x%08x" , sscr0 );
688- out :
689-
690- return ret ;
742+ return ssp_bclk_prepare_enable (dai );
691743}
692744
693745/*
@@ -703,10 +755,8 @@ static void ssp_post_stop(struct dai *dai)
703755 if (ssp -> state [SOF_IPC_STREAM_PLAYBACK ] != COMP_STATE_ACTIVE &&
704756 ssp -> state [SOF_IPC_STREAM_CAPTURE ] != COMP_STATE_ACTIVE ) {
705757 dai_info (dai , "releasing BCLK/MCLK clocks for SSP%d..." , dai -> index );
706- #if CONFIG_INTEL_MN
707- mn_release_bclk (dai -> index );
708- #endif
709- mn_release_mclk (ssp -> config .ssp .mclk_id );
758+ ssp_bclk_disable_unprepare (dai );
759+ ssp_mclk_disable_unprepare (dai );
710760 }
711761}
712762
@@ -907,14 +957,10 @@ static int ssp_probe(struct dai *dai)
907957
908958static int ssp_remove (struct dai * dai )
909959{
910- struct ssp_pdata * ssp = dai_get_drvdata (dai );
911-
912960 pm_runtime_put_sync (SSP_CLK , dai -> index );
913961
914- mn_release_mclk (ssp -> config .ssp .mclk_id );
915- #if CONFIG_INTEL_MN
916- mn_release_bclk (dai -> index );
917- #endif
962+ ssp_mclk_disable_unprepare (dai );
963+ ssp_bclk_disable_unprepare (dai );
918964
919965 /* Disable SSP power */
920966 pm_runtime_put_sync (SSP_POW , dai -> index );
0 commit comments