blob: 3a9fbe18f2f0367acc9e6e303bdd1d89ed9cc9a4 [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) {
239 ret = codec_dai->driver->ops->startup(substream, codec_dai);
240 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700241 printk(KERN_ERR "asoc: can't open codec %s\n",
242 codec_dai->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100243 goto codec_dai_err;
244 }
245 }
246
247 if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
248 ret = rtd->dai_link->ops->startup(substream);
249 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700250 printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100251 goto machine_err;
252 }
253 }
254
Steve Mucklef132c6c2012-06-06 18:30:57 -0700255 /* DSP DAI links compat checks are different */
256 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm)
257 goto dynamic;
258
Liam Girdwoodddee6272011-06-09 14:45:53 +0100259 /* Check that the codec and cpu DAIs are compatible */
260 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
261 runtime->hw.rate_min =
262 max(codec_dai_drv->playback.rate_min,
263 cpu_dai_drv->playback.rate_min);
264 runtime->hw.rate_max =
265 min(codec_dai_drv->playback.rate_max,
266 cpu_dai_drv->playback.rate_max);
267 runtime->hw.channels_min =
268 max(codec_dai_drv->playback.channels_min,
269 cpu_dai_drv->playback.channels_min);
270 runtime->hw.channels_max =
271 min(codec_dai_drv->playback.channels_max,
272 cpu_dai_drv->playback.channels_max);
273 runtime->hw.formats =
274 codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
275 runtime->hw.rates =
276 codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
277 if (codec_dai_drv->playback.rates
278 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
279 runtime->hw.rates |= cpu_dai_drv->playback.rates;
280 if (cpu_dai_drv->playback.rates
281 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
282 runtime->hw.rates |= codec_dai_drv->playback.rates;
283 } else {
284 runtime->hw.rate_min =
285 max(codec_dai_drv->capture.rate_min,
286 cpu_dai_drv->capture.rate_min);
287 runtime->hw.rate_max =
288 min(codec_dai_drv->capture.rate_max,
289 cpu_dai_drv->capture.rate_max);
290 runtime->hw.channels_min =
291 max(codec_dai_drv->capture.channels_min,
292 cpu_dai_drv->capture.channels_min);
293 runtime->hw.channels_max =
294 min(codec_dai_drv->capture.channels_max,
295 cpu_dai_drv->capture.channels_max);
296 runtime->hw.formats =
297 codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
298 runtime->hw.rates =
299 codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
300 if (codec_dai_drv->capture.rates
301 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
302 runtime->hw.rates |= cpu_dai_drv->capture.rates;
303 if (cpu_dai_drv->capture.rates
304 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
305 runtime->hw.rates |= codec_dai_drv->capture.rates;
306 }
307
308 ret = -EINVAL;
309 snd_pcm_limit_hw_rates(runtime);
310 if (!runtime->hw.rates) {
311 printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
312 codec_dai->name, cpu_dai->name);
313 goto config_err;
314 }
315 if (!runtime->hw.formats) {
316 printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
317 codec_dai->name, cpu_dai->name);
318 goto config_err;
319 }
320 if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
321 runtime->hw.channels_min > runtime->hw.channels_max) {
322 printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
323 codec_dai->name, cpu_dai->name);
324 goto config_err;
325 }
326
Mark Brown58ba9b22012-01-16 18:38:51 +0000327 soc_pcm_apply_msb(substream, codec_dai);
328 soc_pcm_apply_msb(substream, cpu_dai);
329
Liam Girdwoodddee6272011-06-09 14:45:53 +0100330 /* Symmetry only applies if we've already got an active stream. */
Dong Aisheng17841022011-08-29 17:15:14 +0800331 if (cpu_dai->active) {
332 ret = soc_pcm_apply_symmetry(substream, cpu_dai);
333 if (ret != 0)
334 goto config_err;
335 }
336
337 if (codec_dai->active) {
338 ret = soc_pcm_apply_symmetry(substream, codec_dai);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100339 if (ret != 0)
340 goto config_err;
341 }
342
343 pr_debug("asoc: %s <-> %s info:\n",
344 codec_dai->name, cpu_dai->name);
345 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
346 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
347 runtime->hw.channels_max);
348 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
349 runtime->hw.rate_max);
350
Steve Mucklef132c6c2012-06-06 18:30:57 -0700351dynamic:
Liam Girdwoodddee6272011-06-09 14:45:53 +0100352 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
353 cpu_dai->playback_active++;
354 codec_dai->playback_active++;
355 } else {
356 cpu_dai->capture_active++;
357 codec_dai->capture_active++;
358 }
359 cpu_dai->active++;
360 codec_dai->active++;
361 rtd->codec->active++;
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100362 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100363 return 0;
364
365config_err:
366 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
367 rtd->dai_link->ops->shutdown(substream);
368
369machine_err:
370 if (codec_dai->driver->ops->shutdown)
371 codec_dai->driver->ops->shutdown(substream, codec_dai);
372
373codec_dai_err:
374 if (platform->driver->ops && platform->driver->ops->close)
375 platform->driver->ops->close(substream);
376
377platform_err:
378 if (cpu_dai->driver->ops->shutdown)
379 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
380out:
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100381 mutex_unlock(&rtd->pcm_mutex);
Mark Brownd6652ef2011-12-03 20:14:31 +0000382
383 pm_runtime_put(platform->dev);
384 pm_runtime_put(codec_dai->dev);
385 pm_runtime_put(cpu_dai->dev);
386
Liam Girdwoodddee6272011-06-09 14:45:53 +0100387 return ret;
388}
389
390/*
391 * Power down the audio subsystem pmdown_time msecs after close is called.
392 * This is to ensure there are no pops or clicks in between any music tracks
393 * due to DAPM power cycling.
394 */
395static void close_delayed_work(struct work_struct *work)
396{
397 struct snd_soc_pcm_runtime *rtd =
398 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
399 struct snd_soc_dai *codec_dai = rtd->codec_dai;
400
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100401 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100402
403 pr_debug("pop wq checking: %s status: %s waiting: %s\n",
404 codec_dai->driver->playback.stream_name,
405 codec_dai->playback_active ? "active" : "inactive",
406 codec_dai->pop_wait ? "yes" : "no");
407
408 /* are we waiting on this codec DAI stream */
409 if (codec_dai->pop_wait == 1) {
410 codec_dai->pop_wait = 0;
Steve Mucklef132c6c2012-06-06 18:30:57 -0700411 snd_soc_dapm_stream_event(rtd,
412 codec_dai->driver->playback.stream_name,
413 SND_SOC_DAPM_STREAM_STOP);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100414 }
415
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100416 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100417}
418
419/*
420 * Called by ALSA when a PCM substream is closed. Private data can be
421 * freed here. The cpu DAI, codec DAI, machine and platform are also
422 * shutdown.
423 */
Liam Girdwood91d5e6b2011-06-09 17:04:59 +0100424static int soc_pcm_close(struct snd_pcm_substream *substream)
Liam Girdwoodddee6272011-06-09 14:45:53 +0100425{
426 struct snd_soc_pcm_runtime *rtd = substream->private_data;
427 struct snd_soc_platform *platform = rtd->platform;
428 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
429 struct snd_soc_dai *codec_dai = rtd->codec_dai;
430 struct snd_soc_codec *codec = rtd->codec;
431
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100432 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100433
434 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
435 cpu_dai->playback_active--;
436 codec_dai->playback_active--;
437 } else {
438 cpu_dai->capture_active--;
439 codec_dai->capture_active--;
440 }
441
442 cpu_dai->active--;
443 codec_dai->active--;
444 codec->active--;
445
Dong Aisheng17841022011-08-29 17:15:14 +0800446 /* clear the corresponding DAIs rate when inactive */
447 if (!cpu_dai->active)
448 cpu_dai->rate = 0;
449
450 if (!codec_dai->active)
451 codec_dai->rate = 0;
Sascha Hauer25b76792011-08-17 09:20:01 +0200452
Liam Girdwoodddee6272011-06-09 14:45:53 +0100453 /* Muting the DAC suppresses artifacts caused during digital
454 * shutdown, for example from stopping clocks.
455 */
456 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
457 snd_soc_dai_digital_mute(codec_dai, 1);
458
459 if (cpu_dai->driver->ops->shutdown)
460 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
461
462 if (codec_dai->driver->ops->shutdown)
463 codec_dai->driver->ops->shutdown(substream, codec_dai);
464
465 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
466 rtd->dai_link->ops->shutdown(substream);
467
468 if (platform->driver->ops && platform->driver->ops->close)
469 platform->driver->ops->close(substream);
470 cpu_dai->runtime = NULL;
471
472 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700473 if (codec->ignore_pmdown_time ||
474 rtd->dai_link->ignore_pmdown_time ||
475 !rtd->pmdown_time) {
Peter Ujfalusi1d69c5c2011-10-14 14:43:33 +0300476 /* powered down playback stream now */
477 snd_soc_dapm_stream_event(rtd,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700478 codec_dai->driver->playback.stream_name,
479 SND_SOC_DAPM_STREAM_STOP);
Peter Ujfalusi1d69c5c2011-10-14 14:43:33 +0300480 } else {
481 /* start delayed pop wq here for playback streams */
482 codec_dai->pop_wait = 1;
483 schedule_delayed_work(&rtd->delayed_work,
484 msecs_to_jiffies(rtd->pmdown_time));
485 }
Liam Girdwoodddee6272011-06-09 14:45:53 +0100486 } else {
487 /* capture streams can be powered down now */
Steve Mucklef132c6c2012-06-06 18:30:57 -0700488 snd_soc_dapm_stream_event(rtd,
489 codec_dai->driver->capture.stream_name,
490 SND_SOC_DAPM_STREAM_STOP);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100491 }
492
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100493 mutex_unlock(&rtd->pcm_mutex);
Mark Brownd6652ef2011-12-03 20:14:31 +0000494
495 pm_runtime_put(platform->dev);
496 pm_runtime_put(codec_dai->dev);
497 pm_runtime_put(cpu_dai->dev);
498
Liam Girdwoodddee6272011-06-09 14:45:53 +0100499 return 0;
500}
501
502/*
503 * Called by ALSA when the PCM substream is prepared, can set format, sample
504 * rate, etc. This function is non atomic and can be called multiple times,
505 * it can refer to the runtime info.
506 */
507static int soc_pcm_prepare(struct snd_pcm_substream *substream)
508{
509 struct snd_soc_pcm_runtime *rtd = substream->private_data;
510 struct snd_soc_platform *platform = rtd->platform;
511 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
512 struct snd_soc_dai *codec_dai = rtd->codec_dai;
513 int ret = 0;
514
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100515 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100516
517 if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
518 ret = rtd->dai_link->ops->prepare(substream);
519 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700520 printk(KERN_ERR "asoc: machine prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100521 goto out;
522 }
523 }
524
525 if (platform->driver->ops && platform->driver->ops->prepare) {
526 ret = platform->driver->ops->prepare(substream);
527 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700528 printk(KERN_ERR "asoc: platform prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100529 goto out;
530 }
531 }
532
533 if (codec_dai->driver->ops->prepare) {
534 ret = codec_dai->driver->ops->prepare(substream, codec_dai);
535 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700536 printk(KERN_ERR "asoc: codec DAI prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100537 goto out;
538 }
539 }
540
541 if (cpu_dai->driver->ops->prepare) {
542 ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
543 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700544 printk(KERN_ERR "asoc: cpu DAI prepare error\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100545 goto out;
546 }
547 }
548
549 /* cancel any delayed stream shutdown that is pending */
550 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
551 codec_dai->pop_wait) {
552 codec_dai->pop_wait = 0;
553 cancel_delayed_work(&rtd->delayed_work);
554 }
555
Steve Mucklef132c6c2012-06-06 18:30:57 -0700556 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
557 snd_soc_dapm_stream_event(rtd,
558 codec_dai->driver->playback.stream_name,
559 SND_SOC_DAPM_STREAM_START);
560 else
561 snd_soc_dapm_stream_event(rtd,
562 codec_dai->driver->capture.stream_name,
563 SND_SOC_DAPM_STREAM_START);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100564
565 snd_soc_dai_digital_mute(codec_dai, 0);
566
567out:
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100568 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100569 return ret;
570}
571
572/*
573 * Called by ALSA when the hardware params are set by application. This
574 * function can also be called multiple times and can allocate buffers
575 * (using snd_pcm_lib_* ). It's non-atomic.
576 */
577static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
578 struct snd_pcm_hw_params *params)
579{
580 struct snd_soc_pcm_runtime *rtd = substream->private_data;
581 struct snd_soc_platform *platform = rtd->platform;
582 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
583 struct snd_soc_dai *codec_dai = rtd->codec_dai;
584 int ret = 0;
585
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100586 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100587
588 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
589 ret = rtd->dai_link->ops->hw_params(substream, params);
590 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700591 printk(KERN_ERR "asoc: machine hw_params failed\n");
Liam Girdwoodddee6272011-06-09 14:45:53 +0100592 goto out;
593 }
594 }
595
596 if (codec_dai->driver->ops->hw_params) {
597 ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
598 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700599 printk(KERN_ERR "asoc: can't set codec %s hw params\n",
600 codec_dai->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100601 goto codec_err;
602 }
603 }
604
605 if (cpu_dai->driver->ops->hw_params) {
606 ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
607 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700608 printk(KERN_ERR "asoc: interface %s hw params failed\n",
609 cpu_dai->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100610 goto interface_err;
611 }
612 }
613
614 if (platform->driver->ops && platform->driver->ops->hw_params) {
615 ret = platform->driver->ops->hw_params(substream, params);
616 if (ret < 0) {
Steve Mucklef132c6c2012-06-06 18:30:57 -0700617 printk(KERN_ERR "asoc: platform %s hw params failed\n",
618 platform->name);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100619 goto platform_err;
620 }
621 }
622
Dong Aisheng17841022011-08-29 17:15:14 +0800623 /* store the rate for each DAIs */
624 cpu_dai->rate = params_rate(params);
625 codec_dai->rate = params_rate(params);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100626
Steve Mucklef132c6c2012-06-06 18:30:57 -0700627 /* malloc a page for hostless IO.
628 * FIXME: rework with alsa-lib changes so that this malloc is not required.
629 */
630 if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) {
631 substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV;
632 substream->dma_buffer.dev.dev = rtd->dev;
633 substream->dma_buffer.dev.dev->coherent_dma_mask = DMA_BIT_MASK(32);
634 substream->dma_buffer.private_data = NULL;
635
636 ret = snd_pcm_lib_malloc_pages(substream, PAGE_SIZE);
637 if (ret < 0)
638 goto platform_err;
639 }
640
Liam Girdwoodddee6272011-06-09 14:45:53 +0100641out:
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100642 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100643 return ret;
644
645platform_err:
646 if (cpu_dai->driver->ops->hw_free)
647 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
648
649interface_err:
650 if (codec_dai->driver->ops->hw_free)
651 codec_dai->driver->ops->hw_free(substream, codec_dai);
652
653codec_err:
654 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
655 rtd->dai_link->ops->hw_free(substream);
656
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100657 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100658 return ret;
659}
660
661/*
662 * Frees resources allocated by hw_params, can be called multiple times
663 */
664static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
665{
666 struct snd_soc_pcm_runtime *rtd = substream->private_data;
667 struct snd_soc_platform *platform = rtd->platform;
668 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
669 struct snd_soc_dai *codec_dai = rtd->codec_dai;
670 struct snd_soc_codec *codec = rtd->codec;
671
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100672 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100673
674 /* apply codec digital mute */
675 if (!codec->active)
676 snd_soc_dai_digital_mute(codec_dai, 1);
677
678 /* free any machine hw params */
679 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
680 rtd->dai_link->ops->hw_free(substream);
681
682 /* free any DMA resources */
683 if (platform->driver->ops && platform->driver->ops->hw_free)
684 platform->driver->ops->hw_free(substream);
685
686 /* now free hw params for the DAIs */
687 if (codec_dai->driver->ops->hw_free)
688 codec_dai->driver->ops->hw_free(substream, codec_dai);
689
690 if (cpu_dai->driver->ops->hw_free)
691 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
692
Steve Mucklef132c6c2012-06-06 18:30:57 -0700693 if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
694 snd_pcm_lib_free_pages(substream);
695
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +0100696 mutex_unlock(&rtd->pcm_mutex);
Liam Girdwoodddee6272011-06-09 14:45:53 +0100697 return 0;
698}
699
700static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
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 int ret;
707
708 if (codec_dai->driver->ops->trigger) {
709 ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
710 if (ret < 0)
711 return ret;
712 }
713
714 if (platform->driver->ops && platform->driver->ops->trigger) {
715 ret = platform->driver->ops->trigger(substream, cmd);
716 if (ret < 0)
717 return ret;
718 }
719
720 if (cpu_dai->driver->ops->trigger) {
721 ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
722 if (ret < 0)
723 return ret;
724 }
725 return 0;
726}
727
Steve Mucklef132c6c2012-06-06 18:30:57 -0700728int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, int cmd)
729{
730 struct snd_soc_pcm_runtime *rtd = substream->private_data;
731 struct snd_soc_platform *platform = rtd->platform;
732 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
733 struct snd_soc_dai *codec_dai = rtd->codec_dai;
734 int ret;
735
736 if (codec_dai->driver->ops->bespoke_trigger) {
737 ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
738 if (ret < 0)
739 return ret;
740 }
741
742 if (platform->driver->bespoke_trigger) {
743 ret = platform->driver->bespoke_trigger(substream, cmd);
744 if (ret < 0)
745 return ret;
746 }
747
748 if (cpu_dai->driver->ops->bespoke_trigger) {
749 ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
750 if (ret < 0)
751 return ret;
752 }
753 return 0;
754}
755
Liam Girdwoodddee6272011-06-09 14:45:53 +0100756/*
757 * soc level wrapper for pointer callback
758 * If cpu_dai, codec_dai, platform driver has the delay callback, than
759 * the runtime->delay will be updated accordingly.
760 */
761static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
762{
763 struct snd_soc_pcm_runtime *rtd = substream->private_data;
764 struct snd_soc_platform *platform = rtd->platform;
765 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
766 struct snd_soc_dai *codec_dai = rtd->codec_dai;
767 struct snd_pcm_runtime *runtime = substream->runtime;
768 snd_pcm_uframes_t offset = 0;
769 snd_pcm_sframes_t delay = 0;
770
771 if (platform->driver->ops && platform->driver->ops->pointer)
772 offset = platform->driver->ops->pointer(substream);
773
774 if (cpu_dai->driver->ops->delay)
775 delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
776
777 if (codec_dai->driver->ops->delay)
778 delay += codec_dai->driver->ops->delay(substream, codec_dai);
779
780 if (platform->driver->delay)
781 delay += platform->driver->delay(substream, codec_dai);
782
783 runtime->delay = delay;
784
785 return offset;
786}
787
Steve Mucklef132c6c2012-06-06 18:30:57 -0700788static inline int be_connect(struct snd_soc_pcm_runtime *fe,
789 struct snd_soc_pcm_runtime *be, int stream)
790{
791 struct snd_soc_dpcm_params *dpcm_params;
792
793 if (!fe->dpcm[stream].runtime) {
794 dev_err(fe->dev, "%s no runtime\n", fe->dai_link->name);
795 return -ENODEV;
796 }
797
798 /* only add new dpcm_paramss */
799 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
800 if (dpcm_params->be == be && dpcm_params->fe == fe)
801 return 0;
802 }
803
804 dpcm_params = kzalloc(sizeof(struct snd_soc_dpcm_params), GFP_KERNEL);
805 if (!dpcm_params)
806 return -ENOMEM;
807
808 dpcm_params->be = be;
809 dpcm_params->fe = fe;
810 be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
811 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_NEW;
812 list_add(&dpcm_params->list_be, &fe->dpcm[stream].be_clients);
813 list_add(&dpcm_params->list_fe, &be->dpcm[stream].fe_clients);
814
815 dev_dbg(fe->dev, " connected new DSP %s path %s %s %s\n",
816 stream ? "capture" : "playback", fe->dai_link->name,
817 stream ? "<-" : "->", be->dai_link->name);
818
819#ifdef CONFIG_DEBUG_FS
820 dpcm_params->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644,
821 fe->debugfs_dpcm_root, &dpcm_params->state);
822#endif
823
824 return 1;
825}
826
827static inline void be_reparent(struct snd_soc_pcm_runtime *fe,
828 struct snd_soc_pcm_runtime *be, int stream)
829{
830 struct snd_soc_dpcm_params *dpcm_params;
831 struct snd_pcm_substream *fe_substream, *be_substream;
832
833 /* reparent if BE is connected to other FEs */
834 if (!be->dpcm[stream].users)
835 return;
836
837 be_substream = snd_soc_dpcm_get_substream(be, stream);
838
839 list_for_each_entry(dpcm_params, &be->dpcm[stream].fe_clients, list_fe) {
840 if (dpcm_params->fe != fe) {
841
842 dev_dbg(fe->dev, " reparent %s path %s %s %s\n",
843 stream ? "capture" : "playback",
844 dpcm_params->fe->dai_link->name,
845 stream ? "<-" : "->", dpcm_params->be->dai_link->name);
846
847 fe_substream = snd_soc_dpcm_get_substream(dpcm_params->fe,
848 stream);
849 be_substream->runtime = fe_substream->runtime;
850 break;
851 }
852 }
853}
854
855static inline void be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
856{
857 struct snd_soc_dpcm_params *dpcm_params, *d;
858
859 list_for_each_entry_safe(dpcm_params, d, &fe->dpcm[stream].be_clients, list_be) {
860 dev_dbg(fe->dev, "BE %s disconnect check for %s\n",
861 stream ? "capture" : "playback",
862 dpcm_params->be->dai_link->name);
863
864 if (dpcm_params->state == SND_SOC_DPCM_LINK_STATE_FREE) {
865 dev_dbg(fe->dev, " freed DSP %s path %s %s %s\n",
866 stream ? "capture" : "playback", fe->dai_link->name,
867 stream ? "<-" : "->", dpcm_params->be->dai_link->name);
868
869 /* BEs still alive need new FE */
870 be_reparent(fe, dpcm_params->be, stream);
871
872#ifdef CONFIG_DEBUG_FS
873 debugfs_remove(dpcm_params->debugfs_state);
874#endif
875
876 list_del(&dpcm_params->list_be);
877 list_del(&dpcm_params->list_fe);
878 kfree(dpcm_params);
879 }
880 }
881}
882
883static struct snd_soc_pcm_runtime *be_get_rtd(struct snd_soc_card *card,
884 struct snd_soc_dapm_widget *widget)
885{
886 struct snd_soc_pcm_runtime *be;
887 int i;
888
889 if (!widget->sname) {
890 dev_err(card->dev, "widget %s has no stream\n", widget->name);
891 return NULL;
892 }
893
894 for (i = 0; i < card->num_links; i++) {
895 be = &card->rtd[i];
896
897 if (!strcmp(widget->sname, be->dai_link->stream_name))
898 return be;
899 }
900
901 dev_err(card->dev, "can't get BE for %s\n", widget->name);
902 return NULL;
903}
904
905static struct snd_soc_dapm_widget *be_get_widget(struct snd_soc_card *card,
906 struct snd_soc_pcm_runtime *rtd)
907{
908 struct snd_soc_dapm_widget *widget;
909
910 list_for_each_entry(widget, &card->widgets, list) {
911
912 if (!widget->sname)
913 continue;
914
915 if (!strcmp(widget->sname, rtd->dai_link->stream_name))
916 return widget;
917 }
918
919 dev_err(card->dev, "can't get widget for %s\n",
920 rtd->dai_link->stream_name);
921 return NULL;
922}
923
924static int widget_in_list(struct snd_soc_dapm_widget_list *list,
925 struct snd_soc_dapm_widget *widget)
926{
927 int i;
928
929 for (i = 0; i < list->num_widgets; i++) {
930 if (widget == list->widgets[i])
931 return 1;
932 }
933
934 return 0;
935}
936
937static int fe_path_get(struct snd_soc_pcm_runtime *fe,
938 int stream, struct snd_soc_dapm_widget_list **list_)
939{
940 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
941 struct snd_soc_dapm_widget_list *list;
942 int paths;
943
944 list = kzalloc(sizeof(struct snd_soc_dapm_widget_list) +
945 sizeof(struct snd_soc_dapm_widget *), GFP_KERNEL);
946 if (list == NULL)
947 return -ENOMEM;
948
949 /* get number of valid DAI paths and their widgets */
950 paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list);
951
952 dev_dbg(fe->dev, "found %d audio %s paths\n", paths,
953 stream ? "capture" : "playback");
954
955 *list_ = list;
956 return paths;
957}
958
959static inline void fe_path_put(struct snd_soc_dapm_widget_list **list)
960{
961 kfree(*list);
962}
963
964static int be_prune_old(struct snd_soc_pcm_runtime *fe, int stream,
965 struct snd_soc_dapm_widget_list **list_)
966{
967 struct snd_soc_card *card = fe->card;
968 struct snd_soc_dpcm_params *dpcm_params;
969 struct snd_soc_dapm_widget_list *list = *list_;
970 struct snd_soc_dapm_widget *widget;
971 int old = 0;
972
973 /* Destroy any old FE <--> BE connections */
974 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
975
976 /* is there a valid widget for this BE */
977 widget = be_get_widget(card, dpcm_params->be);
978 if (!widget) {
979 dev_err(fe->dev, "no widget found for %s\n",
980 dpcm_params->be->dai_link->name);
981 continue;
982 }
983
984 /* prune the BE if it's no longer in our active list */
985 if (widget_in_list(list, widget))
986 continue;
987
988 dev_dbg(fe->dev, "pruning %s BE %s for %s\n",
989 stream ? "capture" : "playback", dpcm_params->be->dai_link->name,
990 fe->dai_link->name);
991 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
992 dpcm_params->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
993 old++;
994 }
995
996 dev_dbg(fe->dev, "found %d old BEs\n", old);
997 return old;
998}
999
1000static int be_add_new(struct snd_soc_pcm_runtime *fe, int stream,
1001 struct snd_soc_dapm_widget_list **list_)
1002{
1003 struct snd_soc_card *card = fe->card;
1004 struct snd_soc_dapm_widget_list *list = *list_;
1005 enum snd_soc_dapm_type be_type;
1006 int i, new = 0, err;
1007
1008 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1009 be_type = snd_soc_dapm_aif_out;
1010 else
1011 be_type = snd_soc_dapm_aif_in;
1012
1013 /* Create any new FE <--> BE connections */
1014 for (i = 0; i < list->num_widgets; i++) {
1015
1016 if (list->widgets[i]->id == be_type) {
1017 struct snd_soc_pcm_runtime *be;
1018
1019 /* is there a valid BE rtd for this widget */
1020 be = be_get_rtd(card, list->widgets[i]);
1021 if (!be) {
1022 dev_err(fe->dev, "no BE found for %s\n",
1023 list->widgets[i]->name);
1024 continue;
1025 }
1026
1027 /* don't connect if FE is not running */
1028 if (!fe->dpcm[stream].runtime)
1029 continue;
1030
1031 /* newly connected FE and BE */
1032 err = be_connect(fe, be, stream);
1033 if (err < 0) {
1034 dev_err(fe->dev, "can't connect %s\n", list->widgets[i]->name);
1035 break;
1036 } else if (err == 0) /* already connected */
1037 continue;
1038
1039 /* new */
1040 be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1041 new++;
1042 }
1043 }
1044
1045 dev_dbg(fe->dev, "found %d new BEs\n", new);
1046 return new;
1047}
1048
1049/*
1050 * Find the corresponding BE DAIs that source or sink audio to this
1051 * FE substream.
1052 */
1053static int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
1054 int stream, struct snd_soc_dapm_widget_list **list, int new)
1055{
1056 if (new)
1057 return be_add_new(fe, stream, list);
1058 else
1059 return be_prune_old(fe, stream, list);
1060 return 0;
1061}
1062
1063/*
1064 * Clear the runtime pending state of all BE's.
1065 */
1066static void fe_clear_pending(struct snd_soc_pcm_runtime *fe, int stream)
1067{
1068 struct snd_soc_dpcm_params *dpcm_params;
1069
1070 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
1071 dpcm_params->be->dpcm[stream].runtime_update =
1072 SND_SOC_DPCM_UPDATE_NO;
1073}
1074
1075/* Unwind the BE startup */
1076static void soc_dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, int stream)
1077{
1078 struct snd_soc_dpcm_params *dpcm_params;
1079
1080 /* disable any enabled and non active backends */
1081 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1082
1083 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1084 struct snd_pcm_substream *be_substream =
1085 snd_soc_dpcm_get_substream(be, stream);
1086
1087 if (be->dpcm[stream].users == 0)
1088 dev_err(be->dev, "no users %s at close - state %d\n",
1089 stream ? "capture" : "playback", be->dpcm[stream].state);
1090
1091 if (--be->dpcm[stream].users != 0)
1092 continue;
1093
1094 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
1095 continue;
1096
1097 soc_pcm_close(be_substream);
1098 be_substream->runtime = NULL;
1099
1100 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1101 }
1102}
1103
1104/* Startup all new BE */
1105static int soc_dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
1106{
1107 struct snd_soc_dpcm_params *dpcm_params;
1108 int err, count = 0;
1109
1110 /* only startup BE DAIs that are either sinks or sources to this FE DAI */
1111 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1112
1113 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1114 struct snd_pcm_substream *be_substream =
1115 snd_soc_dpcm_get_substream(be, stream);
1116
1117 /* is this op for this BE ? */
1118 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1119 continue;
1120
1121 /* first time the dpcm_params is open ? */
1122 if (be->dpcm[stream].users == MAX_BE_USERS)
1123 dev_err(be->dev, "too many users %s at open - state %d\n",
1124 stream ? "capture" : "playback", be->dpcm[stream].state);
1125
1126 if (be->dpcm[stream].users++ != 0)
1127 continue;
1128
1129 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
1130 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
1131 continue;
1132
1133 dev_dbg(be->dev, "dpcm: open BE %s\n", be->dai_link->name);
1134
1135 be_substream->runtime = be->dpcm[stream].runtime;
1136 err = soc_pcm_open(be_substream);
1137 if (err < 0) {
1138 dev_err(be->dev, "BE open failed %d\n", err);
1139 be->dpcm[stream].users--;
1140 if (be->dpcm[stream].users < 0)
1141 dev_err(be->dev, "no users %s at unwind - state %d\n",
1142 stream ? "capture" : "playback",
1143 be->dpcm[stream].state);
1144
1145 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1146 goto unwind;
1147 }
1148
1149 be->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1150 count++;
1151 }
1152
1153 return count;
1154
1155unwind:
1156 /* disable any enabled and non active backends */
1157 list_for_each_entry_continue_reverse(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
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 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1163 continue;
1164
1165 if (be->dpcm[stream].users == 0)
1166 dev_err(be->dev, "no users %s at close - state %d\n",
1167 stream ? "capture" : "playback", be->dpcm[stream].state);
1168
1169 if (--be->dpcm[stream].users != 0)
1170 continue;
1171
1172 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
1173 continue;
1174
1175 soc_pcm_close(be_substream);
1176 be_substream->runtime = NULL;
1177
1178 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1179 }
1180
1181 return err;
1182}
1183
1184void soc_dpcm_set_dynamic_runtime(struct snd_pcm_substream *substream)
1185{
1186 struct snd_pcm_runtime *runtime = substream->runtime;
1187 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1188 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1189 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
1190
1191 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1192 runtime->hw.rate_min = cpu_dai_drv->playback.rate_min;
1193 runtime->hw.rate_max = cpu_dai_drv->playback.rate_max;
1194 runtime->hw.channels_min = cpu_dai_drv->playback.channels_min;
1195 runtime->hw.channels_max = cpu_dai_drv->playback.channels_max;
1196 runtime->hw.formats &= cpu_dai_drv->playback.formats;
1197 runtime->hw.rates = cpu_dai_drv->playback.rates;
1198 } else {
1199 runtime->hw.rate_min = cpu_dai_drv->capture.rate_min;
1200 runtime->hw.rate_max = cpu_dai_drv->capture.rate_max;
1201 runtime->hw.channels_min = cpu_dai_drv->capture.channels_min;
1202 runtime->hw.channels_max = cpu_dai_drv->capture.channels_max;
1203 runtime->hw.formats &= cpu_dai_drv->capture.formats;
1204 runtime->hw.rates = cpu_dai_drv->capture.rates;
1205 }
1206}
1207
1208static int soc_dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
1209{
1210 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1211 struct snd_pcm_runtime *runtime = fe_substream->runtime;
1212 int stream = fe_substream->stream, ret = 0;
1213
1214 mutex_lock(&fe->card->dpcm_mutex);
1215 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1216
1217 ret = soc_dpcm_be_dai_startup(fe, fe_substream->stream);
1218 if (ret < 0) {
1219 dev_err(fe->dev,"dpcm: failed to start some BEs %d\n", ret);
1220 goto be_err;
1221 }
1222
1223 dev_dbg(fe->dev, "dpcm: open FE %s\n", fe->dai_link->name);
1224
1225 /* start the DAI frontend */
1226 ret = soc_pcm_open(fe_substream);
1227 if (ret < 0) {
1228 dev_err(fe->dev,"dpcm: failed to start FE %d\n", ret);
1229 goto unwind;
1230 }
1231
1232 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1233
1234 soc_dpcm_set_dynamic_runtime(fe_substream);
1235 snd_pcm_limit_hw_rates(runtime);
1236
1237 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1238 mutex_unlock(&fe->card->dpcm_mutex);
1239 return 0;
1240
1241unwind:
1242 soc_dpcm_be_dai_startup_unwind(fe, fe_substream->stream);
1243be_err:
1244 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1245 mutex_unlock(&fe->card->dpcm_mutex);
1246 return ret;
1247}
1248
1249/* BE shutdown - called on DAPM sync updates (i.e. FE is already running)*/
1250static int soc_dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1251{
1252 struct snd_soc_dpcm_params *dpcm_params;
1253
1254 /* only shutdown backends that are either sinks or sources to this frontend DAI */
1255 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1256
1257 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1258 struct snd_pcm_substream *be_substream =
1259 snd_soc_dpcm_get_substream(be, stream);
1260
1261 /* is this op for this BE ? */
1262 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1263 continue;
1264
1265 if (be->dpcm[stream].users == 0)
1266 dev_err(be->dev, "no users %s at close - state %d\n",
1267 stream ? "capture" : "playback", be->dpcm[stream].state);
1268
1269 if (--be->dpcm[stream].users != 0)
1270 continue;
1271
1272 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1273 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN))
1274 continue;
1275
1276 dev_dbg(be->dev, "dpcm: close BE %s\n",
1277 dpcm_params->fe->dai_link->name);
1278
1279 soc_pcm_close(be_substream);
1280 be_substream->runtime = NULL;
1281
1282 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1283 }
1284 return 0;
1285}
1286
1287/* FE +BE shutdown - called on FE PCM ops */
1288static int soc_dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
1289{
1290 struct snd_soc_pcm_runtime *fe = substream->private_data;
1291 int stream = substream->stream;
1292
1293 mutex_lock(&fe->card->dpcm_mutex);
1294 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1295
1296 dev_dbg(fe->dev, "dpcm: close FE %s\n", fe->dai_link->name);
1297
1298 /* now shutdown the frontend */
1299 soc_pcm_close(substream);
1300
1301 /* shutdown the BEs */
1302 soc_dpcm_be_dai_shutdown(fe, substream->stream);
1303 /* run the stream event for each BE */
1304 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1305 soc_dpcm_dapm_stream_event(fe, stream,
1306 fe->cpu_dai->driver->playback.stream_name,
1307 SND_SOC_DAPM_STREAM_STOP);
1308 else
1309 soc_dpcm_dapm_stream_event(fe, stream,
1310 fe->cpu_dai->driver->capture.stream_name,
1311 SND_SOC_DAPM_STREAM_STOP);
1312
1313 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1314 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1315
1316 mutex_unlock(&fe->card->dpcm_mutex);
1317 return 0;
1318}
1319
1320static int soc_dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
1321{
1322 struct snd_soc_dpcm_params *dpcm_params;
1323 int ret;
1324
1325 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1326
1327 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1328 struct snd_pcm_substream *be_substream =
1329 snd_soc_dpcm_get_substream(be, stream);
1330
1331 /* is this op for this BE ? */
1332 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1333 continue;
1334
1335 /* only allow hw_params() if no connected FEs are running */
1336 if (!snd_soc_dpcm_can_be_params(fe, be, stream))
1337 continue;
1338
1339 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
1340 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1341 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
1342 continue;
1343
1344 dev_dbg(be->dev, "dpcm: hw_params BE %s\n",
1345 dpcm_params->fe->dai_link->name);
1346
1347 /* copy params for each dpcm_params */
1348 memcpy(&dpcm_params->hw_params, &fe->dpcm[stream].hw_params,
1349 sizeof(struct snd_pcm_hw_params));
1350
1351 /* perform any hw_params fixups */
1352 if (be->dai_link->be_hw_params_fixup) {
1353 ret = be->dai_link->be_hw_params_fixup(be,
1354 &dpcm_params->hw_params);
1355 if (ret < 0) {
1356 dev_err(be->dev,
1357 "dpcm: hw_params BE fixup failed %d\n",
1358 ret);
1359 goto unwind;
1360 }
1361 }
1362
1363 ret = soc_pcm_hw_params(be_substream, &dpcm_params->hw_params);
1364 if (ret < 0) {
1365 dev_err(dpcm_params->be->dev, "dpcm: hw_params BE failed %d\n", ret);
1366 goto unwind;
1367 }
1368
1369 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
1370 }
1371 return 0;
1372
1373unwind:
1374 /* disable any enabled and non active backends */
1375 list_for_each_entry_continue_reverse(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1376 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1377 struct snd_pcm_substream *be_substream =
1378 snd_soc_dpcm_get_substream(be, stream);
1379
1380 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1381 continue;
1382
1383 /* only allow hw_free() if no connected FEs are running */
1384 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1385 continue;
1386
1387 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
1388 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1389 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1390 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1391 continue;
1392
1393 soc_pcm_hw_free(be_substream);
1394 }
1395
1396 return ret;
1397}
1398
1399int soc_dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
1400 struct snd_pcm_hw_params *params)
1401{
1402 struct snd_soc_pcm_runtime *fe = substream->private_data;
1403 int ret, stream = substream->stream;
1404
1405 mutex_lock(&fe->card->dpcm_mutex);
1406 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1407
1408 memcpy(&fe->dpcm[substream->stream].hw_params, params,
1409 sizeof(struct snd_pcm_hw_params));
1410 ret = soc_dpcm_be_dai_hw_params(fe, substream->stream);
1411 if (ret < 0) {
1412 dev_err(fe->dev,"dpcm: hw_params failed for some BEs %d\n", ret);
1413 goto out;
1414 }
1415
1416 dev_dbg(fe->dev, "dpcm: hw_params FE %s rate %d chan %x fmt %d\n",
1417 fe->dai_link->name, params_rate(params), params_channels(params),
1418 params_format(params));
1419
1420 /* call hw_params on the frontend */
1421 ret = soc_pcm_hw_params(substream, params);
1422 if (ret < 0) {
1423 dev_err(fe->dev,"dpcm: hw_params FE failed %d\n", ret);
1424 soc_dpcm_be_dai_hw_free(fe, stream);
1425 } else
1426 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
1427
1428out:
1429 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1430 mutex_unlock(&fe->card->dpcm_mutex);
1431 return ret;
1432}
1433
1434static int dpcm_do_trigger(struct snd_soc_dpcm_params *dpcm_params,
1435 struct snd_pcm_substream *substream, int cmd)
1436{
1437 int ret;
1438
1439 dev_dbg(dpcm_params->be->dev, "dpcm: trigger BE %s cmd %d\n",
1440 dpcm_params->fe->dai_link->name, cmd);
1441
1442 ret = soc_pcm_trigger(substream, cmd);
1443 if (ret < 0)
1444 dev_err(dpcm_params->be->dev,"dpcm: trigger BE failed %d\n", ret);
1445
1446 return ret;
1447}
1448
1449int soc_dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd)
1450{
1451 struct snd_soc_dpcm_params *dpcm_params;
1452 int ret = 0;
1453
1454 if ((cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) ||
1455 (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH))
1456 return ret;
1457
1458 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1459
1460 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1461 struct snd_pcm_substream *be_substream =
1462 snd_soc_dpcm_get_substream(be, stream);
1463
1464 /* is this op for this BE ? */
1465 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1466 continue;
1467
1468 switch (cmd) {
1469 case SNDRV_PCM_TRIGGER_START:
1470 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1471 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1472 continue;
1473
1474 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1475 if (ret)
1476 return ret;
1477
1478 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1479 break;
1480 case SNDRV_PCM_TRIGGER_RESUME:
1481 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
1482 continue;
1483
1484 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1485 if (ret)
1486 return ret;
1487
1488 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1489 break;
1490 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1491 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
1492 continue;
1493
1494 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1495 if (ret)
1496 return ret;
1497
1498 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1499 break;
1500 case SNDRV_PCM_TRIGGER_STOP:
1501 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1502 continue;
1503
1504 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1505 continue;
1506
1507 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1508 if (ret)
1509 return ret;
1510
1511 be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1512 break;
1513 case SNDRV_PCM_TRIGGER_SUSPEND:
1514 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)
1515 continue;
1516
1517 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
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_SUSPEND;
1525 break;
1526 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1527 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1528 continue;
1529
1530 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1531 continue;
1532
1533 ret = dpcm_do_trigger(dpcm_params, be_substream, cmd);
1534 if (ret)
1535 return ret;
1536
1537 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
1538 break;
1539 }
1540 }
1541
1542 return ret;
1543}
1544EXPORT_SYMBOL_GPL(soc_dpcm_be_dai_trigger);
1545
1546int soc_dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
1547{
1548 struct snd_soc_pcm_runtime *fe = substream->private_data;
1549 int stream = substream->stream, ret;
1550 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1551
1552 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1553
1554 switch (trigger) {
1555 case SND_SOC_DPCM_TRIGGER_PRE:
1556 /* call trigger on the frontend before the backend. */
1557
1558 dev_dbg(fe->dev, "dpcm: pre trigger FE %s cmd %d\n",
1559 fe->dai_link->name, cmd);
1560
1561 ret = soc_pcm_trigger(substream, cmd);
1562 if (ret < 0) {
1563 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1564 goto out;
1565 }
1566
1567 ret = soc_dpcm_be_dai_trigger(fe, substream->stream, cmd);
1568 break;
1569 case SND_SOC_DPCM_TRIGGER_POST:
1570 /* call trigger on the frontend after the backend. */
1571
1572 ret = soc_dpcm_be_dai_trigger(fe, substream->stream, cmd);
1573 if (ret < 0) {
1574 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1575 goto out;
1576 }
1577
1578 dev_dbg(fe->dev, "dpcm: post trigger FE %s cmd %d\n",
1579 fe->dai_link->name, cmd);
1580
1581 ret = soc_pcm_trigger(substream, cmd);
1582 break;
1583 case SND_SOC_DPCM_TRIGGER_BESPOKE:
1584 /* bespoke trigger() - handles both FE and BEs */
1585
1586 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd %d\n",
1587 fe->dai_link->name, cmd);
1588
1589 ret = soc_pcm_bespoke_trigger(substream, cmd);
1590 if (ret < 0) {
1591 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1592 goto out;
1593 }
1594 break;
1595 default:
1596 dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd,
1597 fe->dai_link->name);
1598 ret = -EINVAL;
1599 goto out;
1600 }
1601
1602 switch (cmd) {
1603 case SNDRV_PCM_TRIGGER_START:
1604 case SNDRV_PCM_TRIGGER_RESUME:
1605 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1606 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1607 break;
1608 case SNDRV_PCM_TRIGGER_STOP:
1609 case SNDRV_PCM_TRIGGER_SUSPEND:
1610 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1611 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1612 break;
1613 }
1614
1615out:
1616 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1617 return ret;
1618}
1619
1620static int soc_dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
1621{
1622 struct snd_soc_dpcm_params *dpcm_params;
1623 int ret = 0;
1624
1625 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1626
1627 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1628 struct snd_pcm_substream *be_substream =
1629 snd_soc_dpcm_get_substream(be, stream);
1630
1631 /* is this op for this BE ? */
1632 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1633 continue;
1634
1635 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1636 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1637 continue;
1638
1639 dev_dbg(be->dev, "dpcm: prepare BE %s\n",
1640 dpcm_params->fe->dai_link->name);
1641
1642 ret = soc_pcm_prepare(be_substream);
1643 if (ret < 0) {
1644 dev_err(be->dev, "dpcm: backend prepare failed %d\n",
1645 ret);
1646 break;
1647 }
1648
1649 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1650 }
1651 return ret;
1652}
1653
1654int soc_dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
1655{
1656 struct snd_soc_pcm_runtime *fe = substream->private_data;
1657 int stream = substream->stream, ret = 0;
1658
1659 mutex_lock(&fe->card->dpcm_mutex);
1660
1661 dev_dbg(fe->dev, "dpcm: prepare FE %s\n", fe->dai_link->name);
1662
1663 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1664
1665 /* there is no point preparing this FE if there are no BEs */
1666 if (list_empty(&fe->dpcm[stream].be_clients)) {
1667 dev_err(fe->dev, "dpcm: no backend DAIs enabled for %s\n",
1668 fe->dai_link->name);
1669 ret = -EINVAL;
1670 goto out;
1671 }
1672
1673 ret = soc_dpcm_be_dai_prepare(fe, substream->stream);
1674 if (ret < 0)
1675 goto out;
1676
1677 /* call prepare on the frontend */
1678 ret = soc_pcm_prepare(substream);
1679 if (ret < 0) {
1680 dev_err(fe->dev,"dpcm: prepare FE %s failed\n", fe->dai_link->name);
1681 goto out;
1682 }
1683
1684 /* run the stream event for each BE */
1685 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1686 soc_dpcm_dapm_stream_event(fe, stream,
1687 fe->cpu_dai->driver->playback.stream_name,
1688 SND_SOC_DAPM_STREAM_START);
1689 else
1690 soc_dpcm_dapm_stream_event(fe, stream,
1691 fe->cpu_dai->driver->capture.stream_name,
1692 SND_SOC_DAPM_STREAM_START);
1693
1694 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1695
1696out:
1697 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1698 mutex_unlock(&fe->card->dpcm_mutex);
1699 return ret;
1700}
1701
1702static int soc_dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
1703{
1704 struct snd_soc_dpcm_params *dpcm_params;
1705
1706 /* only hw_params backends that are either sinks or sources
1707 * to this frontend DAI */
1708 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1709
1710 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1711 struct snd_pcm_substream *be_substream =
1712 snd_soc_dpcm_get_substream(be, stream);
1713
1714 /* is this op for this BE ? */
1715 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1716 continue;
1717
1718 /* only free hw when no longer used - check all FEs */
1719 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1720 continue;
1721
1722 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1723 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1724 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1725 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1726 continue;
1727
1728 dev_dbg(be->dev, "dpcm: hw_free BE %s\n",
1729 dpcm_params->fe->dai_link->name);
1730
1731 soc_pcm_hw_free(be_substream);
1732
1733 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1734 }
1735
1736 return 0;
1737}
1738
1739int soc_dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
1740{
1741 struct snd_soc_pcm_runtime *fe = substream->private_data;
1742 int err, stream = substream->stream;
1743
1744 mutex_lock(&fe->card->dpcm_mutex);
1745 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1746
1747 dev_dbg(fe->dev, "dpcm: hw_free FE %s\n", fe->dai_link->name);
1748
1749 /* call hw_free on the frontend */
1750 err = soc_pcm_hw_free(substream);
1751 if (err < 0)
1752 dev_err(fe->dev,"dpcm: hw_free FE %s failed\n", fe->dai_link->name);
1753
1754 /* only hw_params backends that are either sinks or sources
1755 * to this frontend DAI */
1756 err = soc_dpcm_be_dai_hw_free(fe, stream);
1757
1758 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1759 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1760
1761 mutex_unlock(&fe->card->dpcm_mutex);
1762 return 0;
1763}
1764
1765static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
1766 unsigned int cmd, void *arg)
1767{
1768 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1769 struct snd_soc_platform *platform = rtd->platform;
1770
1771 if (platform->driver->ops->ioctl)
1772 return platform->driver->ops->ioctl(substream, cmd, arg);
1773 return snd_pcm_lib_ioctl(substream, cmd, arg);
1774}
1775
1776static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1777{
1778 struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream);
1779 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1780 int err;
1781
1782 dev_dbg(fe->dev, "runtime %s close on FE %s\n",
1783 stream ? "capture" : "playback", fe->dai_link->name);
1784
1785 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1786 /* call bespoke trigger - FE takes care of all BE triggers */
1787 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd stop\n",
1788 fe->dai_link->name);
1789
1790 err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
1791 if (err < 0)
1792 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1793 } else {
1794 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd stop\n",
1795 fe->dai_link->name);
1796
1797 err = soc_dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
1798 if (err < 0)
1799 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1800 }
1801
1802 err = soc_dpcm_be_dai_hw_free(fe, stream);
1803 if (err < 0)
1804 dev_err(fe->dev,"dpcm: hw_free FE failed %d\n", err);
1805
1806 err = soc_dpcm_be_dai_shutdown(fe, stream);
1807 if (err < 0)
1808 dev_err(fe->dev,"dpcm: shutdown FE failed %d\n", err);
1809
1810 /* run the stream event for each BE */
1811 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1812 soc_dpcm_dapm_stream_event(fe, stream,
1813 fe->cpu_dai->driver->playback.stream_name,
1814 SND_SOC_DAPM_STREAM_NOP);
1815 else
1816 soc_dpcm_dapm_stream_event(fe, stream,
1817 fe->cpu_dai->driver->capture.stream_name,
1818 SND_SOC_DAPM_STREAM_NOP);
1819
1820 return 0;
1821}
1822
1823static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
1824{
1825 struct snd_pcm_substream *substream = snd_soc_dpcm_get_substream(fe, stream);
1826 struct snd_soc_dpcm_params *dpcm_params;
1827 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1828 int ret;
1829
1830 dev_dbg(fe->dev, "runtime %s open on FE %s\n",
1831 stream ? "capture" : "playback", fe->dai_link->name);
1832
1833 /* Only start the BE if the FE is ready */
1834 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
1835 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
1836 return -EINVAL;
1837
1838 /* startup must always be called for new BEs */
1839 ret = soc_dpcm_be_dai_startup(fe, stream);
1840 if (ret < 0) {
1841 goto disconnect;
1842 return ret;
1843 }
1844
1845 /* keep going if FE state is > open */
1846 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_OPEN)
1847 return 0;
1848
1849 ret = soc_dpcm_be_dai_hw_params(fe, stream);
1850 if (ret < 0) {
1851 goto close;
1852 return ret;
1853 }
1854
1855 /* keep going if FE state is > hw_params */
1856 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_PARAMS)
1857 return 0;
1858
1859
1860 ret = soc_dpcm_be_dai_prepare(fe, stream);
1861 if (ret < 0) {
1862 goto hw_free;
1863 return ret;
1864 }
1865
1866 /* run the stream event for each BE */
1867 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1868 soc_dpcm_dapm_stream_event(fe, stream,
1869 fe->cpu_dai->driver->playback.stream_name,
1870 SND_SOC_DAPM_STREAM_NOP);
1871 else
1872 soc_dpcm_dapm_stream_event(fe, stream,
1873 fe->cpu_dai->driver->capture.stream_name,
1874 SND_SOC_DAPM_STREAM_NOP);
1875
1876 /* keep going if FE state is > prepare */
1877 if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE ||
1878 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
1879 return 0;
1880
1881 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1882 /* call trigger on the frontend - FE takes care of all BE triggers */
1883 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd start\n",
1884 fe->dai_link->name);
1885
1886 ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
1887 if (ret < 0) {
1888 dev_err(fe->dev,"dpcm: bespoke trigger FE failed %d\n", ret);
1889 goto hw_free;
1890 }
1891 } else {
1892 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n",
1893 fe->dai_link->name);
1894
1895 ret = soc_dpcm_be_dai_trigger(fe, stream,
1896 SNDRV_PCM_TRIGGER_START);
1897 if (ret < 0) {
1898 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1899 goto hw_free;
1900 }
1901 }
1902
1903 return 0;
1904
1905hw_free:
1906 soc_dpcm_be_dai_hw_free(fe, stream);
1907close:
1908 soc_dpcm_be_dai_shutdown(fe, stream);
1909disconnect:
1910 /* disconnect any non started BEs */
1911 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
1912 struct snd_soc_pcm_runtime *be = dpcm_params->be;
1913 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1914 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
1915 }
1916
1917 return ret;
1918}
1919
1920static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
1921{
1922 int ret;
1923
1924 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1925 ret = dpcm_run_update_startup(fe, stream);
1926 if (ret < 0)
1927 dev_err(fe->dev, "failed to startup some BEs\n");
1928 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1929
1930 return ret;
1931}
1932
1933static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
1934{
1935 int ret;
1936
1937 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
1938 ret = dpcm_run_update_shutdown(fe, stream);
1939 if (ret < 0)
1940 dev_err(fe->dev, "failed to shutdown some BEs\n");
1941 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1942
1943 return ret;
1944}
1945
1946/* called when any mixer updates change FE -> BE the stream */
1947int soc_dpcm_runtime_update(struct snd_soc_dapm_widget *widget)
1948{
1949 struct snd_soc_card *card;
1950 int i, ret = 0, old, new, paths;
1951
1952 if (widget->codec)
1953 card = widget->codec->card;
1954 else if (widget->platform)
1955 card = widget->platform->card;
1956 else
1957 return -EINVAL;
1958
1959 mutex_lock(&card->dpcm_mutex);
1960
1961 for (i = 0; i < card->num_rtd; i++) {
1962 struct snd_soc_dapm_widget_list *list;
1963 struct snd_soc_pcm_runtime *fe = &card->rtd[i];
1964
1965 /* make sure link is FE */
1966 if (!fe->dai_link->dynamic)
1967 continue;
1968
1969 /* only check active links */
1970 if (!fe->cpu_dai->active)
1971 continue;
1972
1973 /* DAPM sync will call this to update DSP paths */
1974 dev_dbg(fe->dev, "DPCM runtime update for FE %s\n", fe->dai_link->name);
1975
1976 /* skip if FE doesn't have playback capability */
1977 if (!fe->cpu_dai->driver->playback.channels_min)
1978 goto capture;
1979
1980 paths = fe_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
1981 if (paths < 0) {
1982 dev_warn(fe->dev, "%s no valid %s route from source to sink\n",
1983 fe->dai_link->name, "playback");
1984 ret = paths;
1985 goto out;
1986 }
1987
1988 /* update any new playback paths */
1989 new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 1);
1990 if (new) {
1991 dpcm_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
1992 fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
1993 be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
1994 }
1995
1996 /* update any old playback paths */
1997 old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, &list, 0);
1998 if (old) {
1999 dpcm_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
2000 fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
2001 be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
2002 }
2003
2004capture:
2005 /* skip if FE doesn't have capture capability */
2006 if (!fe->cpu_dai->driver->capture.channels_min)
2007 continue;
2008
2009 paths = fe_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
2010 if (paths < 0) {
2011 dev_warn(fe->dev, "%s no valid %s route from source to sink\n",
2012 fe->dai_link->name, "capture");
2013 ret = paths;
2014 goto out;
2015 }
2016
2017 /* update any new capture paths */
2018 new = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 1);
2019 if (new) {
2020 dpcm_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2021 fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
2022 be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
2023 }
2024
2025 /* update any old capture paths */
2026 old = dpcm_process_paths(fe, SNDRV_PCM_STREAM_CAPTURE, &list, 0);
2027 if (old) {
2028 dpcm_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE);
2029 fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
2030 be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
2031 }
2032
2033 fe_path_put(&list);
2034 }
2035
2036out:
2037 mutex_unlock(&card->dpcm_mutex);
2038 return ret;
2039}
2040
2041int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
2042{
2043 struct snd_soc_dpcm_params *dpcm_params;
2044
2045 list_for_each_entry(dpcm_params,
2046 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2047
2048 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2049 struct snd_soc_dai *dai = be->codec_dai;
2050 struct snd_soc_dai_driver *drv = dai->driver;
2051
2052 if (be->dai_link->ignore_suspend)
2053 continue;
2054
2055 dev_dbg(be->dev, "BE digital mute %s\n", be->dai_link->name);
2056
2057 if (drv->ops->digital_mute && dai->playback_active)
2058 drv->ops->digital_mute(dai, mute);
2059 }
2060
2061 return 0;
2062}
2063
2064int soc_dpcm_be_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
2065{
2066 struct snd_soc_dpcm_params *dpcm_params;
2067
2068 /* suspend for playback */
2069 list_for_each_entry(dpcm_params,
2070 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2071
2072 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2073 struct snd_soc_dai *dai = be->cpu_dai;
2074 struct snd_soc_dai_driver *drv = dai->driver;
2075
2076 if (be->dai_link->ignore_suspend)
2077 continue;
2078
2079 dev_dbg(be->dev, "pm: BE CPU DAI playback suspend %s\n",
2080 be->dai_link->name);
2081
2082 if (drv->suspend && !drv->ac97_control)
2083 drv->suspend(dai);
2084 }
2085
2086 /* suspend for capture */
2087 list_for_each_entry(dpcm_params,
2088 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2089
2090 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2091 struct snd_soc_dai *dai = be->cpu_dai;
2092 struct snd_soc_dai_driver *drv = dai->driver;
2093
2094 if (be->dai_link->ignore_suspend)
2095 continue;
2096
2097 dev_dbg(be->dev, "pm: BE CPU DAI capture suspend %s\n",
2098 be->dai_link->name);
2099
2100 if (drv->suspend && !drv->ac97_control)
2101 drv->suspend(dai);
2102 }
2103
2104 return 0;
2105}
2106
2107int soc_dpcm_be_ac97_cpu_dai_suspend(struct snd_soc_pcm_runtime *fe)
2108{
2109 struct snd_soc_dpcm_params *dpcm_params;
2110
2111 /* suspend for playback */
2112 list_for_each_entry(dpcm_params,
2113 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2114
2115 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2116 struct snd_soc_dai *dai = be->cpu_dai;
2117 struct snd_soc_dai_driver *drv = dai->driver;
2118
2119 if (be->dai_link->ignore_suspend)
2120 continue;
2121
2122 dev_dbg(be->dev, "pm: BE CPU DAI playback suspend %s\n",
2123 be->dai_link->name);
2124
2125 if (drv->suspend && drv->ac97_control)
2126 drv->suspend(dai);
2127 }
2128
2129 /* suspend for capture */
2130 list_for_each_entry(dpcm_params,
2131 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2132
2133 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2134 struct snd_soc_dai *dai = be->cpu_dai;
2135 struct snd_soc_dai_driver *drv = dai->driver;
2136
2137 if (be->dai_link->ignore_suspend)
2138 continue;
2139
2140 dev_dbg(be->dev, "pm: BE CPU DAI capture suspend %s\n",
2141 be->dai_link->name);
2142
2143 if (drv->suspend && drv->ac97_control)
2144 drv->suspend(dai);
2145 }
2146
2147 return 0;
2148}
2149
2150int soc_dpcm_be_platform_suspend(struct snd_soc_pcm_runtime *fe)
2151{
2152 struct snd_soc_dpcm_params *dpcm_params;
2153
2154 /* suspend for playback */
2155 list_for_each_entry(dpcm_params,
2156 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2157
2158 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2159 struct snd_soc_platform *platform = be->platform;
2160 struct snd_soc_platform_driver *drv = platform->driver;
2161 struct snd_soc_dai *dai = be->cpu_dai;
2162
2163 if (be->dai_link->ignore_suspend)
2164 continue;
2165
2166 dev_dbg(be->dev, "pm: BE platform playback suspend %s\n",
2167 be->dai_link->name);
2168
2169 if (drv->suspend && !platform->suspended) {
2170 drv->suspend(dai);
2171 platform->suspended = 1;
2172 }
2173 }
2174
2175 /* suspend for capture */
2176 list_for_each_entry(dpcm_params,
2177 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2178
2179 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2180 struct snd_soc_platform *platform = be->platform;
2181 struct snd_soc_platform_driver *drv = platform->driver;
2182 struct snd_soc_dai *dai = be->cpu_dai;
2183
2184 if (be->dai_link->ignore_suspend)
2185 continue;
2186
2187 dev_dbg(be->dev, "pm: BE platform capture suspend %s\n",
2188 be->dai_link->name);
2189
2190 if (drv->suspend && !platform->suspended) {
2191 drv->suspend(dai);
2192 platform->suspended = 1;
2193 }
2194 }
2195 return 0;
2196}
2197
2198int soc_dpcm_fe_suspend(struct snd_soc_pcm_runtime *fe)
2199{
2200 struct snd_soc_dai *dai = fe->cpu_dai;
2201 struct snd_soc_dai_driver *dai_drv = dai->driver;
2202 struct snd_soc_platform *platform = fe->platform;
2203 struct snd_soc_platform_driver *plat_drv = platform->driver;
2204
2205 if (dai_drv->suspend && !dai_drv->ac97_control)
2206 dai_drv->suspend(dai);
2207
2208 if (plat_drv->suspend && !platform->suspended) {
2209 plat_drv->suspend(dai);
2210 platform->suspended = 1;
2211 }
2212
2213 soc_dpcm_be_cpu_dai_suspend(fe);
2214 soc_dpcm_be_platform_suspend(fe);
2215
2216 return 0;
2217}
2218
2219int soc_dpcm_be_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
2220{
2221 struct snd_soc_dpcm_params *dpcm_params;
2222
2223 /* resume for playback */
2224 list_for_each_entry(dpcm_params,
2225 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2226
2227 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2228 struct snd_soc_dai *dai = be->cpu_dai;
2229 struct snd_soc_dai_driver *drv = dai->driver;
2230
2231 if (be->dai_link->ignore_suspend)
2232 continue;
2233
2234 dev_dbg(be->dev, "pm: BE CPU DAI playback resume %s\n",
2235 be->dai_link->name);
2236
2237 if (drv->resume && !drv->ac97_control)
2238 drv->resume(dai);
2239 }
2240
2241 /* suspend for capture */
2242 list_for_each_entry(dpcm_params,
2243 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2244
2245 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2246 struct snd_soc_dai *dai = be->cpu_dai;
2247 struct snd_soc_dai_driver *drv = dai->driver;
2248
2249 if (be->dai_link->ignore_suspend)
2250 continue;
2251
2252 dev_dbg(be->dev, "pm: BE CPU DAI capture resume %s\n",
2253 be->dai_link->name);
2254
2255 if (drv->resume && !drv->ac97_control)
2256 drv->resume(dai);
2257 }
2258
2259 return 0;
2260}
2261
2262int soc_dpcm_be_ac97_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
2263{
2264 struct snd_soc_dpcm_params *dpcm_params;
2265
2266 /* resume for playback */
2267 list_for_each_entry(dpcm_params,
2268 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2269
2270 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2271 struct snd_soc_dai *dai = be->cpu_dai;
2272 struct snd_soc_dai_driver *drv = dai->driver;
2273
2274 if (be->dai_link->ignore_suspend)
2275 continue;
2276
2277 dev_dbg(be->dev, "pm: BE CPU DAI playback resume %s\n",
2278 be->dai_link->name);
2279
2280 if (drv->resume && drv->ac97_control)
2281 drv->resume(dai);
2282 }
2283
2284 /* suspend for capture */
2285 list_for_each_entry(dpcm_params,
2286 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2287
2288 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2289 struct snd_soc_dai *dai = be->cpu_dai;
2290 struct snd_soc_dai_driver *drv = dai->driver;
2291
2292 if (be->dai_link->ignore_suspend)
2293 continue;
2294
2295 dev_dbg(be->dev, "pm: BE CPU DAI capture resume %s\n",
2296 be->dai_link->name);
2297
2298 if (drv->resume && drv->ac97_control)
2299 drv->resume(dai);
2300 }
2301
2302 return 0;
2303}
2304
2305int soc_dpcm_be_platform_resume(struct snd_soc_pcm_runtime *fe)
2306{
2307 struct snd_soc_dpcm_params *dpcm_params;
2308
2309 /* resume for playback */
2310 list_for_each_entry(dpcm_params,
2311 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients, list_be) {
2312
2313 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2314 struct snd_soc_platform *platform = be->platform;
2315 struct snd_soc_platform_driver *drv = platform->driver;
2316 struct snd_soc_dai *dai = be->cpu_dai;
2317
2318 if (be->dai_link->ignore_suspend)
2319 continue;
2320
2321 dev_dbg(be->dev, "pm: BE platform playback resume %s\n",
2322 be->dai_link->name);
2323
2324 if (drv->resume && platform->suspended) {
2325 drv->resume(dai);
2326 platform->suspended = 0;
2327 }
2328 }
2329
2330 /* resume for capture */
2331 list_for_each_entry(dpcm_params,
2332 &fe->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients, list_be) {
2333
2334 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2335 struct snd_soc_platform *platform = be->platform;
2336 struct snd_soc_platform_driver *drv = platform->driver;
2337 struct snd_soc_dai *dai = be->cpu_dai;
2338
2339 if (be->dai_link->ignore_suspend)
2340 continue;
2341
2342 dev_dbg(be->dev, "pm: BE platform capture resume %s\n",
2343 be->dai_link->name);
2344
2345 if (drv->resume && platform->suspended) {
2346 drv->resume(dai);
2347 platform->suspended = 0;
2348 }
2349 }
2350
2351 return 0;
2352}
2353
2354int soc_dpcm_fe_resume(struct snd_soc_pcm_runtime *fe)
2355{
2356 struct snd_soc_dai *dai = fe->cpu_dai;
2357 struct snd_soc_dai_driver *dai_drv = dai->driver;
2358 struct snd_soc_platform *platform = fe->platform;
2359 struct snd_soc_platform_driver *plat_drv = platform->driver;
2360
2361 soc_dpcm_be_cpu_dai_resume(fe);
2362 soc_dpcm_be_platform_resume(fe);
2363
2364 if (dai_drv->resume && !dai_drv->ac97_control)
2365 dai_drv->resume(dai);
2366
2367 if (plat_drv->resume && platform->suspended) {
2368 plat_drv->resume(dai);
2369 platform->suspended = 0;
2370 }
2371
2372 return 0;
2373}
2374
2375/* called when opening FE stream */
2376int soc_dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
2377{
2378 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2379 struct snd_soc_dpcm_params *dpcm_params;
2380 struct snd_soc_dapm_widget_list *list;
2381 int ret;
2382 int stream = fe_substream->stream;
2383
2384 fe->dpcm[stream].runtime = fe_substream->runtime;
2385
2386 if (fe_path_get(fe, stream, &list) <= 0) {
2387 dev_warn(fe->dev, "asoc: %s no valid %s route from source to sink\n",
2388 fe->dai_link->name, stream ? "capture" : "playback");
2389 return -EINVAL;
2390 }
2391
2392 /* calculate valid and active FE <-> BE dpcm_paramss */
2393 dpcm_process_paths(fe, stream, &list, 1);
2394
2395 ret = soc_dpcm_fe_dai_startup(fe_substream);
2396 if (ret < 0) {
2397 /* clean up all links */
2398 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
2399 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
2400
2401 be_disconnect(fe, stream);
2402 fe->dpcm[stream].runtime = NULL;
2403 }
2404
2405 fe_clear_pending(fe, stream);
2406 fe_path_put(&list);
2407 return ret;
2408}
2409
2410/* called when closing FE stream */
2411int soc_dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
2412{
2413 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
2414 struct snd_soc_dpcm_params *dpcm_params;
2415 int stream = fe_substream->stream, ret;
2416
2417 ret = soc_dpcm_fe_dai_shutdown(fe_substream);
2418
2419 /* mark FE's links ready to prune */
2420 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be)
2421 dpcm_params->state = SND_SOC_DPCM_LINK_STATE_FREE;
2422
2423 be_disconnect(fe, stream);
2424
2425 fe->dpcm[stream].runtime = NULL;
2426
2427 return ret;
2428}
2429
Liam Girdwoodddee6272011-06-09 14:45:53 +01002430/* create a new pcm */
2431int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2432{
2433 struct snd_soc_codec *codec = rtd->codec;
2434 struct snd_soc_platform *platform = rtd->platform;
2435 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2436 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002437 struct snd_pcm_substream *substream[2];
Liam Girdwoodddee6272011-06-09 14:45:53 +01002438 struct snd_pcm *pcm;
2439 char new_name[64];
2440 int ret = 0, playback = 0, capture = 0;
2441
Steve Mucklef132c6c2012-06-06 18:30:57 -07002442 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
2443 if (cpu_dai->driver->playback.channels_min)
2444 playback = 1;
2445 if (cpu_dai->driver->capture.channels_min)
2446 capture = 1;
2447 } else {
2448 if (codec_dai->driver->playback.channels_min)
2449 playback = 1;
2450 if (codec_dai->driver->capture.channels_min)
2451 capture = 1;
2452 }
Sangsu Parka5002312012-01-02 17:15:10 +09002453
Steve Mucklef132c6c2012-06-06 18:30:57 -07002454 /* create the PCM */
2455 if (rtd->dai_link->no_pcm) {
2456 snprintf(new_name, sizeof(new_name), "(%s)",
2457 rtd->dai_link->stream_name);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002458
Steve Mucklef132c6c2012-06-06 18:30:57 -07002459 ret = snd_pcm_new_soc_be(rtd->card->snd_card, new_name, num,
2460 playback, capture, &pcm);
2461 } else {
2462 if (rtd->dai_link->dynamic)
2463 snprintf(new_name, sizeof(new_name), "%s (*)",
2464 rtd->dai_link->stream_name);
2465 else
2466 snprintf(new_name, sizeof(new_name), "%s %s-%d",
2467 rtd->dai_link->stream_name, codec_dai->name, num);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002468
Steve Mucklef132c6c2012-06-06 18:30:57 -07002469 ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
2470 capture, &pcm);
2471 }
Liam Girdwoodddee6272011-06-09 14:45:53 +01002472 if (ret < 0) {
2473 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
2474 return ret;
2475 }
Steve Mucklef132c6c2012-06-06 18:30:57 -07002476 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002477
2478 rtd->pcm = pcm;
2479 pcm->private_data = rtd;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002480 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
2481
2482 substream[SNDRV_PCM_STREAM_PLAYBACK] =
2483 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
2484 substream[SNDRV_PCM_STREAM_CAPTURE] =
2485 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
2486
2487 if (rtd->dai_link->no_pcm) {
2488 if (playback)
2489 substream[SNDRV_PCM_STREAM_PLAYBACK]->private_data = rtd;
2490 if (capture)
2491 substream[SNDRV_PCM_STREAM_CAPTURE]->private_data = rtd;
2492 goto out;
2493 }
2494
2495 /* setup any hostless PCMs - i.e. no host IO is performed */
2496 if (rtd->dai_link->no_host_mode) {
2497 if (substream[SNDRV_PCM_STREAM_PLAYBACK]) {
2498 substream[SNDRV_PCM_STREAM_PLAYBACK]->hw_no_buffer = 1;
2499 snd_soc_set_runtime_hwparams(
2500 substream[SNDRV_PCM_STREAM_PLAYBACK],
2501 &no_host_hardware);
2502 }
2503 if (substream[SNDRV_PCM_STREAM_CAPTURE]) {
2504 substream[SNDRV_PCM_STREAM_CAPTURE]->hw_no_buffer = 1;
2505 snd_soc_set_runtime_hwparams(
2506 substream[SNDRV_PCM_STREAM_CAPTURE],
2507 &no_host_hardware);
2508 }
2509 }
2510
2511 /* ASoC PCM operations */
2512 if (rtd->dai_link->dynamic) {
2513 rtd->ops.open = soc_dpcm_fe_dai_open;
2514 rtd->ops.hw_params = soc_dpcm_fe_dai_hw_params;
2515 rtd->ops.prepare = soc_dpcm_fe_dai_prepare;
2516 rtd->ops.trigger = soc_dpcm_fe_dai_trigger;
2517 rtd->ops.hw_free = soc_dpcm_fe_dai_hw_free;
2518 rtd->ops.close = soc_dpcm_fe_dai_close;
2519 rtd->ops.pointer = soc_pcm_pointer;
2520 rtd->ops.ioctl = soc_pcm_ioctl;
2521 } else {
2522 rtd->ops.open = soc_pcm_open;
2523 rtd->ops.hw_params = soc_pcm_hw_params;
2524 rtd->ops.prepare = soc_pcm_prepare;
2525 rtd->ops.trigger = soc_pcm_trigger;
2526 rtd->ops.hw_free = soc_pcm_hw_free;
2527 rtd->ops.close = soc_pcm_close;
2528 rtd->ops.pointer = soc_pcm_pointer;
2529 rtd->ops.ioctl = soc_pcm_ioctl;
2530 }
2531
Liam Girdwoodddee6272011-06-09 14:45:53 +01002532 if (platform->driver->ops) {
Steve Mucklef132c6c2012-06-06 18:30:57 -07002533 rtd->ops.ack = platform->driver->ops->ack;
2534 rtd->ops.copy = platform->driver->ops->copy;
2535 rtd->ops.silence = platform->driver->ops->silence;
2536 rtd->ops.page = platform->driver->ops->page;
2537 rtd->ops.mmap = platform->driver->ops->mmap;
Liam Girdwoodddee6272011-06-09 14:45:53 +01002538 }
2539
2540 if (playback)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002541 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002542
2543 if (capture)
Steve Mucklef132c6c2012-06-06 18:30:57 -07002544 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
Liam Girdwoodddee6272011-06-09 14:45:53 +01002545
2546 if (platform->driver->pcm_new) {
2547 ret = platform->driver->pcm_new(rtd);
2548 if (ret < 0) {
2549 pr_err("asoc: platform pcm constructor failed\n");
2550 return ret;
2551 }
2552 }
2553
2554 pcm->private_free = platform->driver->pcm_free;
Steve Mucklef132c6c2012-06-06 18:30:57 -07002555out:
Liam Girdwoodddee6272011-06-09 14:45:53 +01002556 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
2557 cpu_dai->name);
2558 return ret;
2559}
Steve Mucklef132c6c2012-06-06 18:30:57 -07002560
2561#ifdef CONFIG_DEBUG_FS
2562static char *dpcm_state_string(enum snd_soc_dpcm_state state)
2563{
2564 switch (state) {
2565 case SND_SOC_DPCM_STATE_NEW:
2566 return "new";
2567 case SND_SOC_DPCM_STATE_OPEN:
2568 return "open";
2569 case SND_SOC_DPCM_STATE_HW_PARAMS:
2570 return "hw_params";
2571 case SND_SOC_DPCM_STATE_PREPARE:
2572 return "prepare";
2573 case SND_SOC_DPCM_STATE_START:
2574 return "start";
2575 case SND_SOC_DPCM_STATE_STOP:
2576 return "stop";
2577 case SND_SOC_DPCM_STATE_SUSPEND:
2578 return "suspend";
2579 case SND_SOC_DPCM_STATE_PAUSED:
2580 return "paused";
2581 case SND_SOC_DPCM_STATE_HW_FREE:
2582 return "hw_free";
2583 case SND_SOC_DPCM_STATE_CLOSE:
2584 return "close";
2585 }
2586
2587 return "unknown";
2588}
2589
2590static int soc_dpcm_state_open_file(struct inode *inode, struct file *file)
2591{
2592 file->private_data = inode->i_private;
2593 return 0;
2594}
2595
2596static ssize_t soc_dpcm_show_state(struct snd_soc_pcm_runtime *fe,
2597 int stream, char *buf, size_t size)
2598{
2599 struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
2600 struct snd_soc_dpcm_params *dpcm_params;
2601 ssize_t offset = 0;
2602
2603 /* FE state */
2604 offset += snprintf(buf + offset, size - offset,
2605 "[%s - %s]\n", fe->dai_link->name,
2606 stream ? "Capture" : "Playback");
2607
2608 offset += snprintf(buf + offset, size - offset, "State: %s\n",
2609 dpcm_state_string(fe->dpcm[stream].state));
2610
2611 if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
2612 (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
2613 offset += snprintf(buf + offset, size - offset,
2614 "Hardware Params: "
2615 "Format = %s, Channels = %d, Rate = %d\n",
2616 snd_pcm_format_name(params_format(params)),
2617 params_channels(params),
2618 params_rate(params));
2619
2620 /* BEs state */
2621 offset += snprintf(buf + offset, size - offset, "Backends:\n");
2622
2623 if (list_empty(&fe->dpcm[stream].be_clients)) {
2624 offset += snprintf(buf + offset, size - offset,
2625 " No active DSP links\n");
2626 goto out;
2627 }
2628
2629 list_for_each_entry(dpcm_params, &fe->dpcm[stream].be_clients, list_be) {
2630 struct snd_soc_pcm_runtime *be = dpcm_params->be;
2631
2632 offset += snprintf(buf + offset, size - offset,
2633 "- %s\n", be->dai_link->name);
2634
2635 offset += snprintf(buf + offset, size - offset,
2636 " State: %s\n",
2637 dpcm_state_string(fe->dpcm[stream].state));
2638
2639 if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
2640 (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
2641 offset += snprintf(buf + offset, size - offset,
2642 " Hardware Params: "
2643 "Format = %s, Channels = %d, Rate = %d\n",
2644 snd_pcm_format_name(params_format(params)),
2645 params_channels(params),
2646 params_rate(params));
2647 }
2648
2649out:
2650 return offset;
2651}
2652
2653static ssize_t soc_dpcm_state_read_file(struct file *file, char __user *user_buf,
2654 size_t count, loff_t *ppos)
2655{
2656 struct snd_soc_pcm_runtime *fe = file->private_data;
2657 ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
2658 char *buf;
2659
2660 buf = kmalloc(out_count, GFP_KERNEL);
2661 if (!buf)
2662 return -ENOMEM;
2663
2664 if (fe->cpu_dai->driver->playback.channels_min)
2665 offset += soc_dpcm_show_state(fe, SNDRV_PCM_STREAM_PLAYBACK,
2666 buf + offset, out_count - offset);
2667
2668 if (fe->cpu_dai->driver->capture.channels_min)
2669 offset += soc_dpcm_show_state(fe, SNDRV_PCM_STREAM_CAPTURE,
2670 buf + offset, out_count - offset);
2671
2672 ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
2673
2674 kfree(buf);
2675
2676 return ret;
2677}
2678
2679static const struct file_operations soc_dpcm_state_fops = {
2680 .open = soc_dpcm_state_open_file,
2681 .read = soc_dpcm_state_read_file,
2682 .llseek = default_llseek,
2683};
2684
2685int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
2686{
2687 rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
2688 rtd->card->debugfs_card_root);
2689 if (!rtd->debugfs_dpcm_root) {
2690 dev_dbg(rtd->dev,
2691 "ASoC: Failed to create dpcm debugfs directory %s\n",
2692 rtd->dai_link->name);
2693 return -EINVAL;
2694 }
2695
2696 rtd->debugfs_dpcm_state = debugfs_create_file("state", 0644,
2697 rtd->debugfs_dpcm_root,
2698 rtd, &soc_dpcm_state_fops);
2699
2700 return 0;
2701}
2702#endif