Loading...
1// SPDX-License-Identifier: GPL-2.0+
2//
3// soc-compress.c -- ALSA SoC Compress
4//
5// Copyright (C) 2012 Intel Corp.
6//
7// Authors: Namarta Kohli <namartax.kohli@intel.com>
8// Ramesh Babu K V <ramesh.babu@linux.intel.com>
9// Vinod Koul <vinod.koul@linux.intel.com>
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/delay.h>
14#include <linux/slab.h>
15#include <linux/workqueue.h>
16#include <sound/core.h>
17#include <sound/compress_params.h>
18#include <sound/compress_driver.h>
19#include <sound/soc.h>
20#include <sound/initval.h>
21#include <sound/soc-dpcm.h>
22#include <sound/soc-link.h>
23
24static int snd_soc_compr_components_open(struct snd_compr_stream *cstream)
25{
26 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
27 struct snd_soc_component *component;
28 int ret = 0;
29 int i;
30
31 for_each_rtd_components(rtd, i, component) {
32 ret = snd_soc_component_module_get_when_open(component, cstream);
33 if (ret < 0)
34 break;
35
36 ret = snd_soc_component_compr_open(component, cstream);
37 if (ret < 0)
38 break;
39 }
40
41 return ret;
42}
43
44static void snd_soc_compr_components_free(struct snd_compr_stream *cstream,
45 int rollback)
46{
47 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
48 struct snd_soc_component *component;
49 int i;
50
51 for_each_rtd_components(rtd, i, component) {
52 snd_soc_component_compr_free(component, cstream, rollback);
53 snd_soc_component_module_put_when_close(component, cstream, rollback);
54 }
55}
56
57static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback)
58{
59 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
60 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
61 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
62 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
63
64 snd_soc_dpcm_mutex_lock(rtd);
65
66 if (!rollback)
67 snd_soc_runtime_deactivate(rtd, stream);
68
69 snd_soc_dai_digital_mute(codec_dai, 1, stream);
70
71 if (!snd_soc_dai_active(cpu_dai))
72 cpu_dai->rate = 0;
73
74 if (!snd_soc_dai_active(codec_dai))
75 codec_dai->rate = 0;
76
77 snd_soc_link_compr_shutdown(cstream, rollback);
78
79 snd_soc_compr_components_free(cstream, rollback);
80
81 snd_soc_dai_compr_shutdown(cpu_dai, cstream, rollback);
82
83 if (!rollback)
84 snd_soc_dapm_stream_stop(rtd, stream);
85
86 snd_soc_dpcm_mutex_unlock(rtd);
87
88 snd_soc_pcm_component_pm_runtime_put(rtd, cstream, rollback);
89
90 return 0;
91}
92
93static int soc_compr_free(struct snd_compr_stream *cstream)
94{
95 return soc_compr_clean(cstream, 0);
96}
97
98static int soc_compr_open(struct snd_compr_stream *cstream)
99{
100 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
101 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
102 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
103 int ret;
104
105 ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream);
106 if (ret < 0)
107 goto err_no_lock;
108
109 snd_soc_dpcm_mutex_lock(rtd);
110
111 ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
112 if (ret < 0)
113 goto err;
114
115 ret = snd_soc_compr_components_open(cstream);
116 if (ret < 0)
117 goto err;
118
119 ret = snd_soc_link_compr_startup(cstream);
120 if (ret < 0)
121 goto err;
122
123 snd_soc_runtime_activate(rtd, stream);
124err:
125 snd_soc_dpcm_mutex_unlock(rtd);
126err_no_lock:
127 if (ret < 0)
128 soc_compr_clean(cstream, 1);
129
130 return ret;
131}
132
133static int soc_compr_open_fe(struct snd_compr_stream *cstream)
134{
135 struct snd_soc_pcm_runtime *fe = cstream->private_data;
136 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0);
137 struct snd_soc_dpcm *dpcm;
138 struct snd_soc_dapm_widget_list *list;
139 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
140 int ret;
141
142 snd_soc_card_mutex_lock(fe->card);
143
144 ret = dpcm_path_get(fe, stream, &list);
145 if (ret < 0)
146 goto be_err;
147
148 snd_soc_dpcm_mutex_lock(fe);
149
150 /* calculate valid and active FE <-> BE dpcms */
151 dpcm_process_paths(fe, stream, &list, 1);
152
153 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
154
155 ret = dpcm_be_dai_startup(fe, stream);
156 if (ret < 0) {
157 /* clean up all links */
158 for_each_dpcm_be(fe, stream, dpcm)
159 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
160
161 dpcm_be_disconnect(fe, stream);
162 goto out;
163 }
164
165 ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
166 if (ret < 0)
167 goto out;
168
169 ret = snd_soc_compr_components_open(cstream);
170 if (ret < 0)
171 goto open_err;
172
173 ret = snd_soc_link_compr_startup(cstream);
174 if (ret < 0)
175 goto machine_err;
176
177 dpcm_clear_pending_state(fe, stream);
178 dpcm_path_put(&list);
179
180 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
181 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
182
183 snd_soc_runtime_activate(fe, stream);
184 snd_soc_dpcm_mutex_unlock(fe);
185
186 snd_soc_card_mutex_unlock(fe->card);
187
188 return 0;
189
190machine_err:
191 snd_soc_compr_components_free(cstream, 1);
192open_err:
193 snd_soc_dai_compr_shutdown(cpu_dai, cstream, 1);
194out:
195 dpcm_path_put(&list);
196 snd_soc_dpcm_mutex_unlock(fe);
197be_err:
198 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
199 snd_soc_card_mutex_unlock(fe->card);
200 return ret;
201}
202
203static int soc_compr_free_fe(struct snd_compr_stream *cstream)
204{
205 struct snd_soc_pcm_runtime *fe = cstream->private_data;
206 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0);
207 struct snd_soc_dpcm *dpcm;
208 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
209
210 snd_soc_card_mutex_lock(fe->card);
211
212 snd_soc_dpcm_mutex_lock(fe);
213 snd_soc_runtime_deactivate(fe, stream);
214
215 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
216
217 dpcm_be_dai_hw_free(fe, stream);
218
219 dpcm_be_dai_shutdown(fe, stream);
220
221 /* mark FE's links ready to prune */
222 for_each_dpcm_be(fe, stream, dpcm)
223 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
224
225 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
226
227 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
228 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
229
230 dpcm_be_disconnect(fe, stream);
231
232 snd_soc_dpcm_mutex_unlock(fe);
233
234 snd_soc_link_compr_shutdown(cstream, 0);
235
236 snd_soc_compr_components_free(cstream, 0);
237
238 snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0);
239
240 snd_soc_card_mutex_unlock(fe->card);
241 return 0;
242}
243
244static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
245{
246 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
247 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
248 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
249 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
250 int ret;
251
252 snd_soc_dpcm_mutex_lock(rtd);
253
254 ret = snd_soc_component_compr_trigger(cstream, cmd);
255 if (ret < 0)
256 goto out;
257
258 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
259 if (ret < 0)
260 goto out;
261
262 switch (cmd) {
263 case SNDRV_PCM_TRIGGER_START:
264 snd_soc_dai_digital_mute(codec_dai, 0, stream);
265 break;
266 case SNDRV_PCM_TRIGGER_STOP:
267 snd_soc_dai_digital_mute(codec_dai, 1, stream);
268 break;
269 }
270
271out:
272 snd_soc_dpcm_mutex_unlock(rtd);
273 return ret;
274}
275
276static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
277{
278 struct snd_soc_pcm_runtime *fe = cstream->private_data;
279 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0);
280 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
281 int ret;
282
283 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
284 cmd == SND_COMPR_TRIGGER_DRAIN)
285 return snd_soc_component_compr_trigger(cstream, cmd);
286
287 snd_soc_card_mutex_lock(fe->card);
288
289 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
290 if (ret < 0)
291 goto out;
292
293 ret = snd_soc_component_compr_trigger(cstream, cmd);
294 if (ret < 0)
295 goto out;
296
297 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
298
299 ret = dpcm_be_dai_trigger(fe, stream, cmd);
300
301 switch (cmd) {
302 case SNDRV_PCM_TRIGGER_START:
303 case SNDRV_PCM_TRIGGER_RESUME:
304 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
305 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
306 break;
307 case SNDRV_PCM_TRIGGER_STOP:
308 case SNDRV_PCM_TRIGGER_SUSPEND:
309 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
310 break;
311 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
312 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
313 break;
314 }
315
316out:
317 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
318 snd_soc_card_mutex_unlock(fe->card);
319 return ret;
320}
321
322static int soc_compr_set_params(struct snd_compr_stream *cstream,
323 struct snd_compr_params *params)
324{
325 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
326 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
327 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
328 int ret;
329
330 snd_soc_dpcm_mutex_lock(rtd);
331
332 /*
333 * First we call set_params for the CPU DAI, then the component
334 * driver this should configure the SoC side. If the machine has
335 * compressed ops then we call that as well. The expectation is
336 * that these callbacks will configure everything for this compress
337 * path, like configuring a PCM port for a CODEC.
338 */
339 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
340 if (ret < 0)
341 goto err;
342
343 ret = snd_soc_component_compr_set_params(cstream, params);
344 if (ret < 0)
345 goto err;
346
347 ret = snd_soc_link_compr_set_params(cstream);
348 if (ret < 0)
349 goto err;
350
351 snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START);
352
353 /* cancel any delayed stream shutdown that is pending */
354 rtd->pop_wait = 0;
355 snd_soc_dpcm_mutex_unlock(rtd);
356
357 cancel_delayed_work_sync(&rtd->delayed_work);
358
359 return 0;
360
361err:
362 snd_soc_dpcm_mutex_unlock(rtd);
363 return ret;
364}
365
366static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
367 struct snd_compr_params *params)
368{
369 struct snd_soc_pcm_runtime *fe = cstream->private_data;
370 struct snd_pcm_substream *fe_substream =
371 fe->pcm->streams[cstream->direction].substream;
372 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0);
373 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
374 int ret;
375
376 snd_soc_card_mutex_lock(fe->card);
377
378 /*
379 * Create an empty hw_params for the BE as the machine driver must
380 * fix this up to match DSP decoder and ASRC configuration.
381 * I.e. machine driver fixup for compressed BE is mandatory.
382 */
383 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
384 sizeof(struct snd_pcm_hw_params));
385
386 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
387
388 ret = dpcm_be_dai_hw_params(fe, stream);
389 if (ret < 0)
390 goto out;
391
392 ret = dpcm_be_dai_prepare(fe, stream);
393 if (ret < 0)
394 goto out;
395
396 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
397 if (ret < 0)
398 goto out;
399
400 ret = snd_soc_component_compr_set_params(cstream, params);
401 if (ret < 0)
402 goto out;
403
404 ret = snd_soc_link_compr_set_params(cstream);
405 if (ret < 0)
406 goto out;
407 snd_soc_dpcm_mutex_lock(fe);
408 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
409 snd_soc_dpcm_mutex_unlock(fe);
410 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
411
412out:
413 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
414 snd_soc_card_mutex_unlock(fe->card);
415 return ret;
416}
417
418static int soc_compr_get_params(struct snd_compr_stream *cstream,
419 struct snd_codec *params)
420{
421 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
422 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
423 int ret = 0;
424
425 snd_soc_dpcm_mutex_lock(rtd);
426
427 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
428 if (ret < 0)
429 goto err;
430
431 ret = snd_soc_component_compr_get_params(cstream, params);
432err:
433 snd_soc_dpcm_mutex_unlock(rtd);
434 return ret;
435}
436
437static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
438{
439 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
440 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
441 int ret;
442
443 snd_soc_dpcm_mutex_lock(rtd);
444
445 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
446 if (ret < 0)
447 goto err;
448
449 ret = snd_soc_component_compr_ack(cstream, bytes);
450err:
451 snd_soc_dpcm_mutex_unlock(rtd);
452 return ret;
453}
454
455static int soc_compr_pointer(struct snd_compr_stream *cstream,
456 struct snd_compr_tstamp *tstamp)
457{
458 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
459 int ret;
460 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
461
462 snd_soc_dpcm_mutex_lock(rtd);
463
464 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
465 if (ret < 0)
466 goto out;
467
468 ret = snd_soc_component_compr_pointer(cstream, tstamp);
469out:
470 snd_soc_dpcm_mutex_unlock(rtd);
471 return ret;
472}
473
474static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
475 struct snd_compr_metadata *metadata)
476{
477 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
478 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
479 int ret;
480
481 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
482 if (ret < 0)
483 return ret;
484
485 return snd_soc_component_compr_set_metadata(cstream, metadata);
486}
487
488static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
489 struct snd_compr_metadata *metadata)
490{
491 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
492 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
493 int ret;
494
495 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
496 if (ret < 0)
497 return ret;
498
499 return snd_soc_component_compr_get_metadata(cstream, metadata);
500}
501
502/* ASoC Compress operations */
503static struct snd_compr_ops soc_compr_ops = {
504 .open = soc_compr_open,
505 .free = soc_compr_free,
506 .set_params = soc_compr_set_params,
507 .set_metadata = soc_compr_set_metadata,
508 .get_metadata = soc_compr_get_metadata,
509 .get_params = soc_compr_get_params,
510 .trigger = soc_compr_trigger,
511 .pointer = soc_compr_pointer,
512 .ack = soc_compr_ack,
513 .get_caps = snd_soc_component_compr_get_caps,
514 .get_codec_caps = snd_soc_component_compr_get_codec_caps,
515};
516
517/* ASoC Dynamic Compress operations */
518static struct snd_compr_ops soc_compr_dyn_ops = {
519 .open = soc_compr_open_fe,
520 .free = soc_compr_free_fe,
521 .set_params = soc_compr_set_params_fe,
522 .get_params = soc_compr_get_params,
523 .set_metadata = soc_compr_set_metadata,
524 .get_metadata = soc_compr_get_metadata,
525 .trigger = soc_compr_trigger_fe,
526 .pointer = soc_compr_pointer,
527 .ack = soc_compr_ack,
528 .get_caps = snd_soc_component_compr_get_caps,
529 .get_codec_caps = snd_soc_component_compr_get_codec_caps,
530};
531
532/**
533 * snd_soc_new_compress - create a new compress.
534 *
535 * @rtd: The runtime for which we will create compress
536 * @num: the device index number (zero based - shared with normal PCMs)
537 *
538 * Return: 0 for success, else error.
539 */
540int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
541{
542 struct snd_soc_component *component;
543 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
544 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
545 struct snd_compr *compr;
546 struct snd_pcm *be_pcm;
547 char new_name[64];
548 int ret = 0, direction = 0;
549 int playback = 0, capture = 0;
550 int i;
551
552 /*
553 * make sure these are same value,
554 * and then use these as equally
555 */
556 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK);
557 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE != (int)SND_COMPRESS_CAPTURE);
558
559 if (rtd->dai_link->num_cpus > 1 ||
560 rtd->dai_link->num_codecs > 1) {
561 dev_err(rtd->card->dev,
562 "Compress ASoC: Multi CPU/Codec not supported\n");
563 return -EINVAL;
564 }
565
566 if (!codec_dai) {
567 dev_err(rtd->card->dev, "Missing codec\n");
568 return -EINVAL;
569 }
570
571 /* check client and interface hw capabilities */
572 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
573 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
574 playback = 1;
575 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
576 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
577 capture = 1;
578
579 /*
580 * Compress devices are unidirectional so only one of the directions
581 * should be set, check for that (xor)
582 */
583 if (playback + capture != 1) {
584 dev_err(rtd->card->dev,
585 "Compress ASoC: Invalid direction for P %d, C %d\n",
586 playback, capture);
587 return -EINVAL;
588 }
589
590 if (playback)
591 direction = SND_COMPRESS_PLAYBACK;
592 else
593 direction = SND_COMPRESS_CAPTURE;
594
595 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
596 if (!compr)
597 return -ENOMEM;
598
599 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
600 GFP_KERNEL);
601 if (!compr->ops)
602 return -ENOMEM;
603
604 if (rtd->dai_link->dynamic) {
605 snprintf(new_name, sizeof(new_name), "(%s)",
606 rtd->dai_link->stream_name);
607
608 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
609 rtd->dai_link->dpcm_playback,
610 rtd->dai_link->dpcm_capture, &be_pcm);
611 if (ret < 0) {
612 dev_err(rtd->card->dev,
613 "Compress ASoC: can't create compressed for %s: %d\n",
614 rtd->dai_link->name, ret);
615 return ret;
616 }
617
618 /* inherit atomicity from DAI link */
619 be_pcm->nonatomic = rtd->dai_link->nonatomic;
620
621 rtd->pcm = be_pcm;
622 rtd->fe_compr = 1;
623 if (rtd->dai_link->dpcm_playback)
624 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
625 if (rtd->dai_link->dpcm_capture)
626 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
627 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
628 } else {
629 snprintf(new_name, sizeof(new_name), "%s %s-%d",
630 rtd->dai_link->stream_name, codec_dai->name, num);
631
632 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
633 }
634
635 for_each_rtd_components(rtd, i, component) {
636 if (!component->driver->compress_ops ||
637 !component->driver->compress_ops->copy)
638 continue;
639
640 compr->ops->copy = snd_soc_component_compr_copy;
641 break;
642 }
643
644 ret = snd_compress_new(rtd->card->snd_card, num, direction,
645 new_name, compr);
646 if (ret < 0) {
647 component = snd_soc_rtd_to_codec(rtd, 0)->component;
648 dev_err(component->dev,
649 "Compress ASoC: can't create compress for codec %s: %d\n",
650 component->name, ret);
651 return ret;
652 }
653
654 /* DAPM dai link stream work */
655 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
656
657 rtd->compr = compr;
658 compr->private_data = rtd;
659
660 dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
661 codec_dai->name, cpu_dai->name);
662
663 return 0;
664}
665EXPORT_SYMBOL_GPL(snd_soc_new_compress);
1/*
2 * soc-compress.c -- ALSA SoC Compress
3 *
4 * Copyright (C) 2012 Intel Corp.
5 *
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>
9 *
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.
14 *
15 */
16
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>
28
29static int soc_compr_open(struct snd_compr_stream *cstream)
30{
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;
37
38 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
39
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;
47 }
48 }
49
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;
57 }
58 }
59
60 for_each_rtdcom(rtd, rtdcom) {
61 component = rtdcom->component;
62
63 /* ignore duplication for now */
64 if (platform && (component == &platform->component))
65 continue;
66
67 if (!component->driver->compr_ops ||
68 !component->driver->compr_ops->open)
69 continue;
70
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;
77 }
78 }
79 if (ret < 0)
80 goto machine_err;
81
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;
89 }
90 }
91
92 snd_soc_runtime_activate(rtd, cstream->direction);
93
94 mutex_unlock(&rtd->pcm_mutex);
95
96 return 0;
97
98machine_err:
99 for_each_rtdcom(rtd, rtdcom) {
100 component = rtdcom->component;
101
102 /* ignore duplication for now */
103 if (platform && (component == &platform->component))
104 continue;
105
106 if (!component->driver->compr_ops ||
107 !component->driver->compr_ops->free)
108 continue;
109
110 component->driver->compr_ops->free(cstream);
111 }
112
113 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
114 platform->driver->compr_ops->free(cstream);
115plat_err:
116 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
117 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
118out:
119 mutex_unlock(&rtd->pcm_mutex);
120 return ret;
121}
122
123static int soc_compr_open_fe(struct snd_compr_stream *cstream)
124{
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;
136
137 if (cstream->direction == SND_COMPRESS_PLAYBACK)
138 stream = SNDRV_PCM_STREAM_PLAYBACK;
139 else
140 stream = SNDRV_PCM_STREAM_CAPTURE;
141
142 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
143
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;
151 }
152 }
153
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;
161 }
162 }
163
164 for_each_rtdcom(fe, rtdcom) {
165 component = rtdcom->component;
166
167 /* ignore duplication for now */
168 if (platform && (component == &platform->component))
169 continue;
170
171 if (!component->driver->compr_ops ||
172 !component->driver->compr_ops->open)
173 continue;
174
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;
181 }
182 }
183 if (ret < 0)
184 goto machine_err;
185
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;
192 }
193 }
194
195 fe->dpcm[stream].runtime = fe_substream->runtime;
196
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");
203
204 /* calculate valid and active FE <-> BE dpcms */
205 dpcm_process_paths(fe, stream, &list, 1);
206
207 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
208
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;
214
215 dpcm_be_disconnect(fe, stream);
216 fe->dpcm[stream].runtime = NULL;
217 goto path_err;
218 }
219
220 dpcm_clear_pending_state(fe, stream);
221 dpcm_path_put(&list);
222
223 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
224 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
225
226 snd_soc_runtime_activate(fe, stream);
227
228 mutex_unlock(&fe->card->mutex);
229
230 return 0;
231
232path_err:
233 dpcm_path_put(&list);
234fe_err:
235 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
236 fe->dai_link->compr_ops->shutdown(cstream);
237machine_err:
238 for_each_rtdcom(fe, rtdcom) {
239 component = rtdcom->component;
240
241 /* ignore duplication for now */
242 if (platform && (component == &platform->component))
243 continue;
244
245 if (!component->driver->compr_ops ||
246 !component->driver->compr_ops->free)
247 continue;
248
249 component->driver->compr_ops->free(cstream);
250 }
251
252 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
253 platform->driver->compr_ops->free(cstream);
254plat_err:
255 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
256 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
257out:
258 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
259 mutex_unlock(&fe->card->mutex);
260 return ret;
261}
262
263/*
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.
267 */
268static void close_delayed_work(struct work_struct *work)
269{
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;
273
274 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
275
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");
281
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);
287 }
288
289 mutex_unlock(&rtd->pcm_mutex);
290}
291
292static int soc_compr_free(struct snd_compr_stream *cstream)
293{
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;
301
302 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
303
304 if (cstream->direction == SND_COMPRESS_PLAYBACK)
305 stream = SNDRV_PCM_STREAM_PLAYBACK;
306 else
307 stream = SNDRV_PCM_STREAM_CAPTURE;
308
309 snd_soc_runtime_deactivate(rtd, stream);
310
311 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
312
313 if (!cpu_dai->active)
314 cpu_dai->rate = 0;
315
316 if (!codec_dai->active)
317 codec_dai->rate = 0;
318
319 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
320 rtd->dai_link->compr_ops->shutdown(cstream);
321
322 for_each_rtdcom(rtd, rtdcom) {
323 component = rtdcom->component;
324
325 /* ignore duplication for now */
326 if (platform && (component == &platform->component))
327 continue;
328
329 if (!component->driver->compr_ops ||
330 !component->driver->compr_ops->free)
331 continue;
332
333 component->driver->compr_ops->free(cstream);
334 }
335
336 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
337 platform->driver->compr_ops->free(cstream);
338
339 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
340 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
341
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));
352 }
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);
358 }
359
360 mutex_unlock(&rtd->pcm_mutex);
361 return 0;
362}
363
364static int soc_compr_free_fe(struct snd_compr_stream *cstream)
365{
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;
373
374 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
375
376 if (cstream->direction == SND_COMPRESS_PLAYBACK)
377 stream = SNDRV_PCM_STREAM_PLAYBACK;
378 else
379 stream = SNDRV_PCM_STREAM_CAPTURE;
380
381 snd_soc_runtime_deactivate(fe, stream);
382
383 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
384
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);
388
389 ret = dpcm_be_dai_shutdown(fe, stream);
390
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;
394
395 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
396
397 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
398 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
399
400 dpcm_be_disconnect(fe, stream);
401
402 fe->dpcm[stream].runtime = NULL;
403
404 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
405 fe->dai_link->compr_ops->shutdown(cstream);
406
407 if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
408 platform->driver->compr_ops->free(cstream);
409
410 for_each_rtdcom(fe, rtdcom) {
411 component = rtdcom->component;
412
413 /* ignore duplication for now */
414 if (platform && (component == &platform->component))
415 continue;
416
417 if (!component->driver->compr_ops ||
418 !component->driver->compr_ops->free)
419 continue;
420
421 component->driver->compr_ops->free(cstream);
422 }
423
424 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
425 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
426
427 mutex_unlock(&fe->card->mutex);
428 return 0;
429}
430
431static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
432{
433
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;
441
442 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
443
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;
448 }
449
450 for_each_rtdcom(rtd, rtdcom) {
451 component = rtdcom->component;
452
453 /* ignore duplication for now */
454 if (platform && (component == &platform->component))
455 continue;
456
457 if (!component->driver->compr_ops ||
458 !component->driver->compr_ops->trigger)
459 continue;
460
461 __ret = component->driver->compr_ops->trigger(cstream, cmd);
462 if (__ret < 0)
463 ret = __ret;
464 }
465 if (ret < 0)
466 goto out;
467
468 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
469 cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
470
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;
478 }
479
480out:
481 mutex_unlock(&rtd->pcm_mutex);
482 return ret;
483}
484
485static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
486{
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;
493
494 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
495 cmd == SND_COMPR_TRIGGER_DRAIN) {
496
497 if (platform &&
498 platform->driver->compr_ops &&
499 platform->driver->compr_ops->trigger)
500 return platform->driver->compr_ops->trigger(cstream,
501 cmd);
502
503 for_each_rtdcom(fe, rtdcom) {
504 component = rtdcom->component;
505
506 /* ignore duplication for now */
507 if (platform && (component == &platform->component))
508 continue;
509
510 if (!component->driver->compr_ops ||
511 !component->driver->compr_ops->trigger)
512 continue;
513
514 __ret = component->driver->compr_ops->trigger(cstream, cmd);
515 if (__ret < 0)
516 ret = __ret;
517 }
518 return ret;
519 }
520
521 if (cstream->direction == SND_COMPRESS_PLAYBACK)
522 stream = SNDRV_PCM_STREAM_PLAYBACK;
523 else
524 stream = SNDRV_PCM_STREAM_CAPTURE;
525
526
527 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
528
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;
533 }
534
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;
539 }
540
541 for_each_rtdcom(fe, rtdcom) {
542 component = rtdcom->component;
543
544 /* ignore duplication for now */
545 if (platform && (component == &platform->component))
546 continue;
547
548 if (!component->driver->compr_ops ||
549 !component->driver->compr_ops->trigger)
550 continue;
551
552 __ret = component->driver->compr_ops->trigger(cstream, cmd);
553 if (__ret < 0)
554 ret = __ret;
555 }
556 if (ret < 0)
557 goto out;
558
559 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
560
561 ret = dpcm_be_dai_trigger(fe, stream, cmd);
562
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;
576 }
577
578out:
579 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
580 mutex_unlock(&fe->card->mutex);
581 return ret;
582}
583
584static int soc_compr_set_params(struct snd_compr_stream *cstream,
585 struct snd_compr_params *params)
586{
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;
593
594 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
595
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
601 */
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;
606 }
607
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;
612 }
613
614 for_each_rtdcom(rtd, rtdcom) {
615 component = rtdcom->component;
616
617 /* ignore duplication for now */
618 if (platform && (component == &platform->component))
619 continue;
620
621 if (!component->driver->compr_ops ||
622 !component->driver->compr_ops->set_params)
623 continue;
624
625 __ret = component->driver->compr_ops->set_params(cstream, params);
626 if (__ret < 0)
627 ret = __ret;
628 }
629 if (ret < 0)
630 goto err;
631
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;
636 }
637
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);
644
645 /* cancel any delayed stream shutdown that is pending */
646 rtd->pop_wait = 0;
647 mutex_unlock(&rtd->pcm_mutex);
648
649 cancel_delayed_work_sync(&rtd->delayed_work);
650
651 return ret;
652
653err:
654 mutex_unlock(&rtd->pcm_mutex);
655 return ret;
656}
657
658static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
659 struct snd_compr_params *params)
660{
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;
669
670 if (cstream->direction == SND_COMPRESS_PLAYBACK)
671 stream = SNDRV_PCM_STREAM_PLAYBACK;
672 else
673 stream = SNDRV_PCM_STREAM_CAPTURE;
674
675 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
676
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;
681 }
682
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;
687 }
688
689 for_each_rtdcom(fe, rtdcom) {
690 component = rtdcom->component;
691
692 /* ignore duplication for now */
693 if (platform && (component == &platform->component))
694 continue;
695
696 if (!component->driver->compr_ops ||
697 !component->driver->compr_ops->set_params)
698 continue;
699
700 __ret = component->driver->compr_ops->set_params(cstream, params);
701 if (__ret < 0)
702 ret = __ret;
703 }
704 if (ret < 0)
705 goto out;
706
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;
711 }
712
713 /*
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.
717 */
718 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
719 sizeof(struct snd_pcm_hw_params));
720
721 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
722
723 ret = dpcm_be_dai_hw_params(fe, stream);
724 if (ret < 0)
725 goto out;
726
727 ret = dpcm_be_dai_prepare(fe, stream);
728 if (ret < 0)
729 goto out;
730
731 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
732 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
733
734out:
735 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
736 mutex_unlock(&fe->card->mutex);
737 return ret;
738}
739
740static int soc_compr_get_params(struct snd_compr_stream *cstream,
741 struct snd_codec *params)
742{
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;
749
750 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
751
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;
756 }
757
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;
762 }
763
764 for_each_rtdcom(rtd, rtdcom) {
765 component = rtdcom->component;
766
767 /* ignore duplication for now */
768 if (platform && (component == &platform->component))
769 continue;
770
771 if (!component->driver->compr_ops ||
772 !component->driver->compr_ops->get_params)
773 continue;
774
775 __ret = component->driver->compr_ops->get_params(cstream, params);
776 if (__ret < 0)
777 ret = __ret;
778 }
779
780err:
781 mutex_unlock(&rtd->pcm_mutex);
782 return ret;
783}
784
785static int soc_compr_get_caps(struct snd_compr_stream *cstream,
786 struct snd_compr_caps *caps)
787{
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;
793
794 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
795
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;
800 }
801
802 for_each_rtdcom(rtd, rtdcom) {
803 component = rtdcom->component;
804
805 /* ignore duplication for now */
806 if (platform && (component == &platform->component))
807 continue;
808
809 if (!component->driver->compr_ops ||
810 !component->driver->compr_ops->get_caps)
811 continue;
812
813 __ret = component->driver->compr_ops->get_caps(cstream, caps);
814 if (__ret < 0)
815 ret = __ret;
816 }
817
818err:
819 mutex_unlock(&rtd->pcm_mutex);
820 return ret;
821}
822
823static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
824 struct snd_compr_codec_caps *codec)
825{
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;
831
832 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
833
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;
838 }
839
840 for_each_rtdcom(rtd, rtdcom) {
841 component = rtdcom->component;
842
843 /* ignore duplication for now */
844 if (platform && (component == &platform->component))
845 continue;
846
847 if (!component->driver->compr_ops ||
848 !component->driver->compr_ops->get_codec_caps)
849 continue;
850
851 __ret = component->driver->compr_ops->get_codec_caps(cstream, codec);
852 if (__ret < 0)
853 ret = __ret;
854 }
855
856err:
857 mutex_unlock(&rtd->pcm_mutex);
858 return ret;
859}
860
861static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
862{
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;
869
870 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
871
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;
876 }
877
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;
882 }
883
884 for_each_rtdcom(rtd, rtdcom) {
885 component = rtdcom->component;
886
887 /* ignore duplication for now */
888 if (platform && (component == &platform->component))
889 continue;
890
891 if (!component->driver->compr_ops ||
892 !component->driver->compr_ops->ack)
893 continue;
894
895 __ret = component->driver->compr_ops->ack(cstream, bytes);
896 if (__ret < 0)
897 ret = __ret;
898 }
899
900err:
901 mutex_unlock(&rtd->pcm_mutex);
902 return ret;
903}
904
905static int soc_compr_pointer(struct snd_compr_stream *cstream,
906 struct snd_compr_tstamp *tstamp)
907{
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;
914
915 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
916
917 if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
918 cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
919
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;
924 }
925
926 for_each_rtdcom(rtd, rtdcom) {
927 component = rtdcom->component;
928
929 /* ignore duplication for now */
930 if (platform && (component == &platform->component))
931 continue;
932
933 if (!component->driver->compr_ops ||
934 !component->driver->compr_ops->pointer)
935 continue;
936
937 __ret = component->driver->compr_ops->pointer(cstream, tstamp);
938 if (__ret < 0)
939 ret = __ret;
940 }
941
942err:
943 mutex_unlock(&rtd->pcm_mutex);
944 return ret;
945}
946
947static int soc_compr_copy(struct snd_compr_stream *cstream,
948 char __user *buf, size_t count)
949{
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;
955
956 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
957
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;
962 }
963
964 for_each_rtdcom(rtd, rtdcom) {
965 component = rtdcom->component;
966
967 /* ignore duplication for now */
968 if (platform && (component == &platform->component))
969 continue;
970
971 if (!component->driver->compr_ops ||
972 !component->driver->compr_ops->copy)
973 continue;
974
975 ret = component->driver->compr_ops->copy(cstream, buf, count);
976 break;
977 }
978
979err:
980 mutex_unlock(&rtd->pcm_mutex);
981 return ret;
982}
983
984static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
985 struct snd_compr_metadata *metadata)
986{
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;
993
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;
998 }
999
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;
1004 }
1005
1006 for_each_rtdcom(rtd, rtdcom) {
1007 component = rtdcom->component;
1008
1009 /* ignore duplication for now */
1010 if (platform && (component == &platform->component))
1011 continue;
1012
1013 if (!component->driver->compr_ops ||
1014 !component->driver->compr_ops->set_metadata)
1015 continue;
1016
1017 __ret = component->driver->compr_ops->set_metadata(cstream, metadata);
1018 if (__ret < 0)
1019 ret = __ret;
1020 }
1021
1022 return ret;
1023}
1024
1025static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
1026 struct snd_compr_metadata *metadata)
1027{
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;
1034
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;
1039 }
1040
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;
1045 }
1046
1047 for_each_rtdcom(rtd, rtdcom) {
1048 component = rtdcom->component;
1049
1050 /* ignore duplication for now */
1051 if (platform && (component == &platform->component))
1052 continue;
1053
1054 if (!component->driver->compr_ops ||
1055 !component->driver->compr_ops->get_metadata)
1056 continue;
1057
1058 __ret = component->driver->compr_ops->get_metadata(cstream, metadata);
1059 if (__ret < 0)
1060 ret = __ret;
1061 }
1062
1063 return ret;
1064}
1065
1066/* ASoC Compress operations */
1067static 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
1079};
1080
1081/* ASoC Dynamic Compress operations */
1082static 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
1094};
1095
1096/**
1097 * snd_soc_new_compress - create a new compress.
1098 *
1099 * @rtd: The runtime for which we will create compress
1100 * @num: the device index number (zero based - shared with normal PCMs)
1101 *
1102 * Return: 0 for success, else error.
1103 */
1104int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
1105{
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;
1116
1117 if (rtd->num_codecs > 1) {
1118 dev_err(rtd->card->dev,
1119 "Compress ASoC: Multicodec not supported\n");
1120 return -EINVAL;
1121 }
1122
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;
1128
1129 capture = capture && cpu_dai->driver->capture.channels_min;
1130 playback = playback && cpu_dai->driver->playback.channels_min;
1131
1132 /*
1133 * Compress devices are unidirectional so only one of the directions
1134 * should be set, check for that (xor)
1135 */
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;
1141 }
1142
1143 if (playback)
1144 direction = SND_COMPRESS_PLAYBACK;
1145 else
1146 direction = SND_COMPRESS_CAPTURE;
1147
1148 compr = kzalloc(sizeof(*compr), GFP_KERNEL);
1149 if (!compr)
1150 return -ENOMEM;
1151
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;
1157 }
1158
1159 if (rtd->dai_link->dynamic) {
1160 snprintf(new_name, sizeof(new_name), "(%s)",
1161 rtd->dai_link->stream_name);
1162
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;
1171 }
1172
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);
1183
1184 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
1185 }
1186
1187
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;
1191
1192 for_each_rtdcom(rtd, rtdcom) {
1193 component = rtdcom->component;
1194
1195 /* ignore duplication for now */
1196 if (platform && (component == &platform->component))
1197 continue;
1198
1199 if (!component->driver->compr_ops ||
1200 !component->driver->compr_ops->copy)
1201 continue;
1202
1203 compr->ops->copy = soc_compr_copy;
1204 }
1205
1206
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;
1216 }
1217
1218 /* DAPM dai link stream work */
1219 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
1220
1221 rtd->compr = compr;
1222 compr->private_data = rtd;
1223
1224 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
1225 codec_dai->name, cpu_dai->name);
1226 return ret;
1227
1228compr_err:
1229 kfree(compr);
1230 return ret;
1231}
1232EXPORT_SYMBOL_GPL(snd_soc_new_compress);