@@ -73,6 +73,7 @@ struct cpu_priv {
73
73
* @codec_priv: CODEC private data
74
74
* @cpu_priv: CPU private data
75
75
* @card: ASoC card structure
76
+ * @streams: Mask of current active streams
76
77
* @sample_rate: Current sample rate
77
78
* @sample_format: Current sample format
78
79
* @asrc_rate: ASRC sample rate used by Back-Ends
@@ -89,6 +90,7 @@ struct fsl_asoc_card_priv {
89
90
struct codec_priv codec_priv ;
90
91
struct cpu_priv cpu_priv ;
91
92
struct snd_soc_card card ;
93
+ u8 streams ;
92
94
u32 sample_rate ;
93
95
snd_pcm_format_t sample_format ;
94
96
u32 asrc_rate ;
@@ -151,21 +153,17 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
151
153
struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd (substream );
152
154
struct fsl_asoc_card_priv * priv = snd_soc_card_get_drvdata (rtd -> card );
153
155
bool tx = substream -> stream == SNDRV_PCM_STREAM_PLAYBACK ;
156
+ struct codec_priv * codec_priv = & priv -> codec_priv ;
154
157
struct cpu_priv * cpu_priv = & priv -> cpu_priv ;
155
158
struct device * dev = rtd -> card -> dev ;
159
+ unsigned int pll_out ;
156
160
int ret ;
157
161
158
162
priv -> sample_rate = params_rate (params );
159
163
priv -> sample_format = params_format (params );
164
+ priv -> streams |= BIT (substream -> stream );
160
165
161
- /*
162
- * If codec-dai is DAI Master and all configurations are already in the
163
- * set_bias_level(), bypass the remaining settings in hw_params().
164
- * Note: (dai_fmt & CBM_CFM) includes CBM_CFM and CBM_CFS.
165
- */
166
- if ((priv -> card .set_bias_level &&
167
- priv -> dai_fmt & SND_SOC_DAIFMT_CBM_CFM ) ||
168
- fsl_asoc_card_is_ac97 (priv ))
166
+ if (fsl_asoc_card_is_ac97 (priv ))
169
167
return 0 ;
170
168
171
169
/* Specific configurations of DAIs starts from here */
@@ -174,14 +172,76 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
174
172
cpu_priv -> sysclk_dir [tx ]);
175
173
if (ret && ret != - ENOTSUPP ) {
176
174
dev_err (dev , "failed to set sysclk for cpu dai\n" );
177
- return ret ;
175
+ goto fail ;
178
176
}
179
177
180
178
if (cpu_priv -> slot_width ) {
181
179
ret = snd_soc_dai_set_tdm_slot (asoc_rtd_to_cpu (rtd , 0 ), 0x3 , 0x3 , 2 ,
182
180
cpu_priv -> slot_width );
183
181
if (ret && ret != - ENOTSUPP ) {
184
182
dev_err (dev , "failed to set TDM slot for cpu dai\n" );
183
+ goto fail ;
184
+ }
185
+ }
186
+
187
+ /* Specific configuration for PLL */
188
+ if (codec_priv -> pll_id && codec_priv -> fll_id ) {
189
+ if (priv -> sample_format == SNDRV_PCM_FORMAT_S24_LE )
190
+ pll_out = priv -> sample_rate * 384 ;
191
+ else
192
+ pll_out = priv -> sample_rate * 256 ;
193
+
194
+ ret = snd_soc_dai_set_pll (asoc_rtd_to_codec (rtd , 0 ),
195
+ codec_priv -> pll_id ,
196
+ codec_priv -> mclk_id ,
197
+ codec_priv -> mclk_freq , pll_out );
198
+ if (ret ) {
199
+ dev_err (dev , "failed to start FLL: %d\n" , ret );
200
+ goto fail ;
201
+ }
202
+
203
+ ret = snd_soc_dai_set_sysclk (asoc_rtd_to_codec (rtd , 0 ),
204
+ codec_priv -> fll_id ,
205
+ pll_out , SND_SOC_CLOCK_IN );
206
+
207
+ if (ret && ret != - ENOTSUPP ) {
208
+ dev_err (dev , "failed to set SYSCLK: %d\n" , ret );
209
+ goto fail ;
210
+ }
211
+ }
212
+
213
+ return 0 ;
214
+
215
+ fail :
216
+ priv -> streams &= ~BIT (substream -> stream );
217
+ return ret ;
218
+ }
219
+
220
+ static int fsl_asoc_card_hw_free (struct snd_pcm_substream * substream )
221
+ {
222
+ struct snd_soc_pcm_runtime * rtd = substream -> private_data ;
223
+ struct fsl_asoc_card_priv * priv = snd_soc_card_get_drvdata (rtd -> card );
224
+ struct codec_priv * codec_priv = & priv -> codec_priv ;
225
+ struct device * dev = rtd -> card -> dev ;
226
+ int ret ;
227
+
228
+ priv -> streams &= ~BIT (substream -> stream );
229
+
230
+ if (!priv -> streams && codec_priv -> pll_id && codec_priv -> fll_id ) {
231
+ /* Force freq to be 0 to avoid error message in codec */
232
+ ret = snd_soc_dai_set_sysclk (asoc_rtd_to_codec (rtd , 0 ),
233
+ codec_priv -> mclk_id ,
234
+ 0 ,
235
+ SND_SOC_CLOCK_IN );
236
+ if (ret ) {
237
+ dev_err (dev , "failed to switch away from FLL: %d\n" , ret );
238
+ return ret ;
239
+ }
240
+
241
+ ret = snd_soc_dai_set_pll (asoc_rtd_to_codec (rtd , 0 ),
242
+ codec_priv -> pll_id , 0 , 0 , 0 );
243
+ if (ret && ret != - ENOTSUPP ) {
244
+ dev_err (dev , "failed to stop FLL: %d\n" , ret );
185
245
return ret ;
186
246
}
187
247
}
@@ -191,6 +251,7 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
191
251
192
252
static const struct snd_soc_ops fsl_asoc_card_ops = {
193
253
.hw_params = fsl_asoc_card_hw_params ,
254
+ .hw_free = fsl_asoc_card_hw_free ,
194
255
};
195
256
196
257
static int be_hw_params_fixup (struct snd_soc_pcm_runtime * rtd ,
@@ -254,75 +315,6 @@ static struct snd_soc_dai_link fsl_asoc_card_dai[] = {
254
315
},
255
316
};
256
317
257
- static int fsl_asoc_card_set_bias_level (struct snd_soc_card * card ,
258
- struct snd_soc_dapm_context * dapm ,
259
- enum snd_soc_bias_level level )
260
- {
261
- struct fsl_asoc_card_priv * priv = snd_soc_card_get_drvdata (card );
262
- struct snd_soc_pcm_runtime * rtd ;
263
- struct snd_soc_dai * codec_dai ;
264
- struct codec_priv * codec_priv = & priv -> codec_priv ;
265
- struct device * dev = card -> dev ;
266
- unsigned int pll_out ;
267
- int ret ;
268
-
269
- rtd = snd_soc_get_pcm_runtime (card , & card -> dai_link [0 ]);
270
- codec_dai = asoc_rtd_to_codec (rtd , 0 );
271
- if (dapm -> dev != codec_dai -> dev )
272
- return 0 ;
273
-
274
- switch (level ) {
275
- case SND_SOC_BIAS_PREPARE :
276
- if (dapm -> bias_level != SND_SOC_BIAS_STANDBY )
277
- break ;
278
-
279
- if (priv -> sample_format == SNDRV_PCM_FORMAT_S24_LE )
280
- pll_out = priv -> sample_rate * 384 ;
281
- else
282
- pll_out = priv -> sample_rate * 256 ;
283
-
284
- ret = snd_soc_dai_set_pll (codec_dai , codec_priv -> pll_id ,
285
- codec_priv -> mclk_id ,
286
- codec_priv -> mclk_freq , pll_out );
287
- if (ret ) {
288
- dev_err (dev , "failed to start FLL: %d\n" , ret );
289
- return ret ;
290
- }
291
-
292
- ret = snd_soc_dai_set_sysclk (codec_dai , codec_priv -> fll_id ,
293
- pll_out , SND_SOC_CLOCK_IN );
294
- if (ret && ret != - ENOTSUPP ) {
295
- dev_err (dev , "failed to set SYSCLK: %d\n" , ret );
296
- return ret ;
297
- }
298
- break ;
299
-
300
- case SND_SOC_BIAS_STANDBY :
301
- if (dapm -> bias_level != SND_SOC_BIAS_PREPARE )
302
- break ;
303
-
304
- ret = snd_soc_dai_set_sysclk (codec_dai , codec_priv -> mclk_id ,
305
- codec_priv -> mclk_freq ,
306
- SND_SOC_CLOCK_IN );
307
- if (ret && ret != - ENOTSUPP ) {
308
- dev_err (dev , "failed to switch away from FLL: %d\n" , ret );
309
- return ret ;
310
- }
311
-
312
- ret = snd_soc_dai_set_pll (codec_dai , codec_priv -> pll_id , 0 , 0 , 0 );
313
- if (ret ) {
314
- dev_err (dev , "failed to stop FLL: %d\n" , ret );
315
- return ret ;
316
- }
317
- break ;
318
-
319
- default :
320
- break ;
321
- }
322
-
323
- return 0 ;
324
- }
325
-
326
318
static int fsl_asoc_card_audmux_init (struct device_node * np ,
327
319
struct fsl_asoc_card_priv * priv )
328
320
{
@@ -611,7 +603,6 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
611
603
/* Diversify the card configurations */
612
604
if (of_device_is_compatible (np , "fsl,imx-audio-cs42888" )) {
613
605
codec_dai_name = "cs42888" ;
614
- priv -> card .set_bias_level = NULL ;
615
606
priv -> cpu_priv .sysclk_freq [TX ] = priv -> codec_priv .mclk_freq ;
616
607
priv -> cpu_priv .sysclk_freq [RX ] = priv -> codec_priv .mclk_freq ;
617
608
priv -> cpu_priv .sysclk_dir [TX ] = SND_SOC_CLOCK_OUT ;
@@ -628,26 +619,22 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
628
619
priv -> dai_fmt |= SND_SOC_DAIFMT_CBM_CFM ;
629
620
} else if (of_device_is_compatible (np , "fsl,imx-audio-wm8962" )) {
630
621
codec_dai_name = "wm8962" ;
631
- priv -> card .set_bias_level = fsl_asoc_card_set_bias_level ;
632
622
priv -> codec_priv .mclk_id = WM8962_SYSCLK_MCLK ;
633
623
priv -> codec_priv .fll_id = WM8962_SYSCLK_FLL ;
634
624
priv -> codec_priv .pll_id = WM8962_FLL ;
635
625
priv -> dai_fmt |= SND_SOC_DAIFMT_CBM_CFM ;
636
626
} else if (of_device_is_compatible (np , "fsl,imx-audio-wm8960" )) {
637
627
codec_dai_name = "wm8960-hifi" ;
638
- priv -> card .set_bias_level = fsl_asoc_card_set_bias_level ;
639
628
priv -> codec_priv .fll_id = WM8960_SYSCLK_AUTO ;
640
629
priv -> codec_priv .pll_id = WM8960_SYSCLK_AUTO ;
641
630
priv -> dai_fmt |= SND_SOC_DAIFMT_CBM_CFM ;
642
631
} else if (of_device_is_compatible (np , "fsl,imx-audio-ac97" )) {
643
632
codec_dai_name = "ac97-hifi" ;
644
- priv -> card .set_bias_level = NULL ;
645
633
priv -> dai_fmt = SND_SOC_DAIFMT_AC97 ;
646
634
priv -> card .dapm_routes = audio_map_ac97 ;
647
635
priv -> card .num_dapm_routes = ARRAY_SIZE (audio_map_ac97 );
648
636
} else if (of_device_is_compatible (np , "fsl,imx-audio-mqs" )) {
649
637
codec_dai_name = "fsl-mqs-dai" ;
650
- priv -> card .set_bias_level = NULL ;
651
638
priv -> dai_fmt = SND_SOC_DAIFMT_LEFT_J |
652
639
SND_SOC_DAIFMT_CBS_CFS |
653
640
SND_SOC_DAIFMT_NB_NF ;
@@ -657,7 +644,6 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
657
644
priv -> card .num_dapm_routes = ARRAY_SIZE (audio_map_tx );
658
645
} else if (of_device_is_compatible (np , "fsl,imx-audio-wm8524" )) {
659
646
codec_dai_name = "wm8524-hifi" ;
660
- priv -> card .set_bias_level = NULL ;
661
647
priv -> dai_fmt |= SND_SOC_DAIFMT_CBS_CFS ;
662
648
priv -> dai_link [1 ].dpcm_capture = 0 ;
663
649
priv -> dai_link [2 ].dpcm_capture = 0 ;
0 commit comments