xref: /openbmc/linux/sound/soc/soc-compress.c (revision 8ffdff6a)
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);
631