blob: 65cee5dc27e334f639c39cd96dd0293bb7694157 [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
2049capture:
2050 /* skip if FE doesn't have capture capability */
2051 if (!fe->cpu_dai->driver->capture.channels_min)
2052 continue;
2053
2054 paths = fe_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
2055 if (paths < 0) {
2056 dev_warn(fe->dev, "%s no valid %s route from source to sink\n",
2057 fe->dai_link->name, "capture");
2058 ret = paths;
2059 goto out;
2060 }
2061
2062 /* update any new capture paths */
2063 new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 1);
2064 if (new) {
2065 dpcm_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2066 fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
2067 be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
2068 }
2069
2070 /* update any old capture paths */
2071 old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 0);
2072 if (old) {
2073 dpcm_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2074 fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
2075 be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
2076 }
2077
2078 fe_path_put(&list);
2079 }
2080
2081out:
2082 mutex_unlock(&card->dpcm_mutex);
2083 return ret;
2084}
2085
2086int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
2087{
2088 struct snd_soc_dpcm_params *dpcm_params;
2089
2090 list_for_each_entry(dpcm_params,
2091 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2092
2093 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2094 struct snd_soc_dai *dai = be->codec_dai;
2095 struct snd_soc_dai_driver *drv = dai->driver;
2096
2097 if (be->dai_link->ignore_suspend)
2098 continue;
2099
2100 dev_dbg(be->dev, "BE digital mute %s\n", be->dai_link->name);
2101
2102 if (drv->ops->digital_mute && dai->playback_active)
2103 drv->ops->digital_mute(dai, mute);
2104 }
2105
2106 return 0;
2107}
2108
2109int soc_dpcm_be_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
2110{
2111 struct snd_soc_dpcm_params *dpcm_params;
2112
2113 /* suspend for playback */
2114 list_for_each_entry(dpcm_params,
2115 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2116
2117 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2118 struct snd_soc_dai *dai = be->cpu_dai;
2119 struct snd_soc_dai_driver *drv = dai->driver;
2120
2121 if (be->dai_link->ignore_suspend)
2122 continue;
2123
2124 dev_dbg(be->dev, "pm: BE CPU DAI playback suspend %s\n",
2125 be->dai_link->name);
2126
2127 if (drv->suspend && !drv->ac97_control)
2128 drv->suspend(dai);
2129 }
2130
2131 /* suspend for capture */
2132 list_for_each_entry(dpcm_params,
2133 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2134
2135 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2136 struct snd_soc_dai *dai = be->cpu_dai;
2137 struct snd_soc_dai_driver *drv = dai->driver;
2138
2139 if (be->dai_link->ignore_suspend)
2140 continue;
2141
2142 dev_dbg(be->dev, "pm: BE CPU DAI capture suspend %s\n",
2143 be->dai_link->name);
2144
2145 if (drv->suspend && !drv->ac97_control)
2146 drv->suspend(dai);
2147 }
2148
2149 return 0;
2150}
2151
2152int soc_dpcm_be_ac97_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
2153{
2154 struct snd_soc_dpcm_params *dpcm_params;
2155
2156 /* suspend for playback */
2157 list_for_each_entry(dpcm_params,
2158 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2159
2160 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2161 struct snd_soc_dai *dai = be->cpu_dai;
2162 struct snd_soc_dai_driver *drv = dai->driver;
2163
2164 if (be->dai_link->ignore_suspend)
2165 continue;
2166
2167 dev_dbg(be->dev, "pm: BE CPU DAI playback suspend %s\n",
2168 be->dai_link->name);
2169
2170 if (drv->suspend && drv->ac97_control)
2171 drv->suspend(dai);
2172 }
2173
2174 /* suspend for capture */
2175 list_for_each_entry(dpcm_params,
2176 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2177
2178 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2179 struct snd_soc_dai *dai = be->cpu_dai;
2180 struct snd_soc_dai_driver *drv = dai->driver;
2181
2182 if (be->dai_link->ignore_suspend)
2183 continue;
2184
2185 dev_dbg(be->dev, "pm: BE CPU DAI capture suspend %s\n",
2186 be->dai_link->name);
2187
2188 if (drv->suspend && drv->ac97_control)
2189 drv->suspend(dai);
2190 }
2191
2192 return 0;
2193}
2194
2195int soc_dpcm_be_platform_suspend(struct snd_soc_pcm_runtime *fe)
2196{
2197 struct snd_soc_dpcm_params *dpcm_params;
2198
2199 /* suspend for playback */
2200 list_for_each_entry(dpcm_params,
2201 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2202
2203 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2204 struct snd_soc_platform *platform = be->platform;
2205 struct snd_soc_platform_driver *drv = platform->driver;
2206 struct snd_soc_dai *dai = be->cpu_dai;
2207
2208 if (be->dai_link->ignore_suspend)
2209 continue;
2210
2211 dev_dbg(be->dev, "pm: BE platform playback suspend %s\n",
2212 be->dai_link->name);
2213
2214 if (drv->suspend && !platform->suspended) {
2215 drv->suspend(dai);
2216 platform->suspended = 1;
2217 }
2218 }
2219
2220 /* suspend for capture */
2221 list_for_each_entry(dpcm_params,
2222 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2223
2224 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2225 struct snd_soc_platform *platform = be->platform;
2226 struct snd_soc_platform_driver *drv = platform->driver;
2227 struct snd_soc_dai *dai = be->cpu_dai;
2228
2229 if (be->dai_link->ignore_suspend)
2230 continue;
2231
2232 dev_dbg(be->dev, "pm: BE platform capture suspend %s\n",
2233 be->dai_link->name);
2234
2235 if (drv->suspend && !platform->suspended) {
2236 drv->suspend(dai);
2237 platform->suspended = 1;
2238 }
2239 }
2240 return 0;
2241}
2242
2243int soc_dpcm_fe_suspend(struct snd_soc_pcm_runtime *fe)
2244{
2245 struct snd_soc_dai *dai = fe->cpu_dai;
2246 struct snd_soc_dai_driver *dai_drv = dai->driver;
2247 struct snd_soc_platform *platform = fe->platform;
2248 struct snd_soc_platform_driver *plat_drv = platform->driver;
2249
2250 if (dai_drv->suspend && !dai_drv->ac97_control)
2251 dai_drv->suspend(dai);
2252
2253 if (plat_drv->suspend && !platform->suspended) {
2254 plat_drv->suspend(dai);
2255 platform->suspended = 1;
2256 }
2257
2258 soc_dpcm_be_cpu_dai_suspend(fe);
2259 soc_dpcm_be_platform_suspend(fe);
2260
2261 return 0;
2262}
2263
2264int soc_dpcm_be_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
2265{
2266 struct snd_soc_dpcm_params *dpcm_params;
2267
2268 /* resume for playback */
2269 list_for_each_entry(dpcm_params,
2270 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2271
2272 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2273 struct snd_soc_dai *dai = be->cpu_dai;
2274 struct snd_soc_dai_driver *drv = dai->driver;
2275
2276 if (be->dai_link->ignore_suspend)
2277 continue;
2278
2279 dev_dbg(be->dev, "pm: BE CPU DAI playback resume %s\n",
2280 be->dai_link->name);
2281
2282 if (drv->resume && !drv->ac97_control)
2283 drv->resume(dai);
2284 }
2285
2286 /* suspend for capture */
2287 list_for_each_entry(dpcm_params,
2288 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2289
2290 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2291 struct snd_soc_dai *dai = be->cpu_dai;
2292 struct snd_soc_dai_driver *drv = dai->driver;
2293
2294 if (be->dai_link->ignore_suspend)
2295 continue;
2296
2297 dev_dbg(be->dev, "pm: BE CPU DAI capture resume %s\n",
2298 be->dai_link->name);
2299
2300 if (drv->resume && !drv->ac97_control)
2301 drv->resume(dai);
2302 }
2303
2304 return 0;
2305}
2306
2307int soc_dpcm_be_ac97_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
2308{
2309 struct snd_soc_dpcm_params *dpcm_params;
2310
2311 /* resume for playback */
2312 list_for_each_entry(dpcm_params,
2313 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2314
2315 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2316 struct snd_soc_dai *dai = be->cpu_dai;
2317 struct snd_soc_dai_driver *drv = dai->driver;
2318
2319 if (be->dai_link->ignore_suspend)
2320 continue;
2321
2322 dev_dbg(be->dev, "pm: BE CPU DAI playback resume %s\n",
2323 be->dai_link->name);
2324
2325 if (drv->resume && drv->ac97_control)
2326 drv->resume(dai);
2327 }
2328
2329 /* suspend for capture */
2330 list_for_each_entry(dpcm_params,
2331 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2332
2333 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2334 struct snd_soc_dai *dai = be->cpu_dai;
2335 struct snd_soc_dai_driver *drv = dai->driver;
2336
2337 if (be->dai_link->ignore_suspend)
2338 continue;
2339
2340 dev_dbg(be->dev, "pm: BE CPU DAI capture resume %s\n",
2341 be->dai_link->name);
2342
2343 if (drv->resume && drv->ac97_control)
2344 drv->resume(dai);
2345 }
2346
2347 return 0;
2348}
2349
2350int soc_dpcm_be_platform_resume(struct snd_soc_pcm_runtime *fe)
2351{
2352 struct snd_soc_dpcm_params *dpcm_params;
2353
2354 /* resume for playback */
2355 list_for_each_entry(dpcm_params,
2356 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2357
2358 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2359 struct snd_soc_platform *platform = be->platform;
2360 struct snd_soc_platform_driver *drv = platform->driver;
2361 struct snd_soc_dai *dai = be->cpu_dai;
2362
2363 if (be->dai_link->ignore_suspend)
2364 continue;
2365
2366 dev_dbg(be->dev, "pm: BE platform playback resume %s\n",
2367 be->dai_link->name);
2368
2369 if (drv->resume && platform->suspended) {
2370 drv->resume(dai);
2371 platform->suspended = 0;
2372 }
2373 }
2374
2375 /* resume for capture */
2376 list_for_each_entry(dpcm_params,
2377 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2378
2379 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2380 struct snd_soc_platform *platform = be->platform;
2381 struct snd_soc_platform_driver *drv = platform->driver;
2382 struct snd_soc_dai *dai = be->cpu_dai;
2383
2384 if (be->dai_link->ignore_suspend)
2385 continue;
2386
2387 dev_dbg(be->dev, "pm: BE platform capture resume %s\n",
2388 be->dai_link->name);
2389
2390 if (drv->resume && platform->suspended) {
2391 drv->resume(dai);
2392 platform->suspended = 0;
2393 }
2394 }
2395
2396 return 0;
2397}
2398
2399int soc_dpcm_fe_resume(struct snd_soc_pcm_runtime *fe)
2400{
2401 struct snd_soc_dai *dai = fe->cpu_dai;
2402 struct snd_soc_dai_driver *dai_drv = dai->driver;
2403 struct snd_soc_platform *platform = fe->platform;
2404 struct snd_soc_platform_driver *plat_drv = platform->driver;
2405
2406 soc_dpcm_be_cpu_dai_resume(fe);
2407 soc_dpcm_be_platform_resume(fe);
2408
2409 if (dai_drv->resume && !dai_drv->ac97_control)
2410 dai_drv->resume(dai);
2411
2412 if (plat_drv->resume && platform->suspended) {
2413 plat_drv->resume(dai);
2414 platform->suspended = 0;
2415 }
2416
2417 return 0;
2418}
2419
2420/* called when opening FE stream */
2421int soc_dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
2422{
2423 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2424 struct snd_soc_dpcm_params *dpcm_params;
2425 struct snd_soc_dapm_widget_list *list;
2426 int ret;
2427 int stream = fe_substream->stream;
2428
2429 fe->dpcm[stream].runtime = fe_substream->runtime;
2430
2431 if (fe_path_get(fe, stream, &list) <= 0) {
2432 dev_warn(fe->dev, "asoc: %s no valid %s route from source to sink\n",
2433 fe->dai_link->name, stream ? "capture" : "playback");
2434 return -EINVAL;
2435 }
2436
2437 /* calculate valid and active FE <-> BE dpcm_paramss */
2438 dpcm_process_paths(fe, stream, &list, 1);
2439
2440 ret = soc_dpcm_fe_dai_startup(fe_substream);
2441 if (ret < 0) {
2442 /* clean up all links */
2443 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
2444 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
2445
2446 be_disconnect(fe, stream);
2447 fe->dpcm[stream].runtime = NULL;
2448 }
2449
2450 fe_clear_pending(fe, stream);
2451 fe_path_put(&list);
2452 return ret;
2453}
2454
2455/* called when closing FE stream */
2456int soc_dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
2457{
2458 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2459 struct snd_soc_dpcm_params *dpcm_params;
2460 int stream = fe_substream->stream, ret;
2461
2462 ret = soc_dpcm_fe_dai_shutdown(fe_substream);
2463
2464 /* mark FE's links ready to prune */
2465 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
2466 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
2467
2468 be_disconnect(fe, stream);
2469
2470 fe->dpcm[stream].runtime = NULL;
2471
2472 return ret;
2473}
2474
Liam Girdwoodddee6272011-06-09 14:45:53 +01002475/* create a new pcm */
2476int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2477{
2478 struct snd_soc_codec *codec = rtd->codec;
2479 struct snd_soc_platform *platform = rtd->platform;
2480 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2481 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002482 struct snd_pcm_substream *substream[2];
Liam Girdwoodddee6272011-06-09 14:45:53 +01002483 struct snd_pcm *pcm;
2484 char new_name[64];
2485 int ret = 0, playback = 0, capture = 0;
2486
Steve Mucklef132c6c2012-06-06 18:30:57 -07002487 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
2488 if (cpu_dai->driver->playback.channels_min)
2489 playback = 1;
2490 if (cpu_dai->driver->capture.channels_min)
2491 capture = 1;
2492 } else {
2493 if (codec_dai->driver->playback.channels_min)
2494 playback = 1;
2495 if (codec_dai->driver->capture.channels_min)
2496 capture = 1;
2497 }
Sangsu Parka5002312012-01-02 17:15:10 +09002498
Steve Mucklef132c6c2012-06-06 18:30:57 -07002499 /* create the PCM */
2500 if (rtd->dai_link->no_pcm) {
2501 snprintf(new_name, sizeof(new_name), "(%s)",
2502 rtd->dai_link->stream_name);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002503
Steve Mucklef132c6c2012-06-06 18:30:57 -07002504 ret = snd_pcm_new_soc_be(rtd->card->snd_card, new_name, num,
2505 playback, capture, &pcm);
2506 } else {
2507 if (rtd->dai_link->dynamic)
2508 snprintf(new_name, sizeof(new_name), "%s (*)",
2509 rtd->dai_link->stream_name);
2510 else
2511 snprintf(new_name, sizeof(new_name), "%s %s-%d",
2512 rtd->dai_link->stream_name, codec_dai->name, num);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002513
Steve Mucklef132c6c2012-06-06 18:30:57 -07002514 ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
2515 capture, &pcm);
2516 }
Liam Girdwoodddee6272011-06-09 14:45:53 +01002517 if (ret < 0) {
2518 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
2519 return ret;
2520 }
Steve Mucklef132c6c2012-06-06 18:30:57 -07002521 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002522
2523 rtd->pcm = pcm;
2524 pcm->private_data = rtd;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002525 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
2526
2527 substream[SNDRV_PCM_STREAM_PLAYBACK] =
2528 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
2529 substream[SNDRV_PCM_STREAM_CAPTURE] =
2530 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
2531
2532 if (rtd->dai_link->no_pcm) {
2533 if (playback)
2534 substream[SNDRV_PCM_STREAM_PLAYBACK]->private_data = rtd;
2535 if (capture)
2536 substream[SNDRV_PCM_STREAM_CAPTURE]->private_data = rtd;
2537 goto out;
2538 }
2539
2540 /* setup any hostless PCMs - i.e. no host IO is performed */
2541 if (rtd->dai_link->no_host_mode) {
2542 if (substream[SNDRV_PCM_STREAM_PLAYBACK]) {
2543 substream[SNDRV_PCM_STREAM_PLAYBACK]->hw_no_buffer = 1;
2544 snd_soc_set_runtime_hwparams(
2545 substream[SNDRV_PCM_STREAM_PLAYBACK],
2546 &no_host_hardware);
2547 }
2548 if (substream[SNDRV_PCM_STREAM_CAPTURE]) {
2549 substream[SNDRV_PCM_STREAM_CAPTURE]->hw_no_buffer = 1;
2550 snd_soc_set_runtime_hwparams(
2551 substream[SNDRV_PCM_STREAM_CAPTURE],
2552 &no_host_hardware);
2553 }
2554 }
2555
2556 /* ASoC PCM operations */
2557 if (rtd->dai_link->dynamic) {
2558 rtd->ops.open = soc_dpcm_fe_dai_open;
2559 rtd->ops.hw_params = soc_dpcm_fe_dai_hw_params;
2560 rtd->ops.prepare = soc_dpcm_fe_dai_prepare;
2561 rtd->ops.trigger = soc_dpcm_fe_dai_trigger;
2562 rtd->ops.hw_free = soc_dpcm_fe_dai_hw_free;
2563 rtd->ops.close = soc_dpcm_fe_dai_close;
2564 rtd->ops.pointer = soc_pcm_pointer;
2565 rtd->ops.ioctl = soc_pcm_ioctl;
2566 } else {
2567 rtd->ops.open = soc_pcm_open;
2568 rtd->ops.hw_params = soc_pcm_hw_params;
2569 rtd->ops.prepare = soc_pcm_prepare;
2570 rtd->ops.trigger = soc_pcm_trigger;
2571 rtd->ops.hw_free = soc_pcm_hw_free;
2572 rtd->ops.close = soc_pcm_close;
2573 rtd->ops.pointer = soc_pcm_pointer;
2574 rtd->ops.ioctl = soc_pcm_ioctl;
2575 }
2576
Liam Girdwoodddee6272011-06-09 14:45:53 +01002577 if (platform->driver->ops) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07002578 rtd->ops.ack = platform->driver->ops->ack;
2579 rtd->ops.copy = platform->driver->ops->copy;
2580 rtd->ops.silence = platform->driver->ops->silence;
2581 rtd->ops.page = platform->driver->ops->page;
2582 rtd->ops.mmap = platform->driver->ops->mmap;
Liam Girdwoodddee6272011-06-09 14:45:53 +01002583 }
2584
2585 if (playback)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002586 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002587
2588 if (capture)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002589 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002590
2591 if (platform->driver->pcm_new) {
2592 ret = platform->driver->pcm_new(rtd);
2593 if (ret < 0) {
2594 pr_err("asoc: platform pcm constructor failed\n");
2595 return ret;
2596 }
2597 }
2598
2599 pcm->private_free = platform->driver->pcm_free;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002600out:
Liam Girdwoodddee6272011-06-09 14:45:53 +01002601 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
2602 cpu_dai->name);
2603 return ret;
2604}
Steve Mucklef132c6c2012-06-06 18:30:57 -07002605
2606#ifdef CONFIG_DEBUG_FS
2607static char *dpcm_state_string(enum snd_soc_dpcm_state state)
2608{
2609 switch (state) {
2610 case SND_SOC_DPCM_STATE_NEW:
2611 return "new";
2612 case SND_SOC_DPCM_STATE_OPEN:
2613 return "open";
2614 case SND_SOC_DPCM_STATE_HW_PARAMS:
2615 return "hw_params";
2616 case SND_SOC_DPCM_STATE_PREPARE:
2617 return "prepare";
2618 case SND_SOC_DPCM_STATE_START:
2619 return "start";
2620 case SND_SOC_DPCM_STATE_STOP:
2621 return "stop";
2622 case SND_SOC_DPCM_STATE_SUSPEND:
2623 return "suspend";
2624 case SND_SOC_DPCM_STATE_PAUSED:
2625 return "paused";
2626 case SND_SOC_DPCM_STATE_HW_FREE:
2627 return "hw_free";
2628 case SND_SOC_DPCM_STATE_CLOSE:
2629 return "close";
2630 }
2631
2632 return "unknown";
2633}
2634
2635static int soc_dpcm_state_open_file(struct inode *inode, struct file *file)
2636{
2637 file->private_data = inode->i_private;
2638 return 0;
2639}
2640
2641static ssize_t soc_dpcm_show_state(struct snd_soc_pcm_runtime *fe,
2642 int stream, char *buf, size_t size)
2643{
2644 struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
2645 struct snd_soc_dpcm_params *dpcm_params;
2646 ssize_t offset = 0;
2647
2648 /* FE state */
2649 offset += snprintf(buf + offset, size - offset,
2650 "[%s - %s]\n", fe->dai_link->name,
2651 stream ? "Capture" : "Playback");
2652
2653 offset += snprintf(buf + offset, size - offset, "State: %s\n",
2654 dpcm_state_string(fe->dpcm[stream].state));
2655
2656 if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
2657 (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
2658 offset += snprintf(buf + offset, size - offset,
2659 "Hardware Params: "
2660 "Format = %s, Channels = %d, Rate = %d\n",
2661 snd_pcm_format_name(params_format(params)),
2662 params_channels(params),
2663 params_rate(params));
2664
2665 /* BEs state */
2666 offset += snprintf(buf + offset, size - offset, "Backends:\n");
2667
2668 if (list_empty(&fe->dpcm[stream].be_clients)) {
2669 offset += snprintf(buf + offset, size - offset,
2670 " No active DSP links\n");
2671 goto out;
2672 }
2673
2674 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
2675 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2676
2677 offset += snprintf(buf + offset, size - offset,
2678 "- %s\n", be->dai_link->name);
2679
2680 offset += snprintf(buf + offset, size - offset,
2681 " State: %s\n",
2682 dpcm_state_string(fe->dpcm[stream].state));
2683
2684 if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
2685 (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
2686 offset += snprintf(buf + offset, size - offset,
2687 " Hardware Params: "
2688 "Format = %s, Channels = %d, Rate = %d\n",
2689 snd_pcm_format_name(params_format(params)),
2690 params_channels(params),
2691 params_rate(params));
2692 }
2693
2694out:
2695 return offset;
2696}
2697
2698static ssize_t soc_dpcm_state_read_file(struct file *file, char __user *user_buf,
2699 size_t count, loff_t *ppos)
2700{
2701 struct snd_soc_pcm_runtime *fe = file->private_data;
2702 ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
2703 char *buf;
2704
2705 buf = kmalloc(out_count, GFP_KERNEL);
2706 if (!buf)
2707 return -ENOMEM;
2708
2709 if (fe->cpu_dai->driver->playback.channels_min)
2710 offset += soc_dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK,
2711 buf + offset, out_count - offset);
2712
2713 if (fe->cpu_dai->driver->capture.channels_min)
2714 offset += soc_dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE,
2715 buf + offset, out_count - offset);
2716
2717 ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
2718
2719 kfree(buf);
2720
2721 return ret;
2722}
2723
2724static const struct file_operations soc_dpcm_state_fops = {
2725 .open = soc_dpcm_state_open_file,
2726 .read = soc_dpcm_state_read_file,
2727 .llseek = default_llseek,
2728};
2729
2730int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
2731{
2732 rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
2733 rtd->card->debugfs_card_root);
2734 if (!rtd->debugfs_dpcm_root) {
2735 dev_dbg(rtd->dev,
2736 "ASoC: Failed to create dpcm debugfs directory %s\n",
2737 rtd->dai_link->name);
2738 return -EINVAL;
2739 }
2740
2741 rtd->debugfs_dpcm_state = debugfs_create_file("state", 0644,
2742 rtd->debugfs_dpcm_root,
2743 rtd, &soc_dpcm_state_fops);
2744
2745 return 0;
2746}
2747#endif