blob: 519f325c291acf8d3e42fe69e924a1594b05759e [file] [log] [blame]
Liam Girdwoodddee6272011-06-09 14:45:53 +01001/*
2 * soc-pcm.c -- ALSA SoC PCM
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd.
6 * Copyright (C) 2010 Slimlogic Ltd.
7 * Copyright (C) 2010 Texas Instruments Inc.
8 *
9 * Authors: Liam Girdwood <lrg@ti.com>
10 * Mark Brown <broonie@opensource.wolfsonmicro.com>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 */
18
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/delay.h>
Mark Brownd6652ef2011-12-03 20:14:31 +000022#include <linux/pm_runtime.h>
Liam Girdwoodddee6272011-06-09 14:45:53 +010023#include <linux/slab.h>
24#include <linux/workqueue.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070025#include <linux/debugfs.h>
26#include <linux/dma-mapping.h>
27#include <linux/export.h>
Liam Girdwoodddee6272011-06-09 14:45:53 +010028#include <sound/core.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/soc.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070032#include <sound/soc-dpcm.h>
Liam Girdwoodddee6272011-06-09 14:45:53 +010033#include <sound/initval.h>
34
Steve Mucklef132c6c2012-06-06 18:30:57 -070035#define MAX_BE_USERS 8 /* adjust if too low for everday use */
36
37static int soc_dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
38
39/* ASoC no host IO hardware.
40 * TODO: fine tune these values for all host less transfers.
41 */
42static const struct snd_pcm_hardware no_host_hardware = {
43 .info = SNDRV_PCM_INFO_MMAP |
44 SNDRV_PCM_INFO_MMAP_VALID |
45 SNDRV_PCM_INFO_INTERLEAVED |
46 SNDRV_PCM_INFO_PAUSE |
47 SNDRV_PCM_INFO_RESUME,
48 .formats = SNDRV_PCM_FMTBIT_S16_LE |
49 SNDRV_PCM_FMTBIT_S32_LE,
50 .period_bytes_min = PAGE_SIZE >> 2,
51 .period_bytes_max = PAGE_SIZE >> 1,
52 .periods_min = 2,
53 .periods_max = 4,
54 .buffer_bytes_max = PAGE_SIZE,
55};
56
57/*
58 * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE
59 * are not running, paused or suspended for the specified stream direction.
60 */
61int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
62 struct snd_soc_pcm_runtime *be, int stream)
63{
64 struct snd_soc_dpcm_params *dpcm_params;
65
66 list_for_each_entry(dpcm_params, &be->dpcm[stream].fe_clients, list_fe) {
67
68 if (dpcm_params->fe == fe)
69 continue;
70
71 if (dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_START ||
72 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PAUSED ||
73 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_SUSPEND)
74 return 0;
75 }
76 return 1;
77}
78EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop);
79
80/*
81 * We can only change hw params a BE DAI if any of it's FE are not prepared,
82 * running, paused or suspended for the specified stream direction.
83 */
84static int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
85 struct snd_soc_pcm_runtime *be, int stream)
86{
87 struct snd_soc_dpcm_params *dpcm_params;
88
89 list_for_each_entry(dpcm_params, &be->dpcm[stream].fe_clients, list_fe) {
90
91 if (dpcm_params->fe == fe)
92 continue;
93
94 if (dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_START ||
95 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PAUSED ||
96 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_SUSPEND ||
97 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE)
98 return 0;
99 }
100 return 1;
101}
102
Dong Aisheng17841022011-08-29 17:15:14 +0800103static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
104 struct snd_soc_dai *soc_dai)
Liam Girdwoodddee6272011-06-09 14:45:53 +0100105{
106 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Liam Girdwoodddee6272011-06-09 14:45:53 +0100107 int ret;
108
Dong Aisheng17841022011-08-29 17:15:14 +0800109 if (!soc_dai->driver->symmetric_rates &&
Liam Girdwoodddee6272011-06-09 14:45:53 +0100110 !rtd->dai_link->symmetric_rates)
111 return 0;
112
113 /* This can happen if multiple streams are starting simultaneously -
114 * the second can need to get its constraints before the first has
115 * picked a rate. Complain and allow the application to carry on.
116 */
Dong Aisheng17841022011-08-29 17:15:14 +0800117 if (!soc_dai->rate) {
118 dev_warn(soc_dai->dev,
Liam Girdwoodddee6272011-06-09 14:45:53 +0100119 "Not enforcing symmetric_rates due to race\n");
120 return 0;
121 }
122
Dong Aisheng17841022011-08-29 17:15:14 +0800123 dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100124
125 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
126 SNDRV_PCM_HW_PARAM_RATE,
Dong Aisheng17841022011-08-29 17:15:14 +0800127 soc_dai->rate, soc_dai->rate);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100128 if (ret < 0) {
Dong Aisheng17841022011-08-29 17:15:14 +0800129 dev_err(soc_dai->dev,
Liam Girdwoodddee6272011-06-09 14:45:53 +0100130 "Unable to apply rate symmetry constraint: %d\n", ret);
131 return ret;
132 }
133
134 return 0;
135}
136
137/*
Mark Brown58ba9b22012-01-16 18:38:51 +0000138 * List of sample sizes that might go over the bus for parameter
139 * application. There ought to be a wildcard sample size for things
140 * like the DAC/ADC resolution to use but there isn't right now.
141 */
142static int sample_sizes[] = {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700143 8, 16, 24, 32,
Mark Brown58ba9b22012-01-16 18:38:51 +0000144};
145
146static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
147 struct snd_soc_dai *dai)
148{
149 int ret, i, bits;
150
151 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
152 bits = dai->driver->playback.sig_bits;
153 else
154 bits = dai->driver->capture.sig_bits;
155
156 if (!bits)
157 return;
158
159 for (i = 0; i < ARRAY_SIZE(sample_sizes); i++) {
Mark Brown278047f2012-01-19 18:04:18 +0000160 if (bits >= sample_sizes[i])
161 continue;
162
163 ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0,
164 sample_sizes[i], bits);
Mark Brown58ba9b22012-01-16 18:38:51 +0000165 if (ret != 0)
166 dev_warn(dai->dev,
167 "Failed to set MSB %d/%d: %d\n",
168 bits, sample_sizes[i], ret);
169 }
170}
171
172/*
Steve Mucklef132c6c2012-06-06 18:30:57 -0700173 * stream event, send event to FE and all active BEs.
174 */
175int soc_dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe,
176 int dir, const char *stream, int event)
177{
178 struct snd_soc_dpcm_params *dpcm_params;
179
180 snd_soc_dapm_rtd_stream_event(fe, dir, event);
181
182 list_for_each_entry(dpcm_params, &fe->dpcm[dir].be_clients, list_be) {
183
184 struct snd_soc_pcm_runtime *be = dpcm_params->be;
185
186 dev_dbg(be->dev, "pm: BE %s stream %s event %d dir %d\n",
187 be->dai_link->name, stream, event, dir);
188
189 snd_soc_dapm_rtd_stream_event(be, dir, event);
190 }
191
192 return 0;
193}
194
195/*
Liam Girdwoodddee6272011-06-09 14:45:53 +0100196 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
197 * then initialized and any private data can be allocated. This also calls
198 * startup for the cpu DAI, platform, machine and codec DAI.
199 */
200static int soc_pcm_open(struct snd_pcm_substream *substream)
201{
202 struct snd_soc_pcm_runtime *rtd = substream->private_data;
203 struct snd_pcm_runtime *runtime = substream->runtime;
204 struct snd_soc_platform *platform = rtd->platform;
205 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
206 struct snd_soc_dai *codec_dai = rtd->codec_dai;
207 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
208 struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
209 int ret = 0;
210
Mark Brownd6652ef2011-12-03 20:14:31 +0000211 pm_runtime_get_sync(cpu_dai->dev);
212 pm_runtime_get_sync(codec_dai->dev);
213 pm_runtime_get_sync(platform->dev);
214
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100215 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100216
Steve Mucklef132c6c2012-06-06 18:30:57 -0700217 if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
218 snd_soc_set_runtime_hwparams(substream, &no_host_hardware);
219
Liam Girdwoodddee6272011-06-09 14:45:53 +0100220 /* startup the audio subsystem */
221 if (cpu_dai->driver->ops->startup) {
222 ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
223 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700224 printk(KERN_ERR "asoc: can't open interface %s\n",
225 cpu_dai->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100226 goto out;
227 }
228 }
229
230 if (platform->driver->ops && platform->driver->ops->open) {
231 ret = platform->driver->ops->open(substream);
232 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700233 printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100234 goto platform_err;
235 }
236 }
237
238 if (codec_dai->driver->ops->startup) {
Helen Zeng5749b092012-06-10 11:50:29 -0700239 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
240 ret = codec_dai->driver->ops->startup(substream,
241 codec_dai);
242 if (ret < 0) {
243 printk(KERN_ERR "asoc: can't open codec %s\n",
244 codec_dai->name);
245 goto codec_dai_err;
246 }
247 } else {
248 if (!codec_dai->capture_active) {
249 ret = codec_dai->driver->ops->startup(substream,
250 codec_dai);
251 if (ret < 0) {
252 printk(KERN_ERR "can't open codec %s\n",
253 codec_dai->name);
254 goto codec_dai_err;
255 }
256 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100257 }
258 }
259
260 if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
261 ret = rtd->dai_link->ops->startup(substream);
262 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700263 printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100264 goto machine_err;
265 }
266 }
267
Steve Mucklef132c6c2012-06-06 18:30:57 -0700268 /* DSP DAI links compat checks are different */
269 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm)
270 goto dynamic;
271
Liam Girdwoodddee6272011-06-09 14:45:53 +0100272 /* Check that the codec and cpu DAIs are compatible */
273 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
274 runtime->hw.rate_min =
275 max(codec_dai_drv->playback.rate_min,
276 cpu_dai_drv->playback.rate_min);
277 runtime->hw.rate_max =
278 min(codec_dai_drv->playback.rate_max,
279 cpu_dai_drv->playback.rate_max);
280 runtime->hw.channels_min =
281 max(codec_dai_drv->playback.channels_min,
282 cpu_dai_drv->playback.channels_min);
283 runtime->hw.channels_max =
284 min(codec_dai_drv->playback.channels_max,
285 cpu_dai_drv->playback.channels_max);
286 runtime->hw.formats =
287 codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
288 runtime->hw.rates =
289 codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
290 if (codec_dai_drv->playback.rates
291 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
292 runtime->hw.rates |= cpu_dai_drv->playback.rates;
293 if (cpu_dai_drv->playback.rates
294 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
295 runtime->hw.rates |= codec_dai_drv->playback.rates;
296 } else {
297 runtime->hw.rate_min =
298 max(codec_dai_drv->capture.rate_min,
299 cpu_dai_drv->capture.rate_min);
300 runtime->hw.rate_max =
301 min(codec_dai_drv->capture.rate_max,
302 cpu_dai_drv->capture.rate_max);
303 runtime->hw.channels_min =
304 max(codec_dai_drv->capture.channels_min,
305 cpu_dai_drv->capture.channels_min);
306 runtime->hw.channels_max =
307 min(codec_dai_drv->capture.channels_max,
308 cpu_dai_drv->capture.channels_max);
309 runtime->hw.formats =
310 codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
311 runtime->hw.rates =
312 codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
313 if (codec_dai_drv->capture.rates
314 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
315 runtime->hw.rates |= cpu_dai_drv->capture.rates;
316 if (cpu_dai_drv->capture.rates
317 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
318 runtime->hw.rates |= codec_dai_drv->capture.rates;
319 }
320
321 ret = -EINVAL;
322 snd_pcm_limit_hw_rates(runtime);
323 if (!runtime->hw.rates) {
324 printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
325 codec_dai->name, cpu_dai->name);
326 goto config_err;
327 }
328 if (!runtime->hw.formats) {
329 printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
330 codec_dai->name, cpu_dai->name);
331 goto config_err;
332 }
333 if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
334 runtime->hw.channels_min > runtime->hw.channels_max) {
335 printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
336 codec_dai->name, cpu_dai->name);
337 goto config_err;
338 }
339
Mark Brown58ba9b22012-01-16 18:38:51 +0000340 soc_pcm_apply_msb(substream, codec_dai);
341 soc_pcm_apply_msb(substream, cpu_dai);
342
Liam Girdwoodddee6272011-06-09 14:45:53 +0100343 /* Symmetry only applies if we've already got an active stream. */
Dong Aisheng17841022011-08-29 17:15:14 +0800344 if (cpu_dai->active) {
345 ret = soc_pcm_apply_symmetry(substream, cpu_dai);
346 if (ret != 0)
347 goto config_err;
348 }
349
350 if (codec_dai->active) {
351 ret = soc_pcm_apply_symmetry(substream, codec_dai);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100352 if (ret != 0)
353 goto config_err;
354 }
355
356 pr_debug("asoc: %s <-> %s info:\n",
357 codec_dai->name, cpu_dai->name);
358 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
359 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
360 runtime->hw.channels_max);
361 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
362 runtime->hw.rate_max);
363
Steve Mucklef132c6c2012-06-06 18:30:57 -0700364dynamic:
Liam Girdwoodddee6272011-06-09 14:45:53 +0100365 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
366 cpu_dai->playback_active++;
367 codec_dai->playback_active++;
368 } else {
369 cpu_dai->capture_active++;
370 codec_dai->capture_active++;
371 }
372 cpu_dai->active++;
373 codec_dai->active++;
374 rtd->codec->active++;
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100375 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100376 return 0;
377
378config_err:
379 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
380 rtd->dai_link->ops->shutdown(substream);
381
382machine_err:
383 if (codec_dai->driver->ops->shutdown)
384 codec_dai->driver->ops->shutdown(substream, codec_dai);
385
386codec_dai_err:
387 if (platform->driver->ops && platform->driver->ops->close)
388 platform->driver->ops->close(substream);
389
390platform_err:
391 if (cpu_dai->driver->ops->shutdown)
392 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
393out:
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100394 mutex_unlock(&rtd->pcm_mutex);
Mark Brownd6652ef2011-12-03 20:14:31 +0000395
396 pm_runtime_put(platform->dev);
397 pm_runtime_put(codec_dai->dev);
398 pm_runtime_put(cpu_dai->dev);
399
Liam Girdwoodddee6272011-06-09 14:45:53 +0100400 return ret;
401}
402
403/*
404 * Power down the audio subsystem pmdown_time msecs after close is called.
405 * This is to ensure there are no pops or clicks in between any music tracks
406 * due to DAPM power cycling.
407 */
408static void close_delayed_work(struct work_struct *work)
409{
410 struct snd_soc_pcm_runtime *rtd =
411 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
412 struct snd_soc_dai *codec_dai = rtd->codec_dai;
413
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100414 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100415
416 pr_debug("pop wq checking: %s status: %s waiting: %s\n",
417 codec_dai->driver->playback.stream_name,
418 codec_dai->playback_active ? "active" : "inactive",
419 codec_dai->pop_wait ? "yes" : "no");
420
421 /* are we waiting on this codec DAI stream */
422 if (codec_dai->pop_wait == 1) {
423 codec_dai->pop_wait = 0;
Steve Mucklef132c6c2012-06-06 18:30:57 -0700424 snd_soc_dapm_stream_event(rtd,
425 codec_dai->driver->playback.stream_name,
426 SND_SOC_DAPM_STREAM_STOP);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100427 }
428
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100429 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100430}
431
432/*
433 * Called by ALSA when a PCM substream is closed. Private data can be
434 * freed here. The cpu DAI, codec DAI, machine and platform are also
435 * shutdown.
436 */
Liam Girdwood91d5e6b2011-06-09 17:04:59 +0100437static int soc_pcm_close(struct snd_pcm_substream *substream)
Liam Girdwoodddee6272011-06-09 14:45:53 +0100438{
439 struct snd_soc_pcm_runtime *rtd = substream->private_data;
440 struct snd_soc_platform *platform = rtd->platform;
441 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
442 struct snd_soc_dai *codec_dai = rtd->codec_dai;
443 struct snd_soc_codec *codec = rtd->codec;
444
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100445 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100446
447 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
448 cpu_dai->playback_active--;
449 codec_dai->playback_active--;
450 } else {
451 cpu_dai->capture_active--;
452 codec_dai->capture_active--;
453 }
454
455 cpu_dai->active--;
456 codec_dai->active--;
457 codec->active--;
458
Dong Aisheng17841022011-08-29 17:15:14 +0800459 /* clear the corresponding DAIs rate when inactive */
460 if (!cpu_dai->active)
461 cpu_dai->rate = 0;
462
463 if (!codec_dai->active)
464 codec_dai->rate = 0;
Sascha Hauer25b76792011-08-17 09:20:01 +0200465
Liam Girdwoodddee6272011-06-09 14:45:53 +0100466 /* Muting the DAC suppresses artifacts caused during digital
467 * shutdown, for example from stopping clocks.
468 */
469 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
470 snd_soc_dai_digital_mute(codec_dai, 1);
471
Helen Zengd5131792012-06-28 11:24:11 -0700472 if (cpu_dai->driver->ops->shutdown)
473 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
474
475 if (codec_dai->driver->ops->shutdown) {
Helen Zeng5749b092012-06-10 11:50:29 -0700476 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
477 codec_dai->driver->ops->shutdown(substream, codec_dai);
478 } else {
479 if (!codec_dai->capture_active)
480 codec_dai->driver->ops->shutdown(substream,
481 codec_dai);
482 }
483 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100484
Liam Girdwoodddee6272011-06-09 14:45:53 +0100485 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
486 rtd->dai_link->ops->shutdown(substream);
487
488 if (platform->driver->ops && platform->driver->ops->close)
489 platform->driver->ops->close(substream);
490 cpu_dai->runtime = NULL;
491
492 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700493 if (codec->ignore_pmdown_time ||
494 rtd->dai_link->ignore_pmdown_time ||
495 !rtd->pmdown_time) {
Peter Ujfalusi1d69c5c2011-10-14 14:43:33 +0300496 /* powered down playback stream now */
497 snd_soc_dapm_stream_event(rtd,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700498 codec_dai->driver->playback.stream_name,
499 SND_SOC_DAPM_STREAM_STOP);
Peter Ujfalusi1d69c5c2011-10-14 14:43:33 +0300500 } else {
501 /* start delayed pop wq here for playback streams */
502 codec_dai->pop_wait = 1;
503 schedule_delayed_work(&rtd->delayed_work,
504 msecs_to_jiffies(rtd->pmdown_time));
505 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100506 } else {
507 /* capture streams can be powered down now */
Helen Zeng5749b092012-06-10 11:50:29 -0700508 if (!codec_dai->capture_active)
509 snd_soc_dapm_stream_event(rtd,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700510 codec_dai->driver->capture.stream_name,
511 SND_SOC_DAPM_STREAM_STOP);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100512 }
513
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100514 mutex_unlock(&rtd->pcm_mutex);
Mark Brownd6652ef2011-12-03 20:14:31 +0000515
516 pm_runtime_put(platform->dev);
517 pm_runtime_put(codec_dai->dev);
518 pm_runtime_put(cpu_dai->dev);
519
Liam Girdwoodddee6272011-06-09 14:45:53 +0100520 return 0;
521}
522
523/*
524 * Called by ALSA when the PCM substream is prepared, can set format, sample
525 * rate, etc. This function is non atomic and can be called multiple times,
526 * it can refer to the runtime info.
527 */
528static int soc_pcm_prepare(struct snd_pcm_substream *substream)
529{
530 struct snd_soc_pcm_runtime *rtd = substream->private_data;
531 struct snd_soc_platform *platform = rtd->platform;
532 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
533 struct snd_soc_dai *codec_dai = rtd->codec_dai;
534 int ret = 0;
535
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100536 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100537
538 if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
539 ret = rtd->dai_link->ops->prepare(substream);
540 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700541 printk(KERN_ERR "asoc: machine prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100542 goto out;
543 }
544 }
545
546 if (platform->driver->ops && platform->driver->ops->prepare) {
547 ret = platform->driver->ops->prepare(substream);
548 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700549 printk(KERN_ERR "asoc: platform prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100550 goto out;
551 }
552 }
553
554 if (codec_dai->driver->ops->prepare) {
555 ret = codec_dai->driver->ops->prepare(substream, codec_dai);
556 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700557 printk(KERN_ERR "asoc: codec DAI prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100558 goto out;
559 }
560 }
561
562 if (cpu_dai->driver->ops->prepare) {
563 ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
564 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700565 printk(KERN_ERR "asoc: cpu DAI prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100566 goto out;
567 }
568 }
569
570 /* cancel any delayed stream shutdown that is pending */
571 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
572 codec_dai->pop_wait) {
573 codec_dai->pop_wait = 0;
574 cancel_delayed_work(&rtd->delayed_work);
575 }
576
Steve Mucklef132c6c2012-06-06 18:30:57 -0700577 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
578 snd_soc_dapm_stream_event(rtd,
579 codec_dai->driver->playback.stream_name,
580 SND_SOC_DAPM_STREAM_START);
Helen Zeng5749b092012-06-10 11:50:29 -0700581 else {
582 if (codec_dai->capture_active == 1)
583 snd_soc_dapm_stream_event(rtd,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700584 codec_dai->driver->capture.stream_name,
585 SND_SOC_DAPM_STREAM_START);
Helen Zeng5749b092012-06-10 11:50:29 -0700586 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100587 snd_soc_dai_digital_mute(codec_dai, 0);
588
589out:
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100590 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100591 return ret;
592}
593
594/*
595 * Called by ALSA when the hardware params are set by application. This
596 * function can also be called multiple times and can allocate buffers
597 * (using snd_pcm_lib_* ). It's non-atomic.
598 */
599static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
600 struct snd_pcm_hw_params *params)
601{
602 struct snd_soc_pcm_runtime *rtd = substream->private_data;
603 struct snd_soc_platform *platform = rtd->platform;
604 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
605 struct snd_soc_dai *codec_dai = rtd->codec_dai;
606 int ret = 0;
607
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100608 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100609
610 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
611 ret = rtd->dai_link->ops->hw_params(substream, params);
612 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700613 printk(KERN_ERR "asoc: machine hw_params failed\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100614 goto out;
615 }
616 }
617
618 if (codec_dai->driver->ops->hw_params) {
Helen Zeng5749b092012-06-10 11:50:29 -0700619 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
620 ret = codec_dai->driver->ops->hw_params(substream,
621 params, codec_dai);
622 if (ret < 0) {
623 printk(KERN_ERR "not set codec %s hw params\n",
624 codec_dai->name);
625 goto codec_err;
626 }
627 } else {
628 if (codec_dai->capture_active == 1) {
629 ret = codec_dai->driver->ops->hw_params(
630 substream, params, codec_dai);
631 if (ret < 0) {
632 printk(KERN_ERR "fail: %s hw params\n",
633 codec_dai->name);
634 goto codec_err;
635 }
636 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100637 }
638 }
639
640 if (cpu_dai->driver->ops->hw_params) {
641 ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
642 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700643 printk(KERN_ERR "asoc: interface %s hw params failed\n",
644 cpu_dai->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100645 goto interface_err;
646 }
647 }
648
649 if (platform->driver->ops && platform->driver->ops->hw_params) {
650 ret = platform->driver->ops->hw_params(substream, params);
651 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700652 printk(KERN_ERR "asoc: platform %s hw params failed\n",
653 platform->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100654 goto platform_err;
655 }
656 }
657
Dong Aisheng17841022011-08-29 17:15:14 +0800658 /* store the rate for each DAIs */
659 cpu_dai->rate = params_rate(params);
660 codec_dai->rate = params_rate(params);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100661
Steve Mucklef132c6c2012-06-06 18:30:57 -0700662 /* malloc a page for hostless IO.
663 * FIXME: rework with alsa-lib changes so that this malloc is not required.
664 */
665 if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) {
666 substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV;
667 substream->dma_buffer.dev.dev = rtd->dev;
668 substream->dma_buffer.dev.dev->coherent_dma_mask = DMA_BIT_MASK(32);
669 substream->dma_buffer.private_data = NULL;
670
671 ret = snd_pcm_lib_malloc_pages(substream, PAGE_SIZE);
672 if (ret < 0)
673 goto platform_err;
674 }
675
Liam Girdwoodddee6272011-06-09 14:45:53 +0100676out:
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100677 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100678 return ret;
679
680platform_err:
681 if (cpu_dai->driver->ops->hw_free)
682 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
683
684interface_err:
685 if (codec_dai->driver->ops->hw_free)
686 codec_dai->driver->ops->hw_free(substream, codec_dai);
687
688codec_err:
689 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
690 rtd->dai_link->ops->hw_free(substream);
691
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100692 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100693 return ret;
694}
695
696/*
697 * Frees resources allocated by hw_params, can be called multiple times
698 */
699static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
700{
701 struct snd_soc_pcm_runtime *rtd = substream->private_data;
702 struct snd_soc_platform *platform = rtd->platform;
703 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
704 struct snd_soc_dai *codec_dai = rtd->codec_dai;
705 struct snd_soc_codec *codec = rtd->codec;
706
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100707 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100708
709 /* apply codec digital mute */
710 if (!codec->active)
711 snd_soc_dai_digital_mute(codec_dai, 1);
712
713 /* free any machine hw params */
714 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
715 rtd->dai_link->ops->hw_free(substream);
716
717 /* free any DMA resources */
718 if (platform->driver->ops && platform->driver->ops->hw_free)
719 platform->driver->ops->hw_free(substream);
720
721 /* now free hw params for the DAIs */
722 if (codec_dai->driver->ops->hw_free)
723 codec_dai->driver->ops->hw_free(substream, codec_dai);
724
725 if (cpu_dai->driver->ops->hw_free)
726 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
727
Steve Mucklef132c6c2012-06-06 18:30:57 -0700728 if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
729 snd_pcm_lib_free_pages(substream);
730
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100731 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100732 return 0;
733}
734
735static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
736{
737 struct snd_soc_pcm_runtime *rtd = substream->private_data;
738 struct snd_soc_platform *platform = rtd->platform;
739 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
740 struct snd_soc_dai *codec_dai = rtd->codec_dai;
741 int ret;
742
743 if (codec_dai->driver->ops->trigger) {
Helen Zeng5749b092012-06-10 11:50:29 -0700744 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
745 ret = codec_dai->driver->ops->trigger(substream,
746 cmd, codec_dai);
747 if (ret < 0)
748 return ret;
749 } else {
750 if (codec_dai->capture_active == 1) {
751 ret = codec_dai->driver->ops->trigger(
752 substream, cmd, codec_dai);
753 if (ret < 0)
754 return ret;
755 }
756 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100757 }
758
759 if (platform->driver->ops && platform->driver->ops->trigger) {
760 ret = platform->driver->ops->trigger(substream, cmd);
761 if (ret < 0)
762 return ret;
763 }
764
765 if (cpu_dai->driver->ops->trigger) {
766 ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
767 if (ret < 0)
768 return ret;
769 }
770 return 0;
771}
772
Steve Mucklef132c6c2012-06-06 18:30:57 -0700773int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, int cmd)
774{
775 struct snd_soc_pcm_runtime *rtd = substream->private_data;
776 struct snd_soc_platform *platform = rtd->platform;
777 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
778 struct snd_soc_dai *codec_dai = rtd->codec_dai;
779 int ret;
780
781 if (codec_dai->driver->ops->bespoke_trigger) {
782 ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
783 if (ret < 0)
784 return ret;
785 }
786
787 if (platform->driver->bespoke_trigger) {
788 ret = platform->driver->bespoke_trigger(substream, cmd);
789 if (ret < 0)
790 return ret;
791 }
792
793 if (cpu_dai->driver->ops->bespoke_trigger) {
794 ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
795 if (ret < 0)
796 return ret;
797 }
798 return 0;
799}
800
Liam Girdwoodddee6272011-06-09 14:45:53 +0100801/*
802 * soc level wrapper for pointer callback
803 * If cpu_dai, codec_dai, platform driver has the delay callback, than
804 * the runtime->delay will be updated accordingly.
805 */
806static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
807{
808 struct snd_soc_pcm_runtime *rtd = substream->private_data;
809 struct snd_soc_platform *platform = rtd->platform;
810 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
811 struct snd_soc_dai *codec_dai = rtd->codec_dai;
812 struct snd_pcm_runtime *runtime = substream->runtime;
813 snd_pcm_uframes_t offset = 0;
814 snd_pcm_sframes_t delay = 0;
815
816 if (platform->driver->ops && platform->driver->ops->pointer)
817 offset = platform->driver->ops->pointer(substream);
818
819 if (cpu_dai->driver->ops->delay)
820 delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
821
822 if (codec_dai->driver->ops->delay)
823 delay += codec_dai->driver->ops->delay(substream, codec_dai);
824
825 if (platform->driver->delay)
826 delay += platform->driver->delay(substream, codec_dai);
827
828 runtime->delay = delay;
829
830 return offset;
831}
832
Steve Mucklef132c6c2012-06-06 18:30:57 -0700833static inline int be_connect(struct snd_soc_pcm_runtime *fe,
834 struct snd_soc_pcm_runtime *be, int stream)
835{
836 struct snd_soc_dpcm_params *dpcm_params;
837
838 if (!fe->dpcm[stream].runtime) {
839 dev_err(fe->dev, "%s no runtime\n", fe->dai_link->name);
840 return -ENODEV;
841 }
842
843 /* only add new dpcm_paramss */
844 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
845 if (dpcm_params->be == be && dpcm_params->fe == fe)
846 return 0;
847 }
848
849 dpcm_params = kzalloc(sizeof(struct snd_soc_dpcm_params), GFP_KERNEL);
850 if (!dpcm_params)
851 return -ENOMEM;
852
853 dpcm_params->be = be;
854 dpcm_params->fe = fe;
855 be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
856 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_NEW;
857 list_add(&dpcm_params->list_be, &fe->dpcm[stream].be_clients);
858 list_add(&dpcm_params->list_fe, &be->dpcm[stream].fe_clients);
859
860 dev_dbg(fe->dev, " connected new DSP %s path %s %s %s\n",
861 stream ? "capture" : "playback", fe->dai_link->name,
862 stream ? "<-" : "->", be->dai_link->name);
863
864#ifdef CONFIG_DEBUG_FS
865 dpcm_params->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644,
866 fe->debugfs_dpcm_root, &dpcm_params->state);
867#endif
868
869 return 1;
870}
871
872static inline void be_reparent(struct snd_soc_pcm_runtime *fe,
873 struct snd_soc_pcm_runtime *be, int stream)
874{
875 struct snd_soc_dpcm_params *dpcm_params;
876 struct snd_pcm_substream *fe_substream, *be_substream;
877
878 /* reparent if BE is connected to other FEs */
879 if (!be->dpcm[stream].users)
880 return;
881
882 be_substream = snd_soc_dpcm_get_substream(be, stream);
883
884 list_for_each_entry(dpcm_params, &be->dpcm[stream].fe_clients, list_fe) {
885 if (dpcm_params->fe != fe) {
886
887 dev_dbg(fe->dev, " reparent %s path %s %s %s\n",
888 stream ? "capture" : "playback",
889 dpcm_params->fe->dai_link->name,
890 stream ? "<-" : "->", dpcm_params->be->dai_link->name);
891
892 fe_substream = snd_soc_dpcm_get_substream(dpcm_params->fe,
893 stream);
894 be_substream->runtime = fe_substream->runtime;
895 break;
896 }
897 }
898}
899
900static inline void be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
901{
902 struct snd_soc_dpcm_params *dpcm_params, *d;
903
904 list_for_each_entry_safe(dpcm_params, d, &fe->dpcm[stream].be_clients, list_be) {
905 dev_dbg(fe->dev, "BE %s disconnect check for %s\n",
906 stream ? "capture" : "playback",
907 dpcm_params->be->dai_link->name);
908
909 if (dpcm_params->state == SND_SOC_DPCM_LINK_STATE_FREE) {
910 dev_dbg(fe->dev, " freed DSP %s path %s %s %s\n",
911 stream ? "capture" : "playback", fe->dai_link->name,
912 stream ? "<-" : "->", dpcm_params->be->dai_link->name);
913
914 /* BEs still alive need new FE */
915 be_reparent(fe, dpcm_params->be, stream);
916
917#ifdef CONFIG_DEBUG_FS
918 debugfs_remove(dpcm_params->debugfs_state);
919#endif
920
921 list_del(&dpcm_params->list_be);
922 list_del(&dpcm_params->list_fe);
923 kfree(dpcm_params);
924 }
925 }
926}
927
928static struct snd_soc_pcm_runtime *be_get_rtd(struct snd_soc_card *card,
929 struct snd_soc_dapm_widget *widget)
930{
931 struct snd_soc_pcm_runtime *be;
932 int i;
933
934 if (!widget->sname) {
935 dev_err(card->dev, "widget %s has no stream\n", widget->name);
936 return NULL;
937 }
938
939 for (i = 0; i < card->num_links; i++) {
940 be = &card->rtd[i];
941
942 if (!strcmp(widget->sname, be->dai_link->stream_name))
943 return be;
944 }
945
946 dev_err(card->dev, "can't get BE for %s\n", widget->name);
947 return NULL;
948}
949
950static struct snd_soc_dapm_widget *be_get_widget(struct snd_soc_card *card,
951 struct snd_soc_pcm_runtime *rtd)
952{
953 struct snd_soc_dapm_widget *widget;
954
955 list_for_each_entry(widget, &card->widgets, list) {
956
957 if (!widget->sname)
958 continue;
959
960 if (!strcmp(widget->sname, rtd->dai_link->stream_name))
961 return widget;
962 }
963
964 dev_err(card->dev, "can't get widget for %s\n",
965 rtd->dai_link->stream_name);
966 return NULL;
967}
968
969static int widget_in_list(struct snd_soc_dapm_widget_list *list,
970 struct snd_soc_dapm_widget *widget)
971{
972 int i;
973
974 for (i = 0; i < list->num_widgets; i++) {
975 if (widget == list->widgets[i])
976 return 1;
977 }
978
979 return 0;
980}
981
982static int fe_path_get(struct snd_soc_pcm_runtime *fe,
983 int stream, struct snd_soc_dapm_widget_list **list_)
984{
985 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
986 struct snd_soc_dapm_widget_list *list;
987 int paths;
988
989 list = kzalloc(sizeof(struct snd_soc_dapm_widget_list) +
990 sizeof(struct snd_soc_dapm_widget *), GFP_KERNEL);
991 if (list == NULL)
992 return -ENOMEM;
993
994 /* get number of valid DAI paths and their widgets */
995 paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list);
996
997 dev_dbg(fe->dev, "found %d audio %s paths\n", paths,
998 stream ? "capture" : "playback");
999
1000 *list_ = list;
1001 return paths;
1002}
1003
1004static inline void fe_path_put(struct snd_soc_dapm_widget_list **list)
1005{
1006 kfree(*list);
1007}
1008
1009static int be_prune_old(struct snd_soc_pcm_runtime *fe, int stream,
1010 struct snd_soc_dapm_widget_list **list_)
1011{
1012 struct snd_soc_card *card = fe->card;
1013 struct snd_soc_dpcm_params *dpcm_params;
1014 struct snd_soc_dapm_widget_list *list = *list_;
1015 struct snd_soc_dapm_widget *widget;
1016 int old = 0;
1017
1018 /* Destroy any old FE <--> BE connections */
1019 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1020
1021 /* is there a valid widget for this BE */
1022 widget = be_get_widget(card, dpcm_params->be);
1023 if (!widget) {
1024 dev_err(fe->dev, "no widget found for %s\n",
1025 dpcm_params->be->dai_link->name);
1026 continue;
1027 }
1028
1029 /* prune the BE if it's no longer in our active list */
1030 if (widget_in_list(list, widget))
1031 continue;
1032
1033 dev_dbg(fe->dev, "pruning %s BE %s for %s\n",
1034 stream ? "capture" : "playback", dpcm_params->be->dai_link->name,
1035 fe->dai_link->name);
1036 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
1037 dpcm_params->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1038 old++;
1039 }
1040
1041 dev_dbg(fe->dev, "found %d old BEs\n", old);
1042 return old;
1043}
1044
1045static int be_add_new(struct snd_soc_pcm_runtime *fe, int stream,
1046 struct snd_soc_dapm_widget_list **list_)
1047{
1048 struct snd_soc_card *card = fe->card;
1049 struct snd_soc_dapm_widget_list *list = *list_;
1050 enum snd_soc_dapm_type be_type;
1051 int i, new = 0, err;
1052
1053 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1054 be_type = snd_soc_dapm_aif_out;
1055 else
1056 be_type = snd_soc_dapm_aif_in;
1057
1058 /* Create any new FE <--> BE connections */
1059 for (i = 0; i < list->num_widgets; i++) {
1060
1061 if (list->widgets[i]->id == be_type) {
1062 struct snd_soc_pcm_runtime *be;
1063
1064 /* is there a valid BE rtd for this widget */
1065 be = be_get_rtd(card, list->widgets[i]);
1066 if (!be) {
1067 dev_err(fe->dev, "no BE found for %s\n",
1068 list->widgets[i]->name);
1069 continue;
1070 }
1071
1072 /* don't connect if FE is not running */
1073 if (!fe->dpcm[stream].runtime)
1074 continue;
1075
1076 /* newly connected FE and BE */
1077 err = be_connect(fe, be, stream);
1078 if (err < 0) {
1079 dev_err(fe->dev, "can't connect %s\n", list->widgets[i]->name);
1080 break;
1081 } else if (err == 0) /* already connected */
1082 continue;
1083
1084 /* new */
1085 be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1086 new++;
1087 }
1088 }
1089
1090 dev_dbg(fe->dev, "found %d new BEs\n", new);
1091 return new;
1092}
1093
1094/*
1095 * Find the corresponding BE DAIs that source or sink audio to this
1096 * FE substream.
1097 */
1098static int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
1099 int stream, struct snd_soc_dapm_widget_list **list, int new)
1100{
1101 if (new)
1102 return be_add_new(fe, stream, list);
1103 else
1104 return be_prune_old(fe, stream, list);
1105 return 0;
1106}
1107
1108/*
1109 * Clear the runtime pending state of all BE's.
1110 */
1111static void fe_clear_pending(struct snd_soc_pcm_runtime *fe, int stream)
1112{
1113 struct snd_soc_dpcm_params *dpcm_params;
1114
1115 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
1116 dpcm_params->be->dpcm[stream].runtime_update =
1117 SND_SOC_DPCM_UPDATE_NO;
1118}
1119
1120/* Unwind the BE startup */
1121static void soc_dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, int stream)
1122{
1123 struct snd_soc_dpcm_params *dpcm_params;
1124
1125 /* disable any enabled and non active backends */
1126 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1127
1128 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1129 struct snd_pcm_substream *be_substream =
1130 snd_soc_dpcm_get_substream(be, stream);
1131
1132 if (be->dpcm[stream].users == 0)
1133 dev_err(be->dev, "no users %s at close - state %d\n",
1134 stream ? "capture" : "playback", be->dpcm[stream].state);
1135
1136 if (--be->dpcm[stream].users != 0)
1137 continue;
1138
1139 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
1140 continue;
1141
1142 soc_pcm_close(be_substream);
1143 be_substream->runtime = NULL;
1144
1145 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1146 }
1147}
1148
1149/* Startup all new BE */
1150static int soc_dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
1151{
1152 struct snd_soc_dpcm_params *dpcm_params;
1153 int err, count = 0;
1154
1155 /* only startup BE DAIs that are either sinks or sources to this FE DAI */
1156 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1157
1158 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1159 struct snd_pcm_substream *be_substream =
1160 snd_soc_dpcm_get_substream(be, stream);
1161
1162 /* is this op for this BE ? */
1163 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1164 continue;
1165
1166 /* first time the dpcm_params is open ? */
1167 if (be->dpcm[stream].users == MAX_BE_USERS)
1168 dev_err(be->dev, "too many users %s at open - state %d\n",
1169 stream ? "capture" : "playback", be->dpcm[stream].state);
1170
1171 if (be->dpcm[stream].users++ != 0)
1172 continue;
1173
1174 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
1175 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
1176 continue;
1177
1178 dev_dbg(be->dev, "dpcm: open BE %s\n", be->dai_link->name);
1179
1180 be_substream->runtime = be->dpcm[stream].runtime;
1181 err = soc_pcm_open(be_substream);
1182 if (err < 0) {
1183 dev_err(be->dev, "BE open failed %d\n", err);
1184 be->dpcm[stream].users--;
1185 if (be->dpcm[stream].users < 0)
1186 dev_err(be->dev, "no users %s at unwind - state %d\n",
1187 stream ? "capture" : "playback",
1188 be->dpcm[stream].state);
1189
1190 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1191 goto unwind;
1192 }
1193
1194 be->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1195 count++;
1196 }
1197
1198 return count;
1199
1200unwind:
1201 /* disable any enabled and non active backends */
1202 list_for_each_entry_continue_reverse(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1203 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1204 struct snd_pcm_substream *be_substream =
1205 snd_soc_dpcm_get_substream(be, stream);
1206
1207 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1208 continue;
1209
1210 if (be->dpcm[stream].users == 0)
1211 dev_err(be->dev, "no users %s at close - state %d\n",
1212 stream ? "capture" : "playback", be->dpcm[stream].state);
1213
1214 if (--be->dpcm[stream].users != 0)
1215 continue;
1216
1217 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
1218 continue;
1219
1220 soc_pcm_close(be_substream);
1221 be_substream->runtime = NULL;
1222
1223 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1224 }
1225
1226 return err;
1227}
1228
1229void soc_dpcm_set_dynamic_runtime(struct snd_pcm_substream *substream)
1230{
1231 struct snd_pcm_runtime *runtime = substream->runtime;
1232 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1233 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1234 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
1235
1236 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1237 runtime->hw.rate_min = cpu_dai_drv->playback.rate_min;
1238 runtime->hw.rate_max = cpu_dai_drv->playback.rate_max;
1239 runtime->hw.channels_min = cpu_dai_drv->playback.channels_min;
1240 runtime->hw.channels_max = cpu_dai_drv->playback.channels_max;
1241 runtime->hw.formats &= cpu_dai_drv->playback.formats;
1242 runtime->hw.rates = cpu_dai_drv->playback.rates;
1243 } else {
1244 runtime->hw.rate_min = cpu_dai_drv->capture.rate_min;
1245 runtime->hw.rate_max = cpu_dai_drv->capture.rate_max;
1246 runtime->hw.channels_min = cpu_dai_drv->capture.channels_min;
1247 runtime->hw.channels_max = cpu_dai_drv->capture.channels_max;
1248 runtime->hw.formats &= cpu_dai_drv->capture.formats;
1249 runtime->hw.rates = cpu_dai_drv->capture.rates;
1250 }
1251}
1252
1253static int soc_dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
1254{
1255 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1256 struct snd_pcm_runtime *runtime = fe_substream->runtime;
1257 int stream = fe_substream->stream, ret = 0;
1258
1259 mutex_lock(&fe->card->dpcm_mutex);
1260 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1261
1262 ret = soc_dpcm_be_dai_startup(fe, fe_substream->stream);
1263 if (ret < 0) {
1264 dev_err(fe->dev,"dpcm: failed to start some BEs %d\n", ret);
1265 goto be_err;
1266 }
1267
1268 dev_dbg(fe->dev, "dpcm: open FE %s\n", fe->dai_link->name);
1269
1270 /* start the DAI frontend */
1271 ret = soc_pcm_open(fe_substream);
1272 if (ret < 0) {
1273 dev_err(fe->dev,"dpcm: failed to start FE %d\n", ret);
1274 goto unwind;
1275 }
1276
1277 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1278
1279 soc_dpcm_set_dynamic_runtime(fe_substream);
1280 snd_pcm_limit_hw_rates(runtime);
1281
1282 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1283 mutex_unlock(&fe->card->dpcm_mutex);
1284 return 0;
1285
1286unwind:
1287 soc_dpcm_be_dai_startup_unwind(fe, fe_substream->stream);
1288be_err:
1289 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1290 mutex_unlock(&fe->card->dpcm_mutex);
1291 return ret;
1292}
1293
1294/* BE shutdown - called on DAPM sync updates (i.e. FE is already running)*/
1295static int soc_dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1296{
1297 struct snd_soc_dpcm_params *dpcm_params;
1298
1299 /* only shutdown backends that are either sinks or sources to this frontend DAI */
1300 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1301
1302 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1303 struct snd_pcm_substream *be_substream =
1304 snd_soc_dpcm_get_substream(be, stream);
1305
1306 /* is this op for this BE ? */
1307 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1308 continue;
1309
1310 if (be->dpcm[stream].users == 0)
1311 dev_err(be->dev, "no users %s at close - state %d\n",
1312 stream ? "capture" : "playback", be->dpcm[stream].state);
1313
1314 if (--be->dpcm[stream].users != 0)
1315 continue;
1316
1317 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1318 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN))
1319 continue;
1320
1321 dev_dbg(be->dev, "dpcm: close BE %s\n",
1322 dpcm_params->fe->dai_link->name);
1323
1324 soc_pcm_close(be_substream);
1325 be_substream->runtime = NULL;
1326
1327 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1328 }
1329 return 0;
1330}
1331
1332/* FE +BE shutdown - called on FE PCM ops */
1333static int soc_dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
1334{
1335 struct snd_soc_pcm_runtime *fe = substream->private_data;
1336 int stream = substream->stream;
1337
1338 mutex_lock(&fe->card->dpcm_mutex);
1339 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1340
1341 dev_dbg(fe->dev, "dpcm: close FE %s\n", fe->dai_link->name);
1342
1343 /* now shutdown the frontend */
1344 soc_pcm_close(substream);
1345
1346 /* shutdown the BEs */
1347 soc_dpcm_be_dai_shutdown(fe, substream->stream);
1348 /* run the stream event for each BE */
1349 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1350 soc_dpcm_dapm_stream_event(fe, stream,
1351 fe->cpu_dai->driver->playback.stream_name,
1352 SND_SOC_DAPM_STREAM_STOP);
1353 else
1354 soc_dpcm_dapm_stream_event(fe, stream,
1355 fe->cpu_dai->driver->capture.stream_name,
1356 SND_SOC_DAPM_STREAM_STOP);
1357
1358 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1359 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1360
1361 mutex_unlock(&fe->card->dpcm_mutex);
1362 return 0;
1363}
1364
1365static int soc_dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
1366{
1367 struct snd_soc_dpcm_params *dpcm_params;
1368 int ret;
1369
1370 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1371
1372 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1373 struct snd_pcm_substream *be_substream =
1374 snd_soc_dpcm_get_substream(be, stream);
1375
1376 /* is this op for this BE ? */
1377 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1378 continue;
1379
1380 /* only allow hw_params() if no connected FEs are running */
1381 if (!snd_soc_dpcm_can_be_params(fe, be, stream))
1382 continue;
1383
1384 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
1385 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1386 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
1387 continue;
1388
1389 dev_dbg(be->dev, "dpcm: hw_params BE %s\n",
1390 dpcm_params->fe->dai_link->name);
1391
1392 /* copy params for each dpcm_params */
1393 memcpy(&dpcm_params->hw_params, &fe->dpcm[stream].hw_params,
1394 sizeof(struct snd_pcm_hw_params));
1395
1396 /* perform any hw_params fixups */
1397 if (be->dai_link->be_hw_params_fixup) {
1398 ret = be->dai_link->be_hw_params_fixup(be,
1399 &dpcm_params->hw_params);
1400 if (ret < 0) {
1401 dev_err(be->dev,
1402 "dpcm: hw_params BE fixup failed %d\n",
1403 ret);
1404 goto unwind;
1405 }
1406 }
1407
1408 ret = soc_pcm_hw_params(be_substream, &dpcm_params->hw_params);
1409 if (ret < 0) {
1410 dev_err(dpcm_params->be->dev, "dpcm: hw_params BE failed %d\n", ret);
1411 goto unwind;
1412 }
1413
1414 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
1415 }
1416 return 0;
1417
1418unwind:
1419 /* disable any enabled and non active backends */
1420 list_for_each_entry_continue_reverse(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1421 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1422 struct snd_pcm_substream *be_substream =
1423 snd_soc_dpcm_get_substream(be, stream);
1424
1425 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1426 continue;
1427
1428 /* only allow hw_free() if no connected FEs are running */
1429 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1430 continue;
1431
1432 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
1433 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1434 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1435 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1436 continue;
1437
1438 soc_pcm_hw_free(be_substream);
1439 }
1440
1441 return ret;
1442}
1443
1444int soc_dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
1445 struct snd_pcm_hw_params *params)
1446{
1447 struct snd_soc_pcm_runtime *fe = substream->private_data;
1448 int ret, stream = substream->stream;
1449
1450 mutex_lock(&fe->card->dpcm_mutex);
1451 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1452
1453 memcpy(&fe->dpcm[substream->stream].hw_params, params,
1454 sizeof(struct snd_pcm_hw_params));
1455 ret = soc_dpcm_be_dai_hw_params(fe, substream->stream);
1456 if (ret < 0) {
1457 dev_err(fe->dev,"dpcm: hw_params failed for some BEs %d\n", ret);
1458 goto out;
1459 }
1460
1461 dev_dbg(fe->dev, "dpcm: hw_params FE %s rate %d chan %x fmt %d\n",
1462 fe->dai_link->name, params_rate(params), params_channels(params),
1463 params_format(params));
1464
1465 /* call hw_params on the frontend */
1466 ret = soc_pcm_hw_params(substream, params);
1467 if (ret < 0) {
1468 dev_err(fe->dev,"dpcm: hw_params FE failed %d\n", ret);
1469 soc_dpcm_be_dai_hw_free(fe, stream);
1470 } else
1471 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
1472
1473out:
1474 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1475 mutex_unlock(&fe->card->dpcm_mutex);
1476 return ret;
1477}
1478
1479static int dpcm_do_trigger(struct snd_soc_dpcm_params *dpcm_params,
1480 struct snd_pcm_substream *substream, int cmd)
1481{
1482 int ret;
1483
1484 dev_dbg(dpcm_params->be->dev, "dpcm: trigger BE %s cmd %d\n",
1485 dpcm_params->fe->dai_link->name, cmd);
1486
1487 ret = soc_pcm_trigger(substream, cmd);
1488 if (ret < 0)
1489 dev_err(dpcm_params->be->dev,"dpcm: trigger BE failed %d\n", ret);
1490
1491 return ret;
1492}
1493
1494int soc_dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd)
1495{
1496 struct snd_soc_dpcm_params *dpcm_params;
1497 int ret = 0;
1498
Steve Mucklef132c6c2012-06-06 18:30:57 -07001499
1500 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1501
1502 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1503 struct snd_pcm_substream *be_substream =
1504 snd_soc_dpcm_get_substream(be, stream);
1505
1506 /* is this op for this BE ? */
1507 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1508 continue;
1509
1510 switch (cmd) {
1511 case SNDRV_PCM_TRIGGER_START:
1512 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1513 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1514 continue;
1515
1516 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1517 if (ret)
1518 return ret;
1519
1520 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1521 break;
1522 case SNDRV_PCM_TRIGGER_RESUME:
1523 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
1524 continue;
1525
1526 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1527 if (ret)
1528 return ret;
1529
1530 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1531 break;
1532 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1533 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
1534 continue;
1535
1536 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1537 if (ret)
1538 return ret;
1539
1540 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1541 break;
1542 case SNDRV_PCM_TRIGGER_STOP:
1543 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1544 continue;
1545
1546 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1547 continue;
1548
1549 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1550 if (ret)
1551 return ret;
1552
1553 be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1554 break;
1555 case SNDRV_PCM_TRIGGER_SUSPEND:
1556 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)
1557 continue;
1558
1559 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1560 continue;
1561
1562 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1563 if (ret)
1564 return ret;
1565
1566 be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND;
1567 break;
1568 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1569 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1570 continue;
1571
1572 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1573 continue;
1574
1575 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1576 if (ret)
1577 return ret;
1578
1579 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
1580 break;
1581 }
1582 }
1583
1584 return ret;
1585}
1586EXPORT_SYMBOL_GPL(soc_dpcm_be_dai_trigger);
1587
1588int soc_dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
1589{
1590 struct snd_soc_pcm_runtime *fe = substream->private_data;
1591 int stream = substream->stream, ret;
1592 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1593
1594 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1595
1596 switch (trigger) {
1597 case SND_SOC_DPCM_TRIGGER_PRE:
1598 /* call trigger on the frontend before the backend. */
1599
1600 dev_dbg(fe->dev, "dpcm: pre trigger FE %s cmd %d\n",
1601 fe->dai_link->name, cmd);
1602
1603 ret = soc_pcm_trigger(substream, cmd);
1604 if (ret < 0) {
1605 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1606 goto out;
1607 }
1608
1609 ret = soc_dpcm_be_dai_trigger(fe, substream->stream, cmd);
1610 break;
1611 case SND_SOC_DPCM_TRIGGER_POST:
1612 /* call trigger on the frontend after the backend. */
1613
1614 ret = soc_dpcm_be_dai_trigger(fe, substream->stream, cmd);
1615 if (ret < 0) {
1616 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1617 goto out;
1618 }
1619
1620 dev_dbg(fe->dev, "dpcm: post trigger FE %s cmd %d\n",
1621 fe->dai_link->name, cmd);
1622
1623 ret = soc_pcm_trigger(substream, cmd);
1624 break;
1625 case SND_SOC_DPCM_TRIGGER_BESPOKE:
1626 /* bespoke trigger() - handles both FE and BEs */
1627
1628 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd %d\n",
1629 fe->dai_link->name, cmd);
1630
1631 ret = soc_pcm_bespoke_trigger(substream, cmd);
1632 if (ret < 0) {
1633 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1634 goto out;
1635 }
1636 break;
1637 default:
1638 dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd,
1639 fe->dai_link->name);
1640 ret = -EINVAL;
1641 goto out;
1642 }
1643
1644 switch (cmd) {
1645 case SNDRV_PCM_TRIGGER_START:
1646 case SNDRV_PCM_TRIGGER_RESUME:
1647 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1648 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1649 break;
1650 case SNDRV_PCM_TRIGGER_STOP:
1651 case SNDRV_PCM_TRIGGER_SUSPEND:
Steve Mucklef132c6c2012-06-06 18:30:57 -07001652 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1653 break;
Banajit Goswami17857112013-02-14 18:24:08 -08001654 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1655 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
1656 break;
Steve Mucklef132c6c2012-06-06 18:30:57 -07001657 }
1658
1659out:
1660 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1661 return ret;
1662}
1663
1664static int soc_dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
1665{
1666 struct snd_soc_dpcm_params *dpcm_params;
1667 int ret = 0;
1668
1669 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1670
1671 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1672 struct snd_pcm_substream *be_substream =
1673 snd_soc_dpcm_get_substream(be, stream);
1674
1675 /* is this op for this BE ? */
1676 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1677 continue;
1678
1679 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1680 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1681 continue;
1682
1683 dev_dbg(be->dev, "dpcm: prepare BE %s\n",
1684 dpcm_params->fe->dai_link->name);
1685
1686 ret = soc_pcm_prepare(be_substream);
1687 if (ret < 0) {
1688 dev_err(be->dev, "dpcm: backend prepare failed %d\n",
1689 ret);
1690 break;
1691 }
1692
1693 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1694 }
1695 return ret;
1696}
1697
1698int soc_dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
1699{
1700 struct snd_soc_pcm_runtime *fe = substream->private_data;
1701 int stream = substream->stream, ret = 0;
1702
1703 mutex_lock(&fe->card->dpcm_mutex);
1704
1705 dev_dbg(fe->dev, "dpcm: prepare FE %s\n", fe->dai_link->name);
1706
1707 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1708
1709 /* there is no point preparing this FE if there are no BEs */
1710 if (list_empty(&fe->dpcm[stream].be_clients)) {
1711 dev_err(fe->dev, "dpcm: no backend DAIs enabled for %s\n",
1712 fe->dai_link->name);
1713 ret = -EINVAL;
1714 goto out;
1715 }
1716
1717 ret = soc_dpcm_be_dai_prepare(fe, substream->stream);
1718 if (ret < 0)
1719 goto out;
1720
1721 /* call prepare on the frontend */
1722 ret = soc_pcm_prepare(substream);
1723 if (ret < 0) {
1724 dev_err(fe->dev,"dpcm: prepare FE %s failed\n", fe->dai_link->name);
1725 goto out;
1726 }
1727
1728 /* run the stream event for each BE */
1729 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1730 soc_dpcm_dapm_stream_event(fe, stream,
1731 fe->cpu_dai->driver->playback.stream_name,
1732 SND_SOC_DAPM_STREAM_START);
1733 else
1734 soc_dpcm_dapm_stream_event(fe, stream,
1735 fe->cpu_dai->driver->capture.stream_name,
1736 SND_SOC_DAPM_STREAM_START);
1737
1738 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1739
1740out:
1741 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1742 mutex_unlock(&fe->card->dpcm_mutex);
1743 return ret;
1744}
1745
1746static int soc_dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
1747{
1748 struct snd_soc_dpcm_params *dpcm_params;
1749
1750 /* only hw_params backends that are either sinks or sources
1751 * to this frontend DAI */
1752 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1753
1754 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1755 struct snd_pcm_substream *be_substream =
1756 snd_soc_dpcm_get_substream(be, stream);
1757
1758 /* is this op for this BE ? */
1759 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1760 continue;
1761
1762 /* only free hw when no longer used - check all FEs */
1763 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1764 continue;
1765
1766 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1767 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1768 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
Phani Kumar Uppalapatidb4416e2012-10-25 13:21:15 -07001769 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
Laxminath Kasam09e7ab62013-04-03 14:03:17 +05301770 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
1771 !((be->dpcm[stream].state == SND_SOC_DPCM_STATE_START) &&
1772 ((fe->dpcm[stream].state != SND_SOC_DPCM_STATE_START) &&
1773 (fe->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
1774 (fe->dpcm[stream].state !=
1775 SND_SOC_DPCM_STATE_SUSPEND))))
Steve Mucklef132c6c2012-06-06 18:30:57 -07001776 continue;
1777
1778 dev_dbg(be->dev, "dpcm: hw_free BE %s\n",
1779 dpcm_params->fe->dai_link->name);
1780
1781 soc_pcm_hw_free(be_substream);
1782
1783 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1784 }
1785
1786 return 0;
1787}
1788
1789int soc_dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
1790{
1791 struct snd_soc_pcm_runtime *fe = substream->private_data;
1792 int err, stream = substream->stream;
1793
1794 mutex_lock(&fe->card->dpcm_mutex);
1795 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1796
1797 dev_dbg(fe->dev, "dpcm: hw_free FE %s\n", fe->dai_link->name);
1798
1799 /* call hw_free on the frontend */
1800 err = soc_pcm_hw_free(substream);
1801 if (err < 0)
1802 dev_err(fe->dev,"dpcm: hw_free FE %s failed\n", fe->dai_link->name);
1803
1804 /* only hw_params backends that are either sinks or sources
1805 * to this frontend DAI */
1806 err = soc_dpcm_be_dai_hw_free(fe, stream);
1807
1808 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1809 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1810
1811 mutex_unlock(&fe->card->dpcm_mutex);
1812 return 0;
1813}
1814
1815static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
1816 unsigned int cmd, void *arg)
1817{
1818 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1819 struct snd_soc_platform *platform = rtd->platform;
1820
1821 if (platform->driver->ops->ioctl)
1822 return platform->driver->ops->ioctl(substream, cmd, arg);
1823 return snd_pcm_lib_ioctl(substream, cmd, arg);
1824}
1825
1826static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1827{
1828 struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream);
1829 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1830 int err;
1831
1832 dev_dbg(fe->dev, "runtime %s close on FE %s\n",
1833 stream ? "capture" : "playback", fe->dai_link->name);
1834
1835 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1836 /* call bespoke trigger - FE takes care of all BE triggers */
1837 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd stop\n",
1838 fe->dai_link->name);
1839
1840 err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
1841 if (err < 0)
1842 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1843 } else {
1844 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd stop\n",
1845 fe->dai_link->name);
1846
1847 err = soc_dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
1848 if (err < 0)
1849 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1850 }
1851
1852 err = soc_dpcm_be_dai_hw_free(fe, stream);
1853 if (err < 0)
1854 dev_err(fe->dev,"dpcm: hw_free FE failed %d\n", err);
1855
1856 err = soc_dpcm_be_dai_shutdown(fe, stream);
1857 if (err < 0)
1858 dev_err(fe->dev,"dpcm: shutdown FE failed %d\n", err);
1859
1860 /* run the stream event for each BE */
1861 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1862 soc_dpcm_dapm_stream_event(fe, stream,
1863 fe->cpu_dai->driver->playback.stream_name,
1864 SND_SOC_DAPM_STREAM_NOP);
1865 else
1866 soc_dpcm_dapm_stream_event(fe, stream,
1867 fe->cpu_dai->driver->capture.stream_name,
1868 SND_SOC_DAPM_STREAM_NOP);
1869
1870 return 0;
1871}
1872
1873static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
1874{
1875 struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream);
1876 struct snd_soc_dpcm_params *dpcm_params;
1877 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1878 int ret;
1879
1880 dev_dbg(fe->dev, "runtime %s open on FE %s\n",
1881 stream ? "capture" : "playback", fe->dai_link->name);
1882
1883 /* Only start the BE if the FE is ready */
1884 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
1885 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
1886 return -EINVAL;
1887
1888 /* startup must always be called for new BEs */
1889 ret = soc_dpcm_be_dai_startup(fe, stream);
1890 if (ret < 0) {
1891 goto disconnect;
1892 return ret;
1893 }
1894
1895 /* keep going if FE state is > open */
1896 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_OPEN)
1897 return 0;
1898
1899 ret = soc_dpcm_be_dai_hw_params(fe, stream);
1900 if (ret < 0) {
1901 goto close;
1902 return ret;
1903 }
1904
1905 /* keep going if FE state is > hw_params */
1906 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_PARAMS)
1907 return 0;
1908
1909
1910 ret = soc_dpcm_be_dai_prepare(fe, stream);
1911 if (ret < 0) {
1912 goto hw_free;
1913 return ret;
1914 }
1915
1916 /* run the stream event for each BE */
1917 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1918 soc_dpcm_dapm_stream_event(fe, stream,
1919 fe->cpu_dai->driver->playback.stream_name,
1920 SND_SOC_DAPM_STREAM_NOP);
1921 else
1922 soc_dpcm_dapm_stream_event(fe, stream,
1923 fe->cpu_dai->driver->capture.stream_name,
1924 SND_SOC_DAPM_STREAM_NOP);
1925
1926 /* keep going if FE state is > prepare */
1927 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE ||
1928 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
1929 return 0;
1930
1931 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1932 /* call trigger on the frontend - FE takes care of all BE triggers */
1933 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd start\n",
1934 fe->dai_link->name);
1935
1936 ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
1937 if (ret < 0) {
1938 dev_err(fe->dev,"dpcm: bespoke trigger FE failed %d\n", ret);
1939 goto hw_free;
1940 }
1941 } else {
1942 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n",
1943 fe->dai_link->name);
1944
1945 ret = soc_dpcm_be_dai_trigger(fe, stream,
1946 SNDRV_PCM_TRIGGER_START);
1947 if (ret < 0) {
1948 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1949 goto hw_free;
1950 }
1951 }
1952
1953 return 0;
1954
1955hw_free:
1956 soc_dpcm_be_dai_hw_free(fe, stream);
1957close:
1958 soc_dpcm_be_dai_shutdown(fe, stream);
1959disconnect:
1960 /* disconnect any non started BEs */
1961 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1962 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1963 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1964 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
1965 }
1966
1967 return ret;
1968}
1969
1970static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
1971{
1972 int ret;
1973
1974 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1975 ret = dpcm_run_update_startup(fe, stream);
1976 if (ret < 0)
1977 dev_err(fe->dev, "failed to startup some BEs\n");
1978 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1979
1980 return ret;
1981}
1982
1983static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
1984{
1985 int ret;
1986
1987 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1988 ret = dpcm_run_update_shutdown(fe, stream);
1989 if (ret < 0)
1990 dev_err(fe->dev, "failed to shutdown some BEs\n");
1991 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1992
1993 return ret;
1994}
1995
1996/* called when any mixer updates change FE -> BE the stream */
1997int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
1998{
1999 struct snd_soc_card *card;
2000 int i, ret = 0, old, new, paths;
2001
2002 if (widget->codec)
2003 card = widget->codec->card;
2004 else if (widget->platform)
2005 card = widget->platform->card;
2006 else
2007 return -EINVAL;
2008
2009 mutex_lock(&card->dpcm_mutex);
2010
2011 for (i = 0; i < card->num_rtd; i++) {
2012 struct snd_soc_dapm_widget_list *list;
2013 struct snd_soc_pcm_runtime *fe = &card->rtd[i];
2014
2015 /* make sure link is FE */
2016 if (!fe->dai_link->dynamic)
2017 continue;
2018
2019 /* only check active links */
2020 if (!fe->cpu_dai->active)
2021 continue;
2022
2023 /* DAPM sync will call this to update DSP paths */
2024 dev_dbg(fe->dev, "DPCM runtime update for FE %s\n", fe->dai_link->name);
2025
2026 /* skip if FE doesn't have playback capability */
2027 if (!fe->cpu_dai->driver->playback.channels_min)
2028 goto capture;
2029
2030 paths = fe_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
2031 if (paths < 0) {
2032 dev_warn(fe->dev, "%s no valid %s route from source to sink\n",
2033 fe->dai_link->name, "playback");
2034 ret = paths;
2035 goto out;
2036 }
2037
2038 /* update any new playback paths */
2039 new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 1);
2040 if (new) {
2041 dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
2042 fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
2043 be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
2044 }
2045
2046 /* update any old playback paths */
2047 old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 0);
2048 if (old) {
2049 dpcm_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
2050 fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
2051 be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
2052 }
2053
Banajit Goswamic2b05992012-08-19 23:09:58 -07002054 fe_path_put(&list);
2055
Steve Mucklef132c6c2012-06-06 18:30:57 -07002056capture:
2057 /* skip if FE doesn't have capture capability */
2058 if (!fe->cpu_dai->driver->capture.channels_min)
2059 continue;
2060
2061 paths = fe_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
2062 if (paths < 0) {
2063 dev_warn(fe->dev, "%s no valid %s route from source to sink\n",
2064 fe->dai_link->name, "capture");
2065 ret = paths;
2066 goto out;
2067 }
2068
2069 /* update any new capture paths */
2070 new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 1);
2071 if (new) {
2072 dpcm_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2073 fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
2074 be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
2075 }
2076
2077 /* update any old capture paths */
2078 old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 0);
2079 if (old) {
2080 dpcm_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2081 fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
2082 be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
2083 }
2084
2085 fe_path_put(&list);
2086 }
2087
2088out:
2089 mutex_unlock(&card->dpcm_mutex);
2090 return ret;
2091}
2092
2093int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
2094{
2095 struct snd_soc_dpcm_params *dpcm_params;
2096
2097 list_for_each_entry(dpcm_params,
2098 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2099
2100 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2101 struct snd_soc_dai *dai = be->codec_dai;
2102 struct snd_soc_dai_driver *drv = dai->driver;
2103
2104 if (be->dai_link->ignore_suspend)
2105 continue;
2106
2107 dev_dbg(be->dev, "BE digital mute %s\n", be->dai_link->name);
2108
2109 if (drv->ops->digital_mute && dai->playback_active)
2110 drv->ops->digital_mute(dai, mute);
2111 }
2112
2113 return 0;
2114}
2115
2116int soc_dpcm_be_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
2117{
2118 struct snd_soc_dpcm_params *dpcm_params;
2119
2120 /* suspend for playback */
2121 list_for_each_entry(dpcm_params,
2122 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2123
2124 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2125 struct snd_soc_dai *dai = be->cpu_dai;
2126 struct snd_soc_dai_driver *drv = dai->driver;
2127
2128 if (be->dai_link->ignore_suspend)
2129 continue;
2130
2131 dev_dbg(be->dev, "pm: BE CPU DAI playback suspend %s\n",
2132 be->dai_link->name);
2133
2134 if (drv->suspend && !drv->ac97_control)
2135 drv->suspend(dai);
2136 }
2137
2138 /* suspend for capture */
2139 list_for_each_entry(dpcm_params,
2140 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2141
2142 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2143 struct snd_soc_dai *dai = be->cpu_dai;
2144 struct snd_soc_dai_driver *drv = dai->driver;
2145
2146 if (be->dai_link->ignore_suspend)
2147 continue;
2148
2149 dev_dbg(be->dev, "pm: BE CPU DAI capture suspend %s\n",
2150 be->dai_link->name);
2151
2152 if (drv->suspend && !drv->ac97_control)
2153 drv->suspend(dai);
2154 }
2155
2156 return 0;
2157}
2158
2159int soc_dpcm_be_ac97_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
2160{
2161 struct snd_soc_dpcm_params *dpcm_params;
2162
2163 /* suspend for playback */
2164 list_for_each_entry(dpcm_params,
2165 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2166
2167 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2168 struct snd_soc_dai *dai = be->cpu_dai;
2169 struct snd_soc_dai_driver *drv = dai->driver;
2170
2171 if (be->dai_link->ignore_suspend)
2172 continue;
2173
2174 dev_dbg(be->dev, "pm: BE CPU DAI playback suspend %s\n",
2175 be->dai_link->name);
2176
2177 if (drv->suspend && drv->ac97_control)
2178 drv->suspend(dai);
2179 }
2180
2181 /* suspend for capture */
2182 list_for_each_entry(dpcm_params,
2183 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2184
2185 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2186 struct snd_soc_dai *dai = be->cpu_dai;
2187 struct snd_soc_dai_driver *drv = dai->driver;
2188
2189 if (be->dai_link->ignore_suspend)
2190 continue;
2191
2192 dev_dbg(be->dev, "pm: BE CPU DAI capture suspend %s\n",
2193 be->dai_link->name);
2194
2195 if (drv->suspend && drv->ac97_control)
2196 drv->suspend(dai);
2197 }
2198
2199 return 0;
2200}
2201
2202int soc_dpcm_be_platform_suspend(struct snd_soc_pcm_runtime *fe)
2203{
2204 struct snd_soc_dpcm_params *dpcm_params;
2205
2206 /* suspend for playback */
2207 list_for_each_entry(dpcm_params,
2208 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2209
2210 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2211 struct snd_soc_platform *platform = be->platform;
2212 struct snd_soc_platform_driver *drv = platform->driver;
2213 struct snd_soc_dai *dai = be->cpu_dai;
2214
2215 if (be->dai_link->ignore_suspend)
2216 continue;
2217
2218 dev_dbg(be->dev, "pm: BE platform playback suspend %s\n",
2219 be->dai_link->name);
2220
2221 if (drv->suspend && !platform->suspended) {
2222 drv->suspend(dai);
2223 platform->suspended = 1;
2224 }
2225 }
2226
2227 /* suspend for capture */
2228 list_for_each_entry(dpcm_params,
2229 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2230
2231 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2232 struct snd_soc_platform *platform = be->platform;
2233 struct snd_soc_platform_driver *drv = platform->driver;
2234 struct snd_soc_dai *dai = be->cpu_dai;
2235
2236 if (be->dai_link->ignore_suspend)
2237 continue;
2238
2239 dev_dbg(be->dev, "pm: BE platform capture suspend %s\n",
2240 be->dai_link->name);
2241
2242 if (drv->suspend && !platform->suspended) {
2243 drv->suspend(dai);
2244 platform->suspended = 1;
2245 }
2246 }
2247 return 0;
2248}
2249
2250int soc_dpcm_fe_suspend(struct snd_soc_pcm_runtime *fe)
2251{
2252 struct snd_soc_dai *dai = fe->cpu_dai;
2253 struct snd_soc_dai_driver *dai_drv = dai->driver;
2254 struct snd_soc_platform *platform = fe->platform;
2255 struct snd_soc_platform_driver *plat_drv = platform->driver;
2256
2257 if (dai_drv->suspend && !dai_drv->ac97_control)
2258 dai_drv->suspend(dai);
2259
2260 if (plat_drv->suspend && !platform->suspended) {
2261 plat_drv->suspend(dai);
2262 platform->suspended = 1;
2263 }
2264
2265 soc_dpcm_be_cpu_dai_suspend(fe);
2266 soc_dpcm_be_platform_suspend(fe);
2267
2268 return 0;
2269}
2270
2271int soc_dpcm_be_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
2272{
2273 struct snd_soc_dpcm_params *dpcm_params;
2274
2275 /* resume for playback */
2276 list_for_each_entry(dpcm_params,
2277 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2278
2279 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2280 struct snd_soc_dai *dai = be->cpu_dai;
2281 struct snd_soc_dai_driver *drv = dai->driver;
2282
2283 if (be->dai_link->ignore_suspend)
2284 continue;
2285
2286 dev_dbg(be->dev, "pm: BE CPU DAI playback resume %s\n",
2287 be->dai_link->name);
2288
2289 if (drv->resume && !drv->ac97_control)
2290 drv->resume(dai);
2291 }
2292
2293 /* suspend for capture */
2294 list_for_each_entry(dpcm_params,
2295 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2296
2297 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2298 struct snd_soc_dai *dai = be->cpu_dai;
2299 struct snd_soc_dai_driver *drv = dai->driver;
2300
2301 if (be->dai_link->ignore_suspend)
2302 continue;
2303
2304 dev_dbg(be->dev, "pm: BE CPU DAI capture resume %s\n",
2305 be->dai_link->name);
2306
2307 if (drv->resume && !drv->ac97_control)
2308 drv->resume(dai);
2309 }
2310
2311 return 0;
2312}
2313
2314int soc_dpcm_be_ac97_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
2315{
2316 struct snd_soc_dpcm_params *dpcm_params;
2317
2318 /* resume for playback */
2319 list_for_each_entry(dpcm_params,
2320 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2321
2322 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2323 struct snd_soc_dai *dai = be->cpu_dai;
2324 struct snd_soc_dai_driver *drv = dai->driver;
2325
2326 if (be->dai_link->ignore_suspend)
2327 continue;
2328
2329 dev_dbg(be->dev, "pm: BE CPU DAI playback resume %s\n",
2330 be->dai_link->name);
2331
2332 if (drv->resume && drv->ac97_control)
2333 drv->resume(dai);
2334 }
2335
2336 /* suspend for capture */
2337 list_for_each_entry(dpcm_params,
2338 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2339
2340 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2341 struct snd_soc_dai *dai = be->cpu_dai;
2342 struct snd_soc_dai_driver *drv = dai->driver;
2343
2344 if (be->dai_link->ignore_suspend)
2345 continue;
2346
2347 dev_dbg(be->dev, "pm: BE CPU DAI capture resume %s\n",
2348 be->dai_link->name);
2349
2350 if (drv->resume && drv->ac97_control)
2351 drv->resume(dai);
2352 }
2353
2354 return 0;
2355}
2356
2357int soc_dpcm_be_platform_resume(struct snd_soc_pcm_runtime *fe)
2358{
2359 struct snd_soc_dpcm_params *dpcm_params;
2360
2361 /* resume for playback */
2362 list_for_each_entry(dpcm_params,
2363 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2364
2365 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2366 struct snd_soc_platform *platform = be->platform;
2367 struct snd_soc_platform_driver *drv = platform->driver;
2368 struct snd_soc_dai *dai = be->cpu_dai;
2369
2370 if (be->dai_link->ignore_suspend)
2371 continue;
2372
2373 dev_dbg(be->dev, "pm: BE platform playback resume %s\n",
2374 be->dai_link->name);
2375
2376 if (drv->resume && platform->suspended) {
2377 drv->resume(dai);
2378 platform->suspended = 0;
2379 }
2380 }
2381
2382 /* resume for capture */
2383 list_for_each_entry(dpcm_params,
2384 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2385
2386 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2387 struct snd_soc_platform *platform = be->platform;
2388 struct snd_soc_platform_driver *drv = platform->driver;
2389 struct snd_soc_dai *dai = be->cpu_dai;
2390
2391 if (be->dai_link->ignore_suspend)
2392 continue;
2393
2394 dev_dbg(be->dev, "pm: BE platform capture resume %s\n",
2395 be->dai_link->name);
2396
2397 if (drv->resume && platform->suspended) {
2398 drv->resume(dai);
2399 platform->suspended = 0;
2400 }
2401 }
2402
2403 return 0;
2404}
2405
2406int soc_dpcm_fe_resume(struct snd_soc_pcm_runtime *fe)
2407{
2408 struct snd_soc_dai *dai = fe->cpu_dai;
2409 struct snd_soc_dai_driver *dai_drv = dai->driver;
2410 struct snd_soc_platform *platform = fe->platform;
2411 struct snd_soc_platform_driver *plat_drv = platform->driver;
2412
2413 soc_dpcm_be_cpu_dai_resume(fe);
2414 soc_dpcm_be_platform_resume(fe);
2415
2416 if (dai_drv->resume && !dai_drv->ac97_control)
2417 dai_drv->resume(dai);
2418
2419 if (plat_drv->resume && platform->suspended) {
2420 plat_drv->resume(dai);
2421 platform->suspended = 0;
2422 }
2423
2424 return 0;
2425}
2426
2427/* called when opening FE stream */
2428int soc_dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
2429{
2430 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2431 struct snd_soc_dpcm_params *dpcm_params;
2432 struct snd_soc_dapm_widget_list *list;
2433 int ret;
2434 int stream = fe_substream->stream;
2435
2436 fe->dpcm[stream].runtime = fe_substream->runtime;
2437
2438 if (fe_path_get(fe, stream, &list) <= 0) {
2439 dev_warn(fe->dev, "asoc: %s no valid %s route from source to sink\n",
2440 fe->dai_link->name, stream ? "capture" : "playback");
2441 return -EINVAL;
2442 }
2443
2444 /* calculate valid and active FE <-> BE dpcm_paramss */
2445 dpcm_process_paths(fe, stream, &list, 1);
2446
2447 ret = soc_dpcm_fe_dai_startup(fe_substream);
2448 if (ret < 0) {
2449 /* clean up all links */
2450 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
2451 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
2452
2453 be_disconnect(fe, stream);
2454 fe->dpcm[stream].runtime = NULL;
2455 }
2456
2457 fe_clear_pending(fe, stream);
2458 fe_path_put(&list);
2459 return ret;
2460}
2461
2462/* called when closing FE stream */
2463int soc_dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
2464{
2465 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2466 struct snd_soc_dpcm_params *dpcm_params;
2467 int stream = fe_substream->stream, ret;
2468
2469 ret = soc_dpcm_fe_dai_shutdown(fe_substream);
2470
2471 /* mark FE's links ready to prune */
2472 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
2473 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
2474
2475 be_disconnect(fe, stream);
2476
2477 fe->dpcm[stream].runtime = NULL;
2478
2479 return ret;
2480}
2481
Liam Girdwoodddee6272011-06-09 14:45:53 +01002482/* create a new pcm */
2483int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2484{
2485 struct snd_soc_codec *codec = rtd->codec;
2486 struct snd_soc_platform *platform = rtd->platform;
2487 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2488 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002489 struct snd_pcm_substream *substream[2];
Liam Girdwoodddee6272011-06-09 14:45:53 +01002490 struct snd_pcm *pcm;
2491 char new_name[64];
2492 int ret = 0, playback = 0, capture = 0;
2493
Steve Mucklef132c6c2012-06-06 18:30:57 -07002494 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
2495 if (cpu_dai->driver->playback.channels_min)
2496 playback = 1;
2497 if (cpu_dai->driver->capture.channels_min)
2498 capture = 1;
2499 } else {
2500 if (codec_dai->driver->playback.channels_min)
2501 playback = 1;
2502 if (codec_dai->driver->capture.channels_min)
2503 capture = 1;
2504 }
Sangsu Parka5002312012-01-02 17:15:10 +09002505
Steve Mucklef132c6c2012-06-06 18:30:57 -07002506 /* create the PCM */
2507 if (rtd->dai_link->no_pcm) {
2508 snprintf(new_name, sizeof(new_name), "(%s)",
2509 rtd->dai_link->stream_name);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002510
Steve Mucklef132c6c2012-06-06 18:30:57 -07002511 ret = snd_pcm_new_soc_be(rtd->card->snd_card, new_name, num,
2512 playback, capture, &pcm);
2513 } else {
2514 if (rtd->dai_link->dynamic)
2515 snprintf(new_name, sizeof(new_name), "%s (*)",
2516 rtd->dai_link->stream_name);
2517 else
2518 snprintf(new_name, sizeof(new_name), "%s %s-%d",
2519 rtd->dai_link->stream_name, codec_dai->name, num);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002520
Steve Mucklef132c6c2012-06-06 18:30:57 -07002521 ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
2522 capture, &pcm);
2523 }
Liam Girdwoodddee6272011-06-09 14:45:53 +01002524 if (ret < 0) {
2525 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
2526 return ret;
2527 }
Steve Mucklef132c6c2012-06-06 18:30:57 -07002528 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002529
2530 rtd->pcm = pcm;
2531 pcm->private_data = rtd;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002532 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
2533
2534 substream[SNDRV_PCM_STREAM_PLAYBACK] =
2535 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
2536 substream[SNDRV_PCM_STREAM_CAPTURE] =
2537 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
2538
2539 if (rtd->dai_link->no_pcm) {
2540 if (playback)
2541 substream[SNDRV_PCM_STREAM_PLAYBACK]->private_data = rtd;
2542 if (capture)
2543 substream[SNDRV_PCM_STREAM_CAPTURE]->private_data = rtd;
2544 goto out;
2545 }
2546
2547 /* setup any hostless PCMs - i.e. no host IO is performed */
2548 if (rtd->dai_link->no_host_mode) {
2549 if (substream[SNDRV_PCM_STREAM_PLAYBACK]) {
2550 substream[SNDRV_PCM_STREAM_PLAYBACK]->hw_no_buffer = 1;
2551 snd_soc_set_runtime_hwparams(
2552 substream[SNDRV_PCM_STREAM_PLAYBACK],
2553 &no_host_hardware);
2554 }
2555 if (substream[SNDRV_PCM_STREAM_CAPTURE]) {
2556 substream[SNDRV_PCM_STREAM_CAPTURE]->hw_no_buffer = 1;
2557 snd_soc_set_runtime_hwparams(
2558 substream[SNDRV_PCM_STREAM_CAPTURE],
2559 &no_host_hardware);
2560 }
2561 }
2562
2563 /* ASoC PCM operations */
2564 if (rtd->dai_link->dynamic) {
2565 rtd->ops.open = soc_dpcm_fe_dai_open;
2566 rtd->ops.hw_params = soc_dpcm_fe_dai_hw_params;
2567 rtd->ops.prepare = soc_dpcm_fe_dai_prepare;
2568 rtd->ops.trigger = soc_dpcm_fe_dai_trigger;
2569 rtd->ops.hw_free = soc_dpcm_fe_dai_hw_free;
2570 rtd->ops.close = soc_dpcm_fe_dai_close;
2571 rtd->ops.pointer = soc_pcm_pointer;
2572 rtd->ops.ioctl = soc_pcm_ioctl;
2573 } else {
2574 rtd->ops.open = soc_pcm_open;
2575 rtd->ops.hw_params = soc_pcm_hw_params;
2576 rtd->ops.prepare = soc_pcm_prepare;
2577 rtd->ops.trigger = soc_pcm_trigger;
2578 rtd->ops.hw_free = soc_pcm_hw_free;
2579 rtd->ops.close = soc_pcm_close;
2580 rtd->ops.pointer = soc_pcm_pointer;
2581 rtd->ops.ioctl = soc_pcm_ioctl;
2582 }
2583
Liam Girdwoodddee6272011-06-09 14:45:53 +01002584 if (platform->driver->ops) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07002585 rtd->ops.ack = platform->driver->ops->ack;
2586 rtd->ops.copy = platform->driver->ops->copy;
2587 rtd->ops.silence = platform->driver->ops->silence;
2588 rtd->ops.page = platform->driver->ops->page;
2589 rtd->ops.mmap = platform->driver->ops->mmap;
Santosh Mardie56cad02012-10-09 10:40:17 +05302590 rtd->ops.restart = platform->driver->ops->restart;
Liam Girdwoodddee6272011-06-09 14:45:53 +01002591 }
2592
2593 if (playback)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002594 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002595
2596 if (capture)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002597 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002598
2599 if (platform->driver->pcm_new) {
2600 ret = platform->driver->pcm_new(rtd);
2601 if (ret < 0) {
2602 pr_err("asoc: platform pcm constructor failed\n");
2603 return ret;
2604 }
2605 }
2606
2607 pcm->private_free = platform->driver->pcm_free;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002608out:
Liam Girdwoodddee6272011-06-09 14:45:53 +01002609 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
2610 cpu_dai->name);
2611 return ret;
2612}
Steve Mucklef132c6c2012-06-06 18:30:57 -07002613
2614#ifdef CONFIG_DEBUG_FS
2615static char *dpcm_state_string(enum snd_soc_dpcm_state state)
2616{
2617 switch (state) {
2618 case SND_SOC_DPCM_STATE_NEW:
2619 return "new";
2620 case SND_SOC_DPCM_STATE_OPEN:
2621 return "open";
2622 case SND_SOC_DPCM_STATE_HW_PARAMS:
2623 return "hw_params";
2624 case SND_SOC_DPCM_STATE_PREPARE:
2625 return "prepare";
2626 case SND_SOC_DPCM_STATE_START:
2627 return "start";
2628 case SND_SOC_DPCM_STATE_STOP:
2629 return "stop";
2630 case SND_SOC_DPCM_STATE_SUSPEND:
2631 return "suspend";
2632 case SND_SOC_DPCM_STATE_PAUSED:
2633 return "paused";
2634 case SND_SOC_DPCM_STATE_HW_FREE:
2635 return "hw_free";
2636 case SND_SOC_DPCM_STATE_CLOSE:
2637 return "close";
2638 }
2639
2640 return "unknown";
2641}
2642
2643static int soc_dpcm_state_open_file(struct inode *inode, struct file *file)
2644{
2645 file->private_data = inode->i_private;
2646 return 0;
2647}
2648
2649static ssize_t soc_dpcm_show_state(struct snd_soc_pcm_runtime *fe,
2650 int stream, char *buf, size_t size)
2651{
2652 struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
2653 struct snd_soc_dpcm_params *dpcm_params;
2654 ssize_t offset = 0;
2655
2656 /* FE state */
2657 offset += snprintf(buf + offset, size - offset,
2658 "[%s - %s]\n", fe->dai_link->name,
2659 stream ? "Capture" : "Playback");
2660
2661 offset += snprintf(buf + offset, size - offset, "State: %s\n",
2662 dpcm_state_string(fe->dpcm[stream].state));
2663
2664 if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
2665 (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
2666 offset += snprintf(buf + offset, size - offset,
2667 "Hardware Params: "
2668 "Format = %s, Channels = %d, Rate = %d\n",
2669 snd_pcm_format_name(params_format(params)),
2670 params_channels(params),
2671 params_rate(params));
2672
2673 /* BEs state */
2674 offset += snprintf(buf + offset, size - offset, "Backends:\n");
2675
2676 if (list_empty(&fe->dpcm[stream].be_clients)) {
2677 offset += snprintf(buf + offset, size - offset,
2678 " No active DSP links\n");
2679 goto out;
2680 }
2681
2682 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
2683 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2684
2685 offset += snprintf(buf + offset, size - offset,
2686 "- %s\n", be->dai_link->name);
2687
2688 offset += snprintf(buf + offset, size - offset,
2689 " State: %s\n",
2690 dpcm_state_string(fe->dpcm[stream].state));
2691
2692 if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
2693 (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
2694 offset += snprintf(buf + offset, size - offset,
2695 " Hardware Params: "
2696 "Format = %s, Channels = %d, Rate = %d\n",
2697 snd_pcm_format_name(params_format(params)),
2698 params_channels(params),
2699 params_rate(params));
2700 }
2701
2702out:
2703 return offset;
2704}
2705
2706static ssize_t soc_dpcm_state_read_file(struct file *file, char __user *user_buf,
2707 size_t count, loff_t *ppos)
2708{
2709 struct snd_soc_pcm_runtime *fe = file->private_data;
2710 ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
2711 char *buf;
2712
2713 buf = kmalloc(out_count, GFP_KERNEL);
2714 if (!buf)
2715 return -ENOMEM;
2716
2717 if (fe->cpu_dai->driver->playback.channels_min)
2718 offset += soc_dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK,
2719 buf + offset, out_count - offset);
2720
2721 if (fe->cpu_dai->driver->capture.channels_min)
2722 offset += soc_dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE,
2723 buf + offset, out_count - offset);
2724
2725 ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
2726
2727 kfree(buf);
2728
2729 return ret;
2730}
2731
2732static const struct file_operations soc_dpcm_state_fops = {
2733 .open = soc_dpcm_state_open_file,
2734 .read = soc_dpcm_state_read_file,
2735 .llseek = default_llseek,
2736};
2737
2738int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
2739{
2740 rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
2741 rtd->card->debugfs_card_root);
2742 if (!rtd->debugfs_dpcm_root) {
2743 dev_dbg(rtd->dev,
2744 "ASoC: Failed to create dpcm debugfs directory %s\n",
2745 rtd->dai_link->name);
2746 return -EINVAL;
2747 }
2748
2749 rtd->debugfs_dpcm_state = debugfs_create_file("state", 0644,
2750 rtd->debugfs_dpcm_root,
2751 rtd, &soc_dpcm_state_fops);
2752
2753 return 0;
2754}
2755#endif