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