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