blob: 7938e8c957a2d7f660798075cf4d21a1485664e3 [file] [log] [blame]
Liam Girdwooda00663b2011-01-31 21:23:17 +00001/*
2 * soc-dsp.c -- ALSA SoC Audio DSP
3 *
4 * Copyright (C) 2010 Texas Instruments Inc.
5 *
6 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#define DEBUG
16
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/init.h>
20#include <linux/delay.h>
21#include <linux/pm.h>
22#include <linux/bitops.h>
23#include <linux/debugfs.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26#include <sound/ac97_codec.h>
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h>
32#include <sound/soc-dsp.h>
33
34int soc_pcm_open(struct snd_pcm_substream *);
35void soc_pcm_close(struct snd_pcm_substream *);
36int soc_pcm_hw_params(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
37int soc_pcm_hw_free(struct snd_pcm_substream *);
38int soc_pcm_prepare(struct snd_pcm_substream *);
39int soc_pcm_trigger(struct snd_pcm_substream *, int);
40int soc_pcm_bespoke_trigger(struct snd_pcm_substream *, int);
41
42static int is_be_supported(struct snd_soc_pcm_runtime *rtd, const char *link)
43{
44 struct snd_soc_dsp_link *dsp = rtd->dai_link->dsp_link;
45 int i;
46
47 for (i= 0; i < dsp->num_be; i++) {
48 if(!strcmp(dsp->supported_be[i], link))
49 return 1;
50 }
51 return 0;
52}
53
54static inline int be_connect(struct snd_soc_pcm_runtime *fe,
55 struct snd_soc_pcm_runtime *be, int stream)
56{
57 struct snd_soc_dsp_params *dsp_params;
58
59 /* only add new dsp_paramss */
60 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
61 if (dsp_params->be == be && dsp_params->fe == fe)
62 return 0;
63 }
64
65 dsp_params = kzalloc(sizeof(struct snd_soc_dsp_params), GFP_KERNEL);
66 if (!dsp_params)
67 return -ENOMEM;
68
69 dsp_params->be = be;
70 dsp_params->fe = fe;
71 be->dsp[stream].runtime = fe->dsp[stream].runtime;
72 dsp_params->state = SND_SOC_DSP_LINK_STATE_NEW;
73 list_add(&dsp_params->list_be, &fe->dsp[stream].be_clients);
74 list_add(&dsp_params->list_fe, &be->dsp[stream].fe_clients);
75
76 dev_dbg(&fe->dev, " connected new DSP %s path %s %s %s\n",
77 stream ? "capture" : "playback", fe->dai_link->name,
78 stream ? "<-" : "->", be->dai_link->name);
79
80#ifdef CONFIG_DEBUG_FS
81 dsp_params->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644,
82 fe->debugfs_dsp_root, &dsp_params->state);
83#endif
84
85 return 1;
86}
87
88static inline void be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
89{
90 struct snd_soc_dsp_params *dsp_params, *d;
91
92 list_for_each_entry_safe(dsp_params, d, &fe->dsp[stream].be_clients, list_be) {
93 if (dsp_params->state == SND_SOC_DSP_LINK_STATE_FREE) {
94 dev_dbg(&fe->dev, " freed DSP %s path %s %s %s\n",
95 stream ? "capture" : "playback", fe->dai_link->name,
96 stream ? "<-" : "->", dsp_params->be->dai_link->name);
97
98#ifdef CONFIG_DEBUG_FS
99 debugfs_remove(dsp_params->debugfs_state);
100#endif
101
102 list_del(&dsp_params->list_be);
103 list_del(&dsp_params->list_fe);
104 kfree(dsp_params);
105 }
106 }
107}
108
109/*
110 * Find the corresponding BE DAIs that source or sink audio to this
111 * FE substream.
112 */
113static int dsp_add_new_paths(struct snd_soc_pcm_runtime *fe, int stream,
114 int pending)
115{
116 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
117 struct snd_soc_card *card = fe->card;
118 int i, num, count = 0, err;
119 const char *fe_aif = NULL, *be_aif;
120 enum snd_soc_dapm_type fe_type, be_type;
121
122 dev_dbg(&fe->dev, "scan for new %s %s streams\n", fe->dai_link->name,
123 stream ? "capture" : "playback");
124
125 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
126 fe_type = snd_soc_dapm_aif_in;
127 be_type = snd_soc_dapm_aif_out;
128 } else {
129 fe_type = snd_soc_dapm_aif_out;
130 be_type = snd_soc_dapm_aif_in;
131 }
132
133 /* search card for valid FE AIF that matches our DAI */
134 for (i = 0; i < card->num_links; i++) {
135 struct snd_soc_pcm_runtime *be = &card->rtd[i];
136
137 /* is this a BE DAI link ? */
138 if (be->dai_link->dynamic)
139 continue;
140
141 /* does this DAI have a AIF that matches ours ? */
142 fe_aif = snd_soc_dapm_get_aif(&be->platform->dapm,
143 cpu_dai->driver->name, fe_type);
144 if (fe_aif)
145 break;
146 }
147
148 if (fe_aif == NULL)
149 return 0;
150
151 /* search card for valid BE AIFs */
152 for (i = 0; i < card->num_links; i++) {
153 struct snd_soc_pcm_runtime *be = &card->rtd[i];
154
155 /* is this a BE DAI link ? */
156 if (be->dai_link->dynamic)
157 continue;
158
159 /* BEs must belong to this FE */
160 if (!be->dai_link->no_pcm)
161 continue;
162
163 /* BE must be supported by machine driver */
164 if (!is_be_supported(fe, be->dai_link->name))
165 continue;
166
167 /* get BE AIF */
168 be_aif = snd_soc_dapm_get_aif(&be->platform->dapm,
169 be->dai_link->stream_name, be_type);
170 if (be_aif == NULL)
171 continue;
172
173 /* check for valid dsp_params */
174 num = snd_soc_dapm_query_path(&be->platform->dapm,
175 fe_aif, be_aif, stream);
176
177 dev_dbg(&fe->dev, " scanned %s paths BE %s for stream %s num %d",
178 stream ? "capture" : "playback", be_aif,
179 be->dai_link->stream_name, num);
180
181 /* add backend if we have space */
182 if (num <= 0)
183 continue;
184
185 err = be_connect(fe, be, stream);
186 if (err < 0)
187 break;
188 else if (err == 0)
189 continue;
190
191 be->dsp[stream].runtime_update = pending;
192 count++;
193 }
194
195 /* the number of new paths created */
196 return count;
197}
198
199/*
200 * Find the corresponding BE DAIs that source or sink audio to this
201 * FE substream.
202 */
203static int dsp_prune_old_paths(struct snd_soc_pcm_runtime *fe, int stream,
204 int pending)
205{
206 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
207 struct snd_soc_card *card = fe->card;
208 struct snd_soc_dsp_params *dsp_params;
209 int i, num, count = 0;
210 const char *fe_aif = NULL, *be_aif;
211 enum snd_soc_dapm_type fe_type, be_type;
212
213 dev_dbg(&fe->dev, "scan for old %s %s streams\n", fe->dai_link->name,
214 stream ? "capture" : "playback");
215
216 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
217 fe_type = snd_soc_dapm_aif_in;
218 be_type = snd_soc_dapm_aif_out;
219 } else {
220 fe_type = snd_soc_dapm_aif_out;
221 be_type = snd_soc_dapm_aif_in;
222 }
223
224 /* search card for valid FE AIF that matches our DAI */
225 for (i = 0; i < card->num_links; i++) {
226 struct snd_soc_pcm_runtime *be = &card->rtd[i];
227
228 /* check for frontend */
229 if (be->dai_link->dynamic)
230 continue;
231
232 /* does this DAI have a AIF that matches ours ? */
233 fe_aif = snd_soc_dapm_get_aif(&be->platform->dapm,
234 cpu_dai->driver->name, fe_type);
235 if (fe_aif)
236 break;
237 }
238
239 if (fe_aif == NULL)
240 return 0;
241
242 /* search card for valid BE AIFs */
243 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
244
245 /* get BE AIF */
246 be_aif = snd_soc_dapm_get_aif(&dsp_params->be->platform->dapm,
247 dsp_params->be->dai_link->stream_name, be_type);
248 if (be_aif == NULL) {
249 continue;
250 }
251
252 /* check for valid dsp_params */
253 num = snd_soc_dapm_query_path(&dsp_params->be->platform->dapm,
254 fe_aif, be_aif, stream);
255
256 dev_dbg(&fe->dev, " scanned %s paths BE %s for stream %s num %d",
257 stream ? "capture" : "playback", be_aif,
258 dsp_params->be->dai_link->stream_name, num);
259
260 /* prune backend if no longer used */
261 if (num > 0)
262 continue;
263
264 dsp_params->state = SND_SOC_DSP_LINK_STATE_FREE;
265 dsp_params->be->dsp[stream].runtime_update = pending;
266 count++;
267 }
268
269 /* the number of old paths pruned */
270 return count;
271}
272
273/*
274 * Update the state of all BE's with state old to state new.
275 */
276static void be_state_update(struct snd_soc_pcm_runtime *fe, int stream,
277 enum snd_soc_dsp_link_state old, enum snd_soc_dsp_link_state new)
278{
279 struct snd_soc_dsp_params *dsp_params;
280
281 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
282 if (dsp_params->state == old)
283 dsp_params->state = new;
284 }
285}
286
287/*
288 * Update the state of all BE's to new regardless of current state.
289 */
290static void fe_state_update(struct snd_soc_pcm_runtime *fe, int stream,
291 enum snd_soc_dsp_link_state new)
292{
293 struct snd_soc_dsp_params *dsp_params;
294
295 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be)
296 dsp_params->state = new;
297}
298
299/*
300 * Clear the runtime pending state of all BE's.
301 */
302static void fe_clear_pending(struct snd_soc_pcm_runtime *fe, int stream)
303{
304 struct snd_soc_dsp_params *dsp_params;
305
306 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be)
307 dsp_params->be->dsp[stream].runtime_update = 0;
308}
309
310/* Unwind the BE startup */
311static void soc_dsp_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, int stream)
312{
313 struct snd_soc_dsp_params *dsp_params;
314
315 /* disable any enabled and non active backends */
316 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
317
318 struct snd_pcm_substream *be_substream =
319 snd_soc_dsp_get_substream(dsp_params->be, stream);
320
321 if (--dsp_params->be->dsp[stream].users != 0)
322 continue;
323
324 if (dsp_params->state != SND_SOC_DSP_LINK_STATE_NEW)
325 continue;
326
327 soc_pcm_close(be_substream);
328 be_substream->runtime = NULL;
329 }
330}
331
332/* Startup all new BE */
333static int soc_dsp_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
334{
335 struct snd_soc_dsp_params *dsp_params;
336 int err, count = 0;
337
338 /* only startup BE DAIs that are either sinks or sources to this FE DAI */
339 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
340
341 struct snd_pcm_substream *be_substream =
342 snd_soc_dsp_get_substream(dsp_params->be, stream);
343
344 /* is this op for this BE ? */
345 if (fe->dsp[stream].runtime_update &&
346 !dsp_params->be->dsp[stream].runtime_update)
347 continue;
348
349 /* first time the dsp_params is open ? */
350 if (dsp_params->be->dsp[stream].users++ != 0)
351 continue;
352
353 /* only open and ref count new links */
354 if (dsp_params->state != SND_SOC_DSP_LINK_STATE_NEW)
355 continue;
356
357 dev_dbg(&dsp_params->be->dev, "dsp: open BE %s\n",
358 dsp_params->be->dai_link->name);
359
360 be_substream->runtime = dsp_params->be->dsp[stream].runtime;
361 err = soc_pcm_open(be_substream);
362 if (err < 0)
363 goto unwind;
364 count++;
365 }
366
367 /* update BE state */
368 be_state_update(fe, stream,
369 SND_SOC_DSP_LINK_STATE_NEW, SND_SOC_DSP_LINK_STATE_HW_PARAMS);
370 return count;
371
372unwind:
373 /* disable any enabled and non active backends */
374 list_for_each_entry_continue_reverse(dsp_params, &fe->dsp[stream].be_clients, list_be) {
375
376 struct snd_pcm_substream *be_substream =
377 snd_soc_dsp_get_substream(dsp_params->be, stream);
378
379 if (fe->dsp[stream].runtime_update &&
380 !dsp_params->be->dsp[stream].runtime_update)
381 continue;
382
383 if (--dsp_params->be->dsp[stream].users != 0)
384 continue;
385
386 if (dsp_params->state != SND_SOC_DSP_LINK_STATE_NEW)
387 continue;
388
389 soc_pcm_close(be_substream);
390 be_substream->runtime = NULL;
391 }
392
393 /* update BE state for disconnect */
394 be_state_update(fe, stream,
395 SND_SOC_DSP_LINK_STATE_NEW, SND_SOC_DSP_LINK_STATE_FREE);
396 return err;
397}
398
399void soc_dsp_set_dynamic_runtime(struct snd_pcm_substream *substream)
400{
401 struct snd_pcm_runtime *runtime = substream->runtime;
402 struct snd_soc_pcm_runtime *rtd = substream->private_data;
403 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
404 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
405
406 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
407 runtime->hw.rate_min = cpu_dai_drv->playback.rate_min;
408 runtime->hw.rate_max = cpu_dai_drv->playback.rate_max;
409 runtime->hw.channels_min = cpu_dai_drv->playback.channels_min;
410 runtime->hw.channels_max = cpu_dai_drv->playback.channels_max;
411 runtime->hw.formats &= cpu_dai_drv->playback.formats;
412 runtime->hw.rates = cpu_dai_drv->playback.rates;
413 } else {
414 runtime->hw.rate_min = cpu_dai_drv->capture.rate_min;
415 runtime->hw.rate_max = cpu_dai_drv->capture.rate_max;
416 runtime->hw.channels_min = cpu_dai_drv->capture.channels_min;
417 runtime->hw.channels_max = cpu_dai_drv->capture.channels_max;
418 runtime->hw.formats &= cpu_dai_drv->capture.formats;
419 runtime->hw.rates = cpu_dai_drv->capture.rates;
420 }
421}
422
423static int soc_dsp_fe_dai_startup(struct snd_pcm_substream *fe_substream)
424{
425 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
426 struct snd_pcm_runtime *runtime = fe_substream->runtime;
427 int ret = 0;
428
429 mutex_lock(&fe->card->dsp_mutex);
430
431 ret = soc_dsp_be_dai_startup(fe, fe_substream->stream);
432 if (ret < 0)
433 goto be_err;
434
435 dev_dbg(&fe->dev, "dsp: open FE %s\n", fe->dai_link->name);
436
437 /* start the DAI frontend */
438 ret = soc_pcm_open(fe_substream);
439 if (ret < 0) {
440 dev_err(&fe->dev,"dsp: failed to start FE %d\n", ret);
441 goto unwind;
442 }
443
444 soc_dsp_set_dynamic_runtime(fe_substream);
445 snd_pcm_limit_hw_rates(runtime);
446
447 mutex_unlock(&fe->card->dsp_mutex);
448 return 0;
449
450unwind:
451 soc_dsp_be_dai_startup_unwind(fe, fe_substream->stream);
452be_err:
453 mutex_unlock(&fe->card->dsp_mutex);
454 return ret;
455}
456
457/* BE shutdown - called on DAPM sync updates (i.e. FE is already running)*/
458static int soc_dsp_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
459{
460 struct snd_soc_dsp_params *dsp_params;
461
462 /* only shutdown backends that are either sinks or sources to this frontend DAI */
463 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
464
465 struct snd_pcm_substream *be_substream =
466 snd_soc_dsp_get_substream(dsp_params->be, stream);
467
468 /* is this op for this BE ? */
469 if (fe->dsp[stream].runtime_update &&
470 !dsp_params->be->dsp[stream].runtime_update)
471 continue;
472
473 if (--dsp_params->be->dsp[stream].users != 0)
474 continue;
475
476 if (dsp_params->state != SND_SOC_DSP_LINK_STATE_FREE)
477 continue;
478
479 dev_dbg(&dsp_params->be->dev, "dsp: close BE %s\n",
480 dsp_params->fe->dai_link->name);
481
482 soc_pcm_close(be_substream);
483 be_substream->runtime = NULL;
484 }
485 return 0;
486}
487
488/* FE +BE shutdown - called on FE PCM ops */
489static int soc_dsp_fe_dai_shutdown(struct snd_pcm_substream *substream)
490{
491 struct snd_soc_pcm_runtime *fe = substream->private_data;
492 int stream = substream->stream;
493
494 mutex_lock(&fe->card->dsp_mutex);
495
496 /* shutdown the BEs */
497 soc_dsp_be_dai_shutdown(fe, substream->stream);
498
499 dev_dbg(&fe->dev, "dsp: close FE %s\n", fe->dai_link->name);
500
501 /* now shutdown the frontend */
502 soc_pcm_close(substream);
503
504 /* run the stream event for each BE */
505 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
506 soc_dsp_dapm_stream_event(fe, stream,
507 fe->cpu_dai->driver->playback.stream_name,
508 SND_SOC_DAPM_STREAM_STOP);
509 else
510 soc_dsp_dapm_stream_event(fe, stream,
511 fe->cpu_dai->driver->capture.stream_name,
512 SND_SOC_DAPM_STREAM_STOP);
513
514 mutex_unlock(&fe->card->dsp_mutex);
515 return 0;
516}
517
518static int soc_dsp_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
519{
520 struct snd_soc_dsp_params *dsp_params;
521 int ret;
522
523 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
524
525 struct snd_pcm_substream *be_substream =
526 snd_soc_dsp_get_substream(dsp_params->be, stream);
527
528 /* is this op for this BE ? */
529 if (fe->dsp[stream].runtime_update &&
530 !dsp_params->be->dsp[stream].runtime_update)
531 continue;
532
533 if (dsp_params->state != SND_SOC_DSP_LINK_STATE_HW_PARAMS)
534 continue;
535
536 /* first time the dsp_params is open ? */
537 if (dsp_params->be->dsp[stream].users != 1)
538 continue;
539
540 dev_dbg(&dsp_params->be->dev, "dsp: hw_params BE %s\n",
541 dsp_params->fe->dai_link->name);
542
543 /* copy params for each dsp_params */
544 memcpy(&dsp_params->params, &fe->dsp[stream].params,
545 sizeof(struct snd_pcm_hw_params));
546
547 /* perform any hw_params fixups */
548 if (dsp_params->be->dai_link->be_hw_params_fixup) {
549 ret = dsp_params->be->dai_link->be_hw_params_fixup(dsp_params->be,
550 &dsp_params->params);
551 if (ret < 0) {
552 dev_err(&dsp_params->be->dev,
553 "dsp: hw_params BE fixup failed %d\n", ret);
554 return ret;
555 }
556 }
557
558 ret = soc_pcm_hw_params(be_substream, &dsp_params->params);
559 if (ret < 0) {
560 dev_err(&dsp_params->be->dev, "dsp: hw_params BE failed %d\n", ret);
561 return ret;
562 }
563 }
564 return 0;
565}
566
567int soc_dsp_fe_dai_hw_params(struct snd_pcm_substream *substream,
568 struct snd_pcm_hw_params *params)
569{
570 struct snd_soc_pcm_runtime *fe = substream->private_data;
571 int ret;
572
573 mutex_lock(&fe->card->dsp_mutex);
574
575 memcpy(&fe->dsp[substream->stream].params, params,
576 sizeof(struct snd_pcm_hw_params));
577 ret = soc_dsp_be_dai_hw_params(fe, substream->stream);
578 if (ret < 0)
579 goto out;
580
581 dev_dbg(&fe->dev, "dsp: hw_params FE %s\n", fe->dai_link->name);
582
583 /* call hw_params on the frontend */
584 ret = soc_pcm_hw_params(substream, params);
585 if (ret < 0)
586 dev_err(&fe->dev,"dsp: hw_params FE failed %d\n", ret);
587
588out:
589 mutex_unlock(&fe->card->dsp_mutex);
590 return ret;
591}
592
593static int dsp_do_trigger(struct snd_soc_dsp_params *dsp_params,
594 struct snd_pcm_substream *substream, int cmd)
595{
596 int ret;
597
598 dev_dbg(&dsp_params->be->dev, "dsp: trigger BE %s cmd %d\n",
599 dsp_params->fe->dai_link->name, cmd);
600
601 ret = soc_pcm_trigger(substream, cmd);
602 if (ret < 0)
603 dev_err(&dsp_params->be->dev,"dsp: trigger BE failed %d\n", ret);
604
605 return ret;
606}
607
608int soc_dsp_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd)
609{
610 struct snd_soc_dsp_params *dsp_params;
611 int ret = 0;
612
613 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
614
615 struct snd_pcm_substream *be_substream =
616 snd_soc_dsp_get_substream(dsp_params->be, stream);
617
618 /* is this op for this BE ? */
619 if (fe->dsp[stream].runtime_update &&
620 !dsp_params->be->dsp[stream].runtime_update)
621 continue;
622
623 switch (cmd) {
624 case SNDRV_PCM_TRIGGER_START:
625 /* only start BEs that are not triggered */
626 if (dsp_params->state == SND_SOC_DSP_LINK_STATE_PREPARE) {
627 ret = dsp_do_trigger(dsp_params, be_substream, cmd);
628 if (ret == 0)
629 dsp_params->state = SND_SOC_DSP_LINK_STATE_START;
630 }
631 break;
632 case SNDRV_PCM_TRIGGER_STOP:
633 /* only stop BEs that are being shutdown */
634 if (dsp_params->state == SND_SOC_DSP_LINK_STATE_FREE &&
635 dsp_params->be->dsp[stream].users == 1)
636 ret = dsp_do_trigger(dsp_params, be_substream, cmd);
637 break;
638 case SNDRV_PCM_TRIGGER_SUSPEND:
639 case SNDRV_PCM_TRIGGER_RESUME:
640 /* suspend and resume all BEs */
641 ret = dsp_do_trigger(dsp_params, be_substream, cmd);
642 break;
643 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
644 /* only release Paused BEs */
645 if (dsp_params->state == SND_SOC_DSP_LINK_STATE_PAUSED) {
646 ret = dsp_do_trigger(dsp_params, be_substream, cmd);
647 if (ret == 0)
648 dsp_params->state = SND_SOC_DSP_LINK_STATE_START;
649 }
650 break;
651 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
652 /* only pause active BEs */
653 if (dsp_params->state == SND_SOC_DSP_LINK_STATE_START) {
654 ret = dsp_do_trigger(dsp_params, be_substream, cmd);
655 if (ret == 0)
656 dsp_params->state = SND_SOC_DSP_LINK_STATE_PAUSED;
657 }
658 break;
659 }
660 if (ret < 0)
661 return ret;
662 }
663
664 return ret;
665}
666EXPORT_SYMBOL_GPL(soc_dsp_be_dai_trigger);
667
668int soc_dsp_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
669{
670 struct snd_soc_pcm_runtime *fe = substream->private_data;
671 struct snd_soc_dsp_link *dsp_link = fe->dai_link->dsp_link;
672 int stream = substream->stream, ret;
673
674 switch (dsp_link->trigger[stream]) {
675 case SND_SOC_DSP_TRIGGER_PRE:
676 /* call trigger on the frontend before the backend. */
677
678 dev_dbg(&fe->dev, "dsp: pre trigger FE %s cmd %d\n",
679 fe->dai_link->name, cmd);
680
681 ret = soc_pcm_trigger(substream, cmd);
682 if (ret < 0) {
683 dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
684 return ret;
685 }
686
687 ret = soc_dsp_be_dai_trigger(fe, substream->stream, cmd);
688 break;
689 case SND_SOC_DSP_TRIGGER_POST:
690 /* call trigger on the frontend after the backend. */
691
692 ret = soc_dsp_be_dai_trigger(fe, substream->stream, cmd);
693 if (ret < 0) {
694 dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
695 return ret;
696 }
697
698 dev_dbg(&fe->dev, "dsp: post trigger FE %s cmd %d\n",
699 fe->dai_link->name, cmd);
700
701 ret = soc_pcm_trigger(substream, cmd);
702 break;
703 case SND_SOC_DSP_TRIGGER_BESPOKE:
704 /* bespoke trigger() - handles both FE and BEs */
705
706 dev_dbg(&fe->dev, "dsp: bespoke trigger FE %s cmd %d\n",
707 fe->dai_link->name, cmd);
708
709 ret = soc_pcm_bespoke_trigger(substream, cmd);
710 if (ret < 0) {
711 dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
712 return ret;
713 }
714 break;
715 default:
716 dev_err(&fe->dev, "dsp: invalid trigger cmd %d for %s\n", cmd,
717 fe->dai_link->name);
718 return -EINVAL;
719 }
720
721 return ret;
722}
723
724static int soc_dsp_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
725{
726 struct snd_soc_dsp_params *dsp_params;
727 int ret = 0;
728
729 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
730
731 struct snd_pcm_substream *be_substream =
732 snd_soc_dsp_get_substream(dsp_params->be, stream);
733
734 /* is this op for this BE ? */
735 if (fe->dsp[stream].runtime_update &&
736 !dsp_params->be->dsp[stream].runtime_update)
737 continue;
738
739 /* only prepare ACTIVE or READY BE's */
740 if (dsp_params->state == SND_SOC_DSP_LINK_STATE_NEW ||
741 dsp_params->state == SND_SOC_DSP_LINK_STATE_FREE)
742 continue;
743
744 dev_dbg(&dsp_params->be->dev, "dsp: prepare BE %s\n",
745 dsp_params->fe->dai_link->name);
746
747 ret = soc_pcm_prepare(be_substream);
748 if (ret < 0) {
749 dev_err(&dsp_params->be->dev,"dsp: backend prepare failed %d\n",
750 ret);
751 break;
752 }
753
754 /* mark the BE as active */
755 be_state_update(fe, stream, SND_SOC_DSP_LINK_STATE_HW_PARAMS,
756 SND_SOC_DSP_LINK_STATE_PREPARE);
757 }
758 return ret;
759}
760
761int soc_dsp_fe_dai_prepare(struct snd_pcm_substream *substream)
762{
763 struct snd_soc_pcm_runtime *fe = substream->private_data;
764 int stream = substream->stream, ret = 0;
765
766 mutex_lock(&fe->card->dsp_mutex);
767
768 dev_dbg(&fe->dev, "dsp: prepare FE %s\n", fe->dai_link->name);
769
770 /* there is no point preparing this FE if there are no BEs */
771 if (list_empty(&fe->dsp[stream].be_clients)) {
772 dev_err(&fe->dev, "dsp: no backend DAIs enabled for %s\n",
773 fe->dai_link->name);
774 ret = -EINVAL;
775 goto out;
776 }
777
778 ret = soc_dsp_be_dai_prepare(fe, substream->stream);
779 if (ret < 0)
780 goto out;
781
782 /* mark the BE as active */
783 fe_state_update(fe, stream, SND_SOC_DSP_LINK_STATE_PREPARE);
784
785 /* call prepare on the frontend */
786 ret = soc_pcm_prepare(substream);
787 if (ret < 0) {
788 dev_err(&fe->dev,"dsp: prepare FE %s failed\n", fe->dai_link->name);
789 goto out;
790 }
791
792 /* run the stream event for each BE */
793 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
794 soc_dsp_dapm_stream_event(fe, stream,
795 fe->cpu_dai->driver->playback.stream_name,
796 SNDRV_PCM_TRIGGER_START);
797 else
798 soc_dsp_dapm_stream_event(fe, stream,
799 fe->cpu_dai->driver->capture.stream_name,
800 SNDRV_PCM_TRIGGER_START);
801
802out:
803 mutex_unlock(&fe->card->dsp_mutex);
804 return ret;
805}
806
807static int soc_dsp_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
808{
809 struct snd_soc_dsp_params *dsp_params;
810
811 /* only hw_params backends that are either sinks or sources
812 * to this frontend DAI */
813 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
814
815 struct snd_pcm_substream *be_substream =
816 snd_soc_dsp_get_substream(dsp_params->be, stream);
817
818 /* is this op for this BE ? */
819 if (fe->dsp[stream].runtime_update &&
820 !dsp_params->be->dsp[stream].runtime_update)
821 continue;
822
823 if (dsp_params->state != SND_SOC_DSP_LINK_STATE_FREE)
824 continue;
825
826 /* only free hw when no longer used */
827 if (dsp_params->be->dsp[stream].users != 1)
828 continue;
829
830 dev_dbg(&dsp_params->be->dev, "dsp: hw_free BE %s\n",
831 dsp_params->fe->dai_link->name);
832
833 soc_pcm_hw_free(be_substream);
834 }
835
836 return 0;
837}
838
839int soc_dsp_fe_dai_hw_free(struct snd_pcm_substream *substream)
840{
841 struct snd_soc_pcm_runtime *fe = substream->private_data;
842 int ret, stream = substream->stream;
843
844 mutex_lock(&fe->card->dsp_mutex);
845
846 fe_state_update(fe, stream, SND_SOC_DSP_LINK_STATE_FREE);
847
848 dev_dbg(&fe->dev, "dsp: hw_free FE %s\n", fe->dai_link->name);
849
850 /* call hw_free on the frontend */
851 ret = soc_pcm_hw_free(substream);
852 if (ret < 0)
853 dev_err(&fe->dev,"dsp: hw_free FE %s failed\n", fe->dai_link->name);
854
855 /* only hw_params backends that are either sinks or sources
856 * to this frontend DAI */
857 ret = soc_dsp_be_dai_hw_free(fe, stream);
858
859 mutex_unlock(&fe->card->dsp_mutex);
860 return ret;
861}
862
863/*
864 * FE stream event, send event to all active BEs.
865 */
866int soc_dsp_dapm_stream_event(struct snd_soc_pcm_runtime *fe,
867 int dir, const char *stream, int event)
868{
869 struct snd_soc_dsp_params *dsp_params;
870
871 /* resume for playback */
872 list_for_each_entry(dsp_params, &fe->dsp[dir].be_clients, list_be) {
873
874 struct snd_soc_pcm_runtime *be = dsp_params->be;
875
876 dev_dbg(&be->dev, "pm: BE %s stream %s event %d dir %d\n",
877 be->dai_link->name, stream, event, dir);
878
879 snd_soc_dapm_stream_event(be, stream, event);
880 }
881
882 return 0;
883}
884
885static int dsp_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
886{
887 struct snd_soc_dsp_link *dsp_link = fe->dai_link->dsp_link;
888 struct snd_pcm_substream *substream = snd_soc_dsp_get_substream(fe, stream);
889 struct snd_soc_dsp_params *dsp_params;
890 int ret;
891
892 dev_dbg(&fe->dev, "runtime %s close on FE %s\n",
893 stream ? "capture" : "playback", fe->dai_link->name);
894
895 if (dsp_link->trigger[stream] == SND_SOC_DSP_TRIGGER_BESPOKE) {
896 /* call bespoke trigger - FE takes care of all BE triggers */
897 dev_dbg(&fe->dev, "dsp: bespoke trigger FE %s cmd stop\n",
898 fe->dai_link->name);
899
900 ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
901 if (ret < 0) {
902 dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
903 return ret;
904 }
905 } else {
906
907 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
908
909 dev_dbg(&fe->dev, "dsp: trigger FE %s cmd stop\n",
910 fe->dai_link->name);
911
912 ret = soc_dsp_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
913 if (ret < 0)
914 return ret;
915 }
916 }
917
918 ret = soc_dsp_be_dai_hw_free(fe, stream);
919 if (ret < 0)
920 return ret;
921
922 ret = soc_dsp_be_dai_shutdown(fe, stream);
923 if (ret < 0)
924 return ret;
925
926 /* run the stream event for each BE */
927 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
928 soc_dsp_dapm_stream_event(fe, stream,
929 fe->cpu_dai->driver->playback.stream_name,
930 SNDRV_PCM_TRIGGER_STOP);
931 else
932 soc_dsp_dapm_stream_event(fe, stream,
933 fe->cpu_dai->driver->capture.stream_name,
934 SNDRV_PCM_TRIGGER_STOP);
935
936 return 0;
937}
938
939/* check for running FEs */
940static int dsp_get_be_trigger_cmd(struct snd_soc_pcm_runtime *fe, int stream)
941{
942 struct snd_soc_dsp_params *dsp_be_params, *dsp_fe_params;
943
944 /* get the FEs for each BE */
945 list_for_each_entry(dsp_be_params, &fe->dsp[stream].be_clients, list_be) {
946 struct snd_soc_pcm_runtime *be = dsp_be_params->be;
947
948 /* get the FEs for this BE */
949 list_for_each_entry(dsp_fe_params, &be->dsp[stream].fe_clients, list_fe) {
950
951 if (dsp_fe_params->state == SND_SOC_DSP_LINK_STATE_START)
952 return SND_SOC_DSP_LINK_STATE_START;
953 }
954 }
955 return SND_SOC_DSP_LINK_STATE_PAUSED;
956}
957
958/* check for running BEs */
959static int dsp_get_fe_trigger_cmd(struct snd_soc_pcm_runtime *fe, int stream)
960{
961 struct snd_soc_dsp_params *dsp_be_params;
962
963 /* get the FEs for each BE */
964 list_for_each_entry(dsp_be_params, &fe->dsp[stream].be_clients, list_be) {
965
966 if (dsp_be_params->state == SND_SOC_DSP_LINK_STATE_START)
967 return SND_SOC_DSP_LINK_STATE_START;
968 }
969 return SND_SOC_DSP_LINK_STATE_PAUSED;
970}
971
972static int dsp_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
973{
974 struct snd_soc_dsp_link *dsp_link = fe->dai_link->dsp_link;
975 struct snd_pcm_substream *substream = snd_soc_dsp_get_substream(fe, stream);
976 struct snd_soc_dsp_params *dsp_params;
977 int ret, cmd;
978
979 dev_dbg(&fe->dev, "runtime %s open on FE %s\n",
980 stream ? "capture" : "playback", fe->dai_link->name);
981
982 ret = soc_dsp_be_dai_startup(fe, stream);
983 if (ret < 0)
984 return ret;
985
986 ret = soc_dsp_be_dai_hw_params(fe, stream);
987 if (ret < 0)
988 return ret;
989
990 ret = soc_dsp_be_dai_prepare(fe, stream);
991 if (ret < 0)
992 return ret;
993
994 /* run the stream event for each BE */
995 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
996 soc_dsp_dapm_stream_event(fe, stream,
997 fe->cpu_dai->driver->playback.stream_name,
998 SNDRV_PCM_TRIGGER_START);
999 else
1000 soc_dsp_dapm_stream_event(fe, stream,
1001 fe->cpu_dai->driver->capture.stream_name,
1002 SNDRV_PCM_TRIGGER_START);
1003
1004 if (dsp_link->trigger[stream] == SND_SOC_DSP_TRIGGER_BESPOKE) {
1005
1006 /* there is no point in triggering START iff all BEs are PAUSED */
1007 cmd = dsp_get_fe_trigger_cmd(fe, stream);
1008
1009 /* call trigger on the frontend - FE takes care of all BE triggers */
1010 dev_dbg(&fe->dev, "dsp: bespoke trigger FE %s cmd start\n",
1011 fe->dai_link->name);
1012
1013 ret = soc_pcm_bespoke_trigger(substream, cmd);
1014 if (ret < 0) {
1015 dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret);
1016 return ret;
1017 }
1018
1019 /* successful trigger so update BE trigger status */
1020 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
1021
1022 /* is this op for this BE ? */
1023 if (fe->dsp[stream].runtime_update &&
1024 !dsp_params->be->dsp[stream].runtime_update)
1025 continue;
1026
1027 switch (cmd) {
1028 case SNDRV_PCM_TRIGGER_START:
1029 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1030 case SNDRV_PCM_TRIGGER_RESUME:
1031 dsp_params->state = SND_SOC_DSP_LINK_STATE_START;
1032 break;
1033 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1034 case SNDRV_PCM_TRIGGER_STOP:
1035 case SNDRV_PCM_TRIGGER_SUSPEND:
1036 dsp_params->state = SND_SOC_DSP_LINK_STATE_PAUSED;
1037 break;
1038 }
1039 }
1040 } else {
1041
1042 list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
1043
1044 /* there is no point in triggering start iff all FEs are PAUSED */
1045 cmd = dsp_get_be_trigger_cmd(fe, stream);
1046
1047 dev_dbg(&fe->dev, "dsp: trigger FE %s cmd start\n",
1048 fe->dai_link->name);
1049
1050 ret = soc_dsp_be_dai_trigger(fe, stream, cmd);
1051 if (ret < 0)
1052 return ret;
1053 }
1054 }
1055
1056 return 0;
1057}
1058
1059static int dsp_run_update(struct snd_soc_pcm_runtime *fe, int stream,
1060 int start, int stop)
1061{
1062 int ret = 0;
1063
1064 fe->dsp[stream].runtime_update = 1;
1065
1066 /* startup any new BEs */
1067 if (start) {
1068 ret = dsp_run_update_startup(fe, stream);
1069 if (ret < 0)
1070 dev_err(&fe->dev, "failed to startup BEs\n");
1071 }
1072
1073 /* close down old BEs */
1074 if (stop) {
1075 ret = dsp_run_update_shutdown(fe, stream);
1076 if (ret < 0)
1077 dev_err(&fe->dev, "failed to shutdown BEs\n");
1078 }
1079
1080 fe->dsp[stream].runtime_update = 0;
1081
1082 return ret;
1083}
1084
1085/* called when any mixer updates change FE -> BE the stream */
1086int soc_dsp_runtime_update(struct snd_soc_dapm_widget *widget)
1087{
1088 struct snd_soc_card *card;
1089 int i, ret = 0, start, stop;
1090
1091 if (widget->codec)
1092 card = widget->codec->card;
1093 else if (widget->platform)
1094 card = widget->platform->card;
1095 else
1096 return -EINVAL;
1097
1098 mutex_lock(&widget->dapm->card->dsp_mutex);
1099
1100 for (i = 0; i < card->num_rtd; i++) {
1101 struct snd_soc_pcm_runtime *fe = &card->rtd[i];
1102
1103 /* make sure link is BE */
1104 if (!fe->dai_link->dsp_link)
1105 continue;
1106
1107 /* only check active links */
1108 if (!fe->cpu_dai->active) {
1109 continue;
1110 }
1111
1112 /* DAPM sync will call this to update DSP paths */
1113 dev_dbg(card->dev, "DSP runtime update for FE %s\n", fe->dai_link->name);
1114
1115 /* update any playback paths */
1116 start = dsp_add_new_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, 1);
1117 stop = dsp_prune_old_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, 1);
1118 if (!(start || stop))
1119 goto capture;
1120
1121 /* run PCM ops on new/old playback paths */
1122 ret = dsp_run_update(fe, SNDRV_PCM_STREAM_PLAYBACK, start, stop);
1123 if (ret < 0) {
1124 dev_err(&fe->dev, "failed to update playback FE stream %s\n",
1125 fe->dai_link->stream_name);
1126 }
1127
1128 /* free old playback links */
1129 be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
1130 fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
1131
1132capture:
1133 /* update any capture paths */
1134 start = dsp_add_new_paths(fe, SNDRV_PCM_STREAM_CAPTURE, 1);
1135 stop = dsp_prune_old_paths(fe, SNDRV_PCM_STREAM_CAPTURE, 1);
1136 if (!(start || stop))
1137 continue;
1138
1139 /* run PCM ops on new/old capture paths */
1140 ret = dsp_run_update(fe, SNDRV_PCM_STREAM_CAPTURE, start, stop);
1141 if (ret < 0) {
1142 dev_err(&fe->dev, "failed to update capture FE stream %s\n",
1143 fe->dai_link->stream_name);
1144 }
1145
1146 /* free old capture links */
1147 be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
1148 fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
1149 }
1150
1151 mutex_unlock(&widget->dapm->card->dsp_mutex);
1152 return ret;
1153}
1154
1155int soc_dsp_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
1156{
1157 struct snd_soc_dsp_params *dsp_params;
1158
1159 list_for_each_entry(dsp_params,
1160 &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
1161
1162 struct snd_soc_pcm_runtime *be = dsp_params->be;
1163 struct snd_soc_dai *dai = be->codec_dai;
1164 struct snd_soc_dai_driver *drv = dai->driver;
1165
1166 dev_dbg(&be->dev, "BE digital mute %s\n", be->dai_link->name);
1167
1168 if (be->dai_link->ignore_suspend)
1169 continue;
1170
1171 if (drv->ops->digital_mute && dai->playback_active)
1172 drv->ops->digital_mute(dai, mute);
1173 }
1174
1175 return 0;
1176}
1177
1178int soc_dsp_be_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
1179{
1180 struct snd_soc_dsp_params *dsp_params;
1181
1182 /* suspend for playback */
1183 list_for_each_entry(dsp_params,
1184 &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
1185
1186 struct snd_soc_pcm_runtime *be = dsp_params->be;
1187 struct snd_soc_dai *dai = be->cpu_dai;
1188 struct snd_soc_dai_driver *drv = dai->driver;
1189
1190 dev_dbg(&be->dev, "pm: BE CPU DAI playback suspend %s\n",
1191 be->dai_link->name);
1192
1193 if (be->dai_link->ignore_suspend)
1194 continue;
1195
1196 if (drv->suspend && !drv->ac97_control)
1197 drv->suspend(dai);
1198 }
1199
1200 /* suspend for capture */
1201 list_for_each_entry(dsp_params,
1202 &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
1203
1204 struct snd_soc_pcm_runtime *be = dsp_params->be;
1205 struct snd_soc_dai *dai = be->cpu_dai;
1206 struct snd_soc_dai_driver *drv = dai->driver;
1207
1208 dev_dbg(&be->dev, "pm: BE CPU DAI capture suspend %s\n",
1209 be->dai_link->name);
1210
1211 if (be->dai_link->ignore_suspend)
1212 continue;
1213
1214 if (drv->suspend && !drv->ac97_control)
1215 drv->suspend(dai);
1216 }
1217
1218 return 0;
1219}
1220
1221int soc_dsp_be_ac97_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
1222{
1223 struct snd_soc_dsp_params *dsp_params;
1224
1225 /* suspend for playback */
1226 list_for_each_entry(dsp_params,
1227 &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
1228
1229 struct snd_soc_pcm_runtime *be = dsp_params->be;
1230 struct snd_soc_dai *dai = be->cpu_dai;
1231 struct snd_soc_dai_driver *drv = dai->driver;
1232
1233 dev_dbg(&be->dev, "pm: BE CPU DAI playback suspend %s\n",
1234 be->dai_link->name);
1235
1236 if (be->dai_link->ignore_suspend)
1237 continue;
1238
1239 if (drv->suspend && drv->ac97_control)
1240 drv->suspend(dai);
1241 }
1242
1243 /* suspend for capture */
1244 list_for_each_entry(dsp_params,
1245 &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
1246
1247 struct snd_soc_pcm_runtime *be = dsp_params->be;
1248 struct snd_soc_dai *dai = be->cpu_dai;
1249 struct snd_soc_dai_driver *drv = dai->driver;
1250
1251 dev_dbg(&be->dev, "pm: BE CPU DAI capture suspend %s\n",
1252 be->dai_link->name);
1253
1254 if (be->dai_link->ignore_suspend)
1255 continue;
1256
1257 if (drv->suspend && drv->ac97_control)
1258 drv->suspend(dai);
1259 }
1260
1261 return 0;
1262}
1263
1264int soc_dsp_be_platform_suspend(struct snd_soc_pcm_runtime *fe)
1265{
1266 struct snd_soc_dsp_params *dsp_params;
1267
1268 /* suspend for playback */
1269 list_for_each_entry(dsp_params,
1270 &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
1271
1272 struct snd_soc_pcm_runtime *be = dsp_params->be;
1273 struct snd_soc_platform *platform = be->platform;
1274 struct snd_soc_platform_driver *drv = platform->driver;
1275 struct snd_soc_dai *dai = be->cpu_dai;
1276
1277 dev_dbg(&be->dev, "pm: BE platform playback suspend %s\n",
1278 be->dai_link->name);
1279
1280 if (be->dai_link->ignore_suspend)
1281 continue;
1282
1283 if (drv->suspend && !platform->suspended) {
1284 drv->suspend(dai);
1285 platform->suspended = 1;
1286 }
1287 }
1288
1289 /* suspend for capture */
1290 list_for_each_entry(dsp_params,
1291 &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
1292
1293 struct snd_soc_pcm_runtime *be = dsp_params->be;
1294 struct snd_soc_platform *platform = be->platform;
1295 struct snd_soc_platform_driver *drv = platform->driver;
1296 struct snd_soc_dai *dai = be->cpu_dai;
1297
1298 dev_dbg(&be->dev, "pm: BE platform capture suspend %s\n",
1299 be->dai_link->name);
1300
1301 if (be->dai_link->ignore_suspend)
1302 continue;
1303
1304 if (drv->suspend && !platform->suspended) {
1305 drv->suspend(dai);
1306 platform->suspended = 1;
1307 }
1308 }
1309
1310 return 0;
1311}
1312
1313int soc_dsp_be_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
1314{
1315 struct snd_soc_dsp_params *dsp_params;
1316
1317 /* resume for playback */
1318 list_for_each_entry(dsp_params,
1319 &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
1320
1321 struct snd_soc_pcm_runtime *be = dsp_params->be;
1322 struct snd_soc_dai *dai = be->cpu_dai;
1323 struct snd_soc_dai_driver *drv = dai->driver;
1324
1325 dev_dbg(&be->dev, "pm: BE CPU DAI playback resume %s\n",
1326 be->dai_link->name);
1327
1328 if (be->dai_link->ignore_suspend)
1329 continue;
1330
1331 if (drv->resume && !drv->ac97_control)
1332 drv->resume(dai);
1333 }
1334
1335 /* suspend for capture */
1336 list_for_each_entry(dsp_params,
1337 &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
1338
1339 struct snd_soc_pcm_runtime *be = dsp_params->be;
1340 struct snd_soc_dai *dai = be->cpu_dai;
1341 struct snd_soc_dai_driver *drv = dai->driver;
1342
1343 dev_dbg(&be->dev, "pm: BE CPU DAI capture resume %s\n",
1344 be->dai_link->name);
1345
1346 if (be->dai_link->ignore_suspend)
1347 continue;
1348
1349 if (drv->resume && !drv->ac97_control)
1350 drv->resume(dai);
1351 }
1352
1353 return 0;
1354}
1355
1356int soc_dsp_be_ac97_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
1357{
1358 struct snd_soc_dsp_params *dsp_params;
1359
1360 /* resume for playback */
1361 list_for_each_entry(dsp_params,
1362 &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
1363
1364 struct snd_soc_pcm_runtime *be = dsp_params->be;
1365 struct snd_soc_dai *dai = be->cpu_dai;
1366 struct snd_soc_dai_driver *drv = dai->driver;
1367
1368 dev_dbg(&be->dev, "pm: BE CPU DAI playback resume %s\n",
1369 be->dai_link->name);
1370
1371 if (be->dai_link->ignore_suspend)
1372 continue;
1373
1374 if (drv->resume && drv->ac97_control)
1375 drv->resume(dai);
1376 }
1377
1378 /* suspend for capture */
1379 list_for_each_entry(dsp_params,
1380 &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
1381
1382 struct snd_soc_pcm_runtime *be = dsp_params->be;
1383 struct snd_soc_dai *dai = be->cpu_dai;
1384 struct snd_soc_dai_driver *drv = dai->driver;
1385
1386 dev_dbg(&be->dev, "pm: BE CPU DAI capture resume %s\n",
1387 be->dai_link->name);
1388
1389 if (be->dai_link->ignore_suspend)
1390 continue;
1391
1392 if (drv->resume && drv->ac97_control)
1393 drv->resume(dai);
1394 }
1395
1396 return 0;
1397}
1398
1399int soc_dsp_be_platform_resume(struct snd_soc_pcm_runtime *fe)
1400{
1401 struct snd_soc_dsp_params *dsp_params;
1402
1403 /* resume for playback */
1404 list_for_each_entry(dsp_params,
1405 &fe->dsp[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
1406
1407 struct snd_soc_pcm_runtime *be = dsp_params->be;
1408 struct snd_soc_platform *platform = be->platform;
1409 struct snd_soc_platform_driver *drv = platform->driver;
1410 struct snd_soc_dai *dai = be->cpu_dai;
1411
1412 dev_dbg(&be->dev, "pm: BE platform playback resume %s\n",
1413 be->dai_link->name);
1414
1415 if (be->dai_link->ignore_suspend)
1416 continue;
1417
1418 if (drv->resume && platform->suspended) {
1419 drv->resume(dai);
1420 platform->suspended = 0;
1421 }
1422 }
1423
1424 /* resume for capture */
1425 list_for_each_entry(dsp_params,
1426 &fe->dsp[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
1427
1428 struct snd_soc_pcm_runtime *be = dsp_params->be;
1429 struct snd_soc_platform *platform = be->platform;
1430 struct snd_soc_platform_driver *drv = platform->driver;
1431 struct snd_soc_dai *dai = be->cpu_dai;
1432
1433 dev_dbg(&be->dev, "pm: BE platform capture resume %s\n",
1434 be->dai_link->name);
1435
1436 if (be->dai_link->ignore_suspend)
1437 continue;
1438
1439 if (drv->resume && platform->suspended) {
1440 drv->resume(dai);
1441 platform->suspended = 0;
1442 }
1443 }
1444
1445 return 0;
1446}
1447
1448/* called when opening FE stream */
1449int soc_dsp_fe_dai_open(struct snd_pcm_substream *fe_substream)
1450{
1451 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1452 int err;
1453
1454 fe->dsp[fe_substream->stream].runtime = fe_substream->runtime;
1455
1456 /* calculate valid and active FE <-> BE dsp_paramss */
1457 err = dsp_add_new_paths(fe, fe_substream->stream, 0);
1458 if (err <= 0) {
1459 dev_warn(&fe->dev, "asoc: %s no valid %s route from source to sink\n",
1460 fe->dai_link->name, fe_substream->stream ? "capture" : "playback");
1461 }
1462
1463 return soc_dsp_fe_dai_startup(fe_substream);
1464}
1465
1466/* called when closing FE stream */
1467int soc_dsp_fe_dai_close(struct snd_pcm_substream *fe_substream)
1468{
1469 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1470 int ret;
1471
1472 ret = soc_dsp_fe_dai_shutdown(fe_substream);
1473
1474 be_disconnect(fe, fe_substream->stream);
1475
1476 return ret;
1477}
1478
1479#ifdef CONFIG_DEBUG_FS
1480int soc_dsp_debugfs_add(struct snd_soc_pcm_runtime *rtd)
1481{
1482 rtd->debugfs_dsp_root = debugfs_create_dir(rtd->dai_link->name,
1483 rtd->card->debugfs_card_root);
1484 if (!rtd->debugfs_dsp_root) {
1485 dev_dbg(&rtd->dev,
1486 "ASoC: Failed to create dsp debugfs directory %s\n",
1487 rtd->dai_link->name);
1488 return -EINVAL;
1489 }
1490
1491 return 0;
1492}
1493#endif
1494
1495/* Module information */
1496MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1497MODULE_DESCRIPTION("ALSA SoC DSP Core");
1498MODULE_LICENSE("GPL");