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