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