blob: 8614a9264e820c30805b097bdc0fc09c05a16870 [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>
Iliyan Malchev734dc212012-10-02 09:22:36 -070028#include <linux/bug.h>
Liam Girdwoodddee6272011-06-09 14:45:53 +010029#include <sound/core.h>
30#include <sound/pcm.h>
31#include <sound/pcm_params.h>
32#include <sound/soc.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070033#include <sound/soc-dpcm.h>
Liam Girdwoodddee6272011-06-09 14:45:53 +010034#include <sound/initval.h>
35
Steve Mucklef132c6c2012-06-06 18:30:57 -070036#define MAX_BE_USERS 8 /* adjust if too low for everday use */
37
38static int soc_dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream);
39
40/* ASoC no host IO hardware.
41 * TODO: fine tune these values for all host less transfers.
42 */
43static const struct snd_pcm_hardware no_host_hardware = {
44 .info = SNDRV_PCM_INFO_MMAP |
45 SNDRV_PCM_INFO_MMAP_VALID |
46 SNDRV_PCM_INFO_INTERLEAVED |
47 SNDRV_PCM_INFO_PAUSE |
48 SNDRV_PCM_INFO_RESUME,
49 .formats = SNDRV_PCM_FMTBIT_S16_LE |
50 SNDRV_PCM_FMTBIT_S32_LE,
51 .period_bytes_min = PAGE_SIZE >> 2,
52 .period_bytes_max = PAGE_SIZE >> 1,
53 .periods_min = 2,
54 .periods_max = 4,
55 .buffer_bytes_max = PAGE_SIZE,
56};
57
58/*
59 * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE
60 * are not running, paused or suspended for the specified stream direction.
61 */
62int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
63 struct snd_soc_pcm_runtime *be, int stream)
64{
65 struct snd_soc_dpcm_params *dpcm_params;
66
67 list_for_each_entry(dpcm_params, &be->dpcm[stream].fe_clients, list_fe) {
68
69 if (dpcm_params->fe == fe)
70 continue;
71
72 if (dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_START ||
73 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PAUSED ||
74 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_SUSPEND)
75 return 0;
76 }
77 return 1;
78}
79EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop);
80
81/*
82 * We can only change hw params a BE DAI if any of it's FE are not prepared,
83 * running, paused or suspended for the specified stream direction.
84 */
85static int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
86 struct snd_soc_pcm_runtime *be, int stream)
87{
88 struct snd_soc_dpcm_params *dpcm_params;
89
90 list_for_each_entry(dpcm_params, &be->dpcm[stream].fe_clients, list_fe) {
91
92 if (dpcm_params->fe == fe)
93 continue;
94
95 if (dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_START ||
96 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PAUSED ||
97 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_SUSPEND ||
98 dpcm_params->fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE)
99 return 0;
100 }
101 return 1;
102}
103
Dong Aisheng17841022011-08-29 17:15:14 +0800104static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
105 struct snd_soc_dai *soc_dai)
Liam Girdwoodddee6272011-06-09 14:45:53 +0100106{
107 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Liam Girdwoodddee6272011-06-09 14:45:53 +0100108 int ret;
109
Dong Aisheng17841022011-08-29 17:15:14 +0800110 if (!soc_dai->driver->symmetric_rates &&
Liam Girdwoodddee6272011-06-09 14:45:53 +0100111 !rtd->dai_link->symmetric_rates)
112 return 0;
113
114 /* This can happen if multiple streams are starting simultaneously -
115 * the second can need to get its constraints before the first has
116 * picked a rate. Complain and allow the application to carry on.
117 */
Dong Aisheng17841022011-08-29 17:15:14 +0800118 if (!soc_dai->rate) {
119 dev_warn(soc_dai->dev,
Liam Girdwoodddee6272011-06-09 14:45:53 +0100120 "Not enforcing symmetric_rates due to race\n");
121 return 0;
122 }
123
Dong Aisheng17841022011-08-29 17:15:14 +0800124 dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100125
126 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
127 SNDRV_PCM_HW_PARAM_RATE,
Dong Aisheng17841022011-08-29 17:15:14 +0800128 soc_dai->rate, soc_dai->rate);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100129 if (ret < 0) {
Dong Aisheng17841022011-08-29 17:15:14 +0800130 dev_err(soc_dai->dev,
Liam Girdwoodddee6272011-06-09 14:45:53 +0100131 "Unable to apply rate symmetry constraint: %d\n", ret);
132 return ret;
133 }
134
135 return 0;
136}
137
138/*
Mark Brown58ba9b22012-01-16 18:38:51 +0000139 * List of sample sizes that might go over the bus for parameter
140 * application. There ought to be a wildcard sample size for things
141 * like the DAC/ADC resolution to use but there isn't right now.
142 */
143static int sample_sizes[] = {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700144 8, 16, 24, 32,
Mark Brown58ba9b22012-01-16 18:38:51 +0000145};
146
147static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
148 struct snd_soc_dai *dai)
149{
150 int ret, i, bits;
151
152 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
153 bits = dai->driver->playback.sig_bits;
154 else
155 bits = dai->driver->capture.sig_bits;
156
157 if (!bits)
158 return;
159
160 for (i = 0; i < ARRAY_SIZE(sample_sizes); i++) {
Mark Brown278047f2012-01-19 18:04:18 +0000161 if (bits >= sample_sizes[i])
162 continue;
163
164 ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0,
165 sample_sizes[i], bits);
Mark Brown58ba9b22012-01-16 18:38:51 +0000166 if (ret != 0)
167 dev_warn(dai->dev,
168 "Failed to set MSB %d/%d: %d\n",
169 bits, sample_sizes[i], ret);
170 }
171}
172
173/*
Steve Mucklef132c6c2012-06-06 18:30:57 -0700174 * stream event, send event to FE and all active BEs.
175 */
176int soc_dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe,
177 int dir, const char *stream, int event)
178{
179 struct snd_soc_dpcm_params *dpcm_params;
180
181 snd_soc_dapm_rtd_stream_event(fe, dir, event);
182
183 list_for_each_entry(dpcm_params, &fe->dpcm[dir].be_clients, list_be) {
184
185 struct snd_soc_pcm_runtime *be = dpcm_params->be;
186
187 dev_dbg(be->dev, "pm: BE %s stream %s event %d dir %d\n",
188 be->dai_link->name, stream, event, dir);
189
190 snd_soc_dapm_rtd_stream_event(be, dir, event);
191 }
192
193 return 0;
194}
195
196/*
Liam Girdwoodddee6272011-06-09 14:45:53 +0100197 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
198 * then initialized and any private data can be allocated. This also calls
199 * startup for the cpu DAI, platform, machine and codec DAI.
200 */
201static int soc_pcm_open(struct snd_pcm_substream *substream)
202{
203 struct snd_soc_pcm_runtime *rtd = substream->private_data;
204 struct snd_pcm_runtime *runtime = substream->runtime;
205 struct snd_soc_platform *platform = rtd->platform;
206 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
207 struct snd_soc_dai *codec_dai = rtd->codec_dai;
208 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
209 struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
210 int ret = 0;
211
Mark Brownd6652ef2011-12-03 20:14:31 +0000212 pm_runtime_get_sync(cpu_dai->dev);
213 pm_runtime_get_sync(codec_dai->dev);
214 pm_runtime_get_sync(platform->dev);
215
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100216 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100217
Steve Mucklef132c6c2012-06-06 18:30:57 -0700218 if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
219 snd_soc_set_runtime_hwparams(substream, &no_host_hardware);
220
Liam Girdwoodddee6272011-06-09 14:45:53 +0100221 /* startup the audio subsystem */
222 if (cpu_dai->driver->ops->startup) {
223 ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
224 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700225 printk(KERN_ERR "asoc: can't open interface %s\n",
226 cpu_dai->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100227 goto out;
228 }
229 }
230
231 if (platform->driver->ops && platform->driver->ops->open) {
232 ret = platform->driver->ops->open(substream);
233 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700234 printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100235 goto platform_err;
236 }
237 }
238
239 if (codec_dai->driver->ops->startup) {
Helen Zeng5749b092012-06-10 11:50:29 -0700240 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
241 ret = codec_dai->driver->ops->startup(substream,
242 codec_dai);
243 if (ret < 0) {
244 printk(KERN_ERR "asoc: can't open codec %s\n",
245 codec_dai->name);
246 goto codec_dai_err;
247 }
248 } else {
249 if (!codec_dai->capture_active) {
250 ret = codec_dai->driver->ops->startup(substream,
251 codec_dai);
252 if (ret < 0) {
253 printk(KERN_ERR "can't open codec %s\n",
254 codec_dai->name);
255 goto codec_dai_err;
256 }
257 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100258 }
259 }
260
261 if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
262 ret = rtd->dai_link->ops->startup(substream);
263 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700264 printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100265 goto machine_err;
266 }
267 }
268
Steve Mucklef132c6c2012-06-06 18:30:57 -0700269 /* DSP DAI links compat checks are different */
270 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm)
271 goto dynamic;
272
Liam Girdwoodddee6272011-06-09 14:45:53 +0100273 /* Check that the codec and cpu DAIs are compatible */
274 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
275 runtime->hw.rate_min =
276 max(codec_dai_drv->playback.rate_min,
277 cpu_dai_drv->playback.rate_min);
278 runtime->hw.rate_max =
279 min(codec_dai_drv->playback.rate_max,
280 cpu_dai_drv->playback.rate_max);
281 runtime->hw.channels_min =
282 max(codec_dai_drv->playback.channels_min,
283 cpu_dai_drv->playback.channels_min);
284 runtime->hw.channels_max =
285 min(codec_dai_drv->playback.channels_max,
286 cpu_dai_drv->playback.channels_max);
287 runtime->hw.formats =
288 codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
289 runtime->hw.rates =
290 codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
291 if (codec_dai_drv->playback.rates
292 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
293 runtime->hw.rates |= cpu_dai_drv->playback.rates;
294 if (cpu_dai_drv->playback.rates
295 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
296 runtime->hw.rates |= codec_dai_drv->playback.rates;
297 } else {
298 runtime->hw.rate_min =
299 max(codec_dai_drv->capture.rate_min,
300 cpu_dai_drv->capture.rate_min);
301 runtime->hw.rate_max =
302 min(codec_dai_drv->capture.rate_max,
303 cpu_dai_drv->capture.rate_max);
304 runtime->hw.channels_min =
305 max(codec_dai_drv->capture.channels_min,
306 cpu_dai_drv->capture.channels_min);
307 runtime->hw.channels_max =
308 min(codec_dai_drv->capture.channels_max,
309 cpu_dai_drv->capture.channels_max);
310 runtime->hw.formats =
311 codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
312 runtime->hw.rates =
313 codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
314 if (codec_dai_drv->capture.rates
315 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
316 runtime->hw.rates |= cpu_dai_drv->capture.rates;
317 if (cpu_dai_drv->capture.rates
318 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
319 runtime->hw.rates |= codec_dai_drv->capture.rates;
320 }
321
322 ret = -EINVAL;
323 snd_pcm_limit_hw_rates(runtime);
324 if (!runtime->hw.rates) {
325 printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
326 codec_dai->name, cpu_dai->name);
327 goto config_err;
328 }
329 if (!runtime->hw.formats) {
330 printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
331 codec_dai->name, cpu_dai->name);
332 goto config_err;
333 }
334 if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
335 runtime->hw.channels_min > runtime->hw.channels_max) {
336 printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
337 codec_dai->name, cpu_dai->name);
338 goto config_err;
339 }
340
Mark Brown58ba9b22012-01-16 18:38:51 +0000341 soc_pcm_apply_msb(substream, codec_dai);
342 soc_pcm_apply_msb(substream, cpu_dai);
343
Liam Girdwoodddee6272011-06-09 14:45:53 +0100344 /* Symmetry only applies if we've already got an active stream. */
Dong Aisheng17841022011-08-29 17:15:14 +0800345 if (cpu_dai->active) {
346 ret = soc_pcm_apply_symmetry(substream, cpu_dai);
347 if (ret != 0)
348 goto config_err;
349 }
350
351 if (codec_dai->active) {
352 ret = soc_pcm_apply_symmetry(substream, codec_dai);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100353 if (ret != 0)
354 goto config_err;
355 }
356
357 pr_debug("asoc: %s <-> %s info:\n",
358 codec_dai->name, cpu_dai->name);
359 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
360 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
361 runtime->hw.channels_max);
362 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
363 runtime->hw.rate_max);
364
Steve Mucklef132c6c2012-06-06 18:30:57 -0700365dynamic:
Liam Girdwoodddee6272011-06-09 14:45:53 +0100366 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
367 cpu_dai->playback_active++;
368 codec_dai->playback_active++;
369 } else {
370 cpu_dai->capture_active++;
371 codec_dai->capture_active++;
372 }
373 cpu_dai->active++;
374 codec_dai->active++;
375 rtd->codec->active++;
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100376 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100377 return 0;
378
379config_err:
380 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
381 rtd->dai_link->ops->shutdown(substream);
382
383machine_err:
384 if (codec_dai->driver->ops->shutdown)
385 codec_dai->driver->ops->shutdown(substream, codec_dai);
386
387codec_dai_err:
388 if (platform->driver->ops && platform->driver->ops->close)
389 platform->driver->ops->close(substream);
390
391platform_err:
392 if (cpu_dai->driver->ops->shutdown)
393 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
394out:
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100395 mutex_unlock(&rtd->pcm_mutex);
Mark Brownd6652ef2011-12-03 20:14:31 +0000396
397 pm_runtime_put(platform->dev);
398 pm_runtime_put(codec_dai->dev);
399 pm_runtime_put(cpu_dai->dev);
400
Liam Girdwoodddee6272011-06-09 14:45:53 +0100401 return ret;
402}
403
404/*
405 * Power down the audio subsystem pmdown_time msecs after close is called.
406 * This is to ensure there are no pops or clicks in between any music tracks
407 * due to DAPM power cycling.
408 */
409static void close_delayed_work(struct work_struct *work)
410{
411 struct snd_soc_pcm_runtime *rtd =
412 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
413 struct snd_soc_dai *codec_dai = rtd->codec_dai;
414
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100415 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100416
417 pr_debug("pop wq checking: %s status: %s waiting: %s\n",
418 codec_dai->driver->playback.stream_name,
419 codec_dai->playback_active ? "active" : "inactive",
420 codec_dai->pop_wait ? "yes" : "no");
421
422 /* are we waiting on this codec DAI stream */
423 if (codec_dai->pop_wait == 1) {
424 codec_dai->pop_wait = 0;
Steve Mucklef132c6c2012-06-06 18:30:57 -0700425 snd_soc_dapm_stream_event(rtd,
426 codec_dai->driver->playback.stream_name,
427 SND_SOC_DAPM_STREAM_STOP);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100428 }
429
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100430 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100431}
432
433/*
434 * Called by ALSA when a PCM substream is closed. Private data can be
435 * freed here. The cpu DAI, codec DAI, machine and platform are also
436 * shutdown.
437 */
Liam Girdwood91d5e6b2011-06-09 17:04:59 +0100438static int soc_pcm_close(struct snd_pcm_substream *substream)
Liam Girdwoodddee6272011-06-09 14:45:53 +0100439{
440 struct snd_soc_pcm_runtime *rtd = substream->private_data;
441 struct snd_soc_platform *platform = rtd->platform;
442 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
443 struct snd_soc_dai *codec_dai = rtd->codec_dai;
444 struct snd_soc_codec *codec = rtd->codec;
445
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100446 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100447
448 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
449 cpu_dai->playback_active--;
450 codec_dai->playback_active--;
451 } else {
452 cpu_dai->capture_active--;
453 codec_dai->capture_active--;
454 }
455
456 cpu_dai->active--;
457 codec_dai->active--;
458 codec->active--;
459
Dong Aisheng17841022011-08-29 17:15:14 +0800460 /* clear the corresponding DAIs rate when inactive */
461 if (!cpu_dai->active)
462 cpu_dai->rate = 0;
463
464 if (!codec_dai->active)
465 codec_dai->rate = 0;
Sascha Hauer25b76792011-08-17 09:20:01 +0200466
Liam Girdwoodddee6272011-06-09 14:45:53 +0100467 /* Muting the DAC suppresses artifacts caused during digital
468 * shutdown, for example from stopping clocks.
469 */
470 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
471 snd_soc_dai_digital_mute(codec_dai, 1);
472
Helen Zengd5131792012-06-28 11:24:11 -0700473 if (cpu_dai->driver->ops->shutdown)
474 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
475
476 if (codec_dai->driver->ops->shutdown) {
Helen Zeng5749b092012-06-10 11:50:29 -0700477 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
478 codec_dai->driver->ops->shutdown(substream, codec_dai);
479 } else {
480 if (!codec_dai->capture_active)
481 codec_dai->driver->ops->shutdown(substream,
482 codec_dai);
483 }
484 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100485
Liam Girdwoodddee6272011-06-09 14:45:53 +0100486 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
487 rtd->dai_link->ops->shutdown(substream);
488
489 if (platform->driver->ops && platform->driver->ops->close)
490 platform->driver->ops->close(substream);
491 cpu_dai->runtime = NULL;
492
493 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700494 if (codec->ignore_pmdown_time ||
495 rtd->dai_link->ignore_pmdown_time ||
496 !rtd->pmdown_time) {
Peter Ujfalusi1d69c5c2011-10-14 14:43:33 +0300497 /* powered down playback stream now */
498 snd_soc_dapm_stream_event(rtd,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700499 codec_dai->driver->playback.stream_name,
500 SND_SOC_DAPM_STREAM_STOP);
Peter Ujfalusi1d69c5c2011-10-14 14:43:33 +0300501 } else {
502 /* start delayed pop wq here for playback streams */
503 codec_dai->pop_wait = 1;
504 schedule_delayed_work(&rtd->delayed_work,
505 msecs_to_jiffies(rtd->pmdown_time));
506 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100507 } else {
508 /* capture streams can be powered down now */
Helen Zeng5749b092012-06-10 11:50:29 -0700509 if (!codec_dai->capture_active)
510 snd_soc_dapm_stream_event(rtd,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700511 codec_dai->driver->capture.stream_name,
512 SND_SOC_DAPM_STREAM_STOP);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100513 }
514
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100515 mutex_unlock(&rtd->pcm_mutex);
Mark Brownd6652ef2011-12-03 20:14:31 +0000516
517 pm_runtime_put(platform->dev);
518 pm_runtime_put(codec_dai->dev);
519 pm_runtime_put(cpu_dai->dev);
520
Liam Girdwoodddee6272011-06-09 14:45:53 +0100521 return 0;
522}
523
524/*
525 * Called by ALSA when the PCM substream is prepared, can set format, sample
526 * rate, etc. This function is non atomic and can be called multiple times,
527 * it can refer to the runtime info.
528 */
529static int soc_pcm_prepare(struct snd_pcm_substream *substream)
530{
531 struct snd_soc_pcm_runtime *rtd = substream->private_data;
532 struct snd_soc_platform *platform = rtd->platform;
533 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
534 struct snd_soc_dai *codec_dai = rtd->codec_dai;
535 int ret = 0;
536
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100537 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100538
539 if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
540 ret = rtd->dai_link->ops->prepare(substream);
541 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700542 printk(KERN_ERR "asoc: machine prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100543 goto out;
544 }
545 }
546
547 if (platform->driver->ops && platform->driver->ops->prepare) {
548 ret = platform->driver->ops->prepare(substream);
549 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700550 printk(KERN_ERR "asoc: platform prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100551 goto out;
552 }
553 }
554
555 if (codec_dai->driver->ops->prepare) {
556 ret = codec_dai->driver->ops->prepare(substream, codec_dai);
557 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700558 printk(KERN_ERR "asoc: codec DAI prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100559 goto out;
560 }
561 }
562
563 if (cpu_dai->driver->ops->prepare) {
564 ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
565 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700566 printk(KERN_ERR "asoc: cpu DAI prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100567 goto out;
568 }
569 }
570
571 /* cancel any delayed stream shutdown that is pending */
572 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
573 codec_dai->pop_wait) {
574 codec_dai->pop_wait = 0;
575 cancel_delayed_work(&rtd->delayed_work);
576 }
577
Steve Mucklef132c6c2012-06-06 18:30:57 -0700578 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
579 snd_soc_dapm_stream_event(rtd,
580 codec_dai->driver->playback.stream_name,
581 SND_SOC_DAPM_STREAM_START);
Helen Zeng5749b092012-06-10 11:50:29 -0700582 else {
583 if (codec_dai->capture_active == 1)
584 snd_soc_dapm_stream_event(rtd,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700585 codec_dai->driver->capture.stream_name,
586 SND_SOC_DAPM_STREAM_START);
Helen Zeng5749b092012-06-10 11:50:29 -0700587 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100588 snd_soc_dai_digital_mute(codec_dai, 0);
589
590out:
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100591 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100592 return ret;
593}
594
595/*
596 * Called by ALSA when the hardware params are set by application. This
597 * function can also be called multiple times and can allocate buffers
598 * (using snd_pcm_lib_* ). It's non-atomic.
599 */
600static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
601 struct snd_pcm_hw_params *params)
602{
603 struct snd_soc_pcm_runtime *rtd = substream->private_data;
604 struct snd_soc_platform *platform = rtd->platform;
605 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
606 struct snd_soc_dai *codec_dai = rtd->codec_dai;
607 int ret = 0;
608
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100609 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100610
611 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
612 ret = rtd->dai_link->ops->hw_params(substream, params);
613 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700614 printk(KERN_ERR "asoc: machine hw_params failed\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100615 goto out;
616 }
617 }
618
619 if (codec_dai->driver->ops->hw_params) {
Helen Zeng5749b092012-06-10 11:50:29 -0700620 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
621 ret = codec_dai->driver->ops->hw_params(substream,
622 params, codec_dai);
623 if (ret < 0) {
624 printk(KERN_ERR "not set codec %s hw params\n",
625 codec_dai->name);
626 goto codec_err;
627 }
628 } else {
629 if (codec_dai->capture_active == 1) {
630 ret = codec_dai->driver->ops->hw_params(
631 substream, params, codec_dai);
632 if (ret < 0) {
633 printk(KERN_ERR "fail: %s hw params\n",
634 codec_dai->name);
635 goto codec_err;
636 }
637 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100638 }
639 }
640
641 if (cpu_dai->driver->ops->hw_params) {
642 ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
643 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700644 printk(KERN_ERR "asoc: interface %s hw params failed\n",
645 cpu_dai->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100646 goto interface_err;
647 }
648 }
649
650 if (platform->driver->ops && platform->driver->ops->hw_params) {
651 ret = platform->driver->ops->hw_params(substream, params);
652 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700653 printk(KERN_ERR "asoc: platform %s hw params failed\n",
654 platform->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100655 goto platform_err;
656 }
657 }
658
Dong Aisheng17841022011-08-29 17:15:14 +0800659 /* store the rate for each DAIs */
660 cpu_dai->rate = params_rate(params);
661 codec_dai->rate = params_rate(params);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100662
Steve Mucklef132c6c2012-06-06 18:30:57 -0700663 /* malloc a page for hostless IO.
664 * FIXME: rework with alsa-lib changes so that this malloc is not required.
665 */
666 if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) {
667 substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV;
668 substream->dma_buffer.dev.dev = rtd->dev;
669 substream->dma_buffer.dev.dev->coherent_dma_mask = DMA_BIT_MASK(32);
670 substream->dma_buffer.private_data = NULL;
671
672 ret = snd_pcm_lib_malloc_pages(substream, PAGE_SIZE);
673 if (ret < 0)
674 goto platform_err;
675 }
676
Liam Girdwoodddee6272011-06-09 14:45:53 +0100677out:
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100678 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100679 return ret;
680
681platform_err:
682 if (cpu_dai->driver->ops->hw_free)
683 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
684
685interface_err:
686 if (codec_dai->driver->ops->hw_free)
687 codec_dai->driver->ops->hw_free(substream, codec_dai);
688
689codec_err:
690 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
691 rtd->dai_link->ops->hw_free(substream);
692
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100693 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100694 return ret;
695}
696
697/*
698 * Frees resources allocated by hw_params, can be called multiple times
699 */
700static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
701{
702 struct snd_soc_pcm_runtime *rtd = substream->private_data;
703 struct snd_soc_platform *platform = rtd->platform;
704 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
705 struct snd_soc_dai *codec_dai = rtd->codec_dai;
706 struct snd_soc_codec *codec = rtd->codec;
707
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100708 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100709
710 /* apply codec digital mute */
711 if (!codec->active)
712 snd_soc_dai_digital_mute(codec_dai, 1);
713
714 /* free any machine hw params */
715 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
716 rtd->dai_link->ops->hw_free(substream);
717
718 /* free any DMA resources */
719 if (platform->driver->ops && platform->driver->ops->hw_free)
720 platform->driver->ops->hw_free(substream);
721
722 /* now free hw params for the DAIs */
723 if (codec_dai->driver->ops->hw_free)
724 codec_dai->driver->ops->hw_free(substream, codec_dai);
725
726 if (cpu_dai->driver->ops->hw_free)
727 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
728
Steve Mucklef132c6c2012-06-06 18:30:57 -0700729 if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
730 snd_pcm_lib_free_pages(substream);
731
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100732 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100733 return 0;
734}
735
736static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
737{
738 struct snd_soc_pcm_runtime *rtd = substream->private_data;
739 struct snd_soc_platform *platform = rtd->platform;
740 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
741 struct snd_soc_dai *codec_dai = rtd->codec_dai;
742 int ret;
743
744 if (codec_dai->driver->ops->trigger) {
Helen Zeng5749b092012-06-10 11:50:29 -0700745 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
746 ret = codec_dai->driver->ops->trigger(substream,
747 cmd, codec_dai);
748 if (ret < 0)
749 return ret;
750 } else {
751 if (codec_dai->capture_active == 1) {
752 ret = codec_dai->driver->ops->trigger(
753 substream, cmd, codec_dai);
754 if (ret < 0)
755 return ret;
756 }
757 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100758 }
759
760 if (platform->driver->ops && platform->driver->ops->trigger) {
761 ret = platform->driver->ops->trigger(substream, cmd);
762 if (ret < 0)
763 return ret;
764 }
765
766 if (cpu_dai->driver->ops->trigger) {
767 ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
768 if (ret < 0)
769 return ret;
770 }
771 return 0;
772}
773
Steve Mucklef132c6c2012-06-06 18:30:57 -0700774int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, int cmd)
775{
776 struct snd_soc_pcm_runtime *rtd = substream->private_data;
777 struct snd_soc_platform *platform = rtd->platform;
778 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
779 struct snd_soc_dai *codec_dai = rtd->codec_dai;
780 int ret;
781
782 if (codec_dai->driver->ops->bespoke_trigger) {
783 ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
784 if (ret < 0)
785 return ret;
786 }
787
788 if (platform->driver->bespoke_trigger) {
789 ret = platform->driver->bespoke_trigger(substream, cmd);
790 if (ret < 0)
791 return ret;
792 }
793
794 if (cpu_dai->driver->ops->bespoke_trigger) {
795 ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
796 if (ret < 0)
797 return ret;
798 }
799 return 0;
800}
801
Liam Girdwoodddee6272011-06-09 14:45:53 +0100802/*
803 * soc level wrapper for pointer callback
804 * If cpu_dai, codec_dai, platform driver has the delay callback, than
805 * the runtime->delay will be updated accordingly.
806 */
807static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
808{
809 struct snd_soc_pcm_runtime *rtd = substream->private_data;
810 struct snd_soc_platform *platform = rtd->platform;
811 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
812 struct snd_soc_dai *codec_dai = rtd->codec_dai;
813 struct snd_pcm_runtime *runtime = substream->runtime;
814 snd_pcm_uframes_t offset = 0;
815 snd_pcm_sframes_t delay = 0;
816
817 if (platform->driver->ops && platform->driver->ops->pointer)
818 offset = platform->driver->ops->pointer(substream);
819
820 if (cpu_dai->driver->ops->delay)
821 delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
822
823 if (codec_dai->driver->ops->delay)
824 delay += codec_dai->driver->ops->delay(substream, codec_dai);
825
826 if (platform->driver->delay)
827 delay += platform->driver->delay(substream, codec_dai);
828
829 runtime->delay = delay;
830
831 return offset;
832}
833
Steve Mucklef132c6c2012-06-06 18:30:57 -0700834static inline int be_connect(struct snd_soc_pcm_runtime *fe,
835 struct snd_soc_pcm_runtime *be, int stream)
836{
837 struct snd_soc_dpcm_params *dpcm_params;
838
839 if (!fe->dpcm[stream].runtime) {
840 dev_err(fe->dev, "%s no runtime\n", fe->dai_link->name);
841 return -ENODEV;
842 }
843
844 /* only add new dpcm_paramss */
845 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
846 if (dpcm_params->be == be && dpcm_params->fe == fe)
847 return 0;
848 }
849
850 dpcm_params = kzalloc(sizeof(struct snd_soc_dpcm_params), GFP_KERNEL);
851 if (!dpcm_params)
852 return -ENOMEM;
853
854 dpcm_params->be = be;
855 dpcm_params->fe = fe;
856 be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
857 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_NEW;
858 list_add(&dpcm_params->list_be, &fe->dpcm[stream].be_clients);
859 list_add(&dpcm_params->list_fe, &be->dpcm[stream].fe_clients);
860
861 dev_dbg(fe->dev, " connected new DSP %s path %s %s %s\n",
862 stream ? "capture" : "playback", fe->dai_link->name,
863 stream ? "<-" : "->", be->dai_link->name);
864
865#ifdef CONFIG_DEBUG_FS
866 dpcm_params->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644,
867 fe->debugfs_dpcm_root, &dpcm_params->state);
868#endif
869
870 return 1;
871}
872
873static inline void be_reparent(struct snd_soc_pcm_runtime *fe,
874 struct snd_soc_pcm_runtime *be, int stream)
875{
876 struct snd_soc_dpcm_params *dpcm_params;
877 struct snd_pcm_substream *fe_substream, *be_substream;
878
879 /* reparent if BE is connected to other FEs */
880 if (!be->dpcm[stream].users)
881 return;
882
883 be_substream = snd_soc_dpcm_get_substream(be, stream);
884
885 list_for_each_entry(dpcm_params, &be->dpcm[stream].fe_clients, list_fe) {
886 if (dpcm_params->fe != fe) {
887
888 dev_dbg(fe->dev, " reparent %s path %s %s %s\n",
889 stream ? "capture" : "playback",
890 dpcm_params->fe->dai_link->name,
891 stream ? "<-" : "->", dpcm_params->be->dai_link->name);
892
893 fe_substream = snd_soc_dpcm_get_substream(dpcm_params->fe,
894 stream);
895 be_substream->runtime = fe_substream->runtime;
896 break;
897 }
898 }
899}
900
901static inline void be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
902{
903 struct snd_soc_dpcm_params *dpcm_params, *d;
904
905 list_for_each_entry_safe(dpcm_params, d, &fe->dpcm[stream].be_clients, list_be) {
906 dev_dbg(fe->dev, "BE %s disconnect check for %s\n",
907 stream ? "capture" : "playback",
908 dpcm_params->be->dai_link->name);
909
910 if (dpcm_params->state == SND_SOC_DPCM_LINK_STATE_FREE) {
911 dev_dbg(fe->dev, " freed DSP %s path %s %s %s\n",
912 stream ? "capture" : "playback", fe->dai_link->name,
913 stream ? "<-" : "->", dpcm_params->be->dai_link->name);
914
915 /* BEs still alive need new FE */
916 be_reparent(fe, dpcm_params->be, stream);
917
918#ifdef CONFIG_DEBUG_FS
919 debugfs_remove(dpcm_params->debugfs_state);
920#endif
921
922 list_del(&dpcm_params->list_be);
923 list_del(&dpcm_params->list_fe);
924 kfree(dpcm_params);
925 }
926 }
927}
928
929static struct snd_soc_pcm_runtime *be_get_rtd(struct snd_soc_card *card,
930 struct snd_soc_dapm_widget *widget)
931{
932 struct snd_soc_pcm_runtime *be;
933 int i;
934
935 if (!widget->sname) {
936 dev_err(card->dev, "widget %s has no stream\n", widget->name);
937 return NULL;
938 }
939
940 for (i = 0; i < card->num_links; i++) {
941 be = &card->rtd[i];
942
943 if (!strcmp(widget->sname, be->dai_link->stream_name))
944 return be;
945 }
946
947 dev_err(card->dev, "can't get BE for %s\n", widget->name);
948 return NULL;
949}
950
951static struct snd_soc_dapm_widget *be_get_widget(struct snd_soc_card *card,
952 struct snd_soc_pcm_runtime *rtd)
953{
954 struct snd_soc_dapm_widget *widget;
955
956 list_for_each_entry(widget, &card->widgets, list) {
957
958 if (!widget->sname)
959 continue;
960
961 if (!strcmp(widget->sname, rtd->dai_link->stream_name))
962 return widget;
963 }
964
965 dev_err(card->dev, "can't get widget for %s\n",
966 rtd->dai_link->stream_name);
967 return NULL;
968}
969
970static int widget_in_list(struct snd_soc_dapm_widget_list *list,
971 struct snd_soc_dapm_widget *widget)
972{
973 int i;
974
975 for (i = 0; i < list->num_widgets; i++) {
976 if (widget == list->widgets[i])
977 return 1;
978 }
979
980 return 0;
981}
982
983static int fe_path_get(struct snd_soc_pcm_runtime *fe,
984 int stream, struct snd_soc_dapm_widget_list **list_)
985{
986 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
987 struct snd_soc_dapm_widget_list *list;
988 int paths;
989
990 list = kzalloc(sizeof(struct snd_soc_dapm_widget_list) +
991 sizeof(struct snd_soc_dapm_widget *), GFP_KERNEL);
992 if (list == NULL)
993 return -ENOMEM;
994
995 /* get number of valid DAI paths and their widgets */
996 paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list);
997
998 dev_dbg(fe->dev, "found %d audio %s paths\n", paths,
999 stream ? "capture" : "playback");
1000
1001 *list_ = list;
1002 return paths;
1003}
1004
1005static inline void fe_path_put(struct snd_soc_dapm_widget_list **list)
1006{
1007 kfree(*list);
1008}
1009
1010static int be_prune_old(struct snd_soc_pcm_runtime *fe, int stream,
1011 struct snd_soc_dapm_widget_list **list_)
1012{
1013 struct snd_soc_card *card = fe->card;
1014 struct snd_soc_dpcm_params *dpcm_params;
1015 struct snd_soc_dapm_widget_list *list = *list_;
1016 struct snd_soc_dapm_widget *widget;
1017 int old = 0;
1018
1019 /* Destroy any old FE <--> BE connections */
1020 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1021
1022 /* is there a valid widget for this BE */
1023 widget = be_get_widget(card, dpcm_params->be);
1024 if (!widget) {
1025 dev_err(fe->dev, "no widget found for %s\n",
1026 dpcm_params->be->dai_link->name);
1027 continue;
1028 }
1029
1030 /* prune the BE if it's no longer in our active list */
1031 if (widget_in_list(list, widget))
1032 continue;
1033
1034 dev_dbg(fe->dev, "pruning %s BE %s for %s\n",
1035 stream ? "capture" : "playback", dpcm_params->be->dai_link->name,
1036 fe->dai_link->name);
1037 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
1038 dpcm_params->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1039 old++;
1040 }
1041
1042 dev_dbg(fe->dev, "found %d old BEs\n", old);
1043 return old;
1044}
1045
1046static int be_add_new(struct snd_soc_pcm_runtime *fe, int stream,
1047 struct snd_soc_dapm_widget_list **list_)
1048{
1049 struct snd_soc_card *card = fe->card;
1050 struct snd_soc_dapm_widget_list *list = *list_;
1051 enum snd_soc_dapm_type be_type;
1052 int i, new = 0, err;
1053
1054 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1055 be_type = snd_soc_dapm_aif_out;
1056 else
1057 be_type = snd_soc_dapm_aif_in;
1058
1059 /* Create any new FE <--> BE connections */
1060 for (i = 0; i < list->num_widgets; i++) {
1061
1062 if (list->widgets[i]->id == be_type) {
1063 struct snd_soc_pcm_runtime *be;
1064
1065 /* is there a valid BE rtd for this widget */
1066 be = be_get_rtd(card, list->widgets[i]);
1067 if (!be) {
1068 dev_err(fe->dev, "no BE found for %s\n",
1069 list->widgets[i]->name);
1070 continue;
1071 }
1072
1073 /* don't connect if FE is not running */
1074 if (!fe->dpcm[stream].runtime)
1075 continue;
1076
1077 /* newly connected FE and BE */
1078 err = be_connect(fe, be, stream);
1079 if (err < 0) {
1080 dev_err(fe->dev, "can't connect %s\n", list->widgets[i]->name);
1081 break;
1082 } else if (err == 0) /* already connected */
1083 continue;
1084
1085 /* new */
1086 be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1087 new++;
1088 }
1089 }
1090
1091 dev_dbg(fe->dev, "found %d new BEs\n", new);
1092 return new;
1093}
1094
1095/*
1096 * Find the corresponding BE DAIs that source or sink audio to this
1097 * FE substream.
1098 */
1099static int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
1100 int stream, struct snd_soc_dapm_widget_list **list, int new)
1101{
1102 if (new)
1103 return be_add_new(fe, stream, list);
1104 else
1105 return be_prune_old(fe, stream, list);
1106 return 0;
1107}
1108
1109/*
1110 * Clear the runtime pending state of all BE's.
1111 */
1112static void fe_clear_pending(struct snd_soc_pcm_runtime *fe, int stream)
1113{
1114 struct snd_soc_dpcm_params *dpcm_params;
1115
1116 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
1117 dpcm_params->be->dpcm[stream].runtime_update =
1118 SND_SOC_DPCM_UPDATE_NO;
1119}
1120
1121/* Unwind the BE startup */
1122static void soc_dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, int stream)
1123{
1124 struct snd_soc_dpcm_params *dpcm_params;
1125
1126 /* disable any enabled and non active backends */
1127 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1128
1129 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1130 struct snd_pcm_substream *be_substream =
1131 snd_soc_dpcm_get_substream(be, stream);
1132
1133 if (be->dpcm[stream].users == 0)
1134 dev_err(be->dev, "no users %s at close - state %d\n",
1135 stream ? "capture" : "playback", be->dpcm[stream].state);
1136
1137 if (--be->dpcm[stream].users != 0)
1138 continue;
1139
1140 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
1141 continue;
1142
1143 soc_pcm_close(be_substream);
1144 be_substream->runtime = NULL;
1145
1146 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1147 }
1148}
1149
1150/* Startup all new BE */
1151static int soc_dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
1152{
1153 struct snd_soc_dpcm_params *dpcm_params;
1154 int err, count = 0;
1155
1156 /* only startup BE DAIs that are either sinks or sources to this FE DAI */
1157 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1158
1159 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1160 struct snd_pcm_substream *be_substream =
1161 snd_soc_dpcm_get_substream(be, stream);
1162
1163 /* is this op for this BE ? */
1164 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1165 continue;
1166
1167 /* first time the dpcm_params is open ? */
1168 if (be->dpcm[stream].users == MAX_BE_USERS)
1169 dev_err(be->dev, "too many users %s at open - state %d\n",
1170 stream ? "capture" : "playback", be->dpcm[stream].state);
1171
1172 if (be->dpcm[stream].users++ != 0)
1173 continue;
1174
1175 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
1176 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
1177 continue;
1178
1179 dev_dbg(be->dev, "dpcm: open BE %s\n", be->dai_link->name);
1180
1181 be_substream->runtime = be->dpcm[stream].runtime;
1182 err = soc_pcm_open(be_substream);
1183 if (err < 0) {
1184 dev_err(be->dev, "BE open failed %d\n", err);
1185 be->dpcm[stream].users--;
1186 if (be->dpcm[stream].users < 0)
1187 dev_err(be->dev, "no users %s at unwind - state %d\n",
1188 stream ? "capture" : "playback",
1189 be->dpcm[stream].state);
1190
1191 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1192 goto unwind;
1193 }
1194
1195 be->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1196 count++;
1197 }
1198
1199 return count;
1200
1201unwind:
1202 /* disable any enabled and non active backends */
1203 list_for_each_entry_continue_reverse(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1204 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1205 struct snd_pcm_substream *be_substream =
1206 snd_soc_dpcm_get_substream(be, stream);
1207
1208 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1209 continue;
1210
1211 if (be->dpcm[stream].users == 0)
1212 dev_err(be->dev, "no users %s at close - state %d\n",
1213 stream ? "capture" : "playback", be->dpcm[stream].state);
1214
1215 if (--be->dpcm[stream].users != 0)
1216 continue;
1217
1218 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
1219 continue;
1220
1221 soc_pcm_close(be_substream);
1222 be_substream->runtime = NULL;
1223
1224 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1225 }
1226
1227 return err;
1228}
1229
1230void soc_dpcm_set_dynamic_runtime(struct snd_pcm_substream *substream)
1231{
1232 struct snd_pcm_runtime *runtime = substream->runtime;
1233 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1234 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1235 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
1236
1237 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1238 runtime->hw.rate_min = cpu_dai_drv->playback.rate_min;
1239 runtime->hw.rate_max = cpu_dai_drv->playback.rate_max;
1240 runtime->hw.channels_min = cpu_dai_drv->playback.channels_min;
1241 runtime->hw.channels_max = cpu_dai_drv->playback.channels_max;
1242 runtime->hw.formats &= cpu_dai_drv->playback.formats;
1243 runtime->hw.rates = cpu_dai_drv->playback.rates;
1244 } else {
1245 runtime->hw.rate_min = cpu_dai_drv->capture.rate_min;
1246 runtime->hw.rate_max = cpu_dai_drv->capture.rate_max;
1247 runtime->hw.channels_min = cpu_dai_drv->capture.channels_min;
1248 runtime->hw.channels_max = cpu_dai_drv->capture.channels_max;
1249 runtime->hw.formats &= cpu_dai_drv->capture.formats;
1250 runtime->hw.rates = cpu_dai_drv->capture.rates;
1251 }
1252}
1253
1254static int soc_dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
1255{
1256 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1257 struct snd_pcm_runtime *runtime = fe_substream->runtime;
1258 int stream = fe_substream->stream, ret = 0;
1259
1260 mutex_lock(&fe->card->dpcm_mutex);
1261 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1262
1263 ret = soc_dpcm_be_dai_startup(fe, fe_substream->stream);
1264 if (ret < 0) {
1265 dev_err(fe->dev,"dpcm: failed to start some BEs %d\n", ret);
1266 goto be_err;
1267 }
1268
1269 dev_dbg(fe->dev, "dpcm: open FE %s\n", fe->dai_link->name);
1270
1271 /* start the DAI frontend */
1272 ret = soc_pcm_open(fe_substream);
1273 if (ret < 0) {
1274 dev_err(fe->dev,"dpcm: failed to start FE %d\n", ret);
1275 goto unwind;
1276 }
1277
1278 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1279
1280 soc_dpcm_set_dynamic_runtime(fe_substream);
1281 snd_pcm_limit_hw_rates(runtime);
1282
1283 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1284 mutex_unlock(&fe->card->dpcm_mutex);
1285 return 0;
1286
1287unwind:
1288 soc_dpcm_be_dai_startup_unwind(fe, fe_substream->stream);
1289be_err:
1290 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1291 mutex_unlock(&fe->card->dpcm_mutex);
1292 return ret;
1293}
1294
1295/* BE shutdown - called on DAPM sync updates (i.e. FE is already running)*/
1296static int soc_dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1297{
1298 struct snd_soc_dpcm_params *dpcm_params;
1299
1300 /* only shutdown backends that are either sinks or sources to this frontend DAI */
1301 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1302
1303 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1304 struct snd_pcm_substream *be_substream =
1305 snd_soc_dpcm_get_substream(be, stream);
1306
1307 /* is this op for this BE ? */
1308 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1309 continue;
1310
1311 if (be->dpcm[stream].users == 0)
1312 dev_err(be->dev, "no users %s at close - state %d\n",
1313 stream ? "capture" : "playback", be->dpcm[stream].state);
1314
1315 if (--be->dpcm[stream].users != 0)
1316 continue;
1317
1318 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1319 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN))
1320 continue;
1321
1322 dev_dbg(be->dev, "dpcm: close BE %s\n",
1323 dpcm_params->fe->dai_link->name);
1324
1325 soc_pcm_close(be_substream);
1326 be_substream->runtime = NULL;
1327
1328 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1329 }
1330 return 0;
1331}
1332
1333/* FE +BE shutdown - called on FE PCM ops */
1334static int soc_dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
1335{
1336 struct snd_soc_pcm_runtime *fe = substream->private_data;
1337 int stream = substream->stream;
1338
1339 mutex_lock(&fe->card->dpcm_mutex);
1340 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1341
1342 dev_dbg(fe->dev, "dpcm: close FE %s\n", fe->dai_link->name);
1343
1344 /* now shutdown the frontend */
1345 soc_pcm_close(substream);
1346
1347 /* shutdown the BEs */
1348 soc_dpcm_be_dai_shutdown(fe, substream->stream);
1349 /* run the stream event for each BE */
1350 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1351 soc_dpcm_dapm_stream_event(fe, stream,
1352 fe->cpu_dai->driver->playback.stream_name,
1353 SND_SOC_DAPM_STREAM_STOP);
1354 else
1355 soc_dpcm_dapm_stream_event(fe, stream,
1356 fe->cpu_dai->driver->capture.stream_name,
1357 SND_SOC_DAPM_STREAM_STOP);
1358
1359 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1360 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1361
1362 mutex_unlock(&fe->card->dpcm_mutex);
1363 return 0;
1364}
1365
1366static int soc_dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
1367{
1368 struct snd_soc_dpcm_params *dpcm_params;
1369 int ret;
1370
1371 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1372
1373 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1374 struct snd_pcm_substream *be_substream =
1375 snd_soc_dpcm_get_substream(be, stream);
1376
1377 /* is this op for this BE ? */
1378 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1379 continue;
1380
1381 /* only allow hw_params() if no connected FEs are running */
1382 if (!snd_soc_dpcm_can_be_params(fe, be, stream))
1383 continue;
1384
1385 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
1386 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1387 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
1388 continue;
1389
1390 dev_dbg(be->dev, "dpcm: hw_params BE %s\n",
1391 dpcm_params->fe->dai_link->name);
1392
1393 /* copy params for each dpcm_params */
1394 memcpy(&dpcm_params->hw_params, &fe->dpcm[stream].hw_params,
1395 sizeof(struct snd_pcm_hw_params));
1396
1397 /* perform any hw_params fixups */
1398 if (be->dai_link->be_hw_params_fixup) {
1399 ret = be->dai_link->be_hw_params_fixup(be,
1400 &dpcm_params->hw_params);
1401 if (ret < 0) {
1402 dev_err(be->dev,
1403 "dpcm: hw_params BE fixup failed %d\n",
1404 ret);
1405 goto unwind;
1406 }
1407 }
1408
1409 ret = soc_pcm_hw_params(be_substream, &dpcm_params->hw_params);
1410 if (ret < 0) {
1411 dev_err(dpcm_params->be->dev, "dpcm: hw_params BE failed %d\n", ret);
1412 goto unwind;
1413 }
1414
1415 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
1416 }
1417 return 0;
1418
1419unwind:
1420 /* disable any enabled and non active backends */
1421 list_for_each_entry_continue_reverse(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1422 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1423 struct snd_pcm_substream *be_substream =
1424 snd_soc_dpcm_get_substream(be, stream);
1425
1426 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1427 continue;
1428
1429 /* only allow hw_free() if no connected FEs are running */
1430 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1431 continue;
1432
1433 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
1434 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1435 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1436 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1437 continue;
1438
1439 soc_pcm_hw_free(be_substream);
1440 }
1441
1442 return ret;
1443}
1444
1445int soc_dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
1446 struct snd_pcm_hw_params *params)
1447{
1448 struct snd_soc_pcm_runtime *fe = substream->private_data;
1449 int ret, stream = substream->stream;
1450
1451 mutex_lock(&fe->card->dpcm_mutex);
1452 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1453
1454 memcpy(&fe->dpcm[substream->stream].hw_params, params,
1455 sizeof(struct snd_pcm_hw_params));
1456 ret = soc_dpcm_be_dai_hw_params(fe, substream->stream);
1457 if (ret < 0) {
1458 dev_err(fe->dev,"dpcm: hw_params failed for some BEs %d\n", ret);
1459 goto out;
1460 }
1461
1462 dev_dbg(fe->dev, "dpcm: hw_params FE %s rate %d chan %x fmt %d\n",
1463 fe->dai_link->name, params_rate(params), params_channels(params),
1464 params_format(params));
1465
1466 /* call hw_params on the frontend */
1467 ret = soc_pcm_hw_params(substream, params);
1468 if (ret < 0) {
1469 dev_err(fe->dev,"dpcm: hw_params FE failed %d\n", ret);
1470 soc_dpcm_be_dai_hw_free(fe, stream);
1471 } else
1472 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
1473
1474out:
1475 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1476 mutex_unlock(&fe->card->dpcm_mutex);
1477 return ret;
1478}
1479
1480static int dpcm_do_trigger(struct snd_soc_dpcm_params *dpcm_params,
1481 struct snd_pcm_substream *substream, int cmd)
1482{
1483 int ret;
1484
1485 dev_dbg(dpcm_params->be->dev, "dpcm: trigger BE %s cmd %d\n",
1486 dpcm_params->fe->dai_link->name, cmd);
1487
1488 ret = soc_pcm_trigger(substream, cmd);
1489 if (ret < 0)
1490 dev_err(dpcm_params->be->dev,"dpcm: trigger BE failed %d\n", ret);
1491
1492 return ret;
1493}
1494
1495int soc_dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd)
1496{
1497 struct snd_soc_dpcm_params *dpcm_params;
1498 int ret = 0;
1499
1500 if ((cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) ||
1501 (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH))
1502 return ret;
1503
1504 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1505
1506 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1507 struct snd_pcm_substream *be_substream =
1508 snd_soc_dpcm_get_substream(be, stream);
1509
1510 /* is this op for this BE ? */
1511 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1512 continue;
1513
1514 switch (cmd) {
1515 case SNDRV_PCM_TRIGGER_START:
1516 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1517 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1518 continue;
1519
1520 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1521 if (ret)
1522 return ret;
1523
1524 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1525 break;
1526 case SNDRV_PCM_TRIGGER_RESUME:
1527 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
1528 continue;
1529
1530 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1531 if (ret)
1532 return ret;
1533
1534 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1535 break;
1536 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1537 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
1538 continue;
1539
1540 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1541 if (ret)
1542 return ret;
1543
1544 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1545 break;
1546 case SNDRV_PCM_TRIGGER_STOP:
1547 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1548 continue;
1549
1550 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1551 continue;
1552
1553 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1554 if (ret)
1555 return ret;
1556
1557 be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1558 break;
1559 case SNDRV_PCM_TRIGGER_SUSPEND:
1560 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)
1561 continue;
1562
1563 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1564 continue;
1565
1566 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1567 if (ret)
1568 return ret;
1569
1570 be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND;
1571 break;
1572 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1573 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1574 continue;
1575
1576 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1577 continue;
1578
1579 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1580 if (ret)
1581 return ret;
1582
1583 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
1584 break;
1585 }
1586 }
1587
1588 return ret;
1589}
1590EXPORT_SYMBOL_GPL(soc_dpcm_be_dai_trigger);
1591
1592int soc_dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
1593{
1594 struct snd_soc_pcm_runtime *fe = substream->private_data;
1595 int stream = substream->stream, ret;
1596 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1597
1598 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1599
1600 switch (trigger) {
1601 case SND_SOC_DPCM_TRIGGER_PRE:
1602 /* call trigger on the frontend before the backend. */
1603
1604 dev_dbg(fe->dev, "dpcm: pre trigger FE %s cmd %d\n",
1605 fe->dai_link->name, cmd);
1606
1607 ret = soc_pcm_trigger(substream, cmd);
1608 if (ret < 0) {
1609 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1610 goto out;
1611 }
1612
1613 ret = soc_dpcm_be_dai_trigger(fe, substream->stream, cmd);
1614 break;
1615 case SND_SOC_DPCM_TRIGGER_POST:
1616 /* call trigger on the frontend after the backend. */
1617
1618 ret = soc_dpcm_be_dai_trigger(fe, substream->stream, cmd);
1619 if (ret < 0) {
1620 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1621 goto out;
1622 }
1623
1624 dev_dbg(fe->dev, "dpcm: post trigger FE %s cmd %d\n",
1625 fe->dai_link->name, cmd);
1626
1627 ret = soc_pcm_trigger(substream, cmd);
1628 break;
1629 case SND_SOC_DPCM_TRIGGER_BESPOKE:
1630 /* bespoke trigger() - handles both FE and BEs */
1631
1632 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd %d\n",
1633 fe->dai_link->name, cmd);
1634
1635 ret = soc_pcm_bespoke_trigger(substream, cmd);
1636 if (ret < 0) {
1637 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1638 goto out;
1639 }
1640 break;
1641 default:
1642 dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd,
1643 fe->dai_link->name);
1644 ret = -EINVAL;
1645 goto out;
1646 }
1647
1648 switch (cmd) {
1649 case SNDRV_PCM_TRIGGER_START:
1650 case SNDRV_PCM_TRIGGER_RESUME:
1651 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1652 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1653 break;
1654 case SNDRV_PCM_TRIGGER_STOP:
1655 case SNDRV_PCM_TRIGGER_SUSPEND:
1656 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1657 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1658 break;
1659 }
1660
1661out:
1662 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1663 return ret;
1664}
1665
1666static int soc_dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
1667{
1668 struct snd_soc_dpcm_params *dpcm_params;
1669 int ret = 0;
1670
1671 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1672
1673 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1674 struct snd_pcm_substream *be_substream =
1675 snd_soc_dpcm_get_substream(be, stream);
1676
1677 /* is this op for this BE ? */
1678 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1679 continue;
1680
1681 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1682 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1683 continue;
1684
1685 dev_dbg(be->dev, "dpcm: prepare BE %s\n",
1686 dpcm_params->fe->dai_link->name);
1687
1688 ret = soc_pcm_prepare(be_substream);
1689 if (ret < 0) {
1690 dev_err(be->dev, "dpcm: backend prepare failed %d\n",
1691 ret);
1692 break;
1693 }
1694
1695 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1696 }
1697 return ret;
1698}
1699
1700int soc_dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
1701{
1702 struct snd_soc_pcm_runtime *fe = substream->private_data;
1703 int stream = substream->stream, ret = 0;
1704
1705 mutex_lock(&fe->card->dpcm_mutex);
1706
1707 dev_dbg(fe->dev, "dpcm: prepare FE %s\n", fe->dai_link->name);
1708
1709 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1710
1711 /* there is no point preparing this FE if there are no BEs */
1712 if (list_empty(&fe->dpcm[stream].be_clients)) {
1713 dev_err(fe->dev, "dpcm: no backend DAIs enabled for %s\n",
1714 fe->dai_link->name);
1715 ret = -EINVAL;
1716 goto out;
1717 }
1718
1719 ret = soc_dpcm_be_dai_prepare(fe, substream->stream);
1720 if (ret < 0)
1721 goto out;
1722
1723 /* call prepare on the frontend */
1724 ret = soc_pcm_prepare(substream);
1725 if (ret < 0) {
1726 dev_err(fe->dev,"dpcm: prepare FE %s failed\n", fe->dai_link->name);
1727 goto out;
1728 }
1729
1730 /* run the stream event for each BE */
1731 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1732 soc_dpcm_dapm_stream_event(fe, stream,
1733 fe->cpu_dai->driver->playback.stream_name,
1734 SND_SOC_DAPM_STREAM_START);
1735 else
1736 soc_dpcm_dapm_stream_event(fe, stream,
1737 fe->cpu_dai->driver->capture.stream_name,
1738 SND_SOC_DAPM_STREAM_START);
1739
1740 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1741
1742out:
1743 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1744 mutex_unlock(&fe->card->dpcm_mutex);
1745 return ret;
1746}
1747
1748static int soc_dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
1749{
1750 struct snd_soc_dpcm_params *dpcm_params;
1751
1752 /* only hw_params backends that are either sinks or sources
1753 * to this frontend DAI */
1754 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1755
1756 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1757 struct snd_pcm_substream *be_substream =
1758 snd_soc_dpcm_get_substream(be, stream);
1759
1760 /* is this op for this BE ? */
1761 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1762 continue;
1763
1764 /* only free hw when no longer used - check all FEs */
1765 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1766 continue;
1767
1768 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1769 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1770 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1771 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1772 continue;
1773
1774 dev_dbg(be->dev, "dpcm: hw_free BE %s\n",
1775 dpcm_params->fe->dai_link->name);
1776
1777 soc_pcm_hw_free(be_substream);
1778
1779 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1780 }
1781
1782 return 0;
1783}
1784
1785int soc_dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
1786{
1787 struct snd_soc_pcm_runtime *fe = substream->private_data;
1788 int err, stream = substream->stream;
1789
1790 mutex_lock(&fe->card->dpcm_mutex);
1791 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1792
1793 dev_dbg(fe->dev, "dpcm: hw_free FE %s\n", fe->dai_link->name);
1794
1795 /* call hw_free on the frontend */
1796 err = soc_pcm_hw_free(substream);
1797 if (err < 0)
1798 dev_err(fe->dev,"dpcm: hw_free FE %s failed\n", fe->dai_link->name);
1799
1800 /* only hw_params backends that are either sinks or sources
1801 * to this frontend DAI */
1802 err = soc_dpcm_be_dai_hw_free(fe, stream);
1803
1804 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1805 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1806
1807 mutex_unlock(&fe->card->dpcm_mutex);
1808 return 0;
1809}
1810
1811static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
1812 unsigned int cmd, void *arg)
1813{
1814 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1815 struct snd_soc_platform *platform = rtd->platform;
1816
1817 if (platform->driver->ops->ioctl)
1818 return platform->driver->ops->ioctl(substream, cmd, arg);
1819 return snd_pcm_lib_ioctl(substream, cmd, arg);
1820}
1821
1822static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1823{
1824 struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream);
1825 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1826 int err;
1827
1828 dev_dbg(fe->dev, "runtime %s close on FE %s\n",
1829 stream ? "capture" : "playback", fe->dai_link->name);
1830
1831 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1832 /* call bespoke trigger - FE takes care of all BE triggers */
1833 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd stop\n",
1834 fe->dai_link->name);
1835
1836 err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
1837 if (err < 0)
1838 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1839 } else {
1840 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd stop\n",
1841 fe->dai_link->name);
1842
1843 err = soc_dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
1844 if (err < 0)
1845 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1846 }
1847
1848 err = soc_dpcm_be_dai_hw_free(fe, stream);
1849 if (err < 0)
1850 dev_err(fe->dev,"dpcm: hw_free FE failed %d\n", err);
1851
1852 err = soc_dpcm_be_dai_shutdown(fe, stream);
1853 if (err < 0)
1854 dev_err(fe->dev,"dpcm: shutdown FE failed %d\n", err);
1855
1856 /* run the stream event for each BE */
1857 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1858 soc_dpcm_dapm_stream_event(fe, stream,
1859 fe->cpu_dai->driver->playback.stream_name,
1860 SND_SOC_DAPM_STREAM_NOP);
1861 else
1862 soc_dpcm_dapm_stream_event(fe, stream,
1863 fe->cpu_dai->driver->capture.stream_name,
1864 SND_SOC_DAPM_STREAM_NOP);
1865
1866 return 0;
1867}
1868
1869static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
1870{
1871 struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream);
1872 struct snd_soc_dpcm_params *dpcm_params;
1873 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1874 int ret;
1875
1876 dev_dbg(fe->dev, "runtime %s open on FE %s\n",
1877 stream ? "capture" : "playback", fe->dai_link->name);
1878
1879 /* Only start the BE if the FE is ready */
1880 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
1881 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
1882 return -EINVAL;
1883
1884 /* startup must always be called for new BEs */
1885 ret = soc_dpcm_be_dai_startup(fe, stream);
1886 if (ret < 0) {
1887 goto disconnect;
1888 return ret;
1889 }
1890
1891 /* keep going if FE state is > open */
1892 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_OPEN)
1893 return 0;
1894
1895 ret = soc_dpcm_be_dai_hw_params(fe, stream);
1896 if (ret < 0) {
1897 goto close;
1898 return ret;
1899 }
1900
1901 /* keep going if FE state is > hw_params */
1902 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_PARAMS)
1903 return 0;
1904
1905
1906 ret = soc_dpcm_be_dai_prepare(fe, stream);
1907 if (ret < 0) {
1908 goto hw_free;
1909 return ret;
1910 }
1911
1912 /* run the stream event for each BE */
1913 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1914 soc_dpcm_dapm_stream_event(fe, stream,
1915 fe->cpu_dai->driver->playback.stream_name,
1916 SND_SOC_DAPM_STREAM_NOP);
1917 else
1918 soc_dpcm_dapm_stream_event(fe, stream,
1919 fe->cpu_dai->driver->capture.stream_name,
1920 SND_SOC_DAPM_STREAM_NOP);
1921
1922 /* keep going if FE state is > prepare */
1923 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE ||
1924 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
1925 return 0;
1926
1927 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1928 /* call trigger on the frontend - FE takes care of all BE triggers */
1929 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd start\n",
1930 fe->dai_link->name);
1931
1932 ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
1933 if (ret < 0) {
1934 dev_err(fe->dev,"dpcm: bespoke trigger FE failed %d\n", ret);
1935 goto hw_free;
1936 }
1937 } else {
1938 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n",
1939 fe->dai_link->name);
1940
1941 ret = soc_dpcm_be_dai_trigger(fe, stream,
1942 SNDRV_PCM_TRIGGER_START);
1943 if (ret < 0) {
1944 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1945 goto hw_free;
1946 }
1947 }
1948
1949 return 0;
1950
1951hw_free:
1952 soc_dpcm_be_dai_hw_free(fe, stream);
1953close:
1954 soc_dpcm_be_dai_shutdown(fe, stream);
1955disconnect:
1956 /* disconnect any non started BEs */
1957 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1958 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1959 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1960 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
1961 }
1962
1963 return ret;
1964}
1965
1966static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
1967{
1968 int ret;
1969
1970 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1971 ret = dpcm_run_update_startup(fe, stream);
1972 if (ret < 0)
1973 dev_err(fe->dev, "failed to startup some BEs\n");
1974 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1975
1976 return ret;
1977}
1978
1979static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
1980{
1981 int ret;
1982
1983 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1984 ret = dpcm_run_update_shutdown(fe, stream);
1985 if (ret < 0)
1986 dev_err(fe->dev, "failed to shutdown some BEs\n");
1987 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1988
1989 return ret;
1990}
1991
1992/* called when any mixer updates change FE -> BE the stream */
1993int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
1994{
1995 struct snd_soc_card *card;
1996 int i, ret = 0, old, new, paths;
1997
1998 if (widget->codec)
1999 card = widget->codec->card;
2000 else if (widget->platform)
2001 card = widget->platform->card;
2002 else
2003 return -EINVAL;
2004
2005 mutex_lock(&card->dpcm_mutex);
2006
2007 for (i = 0; i < card->num_rtd; i++) {
2008 struct snd_soc_dapm_widget_list *list;
2009 struct snd_soc_pcm_runtime *fe = &card->rtd[i];
2010
2011 /* make sure link is FE */
2012 if (!fe->dai_link->dynamic)
2013 continue;
2014
2015 /* only check active links */
2016 if (!fe->cpu_dai->active)
2017 continue;
2018
2019 /* DAPM sync will call this to update DSP paths */
2020 dev_dbg(fe->dev, "DPCM runtime update for FE %s\n", fe->dai_link->name);
2021
2022 /* skip if FE doesn't have playback capability */
2023 if (!fe->cpu_dai->driver->playback.channels_min)
2024 goto capture;
2025
2026 paths = fe_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
2027 if (paths < 0) {
2028 dev_warn(fe->dev, "%s no valid %s route from source to sink\n",
2029 fe->dai_link->name, "playback");
Iliyan Malchev734dc212012-10-02 09:22:36 -07002030 WARN_ON(1);
Steve Mucklef132c6c2012-06-06 18:30:57 -07002031 ret = paths;
2032 goto out;
2033 }
2034
2035 /* update any new playback paths */
2036 new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 1);
2037 if (new) {
2038 dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
2039 fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
2040 be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
2041 }
2042
2043 /* update any old playback paths */
2044 old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 0);
2045 if (old) {
2046 dpcm_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
2047 fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
2048 be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
2049 }
2050
2051capture:
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