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