blob: f989b1734dc864125548771b8db0dab703de6231 [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
1499 if ((cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) ||
1500 (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH))
1501 return ret;
1502
1503 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1504
1505 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1506 struct snd_pcm_substream *be_substream =
1507 snd_soc_dpcm_get_substream(be, stream);
1508
1509 /* is this op for this BE ? */
1510 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1511 continue;
1512
1513 switch (cmd) {
1514 case SNDRV_PCM_TRIGGER_START:
1515 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1516 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1517 continue;
1518
1519 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1520 if (ret)
1521 return ret;
1522
1523 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1524 break;
1525 case SNDRV_PCM_TRIGGER_RESUME:
1526 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
1527 continue;
1528
1529 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1530 if (ret)
1531 return ret;
1532
1533 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1534 break;
1535 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1536 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
1537 continue;
1538
1539 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1540 if (ret)
1541 return ret;
1542
1543 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1544 break;
1545 case SNDRV_PCM_TRIGGER_STOP:
1546 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1547 continue;
1548
1549 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1550 continue;
1551
1552 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1553 if (ret)
1554 return ret;
1555
1556 be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1557 break;
1558 case SNDRV_PCM_TRIGGER_SUSPEND:
1559 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)
1560 continue;
1561
1562 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1563 continue;
1564
1565 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1566 if (ret)
1567 return ret;
1568
1569 be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND;
1570 break;
1571 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1572 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1573 continue;
1574
1575 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1576 continue;
1577
1578 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1579 if (ret)
1580 return ret;
1581
1582 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
1583 break;
1584 }
1585 }
1586
1587 return ret;
1588}
1589EXPORT_SYMBOL_GPL(soc_dpcm_be_dai_trigger);
1590
1591int soc_dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
1592{
1593 struct snd_soc_pcm_runtime *fe = substream->private_data;
1594 int stream = substream->stream, ret;
1595 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1596
1597 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1598
1599 switch (trigger) {
1600 case SND_SOC_DPCM_TRIGGER_PRE:
1601 /* call trigger on the frontend before the backend. */
1602
1603 dev_dbg(fe->dev, "dpcm: pre trigger FE %s cmd %d\n",
1604 fe->dai_link->name, cmd);
1605
1606 ret = soc_pcm_trigger(substream, cmd);
1607 if (ret < 0) {
1608 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1609 goto out;
1610 }
1611
1612 ret = soc_dpcm_be_dai_trigger(fe, substream->stream, cmd);
1613 break;
1614 case SND_SOC_DPCM_TRIGGER_POST:
1615 /* call trigger on the frontend after the backend. */
1616
1617 ret = soc_dpcm_be_dai_trigger(fe, substream->stream, cmd);
1618 if (ret < 0) {
1619 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1620 goto out;
1621 }
1622
1623 dev_dbg(fe->dev, "dpcm: post trigger FE %s cmd %d\n",
1624 fe->dai_link->name, cmd);
1625
1626 ret = soc_pcm_trigger(substream, cmd);
1627 break;
1628 case SND_SOC_DPCM_TRIGGER_BESPOKE:
1629 /* bespoke trigger() - handles both FE and BEs */
1630
1631 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd %d\n",
1632 fe->dai_link->name, cmd);
1633
1634 ret = soc_pcm_bespoke_trigger(substream, cmd);
1635 if (ret < 0) {
1636 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1637 goto out;
1638 }
1639 break;
1640 default:
1641 dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd,
1642 fe->dai_link->name);
1643 ret = -EINVAL;
1644 goto out;
1645 }
1646
1647 switch (cmd) {
1648 case SNDRV_PCM_TRIGGER_START:
1649 case SNDRV_PCM_TRIGGER_RESUME:
1650 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1651 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1652 break;
1653 case SNDRV_PCM_TRIGGER_STOP:
1654 case SNDRV_PCM_TRIGGER_SUSPEND:
1655 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1656 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1657 break;
1658 }
1659
1660out:
1661 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1662 return ret;
1663}
1664
1665static int soc_dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
1666{
1667 struct snd_soc_dpcm_params *dpcm_params;
1668 int ret = 0;
1669
1670 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1671
1672 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1673 struct snd_pcm_substream *be_substream =
1674 snd_soc_dpcm_get_substream(be, stream);
1675
1676 /* is this op for this BE ? */
1677 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1678 continue;
1679
1680 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1681 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1682 continue;
1683
1684 dev_dbg(be->dev, "dpcm: prepare BE %s\n",
1685 dpcm_params->fe->dai_link->name);
1686
1687 ret = soc_pcm_prepare(be_substream);
1688 if (ret < 0) {
1689 dev_err(be->dev, "dpcm: backend prepare failed %d\n",
1690 ret);
1691 break;
1692 }
1693
1694 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1695 }
1696 return ret;
1697}
1698
1699int soc_dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
1700{
1701 struct snd_soc_pcm_runtime *fe = substream->private_data;
1702 int stream = substream->stream, ret = 0;
1703
1704 mutex_lock(&fe->card->dpcm_mutex);
1705
1706 dev_dbg(fe->dev, "dpcm: prepare FE %s\n", fe->dai_link->name);
1707
1708 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1709
1710 /* there is no point preparing this FE if there are no BEs */
1711 if (list_empty(&fe->dpcm[stream].be_clients)) {
1712 dev_err(fe->dev, "dpcm: no backend DAIs enabled for %s\n",
1713 fe->dai_link->name);
1714 ret = -EINVAL;
1715 goto out;
1716 }
1717
1718 ret = soc_dpcm_be_dai_prepare(fe, substream->stream);
1719 if (ret < 0)
1720 goto out;
1721
1722 /* call prepare on the frontend */
1723 ret = soc_pcm_prepare(substream);
1724 if (ret < 0) {
1725 dev_err(fe->dev,"dpcm: prepare FE %s failed\n", fe->dai_link->name);
1726 goto out;
1727 }
1728
1729 /* run the stream event for each BE */
1730 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1731 soc_dpcm_dapm_stream_event(fe, stream,
1732 fe->cpu_dai->driver->playback.stream_name,
1733 SND_SOC_DAPM_STREAM_START);
1734 else
1735 soc_dpcm_dapm_stream_event(fe, stream,
1736 fe->cpu_dai->driver->capture.stream_name,
1737 SND_SOC_DAPM_STREAM_START);
1738
1739 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1740
1741out:
1742 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1743 mutex_unlock(&fe->card->dpcm_mutex);
1744 return ret;
1745}
1746
1747static int soc_dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
1748{
1749 struct snd_soc_dpcm_params *dpcm_params;
1750
1751 /* only hw_params backends that are either sinks or sources
1752 * to this frontend DAI */
1753 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1754
1755 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1756 struct snd_pcm_substream *be_substream =
1757 snd_soc_dpcm_get_substream(be, stream);
1758
1759 /* is this op for this BE ? */
1760 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1761 continue;
1762
1763 /* only free hw when no longer used - check all FEs */
1764 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1765 continue;
1766
1767 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1768 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1769 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1770 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1771 continue;
1772
1773 dev_dbg(be->dev, "dpcm: hw_free BE %s\n",
1774 dpcm_params->fe->dai_link->name);
1775
1776 soc_pcm_hw_free(be_substream);
1777
1778 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1779 }
1780
1781 return 0;
1782}
1783
1784int soc_dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
1785{
1786 struct snd_soc_pcm_runtime *fe = substream->private_data;
1787 int err, stream = substream->stream;
1788
1789 mutex_lock(&fe->card->dpcm_mutex);
1790 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1791
1792 dev_dbg(fe->dev, "dpcm: hw_free FE %s\n", fe->dai_link->name);
1793
1794 /* call hw_free on the frontend */
1795 err = soc_pcm_hw_free(substream);
1796 if (err < 0)
1797 dev_err(fe->dev,"dpcm: hw_free FE %s failed\n", fe->dai_link->name);
1798
1799 /* only hw_params backends that are either sinks or sources
1800 * to this frontend DAI */
1801 err = soc_dpcm_be_dai_hw_free(fe, stream);
1802
1803 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1804 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1805
1806 mutex_unlock(&fe->card->dpcm_mutex);
1807 return 0;
1808}
1809
1810static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
1811 unsigned int cmd, void *arg)
1812{
1813 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1814 struct snd_soc_platform *platform = rtd->platform;
1815
1816 if (platform->driver->ops->ioctl)
1817 return platform->driver->ops->ioctl(substream, cmd, arg);
1818 return snd_pcm_lib_ioctl(substream, cmd, arg);
1819}
1820
1821static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1822{
1823 struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream);
1824 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1825 int err;
1826
1827 dev_dbg(fe->dev, "runtime %s close on FE %s\n",
1828 stream ? "capture" : "playback", fe->dai_link->name);
1829
1830 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1831 /* call bespoke trigger - FE takes care of all BE triggers */
1832 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd stop\n",
1833 fe->dai_link->name);
1834
1835 err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
1836 if (err < 0)
1837 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1838 } else {
1839 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd stop\n",
1840 fe->dai_link->name);
1841
1842 err = soc_dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
1843 if (err < 0)
1844 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1845 }
1846
1847 err = soc_dpcm_be_dai_hw_free(fe, stream);
1848 if (err < 0)
1849 dev_err(fe->dev,"dpcm: hw_free FE failed %d\n", err);
1850
1851 err = soc_dpcm_be_dai_shutdown(fe, stream);
1852 if (err < 0)
1853 dev_err(fe->dev,"dpcm: shutdown FE failed %d\n", err);
1854
1855 /* run the stream event for each BE */
1856 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1857 soc_dpcm_dapm_stream_event(fe, stream,
1858 fe->cpu_dai->driver->playback.stream_name,
1859 SND_SOC_DAPM_STREAM_NOP);
1860 else
1861 soc_dpcm_dapm_stream_event(fe, stream,
1862 fe->cpu_dai->driver->capture.stream_name,
1863 SND_SOC_DAPM_STREAM_NOP);
1864
1865 return 0;
1866}
1867
1868static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
1869{
1870 struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream);
1871 struct snd_soc_dpcm_params *dpcm_params;
1872 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1873 int ret;
1874
1875 dev_dbg(fe->dev, "runtime %s open on FE %s\n",
1876 stream ? "capture" : "playback", fe->dai_link->name);
1877
1878 /* Only start the BE if the FE is ready */
1879 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
1880 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
1881 return -EINVAL;
1882
1883 /* startup must always be called for new BEs */
1884 ret = soc_dpcm_be_dai_startup(fe, stream);
1885 if (ret < 0) {
1886 goto disconnect;
1887 return ret;
1888 }
1889
1890 /* keep going if FE state is > open */
1891 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_OPEN)
1892 return 0;
1893
1894 ret = soc_dpcm_be_dai_hw_params(fe, stream);
1895 if (ret < 0) {
1896 goto close;
1897 return ret;
1898 }
1899
1900 /* keep going if FE state is > hw_params */
1901 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_PARAMS)
1902 return 0;
1903
1904
1905 ret = soc_dpcm_be_dai_prepare(fe, stream);
1906 if (ret < 0) {
1907 goto hw_free;
1908 return ret;
1909 }
1910
1911 /* run the stream event for each BE */
1912 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1913 soc_dpcm_dapm_stream_event(fe, stream,
1914 fe->cpu_dai->driver->playback.stream_name,
1915 SND_SOC_DAPM_STREAM_NOP);
1916 else
1917 soc_dpcm_dapm_stream_event(fe, stream,
1918 fe->cpu_dai->driver->capture.stream_name,
1919 SND_SOC_DAPM_STREAM_NOP);
1920
1921 /* keep going if FE state is > prepare */
1922 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE ||
1923 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
1924 return 0;
1925
1926 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1927 /* call trigger on the frontend - FE takes care of all BE triggers */
1928 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd start\n",
1929 fe->dai_link->name);
1930
1931 ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
1932 if (ret < 0) {
1933 dev_err(fe->dev,"dpcm: bespoke trigger FE failed %d\n", ret);
1934 goto hw_free;
1935 }
1936 } else {
1937 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n",
1938 fe->dai_link->name);
1939
1940 ret = soc_dpcm_be_dai_trigger(fe, stream,
1941 SNDRV_PCM_TRIGGER_START);
1942 if (ret < 0) {
1943 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1944 goto hw_free;
1945 }
1946 }
1947
1948 return 0;
1949
1950hw_free:
1951 soc_dpcm_be_dai_hw_free(fe, stream);
1952close:
1953 soc_dpcm_be_dai_shutdown(fe, stream);
1954disconnect:
1955 /* disconnect any non started BEs */
1956 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1957 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1958 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1959 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
1960 }
1961
1962 return ret;
1963}
1964
1965static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
1966{
1967 int ret;
1968
1969 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1970 ret = dpcm_run_update_startup(fe, stream);
1971 if (ret < 0)
1972 dev_err(fe->dev, "failed to startup some BEs\n");
1973 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1974
1975 return ret;
1976}
1977
1978static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
1979{
1980 int ret;
1981
1982 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1983 ret = dpcm_run_update_shutdown(fe, stream);
1984 if (ret < 0)
1985 dev_err(fe->dev, "failed to shutdown some BEs\n");
1986 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1987
1988 return ret;
1989}
1990
1991/* called when any mixer updates change FE -> BE the stream */
1992int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
1993{
1994 struct snd_soc_card *card;
1995 int i, ret = 0, old, new, paths;
1996
1997 if (widget->codec)
1998 card = widget->codec->card;
1999 else if (widget->platform)
2000 card = widget->platform->card;
2001 else
2002 return -EINVAL;
2003
2004 mutex_lock(&card->dpcm_mutex);
2005
2006 for (i = 0; i < card->num_rtd; i++) {
2007 struct snd_soc_dapm_widget_list *list;
2008 struct snd_soc_pcm_runtime *fe = &card->rtd[i];
2009
2010 /* make sure link is FE */
2011 if (!fe->dai_link->dynamic)
2012 continue;
2013
2014 /* only check active links */
2015 if (!fe->cpu_dai->active)
2016 continue;
2017
2018 /* DAPM sync will call this to update DSP paths */
2019 dev_dbg(fe->dev, "DPCM runtime update for FE %s\n", fe->dai_link->name);
2020
2021 /* skip if FE doesn't have playback capability */
2022 if (!fe->cpu_dai->driver->playback.channels_min)
2023 goto capture;
2024
2025 paths = fe_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
2026 if (paths < 0) {
2027 dev_warn(fe->dev, "%s no valid %s route from source to sink\n",
2028 fe->dai_link->name, "playback");
2029 ret = paths;
2030 goto out;
2031 }
2032
2033 /* update any new playback paths */
2034 new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 1);
2035 if (new) {
2036 dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
2037 fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
2038 be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
2039 }
2040
2041 /* update any old playback paths */
2042 old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 0);
2043 if (old) {
2044 dpcm_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
2045 fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
2046 be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
2047 }
2048
Banajit Goswamic2b05992012-08-19 23:09:58 -07002049 fe_path_put(&list);
2050
Steve Mucklef132c6c2012-06-06 18:30:57 -07002051capture:
2052 /* skip if FE doesn't have capture capability */
2053 if (!fe->cpu_dai->driver->capture.channels_min)
2054 continue;
2055
2056 paths = fe_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
2057 if (paths < 0) {
2058 dev_warn(fe->dev, "%s no valid %s route from source to sink\n",
2059 fe->dai_link->name, "capture");
2060 ret = paths;
2061 goto out;
2062 }
2063
2064 /* update any new capture paths */
2065 new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 1);
2066 if (new) {
2067 dpcm_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2068 fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
2069 be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
2070 }
2071
2072 /* update any old capture paths */
2073 old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 0);
2074 if (old) {
2075 dpcm_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2076 fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
2077 be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
2078 }
2079
2080 fe_path_put(&list);
2081 }
2082
2083out:
2084 mutex_unlock(&card->dpcm_mutex);
2085 return ret;
2086}
2087
2088int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
2089{
2090 struct snd_soc_dpcm_params *dpcm_params;
2091
2092 list_for_each_entry(dpcm_params,
2093 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2094
2095 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2096 struct snd_soc_dai *dai = be->codec_dai;
2097 struct snd_soc_dai_driver *drv = dai->driver;
2098
2099 if (be->dai_link->ignore_suspend)
2100 continue;
2101
2102 dev_dbg(be->dev, "BE digital mute %s\n", be->dai_link->name);
2103
2104 if (drv->ops->digital_mute && dai->playback_active)
2105 drv->ops->digital_mute(dai, mute);
2106 }
2107
2108 return 0;
2109}
2110
2111int soc_dpcm_be_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
2112{
2113 struct snd_soc_dpcm_params *dpcm_params;
2114
2115 /* suspend for playback */
2116 list_for_each_entry(dpcm_params,
2117 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2118
2119 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2120 struct snd_soc_dai *dai = be->cpu_dai;
2121 struct snd_soc_dai_driver *drv = dai->driver;
2122
2123 if (be->dai_link->ignore_suspend)
2124 continue;
2125
2126 dev_dbg(be->dev, "pm: BE CPU DAI playback suspend %s\n",
2127 be->dai_link->name);
2128
2129 if (drv->suspend && !drv->ac97_control)
2130 drv->suspend(dai);
2131 }
2132
2133 /* suspend for capture */
2134 list_for_each_entry(dpcm_params,
2135 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2136
2137 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2138 struct snd_soc_dai *dai = be->cpu_dai;
2139 struct snd_soc_dai_driver *drv = dai->driver;
2140
2141 if (be->dai_link->ignore_suspend)
2142 continue;
2143
2144 dev_dbg(be->dev, "pm: BE CPU DAI capture suspend %s\n",
2145 be->dai_link->name);
2146
2147 if (drv->suspend && !drv->ac97_control)
2148 drv->suspend(dai);
2149 }
2150
2151 return 0;
2152}
2153
2154int soc_dpcm_be_ac97_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
2155{
2156 struct snd_soc_dpcm_params *dpcm_params;
2157
2158 /* suspend for playback */
2159 list_for_each_entry(dpcm_params,
2160 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2161
2162 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2163 struct snd_soc_dai *dai = be->cpu_dai;
2164 struct snd_soc_dai_driver *drv = dai->driver;
2165
2166 if (be->dai_link->ignore_suspend)
2167 continue;
2168
2169 dev_dbg(be->dev, "pm: BE CPU DAI playback suspend %s\n",
2170 be->dai_link->name);
2171
2172 if (drv->suspend && drv->ac97_control)
2173 drv->suspend(dai);
2174 }
2175
2176 /* suspend for capture */
2177 list_for_each_entry(dpcm_params,
2178 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2179
2180 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2181 struct snd_soc_dai *dai = be->cpu_dai;
2182 struct snd_soc_dai_driver *drv = dai->driver;
2183
2184 if (be->dai_link->ignore_suspend)
2185 continue;
2186
2187 dev_dbg(be->dev, "pm: BE CPU DAI capture suspend %s\n",
2188 be->dai_link->name);
2189
2190 if (drv->suspend && drv->ac97_control)
2191 drv->suspend(dai);
2192 }
2193
2194 return 0;
2195}
2196
2197int soc_dpcm_be_platform_suspend(struct snd_soc_pcm_runtime *fe)
2198{
2199 struct snd_soc_dpcm_params *dpcm_params;
2200
2201 /* suspend for playback */
2202 list_for_each_entry(dpcm_params,
2203 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2204
2205 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2206 struct snd_soc_platform *platform = be->platform;
2207 struct snd_soc_platform_driver *drv = platform->driver;
2208 struct snd_soc_dai *dai = be->cpu_dai;
2209
2210 if (be->dai_link->ignore_suspend)
2211 continue;
2212
2213 dev_dbg(be->dev, "pm: BE platform playback suspend %s\n",
2214 be->dai_link->name);
2215
2216 if (drv->suspend && !platform->suspended) {
2217 drv->suspend(dai);
2218 platform->suspended = 1;
2219 }
2220 }
2221
2222 /* suspend for capture */
2223 list_for_each_entry(dpcm_params,
2224 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2225
2226 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2227 struct snd_soc_platform *platform = be->platform;
2228 struct snd_soc_platform_driver *drv = platform->driver;
2229 struct snd_soc_dai *dai = be->cpu_dai;
2230
2231 if (be->dai_link->ignore_suspend)
2232 continue;
2233
2234 dev_dbg(be->dev, "pm: BE platform capture suspend %s\n",
2235 be->dai_link->name);
2236
2237 if (drv->suspend && !platform->suspended) {
2238 drv->suspend(dai);
2239 platform->suspended = 1;
2240 }
2241 }
2242 return 0;
2243}
2244
2245int soc_dpcm_fe_suspend(struct snd_soc_pcm_runtime *fe)
2246{
2247 struct snd_soc_dai *dai = fe->cpu_dai;
2248 struct snd_soc_dai_driver *dai_drv = dai->driver;
2249 struct snd_soc_platform *platform = fe->platform;
2250 struct snd_soc_platform_driver *plat_drv = platform->driver;
2251
2252 if (dai_drv->suspend && !dai_drv->ac97_control)
2253 dai_drv->suspend(dai);
2254
2255 if (plat_drv->suspend && !platform->suspended) {
2256 plat_drv->suspend(dai);
2257 platform->suspended = 1;
2258 }
2259
2260 soc_dpcm_be_cpu_dai_suspend(fe);
2261 soc_dpcm_be_platform_suspend(fe);
2262
2263 return 0;
2264}
2265
2266int soc_dpcm_be_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
2267{
2268 struct snd_soc_dpcm_params *dpcm_params;
2269
2270 /* resume for playback */
2271 list_for_each_entry(dpcm_params,
2272 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2273
2274 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2275 struct snd_soc_dai *dai = be->cpu_dai;
2276 struct snd_soc_dai_driver *drv = dai->driver;
2277
2278 if (be->dai_link->ignore_suspend)
2279 continue;
2280
2281 dev_dbg(be->dev, "pm: BE CPU DAI playback resume %s\n",
2282 be->dai_link->name);
2283
2284 if (drv->resume && !drv->ac97_control)
2285 drv->resume(dai);
2286 }
2287
2288 /* suspend for capture */
2289 list_for_each_entry(dpcm_params,
2290 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2291
2292 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2293 struct snd_soc_dai *dai = be->cpu_dai;
2294 struct snd_soc_dai_driver *drv = dai->driver;
2295
2296 if (be->dai_link->ignore_suspend)
2297 continue;
2298
2299 dev_dbg(be->dev, "pm: BE CPU DAI capture resume %s\n",
2300 be->dai_link->name);
2301
2302 if (drv->resume && !drv->ac97_control)
2303 drv->resume(dai);
2304 }
2305
2306 return 0;
2307}
2308
2309int soc_dpcm_be_ac97_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
2310{
2311 struct snd_soc_dpcm_params *dpcm_params;
2312
2313 /* resume for playback */
2314 list_for_each_entry(dpcm_params,
2315 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2316
2317 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2318 struct snd_soc_dai *dai = be->cpu_dai;
2319 struct snd_soc_dai_driver *drv = dai->driver;
2320
2321 if (be->dai_link->ignore_suspend)
2322 continue;
2323
2324 dev_dbg(be->dev, "pm: BE CPU DAI playback resume %s\n",
2325 be->dai_link->name);
2326
2327 if (drv->resume && drv->ac97_control)
2328 drv->resume(dai);
2329 }
2330
2331 /* suspend for capture */
2332 list_for_each_entry(dpcm_params,
2333 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2334
2335 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2336 struct snd_soc_dai *dai = be->cpu_dai;
2337 struct snd_soc_dai_driver *drv = dai->driver;
2338
2339 if (be->dai_link->ignore_suspend)
2340 continue;
2341
2342 dev_dbg(be->dev, "pm: BE CPU DAI capture resume %s\n",
2343 be->dai_link->name);
2344
2345 if (drv->resume && drv->ac97_control)
2346 drv->resume(dai);
2347 }
2348
2349 return 0;
2350}
2351
2352int soc_dpcm_be_platform_resume(struct snd_soc_pcm_runtime *fe)
2353{
2354 struct snd_soc_dpcm_params *dpcm_params;
2355
2356 /* resume for playback */
2357 list_for_each_entry(dpcm_params,
2358 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2359
2360 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2361 struct snd_soc_platform *platform = be->platform;
2362 struct snd_soc_platform_driver *drv = platform->driver;
2363 struct snd_soc_dai *dai = be->cpu_dai;
2364
2365 if (be->dai_link->ignore_suspend)
2366 continue;
2367
2368 dev_dbg(be->dev, "pm: BE platform playback resume %s\n",
2369 be->dai_link->name);
2370
2371 if (drv->resume && platform->suspended) {
2372 drv->resume(dai);
2373 platform->suspended = 0;
2374 }
2375 }
2376
2377 /* resume for capture */
2378 list_for_each_entry(dpcm_params,
2379 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2380
2381 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2382 struct snd_soc_platform *platform = be->platform;
2383 struct snd_soc_platform_driver *drv = platform->driver;
2384 struct snd_soc_dai *dai = be->cpu_dai;
2385
2386 if (be->dai_link->ignore_suspend)
2387 continue;
2388
2389 dev_dbg(be->dev, "pm: BE platform capture resume %s\n",
2390 be->dai_link->name);
2391
2392 if (drv->resume && platform->suspended) {
2393 drv->resume(dai);
2394 platform->suspended = 0;
2395 }
2396 }
2397
2398 return 0;
2399}
2400
2401int soc_dpcm_fe_resume(struct snd_soc_pcm_runtime *fe)
2402{
2403 struct snd_soc_dai *dai = fe->cpu_dai;
2404 struct snd_soc_dai_driver *dai_drv = dai->driver;
2405 struct snd_soc_platform *platform = fe->platform;
2406 struct snd_soc_platform_driver *plat_drv = platform->driver;
2407
2408 soc_dpcm_be_cpu_dai_resume(fe);
2409 soc_dpcm_be_platform_resume(fe);
2410
2411 if (dai_drv->resume && !dai_drv->ac97_control)
2412 dai_drv->resume(dai);
2413
2414 if (plat_drv->resume && platform->suspended) {
2415 plat_drv->resume(dai);
2416 platform->suspended = 0;
2417 }
2418
2419 return 0;
2420}
2421
2422/* called when opening FE stream */
2423int soc_dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
2424{
2425 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2426 struct snd_soc_dpcm_params *dpcm_params;
2427 struct snd_soc_dapm_widget_list *list;
2428 int ret;
2429 int stream = fe_substream->stream;
2430
2431 fe->dpcm[stream].runtime = fe_substream->runtime;
2432
2433 if (fe_path_get(fe, stream, &list) <= 0) {
2434 dev_warn(fe->dev, "asoc: %s no valid %s route from source to sink\n",
2435 fe->dai_link->name, stream ? "capture" : "playback");
2436 return -EINVAL;
2437 }
2438
2439 /* calculate valid and active FE <-> BE dpcm_paramss */
2440 dpcm_process_paths(fe, stream, &list, 1);
2441
2442 ret = soc_dpcm_fe_dai_startup(fe_substream);
2443 if (ret < 0) {
2444 /* clean up all links */
2445 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
2446 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
2447
2448 be_disconnect(fe, stream);
2449 fe->dpcm[stream].runtime = NULL;
2450 }
2451
2452 fe_clear_pending(fe, stream);
2453 fe_path_put(&list);
2454 return ret;
2455}
2456
2457/* called when closing FE stream */
2458int soc_dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
2459{
2460 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2461 struct snd_soc_dpcm_params *dpcm_params;
2462 int stream = fe_substream->stream, ret;
2463
2464 ret = soc_dpcm_fe_dai_shutdown(fe_substream);
2465
2466 /* mark FE's links ready to prune */
2467 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
2468 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
2469
2470 be_disconnect(fe, stream);
2471
2472 fe->dpcm[stream].runtime = NULL;
2473
2474 return ret;
2475}
2476
Liam Girdwoodddee6272011-06-09 14:45:53 +01002477/* create a new pcm */
2478int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2479{
2480 struct snd_soc_codec *codec = rtd->codec;
2481 struct snd_soc_platform *platform = rtd->platform;
2482 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2483 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002484 struct snd_pcm_substream *substream[2];
Liam Girdwoodddee6272011-06-09 14:45:53 +01002485 struct snd_pcm *pcm;
2486 char new_name[64];
2487 int ret = 0, playback = 0, capture = 0;
2488
Steve Mucklef132c6c2012-06-06 18:30:57 -07002489 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
2490 if (cpu_dai->driver->playback.channels_min)
2491 playback = 1;
2492 if (cpu_dai->driver->capture.channels_min)
2493 capture = 1;
2494 } else {
2495 if (codec_dai->driver->playback.channels_min)
2496 playback = 1;
2497 if (codec_dai->driver->capture.channels_min)
2498 capture = 1;
2499 }
Sangsu Parka5002312012-01-02 17:15:10 +09002500
Steve Mucklef132c6c2012-06-06 18:30:57 -07002501 /* create the PCM */
2502 if (rtd->dai_link->no_pcm) {
2503 snprintf(new_name, sizeof(new_name), "(%s)",
2504 rtd->dai_link->stream_name);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002505
Steve Mucklef132c6c2012-06-06 18:30:57 -07002506 ret = snd_pcm_new_soc_be(rtd->card->snd_card, new_name, num,
2507 playback, capture, &pcm);
2508 } else {
2509 if (rtd->dai_link->dynamic)
2510 snprintf(new_name, sizeof(new_name), "%s (*)",
2511 rtd->dai_link->stream_name);
2512 else
2513 snprintf(new_name, sizeof(new_name), "%s %s-%d",
2514 rtd->dai_link->stream_name, codec_dai->name, num);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002515
Steve Mucklef132c6c2012-06-06 18:30:57 -07002516 ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
2517 capture, &pcm);
2518 }
Liam Girdwoodddee6272011-06-09 14:45:53 +01002519 if (ret < 0) {
2520 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
2521 return ret;
2522 }
Steve Mucklef132c6c2012-06-06 18:30:57 -07002523 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002524
2525 rtd->pcm = pcm;
2526 pcm->private_data = rtd;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002527 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
2528
2529 substream[SNDRV_PCM_STREAM_PLAYBACK] =
2530 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
2531 substream[SNDRV_PCM_STREAM_CAPTURE] =
2532 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
2533
2534 if (rtd->dai_link->no_pcm) {
2535 if (playback)
2536 substream[SNDRV_PCM_STREAM_PLAYBACK]->private_data = rtd;
2537 if (capture)
2538 substream[SNDRV_PCM_STREAM_CAPTURE]->private_data = rtd;
2539 goto out;
2540 }
2541
2542 /* setup any hostless PCMs - i.e. no host IO is performed */
2543 if (rtd->dai_link->no_host_mode) {
2544 if (substream[SNDRV_PCM_STREAM_PLAYBACK]) {
2545 substream[SNDRV_PCM_STREAM_PLAYBACK]->hw_no_buffer = 1;
2546 snd_soc_set_runtime_hwparams(
2547 substream[SNDRV_PCM_STREAM_PLAYBACK],
2548 &no_host_hardware);
2549 }
2550 if (substream[SNDRV_PCM_STREAM_CAPTURE]) {
2551 substream[SNDRV_PCM_STREAM_CAPTURE]->hw_no_buffer = 1;
2552 snd_soc_set_runtime_hwparams(
2553 substream[SNDRV_PCM_STREAM_CAPTURE],
2554 &no_host_hardware);
2555 }
2556 }
2557
2558 /* ASoC PCM operations */
2559 if (rtd->dai_link->dynamic) {
2560 rtd->ops.open = soc_dpcm_fe_dai_open;
2561 rtd->ops.hw_params = soc_dpcm_fe_dai_hw_params;
2562 rtd->ops.prepare = soc_dpcm_fe_dai_prepare;
2563 rtd->ops.trigger = soc_dpcm_fe_dai_trigger;
2564 rtd->ops.hw_free = soc_dpcm_fe_dai_hw_free;
2565 rtd->ops.close = soc_dpcm_fe_dai_close;
2566 rtd->ops.pointer = soc_pcm_pointer;
2567 rtd->ops.ioctl = soc_pcm_ioctl;
2568 } else {
2569 rtd->ops.open = soc_pcm_open;
2570 rtd->ops.hw_params = soc_pcm_hw_params;
2571 rtd->ops.prepare = soc_pcm_prepare;
2572 rtd->ops.trigger = soc_pcm_trigger;
2573 rtd->ops.hw_free = soc_pcm_hw_free;
2574 rtd->ops.close = soc_pcm_close;
2575 rtd->ops.pointer = soc_pcm_pointer;
2576 rtd->ops.ioctl = soc_pcm_ioctl;
2577 }
2578
Liam Girdwoodddee6272011-06-09 14:45:53 +01002579 if (platform->driver->ops) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07002580 rtd->ops.ack = platform->driver->ops->ack;
2581 rtd->ops.copy = platform->driver->ops->copy;
2582 rtd->ops.silence = platform->driver->ops->silence;
2583 rtd->ops.page = platform->driver->ops->page;
2584 rtd->ops.mmap = platform->driver->ops->mmap;
Liam Girdwoodddee6272011-06-09 14:45:53 +01002585 }
2586
2587 if (playback)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002588 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002589
2590 if (capture)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002591 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002592
2593 if (platform->driver->pcm_new) {
2594 ret = platform->driver->pcm_new(rtd);
2595 if (ret < 0) {
2596 pr_err("asoc: platform pcm constructor failed\n");
2597 return ret;
2598 }
2599 }
2600
2601 pcm->private_free = platform->driver->pcm_free;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002602out:
Liam Girdwoodddee6272011-06-09 14:45:53 +01002603 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
2604 cpu_dai->name);
2605 return ret;
2606}
Steve Mucklef132c6c2012-06-06 18:30:57 -07002607
2608#ifdef CONFIG_DEBUG_FS
2609static char *dpcm_state_string(enum snd_soc_dpcm_state state)
2610{
2611 switch (state) {
2612 case SND_SOC_DPCM_STATE_NEW:
2613 return "new";
2614 case SND_SOC_DPCM_STATE_OPEN:
2615 return "open";
2616 case SND_SOC_DPCM_STATE_HW_PARAMS:
2617 return "hw_params";
2618 case SND_SOC_DPCM_STATE_PREPARE:
2619 return "prepare";
2620 case SND_SOC_DPCM_STATE_START:
2621 return "start";
2622 case SND_SOC_DPCM_STATE_STOP:
2623 return "stop";
2624 case SND_SOC_DPCM_STATE_SUSPEND:
2625 return "suspend";
2626 case SND_SOC_DPCM_STATE_PAUSED:
2627 return "paused";
2628 case SND_SOC_DPCM_STATE_HW_FREE:
2629 return "hw_free";
2630 case SND_SOC_DPCM_STATE_CLOSE:
2631 return "close";
2632 }
2633
2634 return "unknown";
2635}
2636
2637static int soc_dpcm_state_open_file(struct inode *inode, struct file *file)
2638{
2639 file->private_data = inode->i_private;
2640 return 0;
2641}
2642
2643static ssize_t soc_dpcm_show_state(struct snd_soc_pcm_runtime *fe,
2644 int stream, char *buf, size_t size)
2645{
2646 struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
2647 struct snd_soc_dpcm_params *dpcm_params;
2648 ssize_t offset = 0;
2649
2650 /* FE state */
2651 offset += snprintf(buf + offset, size - offset,
2652 "[%s - %s]\n", fe->dai_link->name,
2653 stream ? "Capture" : "Playback");
2654
2655 offset += snprintf(buf + offset, size - offset, "State: %s\n",
2656 dpcm_state_string(fe->dpcm[stream].state));
2657
2658 if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
2659 (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
2660 offset += snprintf(buf + offset, size - offset,
2661 "Hardware Params: "
2662 "Format = %s, Channels = %d, Rate = %d\n",
2663 snd_pcm_format_name(params_format(params)),
2664 params_channels(params),
2665 params_rate(params));
2666
2667 /* BEs state */
2668 offset += snprintf(buf + offset, size - offset, "Backends:\n");
2669
2670 if (list_empty(&fe->dpcm[stream].be_clients)) {
2671 offset += snprintf(buf + offset, size - offset,
2672 " No active DSP links\n");
2673 goto out;
2674 }
2675
2676 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
2677 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2678
2679 offset += snprintf(buf + offset, size - offset,
2680 "- %s\n", be->dai_link->name);
2681
2682 offset += snprintf(buf + offset, size - offset,
2683 " State: %s\n",
2684 dpcm_state_string(fe->dpcm[stream].state));
2685
2686 if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
2687 (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
2688 offset += snprintf(buf + offset, size - offset,
2689 " Hardware Params: "
2690 "Format = %s, Channels = %d, Rate = %d\n",
2691 snd_pcm_format_name(params_format(params)),
2692 params_channels(params),
2693 params_rate(params));
2694 }
2695
2696out:
2697 return offset;
2698}
2699
2700static ssize_t soc_dpcm_state_read_file(struct file *file, char __user *user_buf,
2701 size_t count, loff_t *ppos)
2702{
2703 struct snd_soc_pcm_runtime *fe = file->private_data;
2704 ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
2705 char *buf;
2706
2707 buf = kmalloc(out_count, GFP_KERNEL);
2708 if (!buf)
2709 return -ENOMEM;
2710
2711 if (fe->cpu_dai->driver->playback.channels_min)
2712 offset += soc_dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK,
2713 buf + offset, out_count - offset);
2714
2715 if (fe->cpu_dai->driver->capture.channels_min)
2716 offset += soc_dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE,
2717 buf + offset, out_count - offset);
2718
2719 ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
2720
2721 kfree(buf);
2722
2723 return ret;
2724}
2725
2726static const struct file_operations soc_dpcm_state_fops = {
2727 .open = soc_dpcm_state_open_file,
2728 .read = soc_dpcm_state_read_file,
2729 .llseek = default_llseek,
2730};
2731
2732int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
2733{
2734 rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
2735 rtd->card->debugfs_card_root);
2736 if (!rtd->debugfs_dpcm_root) {
2737 dev_dbg(rtd->dev,
2738 "ASoC: Failed to create dpcm debugfs directory %s\n",
2739 rtd->dai_link->name);
2740 return -EINVAL;
2741 }
2742
2743 rtd->debugfs_dpcm_state = debugfs_create_file("state", 0644,
2744 rtd->debugfs_dpcm_root,
2745 rtd, &soc_dpcm_state_fops);
2746
2747 return 0;
2748}
2749#endif