Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cris-mirror.git] / sound / soc / soc-compress.c
blob82402688bd8ed33799a95f7ed4786cb5d840be72
1 /*
2 * soc-compress.c -- ALSA SoC Compress
4 * Copyright (C) 2012 Intel Corp.
6 * Authors: Namarta Kohli <namartax.kohli@intel.com>
7 * Ramesh Babu K V <ramesh.babu@linux.intel.com>
8 * Vinod Koul <vinod.koul@linux.intel.com>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/delay.h>
20 #include <linux/slab.h>
21 #include <linux/workqueue.h>
22 #include <sound/core.h>
23 #include <sound/compress_params.h>
24 #include <sound/compress_driver.h>
25 #include <sound/soc.h>
26 #include <sound/initval.h>
27 #include <sound/soc-dpcm.h>
29 static int soc_compr_open(struct snd_compr_stream *cstream)
31 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
32 struct snd_soc_platform *platform = rtd->platform;
33 struct snd_soc_component *component;
34 struct snd_soc_rtdcom_list *rtdcom;
35 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
36 int ret = 0, __ret;
38 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
40 if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
41 ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
42 if (ret < 0) {
43 dev_err(cpu_dai->dev,
44 "Compress ASoC: can't open interface %s: %d\n",
45 cpu_dai->name, ret);
46 goto out;
50 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
51 ret = platform->driver->compr_ops->open(cstream);
52 if (ret < 0) {
53 dev_err(platform->dev,
54 "Compress ASoC: can't open platform %s: %d\n",
55 platform->component.name, ret);
56 goto plat_err;
60 for_each_rtdcom(rtd, rtdcom) {
61 component = rtdcom->component;
63 /* ignore duplication for now */
64 if (platform && (component == &platform->component))
65 continue;
67 if (!component->driver->compr_ops ||
68 !component->driver->compr_ops->open)
69 continue;
71 __ret = component->driver->compr_ops->open(cstream);
72 if (__ret < 0) {
73 dev_err(component->dev,
74 "Compress ASoC: can't open platform %s: %d\n",
75 component->name, __ret);
76 ret = __ret;
79 if (ret < 0)
80 goto machine_err;
82 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
83 ret = rtd->dai_link->compr_ops->startup(cstream);
84 if (ret < 0) {
85 dev_err(rtd->dev,
86 "Compress ASoC: %s startup failed: %d\n",
87 rtd->dai_link->name, ret);
88 goto machine_err;
92 snd_soc_runtime_activate(rtd, cstream->direction);
94 mutex_unlock(&rtd->pcm_mutex);
96 return 0;
98 machine_err:
99 for_each_rtdcom(rtd, rtdcom) {
100 component = rtdcom->component;
102 /* ignore duplication for now */
103 if (platform && (component == &platform->component))
104 continue;
106 if (!component->driver->compr_ops ||
107 !component->driver->compr_ops->free)
108 continue;
110 component->driver->compr_ops->free(cstream);
113 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
114 platform->driver->compr_ops->free(cstream);
115 plat_err:
116 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
117 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
118 out:
119 mutex_unlock(&rtd->pcm_mutex);
120 return ret;
123 static int soc_compr_open_fe(struct snd_compr_stream *cstream)
125 struct snd_soc_pcm_runtime *fe = cstream->private_data;
126 struct snd_pcm_substream *fe_substream =
127 fe->pcm->streams[cstream->direction].substream;
128 struct snd_soc_platform *platform = fe->platform;
129 struct snd_soc_component *component;
130 struct snd_soc_rtdcom_list *rtdcom;
131 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
132 struct snd_soc_dpcm *dpcm;
133 struct snd_soc_dapm_widget_list *list;
134 int stream;
135 int ret = 0, __ret;
137 if (cstream->direction == SND_COMPRESS_PLAYBACK)
138 stream = SNDRV_PCM_STREAM_PLAYBACK;
139 else
140 stream = SNDRV_PCM_STREAM_CAPTURE;
142 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
144 if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
145 ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
146 if (ret < 0) {
147 dev_err(cpu_dai->dev,
148 "Compress ASoC: can't open interface %s: %d\n",
149 cpu_dai->name, ret);
150 goto out;
154 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
155 ret = platform->driver->compr_ops->open(cstream);
156 if (ret < 0) {
157 dev_err(platform->dev,
158 "Compress ASoC: can't open platform %s: %d\n",
159 platform->component.name, ret);
160 goto plat_err;
164 for_each_rtdcom(fe, rtdcom) {
165 component = rtdcom->component;
167 /* ignore duplication for now */
168 if (platform && (component == &platform->component))
169 continue;
171 if (!component->driver->compr_ops ||
172 !component->driver->compr_ops->open)
173 continue;
175 __ret = component->driver->compr_ops->open(cstream);
176 if (__ret < 0) {
177 dev_err(component->dev,
178 "Compress ASoC: can't open platform %s: %d\n",
179 component->name, __ret);
180 ret = __ret;
183 if (ret < 0)
184 goto machine_err;
186 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
187 ret = fe->dai_link->compr_ops->startup(cstream);
188 if (ret < 0) {
189 pr_err("Compress ASoC: %s startup failed: %d\n",
190 fe->dai_link->name, ret);
191 goto machine_err;
195 fe->dpcm[stream].runtime = fe_substream->runtime;
197 ret = dpcm_path_get(fe, stream, &list);
198 if (ret < 0)
199 goto fe_err;
200 else if (ret == 0)
201 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
202 fe->dai_link->name, stream ? "capture" : "playback");
204 /* calculate valid and active FE <-> BE dpcms */
205 dpcm_process_paths(fe, stream, &list, 1);
207 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
209 ret = dpcm_be_dai_startup(fe, stream);
210 if (ret < 0) {
211 /* clean up all links */
212 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
213 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
215 dpcm_be_disconnect(fe, stream);
216 fe->dpcm[stream].runtime = NULL;
217 goto path_err;
220 dpcm_clear_pending_state(fe, stream);
221 dpcm_path_put(&list);
223 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
224 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
226 snd_soc_runtime_activate(fe, stream);
228 mutex_unlock(&fe->card->mutex);
230 return 0;
232 path_err:
233 dpcm_path_put(&list);
234 fe_err:
235 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
236 fe->dai_link->compr_ops->shutdown(cstream);
237 machine_err:
238 for_each_rtdcom(fe, rtdcom) {
239 component = rtdcom->component;
241 /* ignore duplication for now */
242 if (platform && (component == &platform->component))
243 continue;
245 if (!component->driver->compr_ops ||
246 !component->driver->compr_ops->free)
247 continue;
249 component->driver->compr_ops->free(cstream);
252 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
253 platform->driver->compr_ops->free(cstream);
254 plat_err:
255 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
256 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
257 out:
258 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
259 mutex_unlock(&fe->card->mutex);
260 return ret;
264 * Power down the audio subsystem pmdown_time msecs after close is called.
265 * This is to ensure there are no pops or clicks in between any music tracks
266 * due to DAPM power cycling.
268 static void close_delayed_work(struct work_struct *work)
270 struct snd_soc_pcm_runtime *rtd =
271 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
272 struct snd_soc_dai *codec_dai = rtd->codec_dai;
274 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
276 dev_dbg(rtd->dev,
277 "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n",
278 codec_dai->driver->playback.stream_name,
279 codec_dai->playback_active ? "active" : "inactive",
280 rtd->pop_wait ? "yes" : "no");
282 /* are we waiting on this codec DAI stream */
283 if (rtd->pop_wait == 1) {
284 rtd->pop_wait = 0;
285 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
286 SND_SOC_DAPM_STREAM_STOP);
289 mutex_unlock(&rtd->pcm_mutex);
292 static int soc_compr_free(struct snd_compr_stream *cstream)
294 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
295 struct snd_soc_platform *platform = rtd->platform;
296 struct snd_soc_component *component;
297 struct snd_soc_rtdcom_list *rtdcom;
298 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
299 struct snd_soc_dai *codec_dai = rtd->codec_dai;
300 int stream;
302 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
304 if (cstream->direction == SND_COMPRESS_PLAYBACK)
305 stream = SNDRV_PCM_STREAM_PLAYBACK;
306 else
307 stream = SNDRV_PCM_STREAM_CAPTURE;
309 snd_soc_runtime_deactivate(rtd, stream);
311 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
313 if (!cpu_dai->active)
314 cpu_dai->rate = 0;
316 if (!codec_dai->active)
317 codec_dai->rate = 0;
319 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
320 rtd->dai_link->compr_ops->shutdown(cstream);
322 for_each_rtdcom(rtd, rtdcom) {
323 component = rtdcom->component;
325 /* ignore duplication for now */
326 if (platform && (component == &platform->component))
327 continue;
329 if (!component->driver->compr_ops ||
330 !component->driver->compr_ops->free)
331 continue;
333 component->driver->compr_ops->free(cstream);
336 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
337 platform->driver->compr_ops->free(cstream);
339 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
340 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
342 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
343 if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
344 snd_soc_dapm_stream_event(rtd,
345 SNDRV_PCM_STREAM_PLAYBACK,
346 SND_SOC_DAPM_STREAM_STOP);
347 } else {
348 rtd->pop_wait = 1;
349 queue_delayed_work(system_power_efficient_wq,
350 &rtd->delayed_work,
351 msecs_to_jiffies(rtd->pmdown_time));
353 } else {
354 /* capture streams can be powered down now */
355 snd_soc_dapm_stream_event(rtd,
356 SNDRV_PCM_STREAM_CAPTURE,
357 SND_SOC_DAPM_STREAM_STOP);
360 mutex_unlock(&rtd->pcm_mutex);
361 return 0;
364 static int soc_compr_free_fe(struct snd_compr_stream *cstream)
366 struct snd_soc_pcm_runtime *fe = cstream->private_data;
367 struct snd_soc_platform *platform = fe->platform;
368 struct snd_soc_component *component;
369 struct snd_soc_rtdcom_list *rtdcom;
370 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
371 struct snd_soc_dpcm *dpcm;
372 int stream, ret;
374 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
376 if (cstream->direction == SND_COMPRESS_PLAYBACK)
377 stream = SNDRV_PCM_STREAM_PLAYBACK;
378 else
379 stream = SNDRV_PCM_STREAM_CAPTURE;
381 snd_soc_runtime_deactivate(fe, stream);
383 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
385 ret = dpcm_be_dai_hw_free(fe, stream);
386 if (ret < 0)
387 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
389 ret = dpcm_be_dai_shutdown(fe, stream);
391 /* mark FE's links ready to prune */
392 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
393 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
395 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
397 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
398 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
400 dpcm_be_disconnect(fe, stream);
402 fe->dpcm[stream].runtime = NULL;
404 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
405 fe->dai_link->compr_ops->shutdown(cstream);
407 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
408 platform->driver->compr_ops->free(cstream);
410 for_each_rtdcom(fe, rtdcom) {
411 component = rtdcom->component;
413 /* ignore duplication for now */
414 if (platform && (component == &platform->component))
415 continue;
417 if (!component->driver->compr_ops ||
418 !component->driver->compr_ops->free)
419 continue;
421 component->driver->compr_ops->free(cstream);
424 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
425 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
427 mutex_unlock(&fe->card->mutex);
428 return 0;
431 static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
434 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
435 struct snd_soc_platform *platform = rtd->platform;
436 struct snd_soc_component *component;
437 struct snd_soc_rtdcom_list *rtdcom;
438 struct snd_soc_dai *codec_dai = rtd->codec_dai;
439 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
440 int ret = 0, __ret;
442 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
444 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
445 ret = platform->driver->compr_ops->trigger(cstream, cmd);
446 if (ret < 0)
447 goto out;
450 for_each_rtdcom(rtd, rtdcom) {
451 component = rtdcom->component;
453 /* ignore duplication for now */
454 if (platform && (component == &platform->component))
455 continue;
457 if (!component->driver->compr_ops ||
458 !component->driver->compr_ops->trigger)
459 continue;
461 __ret = component->driver->compr_ops->trigger(cstream, cmd);
462 if (__ret < 0)
463 ret = __ret;
465 if (ret < 0)
466 goto out;
468 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
469 cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
471 switch (cmd) {
472 case SNDRV_PCM_TRIGGER_START:
473 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
474 break;
475 case SNDRV_PCM_TRIGGER_STOP:
476 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
477 break;
480 out:
481 mutex_unlock(&rtd->pcm_mutex);
482 return ret;
485 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
487 struct snd_soc_pcm_runtime *fe = cstream->private_data;
488 struct snd_soc_platform *platform = fe->platform;
489 struct snd_soc_component *component;
490 struct snd_soc_rtdcom_list *rtdcom;
491 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
492 int ret = 0, __ret, stream;
494 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
495 cmd == SND_COMPR_TRIGGER_DRAIN) {
497 if (platform &&
498 platform->driver->compr_ops &&
499 platform->driver->compr_ops->trigger)
500 return platform->driver->compr_ops->trigger(cstream,
501 cmd);
503 for_each_rtdcom(fe, rtdcom) {
504 component = rtdcom->component;
506 /* ignore duplication for now */
507 if (platform && (component == &platform->component))
508 continue;
510 if (!component->driver->compr_ops ||
511 !component->driver->compr_ops->trigger)
512 continue;
514 __ret = component->driver->compr_ops->trigger(cstream, cmd);
515 if (__ret < 0)
516 ret = __ret;
518 return ret;
521 if (cstream->direction == SND_COMPRESS_PLAYBACK)
522 stream = SNDRV_PCM_STREAM_PLAYBACK;
523 else
524 stream = SNDRV_PCM_STREAM_CAPTURE;
527 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
529 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
530 ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
531 if (ret < 0)
532 goto out;
535 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
536 ret = platform->driver->compr_ops->trigger(cstream, cmd);
537 if (ret < 0)
538 goto out;
541 for_each_rtdcom(fe, rtdcom) {
542 component = rtdcom->component;
544 /* ignore duplication for now */
545 if (platform && (component == &platform->component))
546 continue;
548 if (!component->driver->compr_ops ||
549 !component->driver->compr_ops->trigger)
550 continue;
552 __ret = component->driver->compr_ops->trigger(cstream, cmd);
553 if (__ret < 0)
554 ret = __ret;
556 if (ret < 0)
557 goto out;
559 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
561 ret = dpcm_be_dai_trigger(fe, stream, cmd);
563 switch (cmd) {
564 case SNDRV_PCM_TRIGGER_START:
565 case SNDRV_PCM_TRIGGER_RESUME:
566 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
567 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
568 break;
569 case SNDRV_PCM_TRIGGER_STOP:
570 case SNDRV_PCM_TRIGGER_SUSPEND:
571 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
572 break;
573 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
574 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
575 break;
578 out:
579 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
580 mutex_unlock(&fe->card->mutex);
581 return ret;
584 static int soc_compr_set_params(struct snd_compr_stream *cstream,
585 struct snd_compr_params *params)
587 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
588 struct snd_soc_platform *platform = rtd->platform;
589 struct snd_soc_component *component;
590 struct snd_soc_rtdcom_list *rtdcom;
591 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
592 int ret = 0, __ret;
594 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
596 /* first we call set_params for the platform driver
597 * this should configure the soc side
598 * if the machine has compressed ops then we call that as well
599 * expectation is that platform and machine will configure everything
600 * for this compress path, like configuring pcm port for codec
602 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
603 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
604 if (ret < 0)
605 goto err;
608 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
609 ret = platform->driver->compr_ops->set_params(cstream, params);
610 if (ret < 0)
611 goto err;
614 for_each_rtdcom(rtd, rtdcom) {
615 component = rtdcom->component;
617 /* ignore duplication for now */
618 if (platform && (component == &platform->component))
619 continue;
621 if (!component->driver->compr_ops ||
622 !component->driver->compr_ops->set_params)
623 continue;
625 __ret = component->driver->compr_ops->set_params(cstream, params);
626 if (__ret < 0)
627 ret = __ret;
629 if (ret < 0)
630 goto err;
632 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
633 ret = rtd->dai_link->compr_ops->set_params(cstream);
634 if (ret < 0)
635 goto err;
638 if (cstream->direction == SND_COMPRESS_PLAYBACK)
639 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
640 SND_SOC_DAPM_STREAM_START);
641 else
642 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
643 SND_SOC_DAPM_STREAM_START);
645 /* cancel any delayed stream shutdown that is pending */
646 rtd->pop_wait = 0;
647 mutex_unlock(&rtd->pcm_mutex);
649 cancel_delayed_work_sync(&rtd->delayed_work);
651 return ret;
653 err:
654 mutex_unlock(&rtd->pcm_mutex);
655 return ret;
658 static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
659 struct snd_compr_params *params)
661 struct snd_soc_pcm_runtime *fe = cstream->private_data;
662 struct snd_pcm_substream *fe_substream =
663 fe->pcm->streams[cstream->direction].substream;
664 struct snd_soc_platform *platform = fe->platform;
665 struct snd_soc_component *component;
666 struct snd_soc_rtdcom_list *rtdcom;
667 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
668 int ret = 0, __ret, stream;
670 if (cstream->direction == SND_COMPRESS_PLAYBACK)
671 stream = SNDRV_PCM_STREAM_PLAYBACK;
672 else
673 stream = SNDRV_PCM_STREAM_CAPTURE;
675 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
677 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
678 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
679 if (ret < 0)
680 goto out;
683 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
684 ret = platform->driver->compr_ops->set_params(cstream, params);
685 if (ret < 0)
686 goto out;
689 for_each_rtdcom(fe, rtdcom) {
690 component = rtdcom->component;
692 /* ignore duplication for now */
693 if (platform && (component == &platform->component))
694 continue;
696 if (!component->driver->compr_ops ||
697 !component->driver->compr_ops->set_params)
698 continue;
700 __ret = component->driver->compr_ops->set_params(cstream, params);
701 if (__ret < 0)
702 ret = __ret;
704 if (ret < 0)
705 goto out;
707 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
708 ret = fe->dai_link->compr_ops->set_params(cstream);
709 if (ret < 0)
710 goto out;
714 * Create an empty hw_params for the BE as the machine driver must
715 * fix this up to match DSP decoder and ASRC configuration.
716 * I.e. machine driver fixup for compressed BE is mandatory.
718 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
719 sizeof(struct snd_pcm_hw_params));
721 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
723 ret = dpcm_be_dai_hw_params(fe, stream);
724 if (ret < 0)
725 goto out;
727 ret = dpcm_be_dai_prepare(fe, stream);
728 if (ret < 0)
729 goto out;
731 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
732 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
734 out:
735 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
736 mutex_unlock(&fe->card->mutex);
737 return ret;
740 static int soc_compr_get_params(struct snd_compr_stream *cstream,
741 struct snd_codec *params)
743 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
744 struct snd_soc_platform *platform = rtd->platform;
745 struct snd_soc_component *component;
746 struct snd_soc_rtdcom_list *rtdcom;
747 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
748 int ret = 0, __ret;
750 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
752 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
753 ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
754 if (ret < 0)
755 goto err;
758 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_params) {
759 ret = platform->driver->compr_ops->get_params(cstream, params);
760 if (ret < 0)
761 goto err;
764 for_each_rtdcom(rtd, rtdcom) {
765 component = rtdcom->component;
767 /* ignore duplication for now */
768 if (platform && (component == &platform->component))
769 continue;
771 if (!component->driver->compr_ops ||
772 !component->driver->compr_ops->get_params)
773 continue;
775 __ret = component->driver->compr_ops->get_params(cstream, params);
776 if (__ret < 0)
777 ret = __ret;
780 err:
781 mutex_unlock(&rtd->pcm_mutex);
782 return ret;
785 static int soc_compr_get_caps(struct snd_compr_stream *cstream,
786 struct snd_compr_caps *caps)
788 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
789 struct snd_soc_platform *platform = rtd->platform;
790 struct snd_soc_component *component;
791 struct snd_soc_rtdcom_list *rtdcom;
792 int ret = 0, __ret;
794 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
796 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_caps) {
797 ret = platform->driver->compr_ops->get_caps(cstream, caps);
798 if (ret < 0)
799 goto err;
802 for_each_rtdcom(rtd, rtdcom) {
803 component = rtdcom->component;
805 /* ignore duplication for now */
806 if (platform && (component == &platform->component))
807 continue;
809 if (!component->driver->compr_ops ||
810 !component->driver->compr_ops->get_caps)
811 continue;
813 __ret = component->driver->compr_ops->get_caps(cstream, caps);
814 if (__ret < 0)
815 ret = __ret;
818 err:
819 mutex_unlock(&rtd->pcm_mutex);
820 return ret;
823 static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
824 struct snd_compr_codec_caps *codec)
826 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
827 struct snd_soc_platform *platform = rtd->platform;
828 struct snd_soc_component *component;
829 struct snd_soc_rtdcom_list *rtdcom;
830 int ret = 0, __ret;
832 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
834 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) {
835 ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
836 if (ret < 0)
837 goto err;
840 for_each_rtdcom(rtd, rtdcom) {
841 component = rtdcom->component;
843 /* ignore duplication for now */
844 if (platform && (component == &platform->component))
845 continue;
847 if (!component->driver->compr_ops ||
848 !component->driver->compr_ops->get_codec_caps)
849 continue;
851 __ret = component->driver->compr_ops->get_codec_caps(cstream, codec);
852 if (__ret < 0)
853 ret = __ret;
856 err:
857 mutex_unlock(&rtd->pcm_mutex);
858 return ret;
861 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
863 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
864 struct snd_soc_platform *platform = rtd->platform;
865 struct snd_soc_component *component;
866 struct snd_soc_rtdcom_list *rtdcom;
867 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
868 int ret = 0, __ret;
870 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
872 if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
873 ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
874 if (ret < 0)
875 goto err;
878 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->ack) {
879 ret = platform->driver->compr_ops->ack(cstream, bytes);
880 if (ret < 0)
881 goto err;
884 for_each_rtdcom(rtd, rtdcom) {
885 component = rtdcom->component;
887 /* ignore duplication for now */
888 if (platform && (component == &platform->component))
889 continue;
891 if (!component->driver->compr_ops ||
892 !component->driver->compr_ops->ack)
893 continue;
895 __ret = component->driver->compr_ops->ack(cstream, bytes);
896 if (__ret < 0)
897 ret = __ret;
900 err:
901 mutex_unlock(&rtd->pcm_mutex);
902 return ret;
905 static int soc_compr_pointer(struct snd_compr_stream *cstream,
906 struct snd_compr_tstamp *tstamp)
908 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
909 struct snd_soc_platform *platform = rtd->platform;
910 struct snd_soc_component *component;
911 struct snd_soc_rtdcom_list *rtdcom;
912 int ret = 0, __ret;
913 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
915 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
917 if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
918 cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
920 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->pointer) {
921 ret = platform->driver->compr_ops->pointer(cstream, tstamp);
922 if (ret < 0)
923 goto err;
926 for_each_rtdcom(rtd, rtdcom) {
927 component = rtdcom->component;
929 /* ignore duplication for now */
930 if (platform && (component == &platform->component))
931 continue;
933 if (!component->driver->compr_ops ||
934 !component->driver->compr_ops->pointer)
935 continue;
937 __ret = component->driver->compr_ops->pointer(cstream, tstamp);
938 if (__ret < 0)
939 ret = __ret;
942 err:
943 mutex_unlock(&rtd->pcm_mutex);
944 return ret;
947 static int soc_compr_copy(struct snd_compr_stream *cstream,
948 char __user *buf, size_t count)
950 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
951 struct snd_soc_platform *platform = rtd->platform;
952 struct snd_soc_component *component;
953 struct snd_soc_rtdcom_list *rtdcom;
954 int ret = 0;
956 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
958 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy) {
959 ret = platform->driver->compr_ops->copy(cstream, buf, count);
960 if (ret < 0)
961 goto err;
964 for_each_rtdcom(rtd, rtdcom) {
965 component = rtdcom->component;
967 /* ignore duplication for now */
968 if (platform && (component == &platform->component))
969 continue;
971 if (!component->driver->compr_ops ||
972 !component->driver->compr_ops->copy)
973 continue;
975 ret = component->driver->compr_ops->copy(cstream, buf, count);
976 break;
979 err:
980 mutex_unlock(&rtd->pcm_mutex);
981 return ret;
984 static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
985 struct snd_compr_metadata *metadata)
987 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
988 struct snd_soc_platform *platform = rtd->platform;
989 struct snd_soc_component *component;
990 struct snd_soc_rtdcom_list *rtdcom;
991 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
992 int ret = 0, __ret;
994 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
995 ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
996 if (ret < 0)
997 return ret;
1000 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_metadata) {
1001 ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
1002 if (ret < 0)
1003 return ret;
1006 for_each_rtdcom(rtd, rtdcom) {
1007 component = rtdcom->component;
1009 /* ignore duplication for now */
1010 if (platform && (component == &platform->component))
1011 continue;
1013 if (!component->driver->compr_ops ||
1014 !component->driver->compr_ops->set_metadata)
1015 continue;
1017 __ret = component->driver->compr_ops->set_metadata(cstream, metadata);
1018 if (__ret < 0)
1019 ret = __ret;
1022 return ret;
1025 static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
1026 struct snd_compr_metadata *metadata)
1028 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
1029 struct snd_soc_platform *platform = rtd->platform;
1030 struct snd_soc_component *component;
1031 struct snd_soc_rtdcom_list *rtdcom;
1032 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1033 int ret = 0, __ret;
1035 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
1036 ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
1037 if (ret < 0)
1038 return ret;
1041 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_metadata) {
1042 ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
1043 if (ret < 0)
1044 return ret;
1047 for_each_rtdcom(rtd, rtdcom) {
1048 component = rtdcom->component;
1050 /* ignore duplication for now */
1051 if (platform && (component == &platform->component))
1052 continue;
1054 if (!component->driver->compr_ops ||
1055 !component->driver->compr_ops->get_metadata)
1056 continue;
1058 __ret = component->driver->compr_ops->get_metadata(cstream, metadata);
1059 if (__ret < 0)
1060 ret = __ret;
1063 return ret;
1066 /* ASoC Compress operations */
1067 static struct snd_compr_ops soc_compr_ops = {
1068 .open = soc_compr_open,
1069 .free = soc_compr_free,
1070 .set_params = soc_compr_set_params,
1071 .set_metadata = soc_compr_set_metadata,
1072 .get_metadata = soc_compr_get_metadata,
1073 .get_params = soc_compr_get_params,
1074 .trigger = soc_compr_trigger,
1075 .pointer = soc_compr_pointer,
1076 .ack = soc_compr_ack,
1077 .get_caps = soc_compr_get_caps,
1078 .get_codec_caps = soc_compr_get_codec_caps
1081 /* ASoC Dynamic Compress operations */
1082 static struct snd_compr_ops soc_compr_dyn_ops = {
1083 .open = soc_compr_open_fe,
1084 .free = soc_compr_free_fe,
1085 .set_params = soc_compr_set_params_fe,
1086 .get_params = soc_compr_get_params,
1087 .set_metadata = soc_compr_set_metadata,
1088 .get_metadata = soc_compr_get_metadata,
1089 .trigger = soc_compr_trigger_fe,
1090 .pointer = soc_compr_pointer,
1091 .ack = soc_compr_ack,
1092 .get_caps = soc_compr_get_caps,
1093 .get_codec_caps = soc_compr_get_codec_caps
1097 * snd_soc_new_compress - create a new compress.
1099 * @rtd: The runtime for which we will create compress
1100 * @num: the device index number (zero based - shared with normal PCMs)
1102 * Return: 0 for success, else error.
1104 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
1106 struct snd_soc_platform *platform = rtd->platform;
1107 struct snd_soc_component *component;
1108 struct snd_soc_rtdcom_list *rtdcom;
1109 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1110 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1111 struct snd_compr *compr;
1112 struct snd_pcm *be_pcm;
1113 char new_name[64];
1114 int ret = 0, direction = 0;
1115 int playback = 0, capture = 0;
1117 if (rtd->num_codecs > 1) {
1118 dev_err(rtd->card->dev,
1119 "Compress ASoC: Multicodec not supported\n");
1120 return -EINVAL;
1123 /* check client and interface hw capabilities */
1124 if (codec_dai->driver->playback.channels_min)
1125 playback = 1;
1126 if (codec_dai->driver->capture.channels_min)
1127 capture = 1;
1129 capture = capture && cpu_dai->driver->capture.channels_min;
1130 playback = playback && cpu_dai->driver->playback.channels_min;
1133 * Compress devices are unidirectional so only one of the directions
1134 * should be set, check for that (xor)
1136 if (playback + capture != 1) {
1137 dev_err(rtd->card->dev,
1138 "Compress ASoC: Invalid direction for P %d, C %d\n",
1139 playback, capture);
1140 return -EINVAL;
1143 if (playback)
1144 direction = SND_COMPRESS_PLAYBACK;
1145 else
1146 direction = SND_COMPRESS_CAPTURE;
1148 compr = kzalloc(sizeof(*compr), GFP_KERNEL);
1149 if (!compr)
1150 return -ENOMEM;
1152 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
1153 GFP_KERNEL);
1154 if (!compr->ops) {
1155 ret = -ENOMEM;
1156 goto compr_err;
1159 if (rtd->dai_link->dynamic) {
1160 snprintf(new_name, sizeof(new_name), "(%s)",
1161 rtd->dai_link->stream_name);
1163 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
1164 rtd->dai_link->dpcm_playback,
1165 rtd->dai_link->dpcm_capture, &be_pcm);
1166 if (ret < 0) {
1167 dev_err(rtd->card->dev,
1168 "Compress ASoC: can't create compressed for %s: %d\n",
1169 rtd->dai_link->name, ret);
1170 goto compr_err;
1173 rtd->pcm = be_pcm;
1174 rtd->fe_compr = 1;
1175 if (rtd->dai_link->dpcm_playback)
1176 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
1177 else if (rtd->dai_link->dpcm_capture)
1178 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
1179 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
1180 } else {
1181 snprintf(new_name, sizeof(new_name), "%s %s-%d",
1182 rtd->dai_link->stream_name, codec_dai->name, num);
1184 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
1188 /* Add copy callback for not memory mapped DSPs */
1189 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy)
1190 compr->ops->copy = soc_compr_copy;
1192 for_each_rtdcom(rtd, rtdcom) {
1193 component = rtdcom->component;
1195 /* ignore duplication for now */
1196 if (platform && (component == &platform->component))
1197 continue;
1199 if (!component->driver->compr_ops ||
1200 !component->driver->compr_ops->copy)
1201 continue;
1203 compr->ops->copy = soc_compr_copy;
1207 mutex_init(&compr->lock);
1208 ret = snd_compress_new(rtd->card->snd_card, num, direction,
1209 new_name, compr);
1210 if (ret < 0) {
1211 component = rtd->codec_dai->component;
1212 dev_err(component->dev,
1213 "Compress ASoC: can't create compress for codec %s: %d\n",
1214 component->name, ret);
1215 goto compr_err;
1218 /* DAPM dai link stream work */
1219 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
1221 rtd->compr = compr;
1222 compr->private_data = rtd;
1224 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
1225 codec_dai->name, cpu_dai->name);
1226 return ret;
1228 compr_err:
1229 kfree(compr);
1230 return ret;
1232 EXPORT_SYMBOL_GPL(snd_soc_new_compress);