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