ASoC: soc-component: add snd_soc_component_compr_set_params()
[linux-2.6-microblaze.git] / sound / soc / soc-compress.c
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 #include <linux/pm_runtime.h>
24
25 static int soc_compr_open(struct snd_compr_stream *cstream)
26 {
27         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
28         struct snd_soc_component *component = NULL;
29         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
30         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
31         int ret;
32
33         ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream);
34         if (ret < 0)
35                 goto pm_err;
36
37         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
38
39         ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
40         if (ret < 0)
41                 goto out;
42
43         ret = snd_soc_component_compr_open(cstream, &component);
44         if (ret < 0)
45                 goto machine_err;
46
47         ret = snd_soc_link_compr_startup(cstream);
48         if (ret < 0)
49                 goto machine_err;
50
51         snd_soc_runtime_activate(rtd, stream);
52
53         mutex_unlock(&rtd->card->pcm_mutex);
54
55         return 0;
56
57 machine_err:
58         snd_soc_component_compr_free(cstream, component);
59
60         snd_soc_dai_compr_shutdown(cpu_dai, cstream);
61 out:
62         mutex_unlock(&rtd->card->pcm_mutex);
63 pm_err:
64         snd_soc_pcm_component_pm_runtime_put(rtd, cstream, 1);
65
66         return ret;
67 }
68
69 static int soc_compr_open_fe(struct snd_compr_stream *cstream)
70 {
71         struct snd_soc_pcm_runtime *fe = cstream->private_data;
72         struct snd_pcm_substream *fe_substream =
73                  fe->pcm->streams[cstream->direction].substream;
74         struct snd_soc_component *component;
75         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
76         struct snd_soc_dpcm *dpcm;
77         struct snd_soc_dapm_widget_list *list;
78         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
79         int ret;
80
81         mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
82         fe->dpcm[stream].runtime = fe_substream->runtime;
83
84         ret = dpcm_path_get(fe, stream, &list);
85         if (ret < 0)
86                 goto be_err;
87         else if (ret == 0)
88                 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
89                         fe->dai_link->name, stream ? "capture" : "playback");
90         /* calculate valid and active FE <-> BE dpcms */
91         dpcm_process_paths(fe, stream, &list, 1);
92         fe->dpcm[stream].runtime = fe_substream->runtime;
93
94         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
95
96         ret = dpcm_be_dai_startup(fe, stream);
97         if (ret < 0) {
98                 /* clean up all links */
99                 for_each_dpcm_be(fe, stream, dpcm)
100                         dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
101
102                 dpcm_be_disconnect(fe, stream);
103                 fe->dpcm[stream].runtime = NULL;
104                 goto out;
105         }
106
107         ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
108         if (ret < 0)
109                 goto out;
110
111         ret = snd_soc_component_compr_open(cstream, &component);
112         if (ret < 0)
113                 goto open_err;
114
115         ret = snd_soc_link_compr_startup(cstream);
116         if (ret < 0)
117                 goto machine_err;
118
119         dpcm_clear_pending_state(fe, stream);
120         dpcm_path_put(&list);
121
122         fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
123         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
124
125         snd_soc_runtime_activate(fe, stream);
126
127         mutex_unlock(&fe->card->mutex);
128
129         return 0;
130
131 machine_err:
132         snd_soc_component_compr_free(cstream, component);
133 open_err:
134         snd_soc_dai_compr_shutdown(cpu_dai, cstream);
135 out:
136         dpcm_path_put(&list);
137 be_err:
138         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
139         mutex_unlock(&fe->card->mutex);
140         return ret;
141 }
142
143 static int soc_compr_free(struct snd_compr_stream *cstream)
144 {
145         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
146         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
147         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
148         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
149
150         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
151
152         snd_soc_runtime_deactivate(rtd, stream);
153
154         snd_soc_dai_digital_mute(codec_dai, 1, stream);
155
156         if (!snd_soc_dai_active(cpu_dai))
157                 cpu_dai->rate = 0;
158
159         if (!snd_soc_dai_active(codec_dai))
160                 codec_dai->rate = 0;
161
162         snd_soc_link_compr_shutdown(cstream);
163
164         snd_soc_component_compr_free(cstream, NULL);
165
166         snd_soc_dai_compr_shutdown(cpu_dai, cstream);
167
168         snd_soc_dapm_stream_stop(rtd, stream);
169
170         mutex_unlock(&rtd->card->pcm_mutex);
171
172         snd_soc_pcm_component_pm_runtime_put(rtd, cstream, 0);
173
174         return 0;
175 }
176
177 static int soc_compr_free_fe(struct snd_compr_stream *cstream)
178 {
179         struct snd_soc_pcm_runtime *fe = cstream->private_data;
180         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
181         struct snd_soc_dpcm *dpcm;
182         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
183         int ret;
184
185         mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
186
187         snd_soc_runtime_deactivate(fe, stream);
188
189         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
190
191         ret = dpcm_be_dai_hw_free(fe, stream);
192         if (ret < 0)
193                 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
194
195         ret = dpcm_be_dai_shutdown(fe, stream);
196
197         /* mark FE's links ready to prune */
198         for_each_dpcm_be(fe, stream, dpcm)
199                 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
200
201         dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
202
203         fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
204         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
205
206         dpcm_be_disconnect(fe, stream);
207
208         fe->dpcm[stream].runtime = NULL;
209
210         snd_soc_link_compr_shutdown(cstream);
211
212         snd_soc_component_compr_free(cstream, NULL);
213
214         snd_soc_dai_compr_shutdown(cpu_dai, cstream);
215
216         mutex_unlock(&fe->card->mutex);
217         return 0;
218 }
219
220 static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
221 {
222         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
223         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
224         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
225         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
226         int ret;
227
228         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
229
230         ret = snd_soc_component_compr_trigger(cstream, cmd);
231         if (ret < 0)
232                 goto out;
233
234         ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
235         if (ret < 0)
236                 goto out;
237
238         switch (cmd) {
239         case SNDRV_PCM_TRIGGER_START:
240                 snd_soc_dai_digital_mute(codec_dai, 0, stream);
241                 break;
242         case SNDRV_PCM_TRIGGER_STOP:
243                 snd_soc_dai_digital_mute(codec_dai, 1, stream);
244                 break;
245         }
246
247 out:
248         mutex_unlock(&rtd->card->pcm_mutex);
249         return ret;
250 }
251
252 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
253 {
254         struct snd_soc_pcm_runtime *fe = cstream->private_data;
255         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
256         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
257         int ret;
258
259         if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
260             cmd == SND_COMPR_TRIGGER_DRAIN)
261                 return snd_soc_component_compr_trigger(cstream, cmd);
262
263         mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
264
265         ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
266         if (ret < 0)
267                 goto out;
268
269         ret = snd_soc_component_compr_trigger(cstream, cmd);
270         if (ret < 0)
271                 goto out;
272
273         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
274
275         ret = dpcm_be_dai_trigger(fe, stream, cmd);
276
277         switch (cmd) {
278         case SNDRV_PCM_TRIGGER_START:
279         case SNDRV_PCM_TRIGGER_RESUME:
280         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
281                 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
282                 break;
283         case SNDRV_PCM_TRIGGER_STOP:
284         case SNDRV_PCM_TRIGGER_SUSPEND:
285                 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
286                 break;
287         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
288                 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
289                 break;
290         }
291
292 out:
293         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
294         mutex_unlock(&fe->card->mutex);
295         return ret;
296 }
297
298 static int soc_compr_set_params(struct snd_compr_stream *cstream,
299                                 struct snd_compr_params *params)
300 {
301         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
302         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
303         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
304         int ret;
305
306         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
307
308         /*
309          * First we call set_params for the CPU DAI, then the component
310          * driver this should configure the SoC side. If the machine has
311          * compressed ops then we call that as well. The expectation is
312          * that these callbacks will configure everything for this compress
313          * path, like configuring a PCM port for a CODEC.
314          */
315         ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
316         if (ret < 0)
317                 goto err;
318
319         ret = snd_soc_component_compr_set_params(cstream, params);
320         if (ret < 0)
321                 goto err;
322
323         ret = snd_soc_link_compr_set_params(cstream);
324         if (ret < 0)
325                 goto err;
326
327         snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START);
328
329         /* cancel any delayed stream shutdown that is pending */
330         rtd->pop_wait = 0;
331         mutex_unlock(&rtd->card->pcm_mutex);
332
333         cancel_delayed_work_sync(&rtd->delayed_work);
334
335         return 0;
336
337 err:
338         mutex_unlock(&rtd->card->pcm_mutex);
339         return ret;
340 }
341
342 static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
343                                    struct snd_compr_params *params)
344 {
345         struct snd_soc_pcm_runtime *fe = cstream->private_data;
346         struct snd_pcm_substream *fe_substream =
347                  fe->pcm->streams[cstream->direction].substream;
348         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
349         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
350         int ret;
351
352         mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
353
354         /*
355          * Create an empty hw_params for the BE as the machine driver must
356          * fix this up to match DSP decoder and ASRC configuration.
357          * I.e. machine driver fixup for compressed BE is mandatory.
358          */
359         memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
360                 sizeof(struct snd_pcm_hw_params));
361
362         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
363
364         ret = dpcm_be_dai_hw_params(fe, stream);
365         if (ret < 0)
366                 goto out;
367
368         ret = dpcm_be_dai_prepare(fe, stream);
369         if (ret < 0)
370                 goto out;
371
372         ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
373         if (ret < 0)
374                 goto out;
375
376         ret = snd_soc_component_compr_set_params(cstream, params);
377         if (ret < 0)
378                 goto out;
379
380         ret = snd_soc_link_compr_set_params(cstream);
381         if (ret < 0)
382                 goto out;
383
384         dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
385         fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
386
387 out:
388         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
389         mutex_unlock(&fe->card->mutex);
390         return ret;
391 }
392
393 static int soc_compr_get_params(struct snd_compr_stream *cstream,
394                                 struct snd_codec *params)
395 {
396         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
397         struct snd_soc_component *component;
398         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
399         int i, ret = 0;
400
401         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
402
403         ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
404         if (ret < 0)
405                 goto err;
406
407         for_each_rtd_components(rtd, i, component) {
408                 if (!component->driver->compress_ops ||
409                     !component->driver->compress_ops->get_params)
410                         continue;
411
412                 ret = component->driver->compress_ops->get_params(
413                         component, cstream, params);
414                 break;
415         }
416
417 err:
418         mutex_unlock(&rtd->card->pcm_mutex);
419         return ret;
420 }
421
422 static int soc_compr_get_caps(struct snd_compr_stream *cstream,
423                               struct snd_compr_caps *caps)
424 {
425         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
426         struct snd_soc_component *component;
427         int i, ret = 0;
428
429         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
430
431         for_each_rtd_components(rtd, i, component) {
432                 if (!component->driver->compress_ops ||
433                     !component->driver->compress_ops->get_caps)
434                         continue;
435
436                 ret = component->driver->compress_ops->get_caps(
437                         component, cstream, caps);
438                 break;
439         }
440
441         mutex_unlock(&rtd->card->pcm_mutex);
442         return ret;
443 }
444
445 static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
446                                     struct snd_compr_codec_caps *codec)
447 {
448         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
449         struct snd_soc_component *component;
450         int i, ret = 0;
451
452         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
453
454         for_each_rtd_components(rtd, i, component) {
455                 if (!component->driver->compress_ops ||
456                     !component->driver->compress_ops->get_codec_caps)
457                         continue;
458
459                 ret = component->driver->compress_ops->get_codec_caps(
460                         component, cstream, codec);
461                 break;
462         }
463
464         mutex_unlock(&rtd->card->pcm_mutex);
465         return ret;
466 }
467
468 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
469 {
470         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
471         struct snd_soc_component *component;
472         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
473         int i, ret = 0;
474
475         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
476
477         ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
478         if (ret < 0)
479                 goto err;
480
481         for_each_rtd_components(rtd, i, component) {
482                 if (!component->driver->compress_ops ||
483                     !component->driver->compress_ops->ack)
484                         continue;
485
486                 ret = component->driver->compress_ops->ack(
487                         component, cstream, bytes);
488                 if (ret < 0)
489                         goto err;
490         }
491
492 err:
493         mutex_unlock(&rtd->card->pcm_mutex);
494         return ret;
495 }
496
497 static int soc_compr_pointer(struct snd_compr_stream *cstream,
498                              struct snd_compr_tstamp *tstamp)
499 {
500         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
501         struct snd_soc_component *component;
502         int i, ret = 0;
503         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
504
505         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
506
507         ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
508         if (ret < 0)
509                 goto out;
510
511         for_each_rtd_components(rtd, i, component) {
512                 if (!component->driver->compress_ops ||
513                     !component->driver->compress_ops->pointer)
514                         continue;
515
516                 ret = component->driver->compress_ops->pointer(
517                         component, cstream, tstamp);
518                 break;
519         }
520 out:
521         mutex_unlock(&rtd->card->pcm_mutex);
522         return ret;
523 }
524
525 static int soc_compr_copy(struct snd_compr_stream *cstream,
526                           char __user *buf, size_t count)
527 {
528         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
529         struct snd_soc_component *component;
530         int i, ret = 0;
531
532         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
533
534         for_each_rtd_components(rtd, i, component) {
535                 if (!component->driver->compress_ops ||
536                     !component->driver->compress_ops->copy)
537                         continue;
538
539                 ret = component->driver->compress_ops->copy(
540                         component, cstream, buf, count);
541                 break;
542         }
543
544         mutex_unlock(&rtd->card->pcm_mutex);
545         return ret;
546 }
547
548 static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
549                                   struct snd_compr_metadata *metadata)
550 {
551         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
552         struct snd_soc_component *component;
553         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
554         int i, ret;
555
556         ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
557         if (ret < 0)
558                 return ret;
559
560         for_each_rtd_components(rtd, i, component) {
561                 if (!component->driver->compress_ops ||
562                     !component->driver->compress_ops->set_metadata)
563                         continue;
564
565                 ret = component->driver->compress_ops->set_metadata(
566                         component, cstream, metadata);
567                 if (ret < 0)
568                         return ret;
569         }
570
571         return 0;
572 }
573
574 static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
575                                   struct snd_compr_metadata *metadata)
576 {
577         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
578         struct snd_soc_component *component;
579         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
580         int i, ret;
581
582         ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
583         if (ret < 0)
584                 return ret;
585
586         for_each_rtd_components(rtd, i, component) {
587                 if (!component->driver->compress_ops ||
588                     !component->driver->compress_ops->get_metadata)
589                         continue;
590
591                 return component->driver->compress_ops->get_metadata(
592                         component, cstream, metadata);
593         }
594
595         return 0;
596 }
597
598 /* ASoC Compress operations */
599 static struct snd_compr_ops soc_compr_ops = {
600         .open           = soc_compr_open,
601         .free           = soc_compr_free,
602         .set_params     = soc_compr_set_params,
603         .set_metadata   = soc_compr_set_metadata,
604         .get_metadata   = soc_compr_get_metadata,
605         .get_params     = soc_compr_get_params,
606         .trigger        = soc_compr_trigger,
607         .pointer        = soc_compr_pointer,
608         .ack            = soc_compr_ack,
609         .get_caps       = soc_compr_get_caps,
610         .get_codec_caps = soc_compr_get_codec_caps
611 };
612
613 /* ASoC Dynamic Compress operations */
614 static struct snd_compr_ops soc_compr_dyn_ops = {
615         .open           = soc_compr_open_fe,
616         .free           = soc_compr_free_fe,
617         .set_params     = soc_compr_set_params_fe,
618         .get_params     = soc_compr_get_params,
619         .set_metadata   = soc_compr_set_metadata,
620         .get_metadata   = soc_compr_get_metadata,
621         .trigger        = soc_compr_trigger_fe,
622         .pointer        = soc_compr_pointer,
623         .ack            = soc_compr_ack,
624         .get_caps       = soc_compr_get_caps,
625         .get_codec_caps = soc_compr_get_codec_caps
626 };
627
628 /**
629  * snd_soc_new_compress - create a new compress.
630  *
631  * @rtd: The runtime for which we will create compress
632  * @num: the device index number (zero based - shared with normal PCMs)
633  *
634  * Return: 0 for success, else error.
635  */
636 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
637 {
638         struct snd_soc_component *component;
639         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
640         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
641         struct snd_compr *compr;
642         struct snd_pcm *be_pcm;
643         char new_name[64];
644         int ret = 0, direction = 0;
645         int playback = 0, capture = 0;
646         int i;
647
648         /*
649          * make sure these are same value,
650          * and then use these as equally
651          */
652         BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK);
653         BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE  != (int)SND_COMPRESS_CAPTURE);
654
655         if (rtd->num_cpus > 1 ||
656             rtd->num_codecs > 1) {
657                 dev_err(rtd->card->dev,
658                         "Compress ASoC: Multi CPU/Codec not supported\n");
659                 return -EINVAL;
660         }
661
662         /* check client and interface hw capabilities */
663         if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
664             snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
665                 playback = 1;
666         if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
667             snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
668                 capture = 1;
669
670         /*
671          * Compress devices are unidirectional so only one of the directions
672          * should be set, check for that (xor)
673          */
674         if (playback + capture != 1) {
675                 dev_err(rtd->card->dev,
676                         "Compress ASoC: Invalid direction for P %d, C %d\n",
677                         playback, capture);
678                 return -EINVAL;
679         }
680
681         if (playback)
682                 direction = SND_COMPRESS_PLAYBACK;
683         else
684                 direction = SND_COMPRESS_CAPTURE;
685
686         compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
687         if (!compr)
688                 return -ENOMEM;
689
690         compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
691                                   GFP_KERNEL);
692         if (!compr->ops)
693                 return -ENOMEM;
694
695         if (rtd->dai_link->dynamic) {
696                 snprintf(new_name, sizeof(new_name), "(%s)",
697                         rtd->dai_link->stream_name);
698
699                 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
700                                 rtd->dai_link->dpcm_playback,
701                                 rtd->dai_link->dpcm_capture, &be_pcm);
702                 if (ret < 0) {
703                         dev_err(rtd->card->dev,
704                                 "Compress ASoC: can't create compressed for %s: %d\n",
705                                 rtd->dai_link->name, ret);
706                         return ret;
707                 }
708
709                 rtd->pcm = be_pcm;
710                 rtd->fe_compr = 1;
711                 if (rtd->dai_link->dpcm_playback)
712                         be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
713                 else if (rtd->dai_link->dpcm_capture)
714                         be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
715                 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
716         } else {
717                 snprintf(new_name, sizeof(new_name), "%s %s-%d",
718                         rtd->dai_link->stream_name, codec_dai->name, num);
719
720                 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
721         }
722
723         for_each_rtd_components(rtd, i, component) {
724                 if (!component->driver->compress_ops ||
725                     !component->driver->compress_ops->copy)
726                         continue;
727
728                 compr->ops->copy = soc_compr_copy;
729                 break;
730         }
731
732         mutex_init(&compr->lock);
733         ret = snd_compress_new(rtd->card->snd_card, num, direction,
734                                 new_name, compr);
735         if (ret < 0) {
736                 component = asoc_rtd_to_codec(rtd, 0)->component;
737                 dev_err(component->dev,
738                         "Compress ASoC: can't create compress for codec %s: %d\n",
739                         component->name, ret);
740                 return ret;
741         }
742
743         /* DAPM dai link stream work */
744         rtd->close_delayed_work_func = snd_soc_close_delayed_work;
745
746         rtd->compr = compr;
747         compr->private_data = rtd;
748
749         dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
750                 codec_dai->name, cpu_dai->name);
751
752         return 0;
753 }
754 EXPORT_SYMBOL_GPL(snd_soc_new_compress);