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