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;
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);
44 "Compress ASoC: can't open interface %s: %d\n",
50 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
51 ret = platform->driver->compr_ops->open(cstream);
53 dev_err(platform->dev,
54 "Compress ASoC: can't open platform %s: %d\n",
55 platform->component.name, ret);
60 for_each_rtdcom(rtd, rtdcom) {
61 component = rtdcom->component;
63 /* ignore duplication for now */
64 if (platform && (component == &platform->component))
67 if (!component->driver->compr_ops ||
68 !component->driver->compr_ops->open)
71 ret = component->driver->compr_ops->open(cstream);
73 dev_err(component->dev,
74 "Compress ASoC: can't open platform %s: %d\n",
75 component->name, ret);
81 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
82 ret = rtd->dai_link->compr_ops->startup(cstream);
85 "Compress ASoC: %s startup failed: %d\n",
86 rtd->dai_link->name, ret);
91 snd_soc_runtime_activate(rtd, cstream->direction);
93 mutex_unlock(&rtd->pcm_mutex);
98 for_each_rtdcom(rtd, rtdcom) {
99 struct snd_soc_component *err_comp = rtdcom->component;
101 if (err_comp == component)
104 /* ignore duplication for now */
105 if (platform && (err_comp == &platform->component))
108 if (!err_comp->driver->compr_ops ||
109 !err_comp->driver->compr_ops->free)
112 err_comp->driver->compr_ops->free(cstream);
115 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
116 platform->driver->compr_ops->free(cstream);
118 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
119 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
121 mutex_unlock(&rtd->pcm_mutex);
125 static int soc_compr_open_fe(struct snd_compr_stream *cstream)
127 struct snd_soc_pcm_runtime *fe = cstream->private_data;
128 struct snd_pcm_substream *fe_substream =
129 fe->pcm->streams[cstream->direction].substream;
130 struct snd_soc_platform *platform = fe->platform;
131 struct snd_soc_component *component;
132 struct snd_soc_rtdcom_list *rtdcom;
133 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
134 struct snd_soc_dpcm *dpcm;
135 struct snd_soc_dapm_widget_list *list;
139 if (cstream->direction == SND_COMPRESS_PLAYBACK)
140 stream = SNDRV_PCM_STREAM_PLAYBACK;
142 stream = SNDRV_PCM_STREAM_CAPTURE;
144 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
146 if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
147 ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
149 dev_err(cpu_dai->dev,
150 "Compress ASoC: can't open interface %s: %d\n",
156 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
157 ret = platform->driver->compr_ops->open(cstream);
159 dev_err(platform->dev,
160 "Compress ASoC: can't open platform %s: %d\n",
161 platform->component.name, ret);
166 for_each_rtdcom(fe, rtdcom) {
167 component = rtdcom->component;
169 /* ignore duplication for now */
170 if (platform && (component == &platform->component))
173 if (!component->driver->compr_ops ||
174 !component->driver->compr_ops->open)
177 ret = component->driver->compr_ops->open(cstream);
179 dev_err(component->dev,
180 "Compress ASoC: can't open platform %s: %d\n",
181 component->name, ret);
187 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
188 ret = fe->dai_link->compr_ops->startup(cstream);
190 pr_err("Compress ASoC: %s startup failed: %d\n",
191 fe->dai_link->name, ret);
196 fe->dpcm[stream].runtime = fe_substream->runtime;
198 ret = dpcm_path_get(fe, stream, &list);
202 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
203 fe->dai_link->name, stream ? "capture" : "playback");
205 /* calculate valid and active FE <-> BE dpcms */
206 dpcm_process_paths(fe, stream, &list, 1);
208 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
210 ret = dpcm_be_dai_startup(fe, stream);
212 /* clean up all links */
213 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
214 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
216 dpcm_be_disconnect(fe, stream);
217 fe->dpcm[stream].runtime = NULL;
221 dpcm_clear_pending_state(fe, stream);
222 dpcm_path_put(&list);
224 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
225 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
227 snd_soc_runtime_activate(fe, stream);
229 mutex_unlock(&fe->card->mutex);
234 dpcm_path_put(&list);
236 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
237 fe->dai_link->compr_ops->shutdown(cstream);
239 for_each_rtdcom(fe, rtdcom) {
240 struct snd_soc_component *err_comp = rtdcom->component;
242 if (err_comp == component)
245 /* ignore duplication for now */
246 if (platform && (err_comp == &platform->component))
249 if (!err_comp->driver->compr_ops ||
250 !err_comp->driver->compr_ops->free)
253 err_comp->driver->compr_ops->free(cstream);
256 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
257 platform->driver->compr_ops->free(cstream);
259 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
260 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
262 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
263 mutex_unlock(&fe->card->mutex);
268 * Power down the audio subsystem pmdown_time msecs after close is called.
269 * This is to ensure there are no pops or clicks in between any music tracks
270 * due to DAPM power cycling.
272 static void close_delayed_work(struct work_struct *work)
274 struct snd_soc_pcm_runtime *rtd =
275 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
276 struct snd_soc_dai *codec_dai = rtd->codec_dai;
278 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
281 "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n",
282 codec_dai->driver->playback.stream_name,
283 codec_dai->playback_active ? "active" : "inactive",
284 rtd->pop_wait ? "yes" : "no");
286 /* are we waiting on this codec DAI stream */
287 if (rtd->pop_wait == 1) {
289 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
290 SND_SOC_DAPM_STREAM_STOP);
293 mutex_unlock(&rtd->pcm_mutex);
296 static int soc_compr_free(struct snd_compr_stream *cstream)
298 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
299 struct snd_soc_platform *platform = rtd->platform;
300 struct snd_soc_component *component;
301 struct snd_soc_rtdcom_list *rtdcom;
302 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
303 struct snd_soc_dai *codec_dai = rtd->codec_dai;
306 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
308 if (cstream->direction == SND_COMPRESS_PLAYBACK)
309 stream = SNDRV_PCM_STREAM_PLAYBACK;
311 stream = SNDRV_PCM_STREAM_CAPTURE;
313 snd_soc_runtime_deactivate(rtd, stream);
315 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
317 if (!cpu_dai->active)
320 if (!codec_dai->active)
323 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
324 rtd->dai_link->compr_ops->shutdown(cstream);
326 for_each_rtdcom(rtd, rtdcom) {
327 component = rtdcom->component;
329 /* ignore duplication for now */
330 if (platform && (component == &platform->component))
333 if (!component->driver->compr_ops ||
334 !component->driver->compr_ops->free)
337 component->driver->compr_ops->free(cstream);
340 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
341 platform->driver->compr_ops->free(cstream);
343 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
344 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
346 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
347 if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
348 snd_soc_dapm_stream_event(rtd,
349 SNDRV_PCM_STREAM_PLAYBACK,
350 SND_SOC_DAPM_STREAM_STOP);
353 queue_delayed_work(system_power_efficient_wq,
355 msecs_to_jiffies(rtd->pmdown_time));
358 /* capture streams can be powered down now */
359 snd_soc_dapm_stream_event(rtd,
360 SNDRV_PCM_STREAM_CAPTURE,
361 SND_SOC_DAPM_STREAM_STOP);
364 mutex_unlock(&rtd->pcm_mutex);
368 static int soc_compr_free_fe(struct snd_compr_stream *cstream)
370 struct snd_soc_pcm_runtime *fe = cstream->private_data;
371 struct snd_soc_platform *platform = fe->platform;
372 struct snd_soc_component *component;
373 struct snd_soc_rtdcom_list *rtdcom;
374 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
375 struct snd_soc_dpcm *dpcm;
378 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
380 if (cstream->direction == SND_COMPRESS_PLAYBACK)
381 stream = SNDRV_PCM_STREAM_PLAYBACK;
383 stream = SNDRV_PCM_STREAM_CAPTURE;
385 snd_soc_runtime_deactivate(fe, stream);
387 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
389 ret = dpcm_be_dai_hw_free(fe, stream);
391 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
393 ret = dpcm_be_dai_shutdown(fe, stream);
395 /* mark FE's links ready to prune */
396 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
397 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
399 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
401 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
402 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
404 dpcm_be_disconnect(fe, stream);
406 fe->dpcm[stream].runtime = NULL;
408 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
409 fe->dai_link->compr_ops->shutdown(cstream);
411 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
412 platform->driver->compr_ops->free(cstream);
414 for_each_rtdcom(fe, rtdcom) {
415 component = rtdcom->component;
417 /* ignore duplication for now */
418 if (platform && (component == &platform->component))
421 if (!component->driver->compr_ops ||
422 !component->driver->compr_ops->free)
425 component->driver->compr_ops->free(cstream);
428 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
429 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
431 mutex_unlock(&fe->card->mutex);
435 static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
438 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
439 struct snd_soc_platform *platform = rtd->platform;
440 struct snd_soc_component *component;
441 struct snd_soc_rtdcom_list *rtdcom;
442 struct snd_soc_dai *codec_dai = rtd->codec_dai;
443 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
446 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
448 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
449 ret = platform->driver->compr_ops->trigger(cstream, cmd);
454 for_each_rtdcom(rtd, rtdcom) {
455 component = rtdcom->component;
457 /* ignore duplication for now */
458 if (platform && (component == &platform->component))
461 if (!component->driver->compr_ops ||
462 !component->driver->compr_ops->trigger)
465 __ret = component->driver->compr_ops->trigger(cstream, cmd);
472 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
473 cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
476 case SNDRV_PCM_TRIGGER_START:
477 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
479 case SNDRV_PCM_TRIGGER_STOP:
480 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
485 mutex_unlock(&rtd->pcm_mutex);
489 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
491 struct snd_soc_pcm_runtime *fe = cstream->private_data;
492 struct snd_soc_platform *platform = fe->platform;
493 struct snd_soc_component *component;
494 struct snd_soc_rtdcom_list *rtdcom;
495 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
496 int ret = 0, __ret, stream;
498 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
499 cmd == SND_COMPR_TRIGGER_DRAIN) {
502 platform->driver->compr_ops &&
503 platform->driver->compr_ops->trigger)
504 return platform->driver->compr_ops->trigger(cstream,
507 for_each_rtdcom(fe, rtdcom) {
508 component = rtdcom->component;
510 /* ignore duplication for now */
511 if (platform && (component == &platform->component))
514 if (!component->driver->compr_ops ||
515 !component->driver->compr_ops->trigger)
518 __ret = component->driver->compr_ops->trigger(cstream, cmd);
525 if (cstream->direction == SND_COMPRESS_PLAYBACK)
526 stream = SNDRV_PCM_STREAM_PLAYBACK;
528 stream = SNDRV_PCM_STREAM_CAPTURE;
531 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
533 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
534 ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
539 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
540 ret = platform->driver->compr_ops->trigger(cstream, cmd);
545 for_each_rtdcom(fe, rtdcom) {
546 component = rtdcom->component;
548 /* ignore duplication for now */
549 if (platform && (component == &platform->component))
552 if (!component->driver->compr_ops ||
553 !component->driver->compr_ops->trigger)
556 __ret = component->driver->compr_ops->trigger(cstream, cmd);
563 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
565 ret = dpcm_be_dai_trigger(fe, stream, cmd);
568 case SNDRV_PCM_TRIGGER_START:
569 case SNDRV_PCM_TRIGGER_RESUME:
570 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
571 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
573 case SNDRV_PCM_TRIGGER_STOP:
574 case SNDRV_PCM_TRIGGER_SUSPEND:
575 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
577 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
578 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
583 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
584 mutex_unlock(&fe->card->mutex);
588 static int soc_compr_set_params(struct snd_compr_stream *cstream,
589 struct snd_compr_params *params)
591 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
592 struct snd_soc_platform *platform = rtd->platform;
593 struct snd_soc_component *component;
594 struct snd_soc_rtdcom_list *rtdcom;
595 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
598 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
600 /* first we call set_params for the platform driver
601 * this should configure the soc side
602 * if the machine has compressed ops then we call that as well
603 * expectation is that platform and machine will configure everything
604 * for this compress path, like configuring pcm port for codec
606 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
607 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
612 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
613 ret = platform->driver->compr_ops->set_params(cstream, params);
618 for_each_rtdcom(rtd, rtdcom) {
619 component = rtdcom->component;
621 /* ignore duplication for now */
622 if (platform && (component == &platform->component))
625 if (!component->driver->compr_ops ||
626 !component->driver->compr_ops->set_params)
629 __ret = component->driver->compr_ops->set_params(cstream, params);
636 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
637 ret = rtd->dai_link->compr_ops->set_params(cstream);
642 if (cstream->direction == SND_COMPRESS_PLAYBACK)
643 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
644 SND_SOC_DAPM_STREAM_START);
646 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
647 SND_SOC_DAPM_STREAM_START);
649 /* cancel any delayed stream shutdown that is pending */
651 mutex_unlock(&rtd->pcm_mutex);
653 cancel_delayed_work_sync(&rtd->delayed_work);
658 mutex_unlock(&rtd->pcm_mutex);
662 static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
663 struct snd_compr_params *params)
665 struct snd_soc_pcm_runtime *fe = cstream->private_data;
666 struct snd_pcm_substream *fe_substream =
667 fe->pcm->streams[cstream->direction].substream;
668 struct snd_soc_platform *platform = fe->platform;
669 struct snd_soc_component *component;
670 struct snd_soc_rtdcom_list *rtdcom;
671 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
672 int ret = 0, __ret, stream;
674 if (cstream->direction == SND_COMPRESS_PLAYBACK)
675 stream = SNDRV_PCM_STREAM_PLAYBACK;
677 stream = SNDRV_PCM_STREAM_CAPTURE;
679 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
681 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
682 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
687 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
688 ret = platform->driver->compr_ops->set_params(cstream, params);
693 for_each_rtdcom(fe, rtdcom) {
694 component = rtdcom->component;
696 /* ignore duplication for now */
697 if (platform && (component == &platform->component))
700 if (!component->driver->compr_ops ||
701 !component->driver->compr_ops->set_params)
704 __ret = component->driver->compr_ops->set_params(cstream, params);
711 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
712 ret = fe->dai_link->compr_ops->set_params(cstream);
718 * Create an empty hw_params for the BE as the machine driver must
719 * fix this up to match DSP decoder and ASRC configuration.
720 * I.e. machine driver fixup for compressed BE is mandatory.
722 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
723 sizeof(struct snd_pcm_hw_params));
725 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
727 ret = dpcm_be_dai_hw_params(fe, stream);
731 ret = dpcm_be_dai_prepare(fe, stream);
735 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
736 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
739 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
740 mutex_unlock(&fe->card->mutex);
744 static int soc_compr_get_params(struct snd_compr_stream *cstream,
745 struct snd_codec *params)
747 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
748 struct snd_soc_platform *platform = rtd->platform;
749 struct snd_soc_component *component;
750 struct snd_soc_rtdcom_list *rtdcom;
751 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
754 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
756 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
757 ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
762 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_params) {
763 ret = platform->driver->compr_ops->get_params(cstream, params);
768 for_each_rtdcom(rtd, rtdcom) {
769 component = rtdcom->component;
771 /* ignore duplication for now */
772 if (platform && (component == &platform->component))
775 if (!component->driver->compr_ops ||
776 !component->driver->compr_ops->get_params)
779 __ret = component->driver->compr_ops->get_params(cstream, params);
785 mutex_unlock(&rtd->pcm_mutex);
789 static int soc_compr_get_caps(struct snd_compr_stream *cstream,
790 struct snd_compr_caps *caps)
792 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
793 struct snd_soc_platform *platform = rtd->platform;
794 struct snd_soc_component *component;
795 struct snd_soc_rtdcom_list *rtdcom;
798 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
800 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_caps) {
801 ret = platform->driver->compr_ops->get_caps(cstream, caps);
806 for_each_rtdcom(rtd, rtdcom) {
807 component = rtdcom->component;
809 /* ignore duplication for now */
810 if (platform && (component == &platform->component))
813 if (!component->driver->compr_ops ||
814 !component->driver->compr_ops->get_caps)
817 __ret = component->driver->compr_ops->get_caps(cstream, caps);
823 mutex_unlock(&rtd->pcm_mutex);
827 static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
828 struct snd_compr_codec_caps *codec)
830 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
831 struct snd_soc_platform *platform = rtd->platform;
832 struct snd_soc_component *component;
833 struct snd_soc_rtdcom_list *rtdcom;
836 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
838 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) {
839 ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
844 for_each_rtdcom(rtd, rtdcom) {
845 component = rtdcom->component;
847 /* ignore duplication for now */
848 if (platform && (component == &platform->component))
851 if (!component->driver->compr_ops ||
852 !component->driver->compr_ops->get_codec_caps)
855 __ret = component->driver->compr_ops->get_codec_caps(cstream, codec);
861 mutex_unlock(&rtd->pcm_mutex);
865 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
867 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
868 struct snd_soc_platform *platform = rtd->platform;
869 struct snd_soc_component *component;
870 struct snd_soc_rtdcom_list *rtdcom;
871 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
874 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
876 if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
877 ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
882 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->ack) {
883 ret = platform->driver->compr_ops->ack(cstream, bytes);
888 for_each_rtdcom(rtd, rtdcom) {
889 component = rtdcom->component;
891 /* ignore duplication for now */
892 if (platform && (component == &platform->component))
895 if (!component->driver->compr_ops ||
896 !component->driver->compr_ops->ack)
899 __ret = component->driver->compr_ops->ack(cstream, bytes);
905 mutex_unlock(&rtd->pcm_mutex);
909 static int soc_compr_pointer(struct snd_compr_stream *cstream,
910 struct snd_compr_tstamp *tstamp)
912 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
913 struct snd_soc_platform *platform = rtd->platform;
914 struct snd_soc_component *component;
915 struct snd_soc_rtdcom_list *rtdcom;
917 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
919 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
921 if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
922 cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
924 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->pointer) {
925 ret = platform->driver->compr_ops->pointer(cstream, tstamp);
930 for_each_rtdcom(rtd, rtdcom) {
931 component = rtdcom->component;
933 /* ignore duplication for now */
934 if (platform && (component == &platform->component))
937 if (!component->driver->compr_ops ||
938 !component->driver->compr_ops->pointer)
941 __ret = component->driver->compr_ops->pointer(cstream, tstamp);
947 mutex_unlock(&rtd->pcm_mutex);
951 static int soc_compr_copy(struct snd_compr_stream *cstream,
952 char __user *buf, size_t count)
954 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
955 struct snd_soc_platform *platform = rtd->platform;
956 struct snd_soc_component *component;
957 struct snd_soc_rtdcom_list *rtdcom;
960 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
962 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy) {
963 ret = platform->driver->compr_ops->copy(cstream, buf, count);
968 for_each_rtdcom(rtd, rtdcom) {
969 component = rtdcom->component;
971 /* ignore duplication for now */
972 if (platform && (component == &platform->component))
975 if (!component->driver->compr_ops ||
976 !component->driver->compr_ops->copy)
979 ret = component->driver->compr_ops->copy(cstream, buf, count);
984 mutex_unlock(&rtd->pcm_mutex);
988 static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
989 struct snd_compr_metadata *metadata)
991 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
992 struct snd_soc_platform *platform = rtd->platform;
993 struct snd_soc_component *component;
994 struct snd_soc_rtdcom_list *rtdcom;
995 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
998 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
999 ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
1004 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_metadata) {
1005 ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
1010 for_each_rtdcom(rtd, rtdcom) {
1011 component = rtdcom->component;
1013 /* ignore duplication for now */
1014 if (platform && (component == &platform->component))
1017 if (!component->driver->compr_ops ||
1018 !component->driver->compr_ops->set_metadata)
1021 __ret = component->driver->compr_ops->set_metadata(cstream, metadata);
1029 static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
1030 struct snd_compr_metadata *metadata)
1032 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
1033 struct snd_soc_platform *platform = rtd->platform;
1034 struct snd_soc_component *component;
1035 struct snd_soc_rtdcom_list *rtdcom;
1036 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1039 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
1040 ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
1045 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_metadata) {
1046 ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
1051 for_each_rtdcom(rtd, rtdcom) {
1052 component = rtdcom->component;
1054 /* ignore duplication for now */
1055 if (platform && (component == &platform->component))
1058 if (!component->driver->compr_ops ||
1059 !component->driver->compr_ops->get_metadata)
1062 __ret = component->driver->compr_ops->get_metadata(cstream, metadata);
1070 /* ASoC Compress operations */
1071 static struct snd_compr_ops soc_compr_ops = {
1072 .open = soc_compr_open,
1073 .free = soc_compr_free,
1074 .set_params = soc_compr_set_params,
1075 .set_metadata = soc_compr_set_metadata,
1076 .get_metadata = soc_compr_get_metadata,
1077 .get_params = soc_compr_get_params,
1078 .trigger = soc_compr_trigger,
1079 .pointer = soc_compr_pointer,
1080 .ack = soc_compr_ack,
1081 .get_caps = soc_compr_get_caps,
1082 .get_codec_caps = soc_compr_get_codec_caps
1085 /* ASoC Dynamic Compress operations */
1086 static struct snd_compr_ops soc_compr_dyn_ops = {
1087 .open = soc_compr_open_fe,
1088 .free = soc_compr_free_fe,
1089 .set_params = soc_compr_set_params_fe,
1090 .get_params = soc_compr_get_params,
1091 .set_metadata = soc_compr_set_metadata,
1092 .get_metadata = soc_compr_get_metadata,
1093 .trigger = soc_compr_trigger_fe,
1094 .pointer = soc_compr_pointer,
1095 .ack = soc_compr_ack,
1096 .get_caps = soc_compr_get_caps,
1097 .get_codec_caps = soc_compr_get_codec_caps
1101 * snd_soc_new_compress - create a new compress.
1103 * @rtd: The runtime for which we will create compress
1104 * @num: the device index number (zero based - shared with normal PCMs)
1106 * Return: 0 for success, else error.
1108 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
1110 struct snd_soc_platform *platform = rtd->platform;
1111 struct snd_soc_component *component;
1112 struct snd_soc_rtdcom_list *rtdcom;
1113 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1114 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1115 struct snd_compr *compr;
1116 struct snd_pcm *be_pcm;
1118 int ret = 0, direction = 0;
1119 int playback = 0, capture = 0;
1121 if (rtd->num_codecs > 1) {
1122 dev_err(rtd->card->dev,
1123 "Compress ASoC: Multicodec not supported\n");
1127 /* check client and interface hw capabilities */
1128 if (codec_dai->driver->playback.channels_min)
1130 if (codec_dai->driver->capture.channels_min)
1133 capture = capture && cpu_dai->driver->capture.channels_min;
1134 playback = playback && cpu_dai->driver->playback.channels_min;
1137 * Compress devices are unidirectional so only one of the directions
1138 * should be set, check for that (xor)
1140 if (playback + capture != 1) {
1141 dev_err(rtd->card->dev,
1142 "Compress ASoC: Invalid direction for P %d, C %d\n",
1148 direction = SND_COMPRESS_PLAYBACK;
1150 direction = SND_COMPRESS_CAPTURE;
1152 compr = kzalloc(sizeof(*compr), GFP_KERNEL);
1156 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
1163 if (rtd->dai_link->dynamic) {
1164 snprintf(new_name, sizeof(new_name), "(%s)",
1165 rtd->dai_link->stream_name);
1167 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
1168 rtd->dai_link->dpcm_playback,
1169 rtd->dai_link->dpcm_capture, &be_pcm);
1171 dev_err(rtd->card->dev,
1172 "Compress ASoC: can't create compressed for %s: %d\n",
1173 rtd->dai_link->name, ret);
1179 if (rtd->dai_link->dpcm_playback)
1180 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
1181 else if (rtd->dai_link->dpcm_capture)
1182 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
1183 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
1185 snprintf(new_name, sizeof(new_name), "%s %s-%d",
1186 rtd->dai_link->stream_name, codec_dai->name, num);
1188 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
1192 /* Add copy callback for not memory mapped DSPs */
1193 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy)
1194 compr->ops->copy = soc_compr_copy;
1196 for_each_rtdcom(rtd, rtdcom) {
1197 component = rtdcom->component;
1199 /* ignore duplication for now */
1200 if (platform && (component == &platform->component))
1203 if (!component->driver->compr_ops ||
1204 !component->driver->compr_ops->copy)
1207 compr->ops->copy = soc_compr_copy;
1211 mutex_init(&compr->lock);
1212 ret = snd_compress_new(rtd->card->snd_card, num, direction,
1215 component = rtd->codec_dai->component;
1216 dev_err(component->dev,
1217 "Compress ASoC: can't create compress for codec %s: %d\n",
1218 component->name, ret);
1222 /* DAPM dai link stream work */
1223 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
1226 compr->private_data = rtd;
1228 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
1229 codec_dai->name, cpu_dai->name);
1236 EXPORT_SYMBOL_GPL(snd_soc_new_compress);