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