Merge tag 'x86_seves_for_v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-starfive.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 #include <sound/soc-link.h>
23 #include <linux/pm_runtime.h>
24
25 static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback)
26 {
27         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
28         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
29         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
30         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
31
32         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
33
34         if (!rollback)
35                 snd_soc_runtime_deactivate(rtd, stream);
36
37         snd_soc_dai_digital_mute(codec_dai, 1, stream);
38
39         if (!snd_soc_dai_active(cpu_dai))
40                 cpu_dai->rate = 0;
41
42         if (!snd_soc_dai_active(codec_dai))
43                 codec_dai->rate = 0;
44
45         snd_soc_link_compr_shutdown(cstream, rollback);
46
47         snd_soc_component_compr_free(cstream, rollback);
48
49         snd_soc_dai_compr_shutdown(cpu_dai, cstream, rollback);
50
51         if (!rollback)
52                 snd_soc_dapm_stream_stop(rtd, stream);
53
54         mutex_unlock(&rtd->card->pcm_mutex);
55
56         snd_soc_pcm_component_pm_runtime_put(rtd, cstream, rollback);
57
58         return 0;
59 }
60
61 static int soc_compr_free(struct snd_compr_stream *cstream)
62 {
63         return soc_compr_clean(cstream, 0);
64 }
65
66 static int soc_compr_open(struct snd_compr_stream *cstream)
67 {
68         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
69         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
70         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
71         int ret;
72
73         ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream);
74         if (ret < 0)
75                 goto err_no_lock;
76
77         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
78
79         ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
80         if (ret < 0)
81                 goto err;
82
83         ret = snd_soc_component_compr_open(cstream);
84         if (ret < 0)
85                 goto err;
86
87         ret = snd_soc_link_compr_startup(cstream);
88         if (ret < 0)
89                 goto err;
90
91         snd_soc_runtime_activate(rtd, stream);
92 err:
93         mutex_unlock(&rtd->card->pcm_mutex);
94 err_no_lock:
95         if (ret < 0)
96                 soc_compr_clean(cstream, 1);
97
98         return ret;
99 }
100
101 static int soc_compr_open_fe(struct snd_compr_stream *cstream)
102 {
103         struct snd_soc_pcm_runtime *fe = cstream->private_data;
104         struct snd_pcm_substream *fe_substream =
105                  fe->pcm->streams[cstream->direction].substream;
106         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
107         struct snd_soc_dpcm *dpcm;
108         struct snd_soc_dapm_widget_list *list;
109         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
110         int ret;
111
112         mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
113         fe->dpcm[stream].runtime = fe_substream->runtime;
114
115         ret = dpcm_path_get(fe, stream, &list);
116         if (ret < 0)
117                 goto be_err;
118         else if (ret == 0)
119                 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
120                         fe->dai_link->name, stream ? "capture" : "playback");
121         /* calculate valid and active FE <-> BE dpcms */
122         dpcm_process_paths(fe, stream, &list, 1);
123         fe->dpcm[stream].runtime = fe_substream->runtime;
124
125         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
126
127         ret = dpcm_be_dai_startup(fe, stream);
128         if (ret < 0) {
129                 /* clean up all links */
130                 for_each_dpcm_be(fe, stream, dpcm)
131                         dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
132
133                 dpcm_be_disconnect(fe, stream);
134                 fe->dpcm[stream].runtime = NULL;
135                 goto out;
136         }
137
138         ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
139         if (ret < 0)
140                 goto out;
141
142         ret = snd_soc_component_compr_open(cstream);
143         if (ret < 0)
144                 goto open_err;
145
146         ret = snd_soc_link_compr_startup(cstream);
147         if (ret < 0)
148                 goto machine_err;
149
150         dpcm_clear_pending_state(fe, stream);
151         dpcm_path_put(&list);
152
153         fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
154         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
155
156         snd_soc_runtime_activate(fe, stream);
157
158         mutex_unlock(&fe->card->mutex);
159
160         return 0;
161
162 machine_err:
163         snd_soc_component_compr_free(cstream, 1);
164 open_err:
165         snd_soc_dai_compr_shutdown(cpu_dai, cstream, 1);
166 out:
167         dpcm_path_put(&list);
168 be_err:
169         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
170         mutex_unlock(&fe->card->mutex);
171         return ret;
172 }
173
174 static int soc_compr_free_fe(struct snd_compr_stream *cstream)
175 {
176         struct snd_soc_pcm_runtime *fe = cstream->private_data;
177         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
178         struct snd_soc_dpcm *dpcm;
179         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
180         int ret;
181
182         mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
183
184         snd_soc_runtime_deactivate(fe, stream);
185
186         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
187
188         ret = dpcm_be_dai_hw_free(fe, stream);
189         if (ret < 0)
190                 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
191
192         ret = dpcm_be_dai_shutdown(fe, stream);
193
194         /* mark FE's links ready to prune */
195         for_each_dpcm_be(fe, stream, dpcm)
196                 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
197
198         dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
199
200         fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
201         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
202
203         dpcm_be_disconnect(fe, stream);
204
205         fe->dpcm[stream].runtime = NULL;
206
207         snd_soc_link_compr_shutdown(cstream, 0);
208
209         snd_soc_component_compr_free(cstream, 0);
210
211         snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0);
212
213         mutex_unlock(&fe->card->mutex);
214         return 0;
215 }
216
217 static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
218 {
219         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
220         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
221         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
222         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
223         int ret;
224
225         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
226
227         ret = snd_soc_component_compr_trigger(cstream, cmd);
228         if (ret < 0)
229                 goto out;
230
231         ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
232         if (ret < 0)
233                 goto out;
234
235         switch (cmd) {
236         case SNDRV_PCM_TRIGGER_START:
237                 snd_soc_dai_digital_mute(codec_dai, 0, stream);
238                 break;
239         case SNDRV_PCM_TRIGGER_STOP:
240                 snd_soc_dai_digital_mute(codec_dai, 1, stream);
241                 break;
242         }
243
244 out:
245         mutex_unlock(&rtd->card->pcm_mutex);
246         return ret;
247 }
248
249 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
250 {
251         struct snd_soc_pcm_runtime *fe = cstream->private_data;
252         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
253         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
254         int ret;
255
256         if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
257             cmd == SND_COMPR_TRIGGER_DRAIN)
258                 return snd_soc_component_compr_trigger(cstream, cmd);
259
260         mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
261
262         ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
263         if (ret < 0)
264                 goto out;
265
266         ret = snd_soc_component_compr_trigger(cstream, cmd);
267         if (ret < 0)
268                 goto out;
269
270         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
271
272         ret = dpcm_be_dai_trigger(fe, stream, cmd);
273
274         switch (cmd) {
275         case SNDRV_PCM_TRIGGER_START:
276         case SNDRV_PCM_TRIGGER_RESUME:
277         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
278                 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
279                 break;
280         case SNDRV_PCM_TRIGGER_STOP:
281         case SNDRV_PCM_TRIGGER_SUSPEND:
282                 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
283                 break;
284         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
285                 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
286                 break;
287         }
288
289 out:
290         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
291         mutex_unlock(&fe->card->mutex);
292         return ret;
293 }
294
295 static int soc_compr_set_params(struct snd_compr_stream *cstream,
296                                 struct snd_compr_params *params)
297 {
298         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
299         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
300         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
301         int ret;
302
303         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
304
305         /*
306          * First we call set_params for the CPU DAI, then the component
307          * driver this should configure the SoC side. If the machine has
308          * compressed ops then we call that as well. The expectation is
309          * that these callbacks will configure everything for this compress
310          * path, like configuring a PCM port for a CODEC.
311          */
312         ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
313         if (ret < 0)
314                 goto err;
315
316         ret = snd_soc_component_compr_set_params(cstream, params);
317         if (ret < 0)
318                 goto err;
319
320         ret = snd_soc_link_compr_set_params(cstream);
321         if (ret < 0)
322                 goto err;
323
324         snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START);
325
326         /* cancel any delayed stream shutdown that is pending */
327         rtd->pop_wait = 0;
328         mutex_unlock(&rtd->card->pcm_mutex);
329
330         cancel_delayed_work_sync(&rtd->delayed_work);
331
332         return 0;
333
334 err:
335         mutex_unlock(&rtd->card->pcm_mutex);
336         return ret;
337 }
338
339 static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
340                                    struct snd_compr_params *params)
341 {
342         struct snd_soc_pcm_runtime *fe = cstream->private_data;
343         struct snd_pcm_substream *fe_substream =
344                  fe->pcm->streams[cstream->direction].substream;
345         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
346         int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
347         int ret;
348
349         mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
350
351         /*
352          * Create an empty hw_params for the BE as the machine driver must
353          * fix this up to match DSP decoder and ASRC configuration.
354          * I.e. machine driver fixup for compressed BE is mandatory.
355          */
356         memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
357                 sizeof(struct snd_pcm_hw_params));
358
359         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
360
361         ret = dpcm_be_dai_hw_params(fe, stream);
362         if (ret < 0)
363                 goto out;
364
365         ret = dpcm_be_dai_prepare(fe, stream);
366         if (ret < 0)
367                 goto out;
368
369         ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
370         if (ret < 0)
371                 goto out;
372
373         ret = snd_soc_component_compr_set_params(cstream, params);
374         if (ret < 0)
375                 goto out;
376
377         ret = snd_soc_link_compr_set_params(cstream);
378         if (ret < 0)
379                 goto out;
380
381         dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
382         fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
383
384 out:
385         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
386         mutex_unlock(&fe->card->mutex);
387         return ret;
388 }
389
390 static int soc_compr_get_params(struct snd_compr_stream *cstream,
391                                 struct snd_codec *params)
392 {
393         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
394         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
395         int ret = 0;
396
397         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
398
399         ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
400         if (ret < 0)
401                 goto err;
402
403         ret = snd_soc_component_compr_get_params(cstream, params);
404 err:
405         mutex_unlock(&rtd->card->pcm_mutex);
406         return ret;
407 }
408
409 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
410 {
411         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
412         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
413         int ret;
414
415         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
416
417         ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
418         if (ret < 0)
419                 goto err;
420
421         ret = snd_soc_component_compr_ack(cstream, bytes);
422 err:
423         mutex_unlock(&rtd->card->pcm_mutex);
424         return ret;
425 }
426
427 static int soc_compr_pointer(struct snd_compr_stream *cstream,
428                              struct snd_compr_tstamp *tstamp)
429 {
430         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
431         int ret;
432         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
433
434         mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
435
436         ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
437         if (ret < 0)
438                 goto out;
439
440         ret = snd_soc_component_compr_pointer(cstream, tstamp);
441 out:
442         mutex_unlock(&rtd->card->pcm_mutex);
443         return ret;
444 }
445
446 static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
447                                   struct snd_compr_metadata *metadata)
448 {
449         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
450         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
451         int ret;
452
453         ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
454         if (ret < 0)
455                 return ret;
456
457         return snd_soc_component_compr_set_metadata(cstream, metadata);
458 }
459
460 static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
461                                   struct snd_compr_metadata *metadata)
462 {
463         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
464         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
465         int ret;
466
467         ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
468         if (ret < 0)
469                 return ret;
470
471         return snd_soc_component_compr_get_metadata(cstream, metadata);
472 }
473
474 /* ASoC Compress operations */
475 static struct snd_compr_ops soc_compr_ops = {
476         .open           = soc_compr_open,
477         .free           = soc_compr_free,
478         .set_params     = soc_compr_set_params,
479         .set_metadata   = soc_compr_set_metadata,
480         .get_metadata   = soc_compr_get_metadata,
481         .get_params     = soc_compr_get_params,
482         .trigger        = soc_compr_trigger,
483         .pointer        = soc_compr_pointer,
484         .ack            = soc_compr_ack,
485         .get_caps       = snd_soc_component_compr_get_caps,
486         .get_codec_caps = snd_soc_component_compr_get_codec_caps,
487 };
488
489 /* ASoC Dynamic Compress operations */
490 static struct snd_compr_ops soc_compr_dyn_ops = {
491         .open           = soc_compr_open_fe,
492         .free           = soc_compr_free_fe,
493         .set_params     = soc_compr_set_params_fe,
494         .get_params     = soc_compr_get_params,
495         .set_metadata   = soc_compr_set_metadata,
496         .get_metadata   = soc_compr_get_metadata,
497         .trigger        = soc_compr_trigger_fe,
498         .pointer        = soc_compr_pointer,
499         .ack            = soc_compr_ack,
500         .get_caps       = snd_soc_component_compr_get_caps,
501         .get_codec_caps = snd_soc_component_compr_get_codec_caps,
502 };
503
504 /**
505  * snd_soc_new_compress - create a new compress.
506  *
507  * @rtd: The runtime for which we will create compress
508  * @num: the device index number (zero based - shared with normal PCMs)
509  *
510  * Return: 0 for success, else error.
511  */
512 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
513 {
514         struct snd_soc_component *component;
515         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
516         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
517         struct snd_compr *compr;
518         struct snd_pcm *be_pcm;
519         char new_name[64];
520         int ret = 0, direction = 0;
521         int playback = 0, capture = 0;
522         int i;
523
524         /*
525          * make sure these are same value,
526          * and then use these as equally
527          */
528         BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK);
529         BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE  != (int)SND_COMPRESS_CAPTURE);
530
531         if (rtd->num_cpus > 1 ||
532             rtd->num_codecs > 1) {
533                 dev_err(rtd->card->dev,
534                         "Compress ASoC: Multi CPU/Codec not supported\n");
535                 return -EINVAL;
536         }
537
538         /* check client and interface hw capabilities */
539         if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
540             snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
541                 playback = 1;
542         if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
543             snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
544                 capture = 1;
545
546         /*
547          * Compress devices are unidirectional so only one of the directions
548          * should be set, check for that (xor)
549          */
550         if (playback + capture != 1) {
551                 dev_err(rtd->card->dev,
552                         "Compress ASoC: Invalid direction for P %d, C %d\n",
553                         playback, capture);
554                 return -EINVAL;
555         }
556
557         if (playback)
558                 direction = SND_COMPRESS_PLAYBACK;
559         else
560                 direction = SND_COMPRESS_CAPTURE;
561
562         compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
563         if (!compr)
564                 return -ENOMEM;
565
566         compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
567                                   GFP_KERNEL);
568         if (!compr->ops)
569                 return -ENOMEM;
570
571         if (rtd->dai_link->dynamic) {
572                 snprintf(new_name, sizeof(new_name), "(%s)",
573                         rtd->dai_link->stream_name);
574
575                 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
576                                 rtd->dai_link->dpcm_playback,
577                                 rtd->dai_link->dpcm_capture, &be_pcm);
578                 if (ret < 0) {
579                         dev_err(rtd->card->dev,
580                                 "Compress ASoC: can't create compressed for %s: %d\n",
581                                 rtd->dai_link->name, ret);
582                         return ret;
583                 }
584
585                 rtd->pcm = be_pcm;
586                 rtd->fe_compr = 1;
587                 if (rtd->dai_link->dpcm_playback)
588                         be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
589                 else if (rtd->dai_link->dpcm_capture)
590                         be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
591                 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
592         } else {
593                 snprintf(new_name, sizeof(new_name), "%s %s-%d",
594                         rtd->dai_link->stream_name, codec_dai->name, num);
595
596                 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
597         }
598
599         for_each_rtd_components(rtd, i, component) {
600                 if (!component->driver->compress_ops ||
601                     !component->driver->compress_ops->copy)
602                         continue;
603
604                 compr->ops->copy = snd_soc_component_compr_copy;
605                 break;
606         }
607
608         mutex_init(&compr->lock);
609         ret = snd_compress_new(rtd->card->snd_card, num, direction,
610                                 new_name, compr);
611         if (ret < 0) {
612                 component = asoc_rtd_to_codec(rtd, 0)->component;
613                 dev_err(component->dev,
614                         "Compress ASoC: can't create compress for codec %s: %d\n",
615                         component->name, ret);
616                 return ret;
617         }
618
619         /* DAPM dai link stream work */
620         rtd->close_delayed_work_func = snd_soc_close_delayed_work;
621
622         rtd->compr = compr;
623         compr->private_data = rtd;
624
625         dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
626                 codec_dai->name, cpu_dai->name);
627
628         return 0;
629 }
630 EXPORT_SYMBOL_GPL(snd_soc_new_compress);