Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/fsl/fsl_asrc_m2m.c
52848 views
1
// SPDX-License-Identifier: GPL-2.0
2
//
3
// Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
4
// Copyright (C) 2019-2024 NXP
5
//
6
// Freescale ASRC Memory to Memory (M2M) driver
7
8
#include <linux/dma/imx-dma.h>
9
#include <linux/dma-buf.h>
10
#include <linux/dma-mapping.h>
11
#include <linux/pm_runtime.h>
12
#include <sound/asound.h>
13
#include <sound/dmaengine_pcm.h>
14
#include <sound/initval.h>
15
16
#include "fsl_asrc_common.h"
17
18
#define DIR_STR(dir) (dir) == IN ? "in" : "out"
19
20
#define ASRC_xPUT_DMA_CALLBACK(dir) \
21
(((dir) == IN) ? asrc_input_dma_callback \
22
: asrc_output_dma_callback)
23
24
/* Maximum output and capture buffer size */
25
#define ASRC_M2M_BUFFER_SIZE (512 * 1024)
26
27
/* Maximum output and capture period size */
28
#define ASRC_M2M_PERIOD_SIZE (48 * 1024)
29
30
/* dma complete callback */
31
static void asrc_input_dma_callback(void *data)
32
{
33
struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data;
34
35
complete(&pair->complete[IN]);
36
}
37
38
/* dma complete callback */
39
static void asrc_output_dma_callback(void *data)
40
{
41
struct fsl_asrc_pair *pair = (struct fsl_asrc_pair *)data;
42
43
complete(&pair->complete[OUT]);
44
}
45
46
/**
47
*asrc_read_last_fifo: read all the remaining data from FIFO
48
*@pair: Structure pointer of fsl_asrc_pair
49
*@dma_vaddr: virtual address of capture buffer
50
*@length: payload length of capture buffer
51
*/
52
static void asrc_read_last_fifo(struct fsl_asrc_pair *pair, void *dma_vaddr, u32 *length)
53
{
54
struct fsl_asrc *asrc = pair->asrc;
55
enum asrc_pair_index index = pair->index;
56
u32 i, reg, size, t_size = 0, width;
57
u32 *reg32 = NULL;
58
u16 *reg16 = NULL;
59
u8 *reg24 = NULL;
60
61
width = snd_pcm_format_physical_width(pair->sample_format[OUT]);
62
if (width == 32)
63
reg32 = dma_vaddr + *length;
64
else if (width == 16)
65
reg16 = dma_vaddr + *length;
66
else
67
reg24 = dma_vaddr + *length;
68
retry:
69
size = asrc->get_output_fifo_size(pair);
70
if (size + *length > ASRC_M2M_BUFFER_SIZE)
71
goto end;
72
73
for (i = 0; i < size * pair->channels; i++) {
74
regmap_read(asrc->regmap, asrc->get_fifo_addr(OUT, index), &reg);
75
if (reg32) {
76
*reg32++ = reg;
77
} else if (reg16) {
78
*reg16++ = (u16)reg;
79
} else {
80
*reg24++ = (u8)reg;
81
*reg24++ = (u8)(reg >> 8);
82
*reg24++ = (u8)(reg >> 16);
83
}
84
}
85
t_size += size;
86
87
/* In case there is data left in FIFO */
88
if (size)
89
goto retry;
90
end:
91
/* Update payload length */
92
if (reg32)
93
*length += t_size * pair->channels * 4;
94
else if (reg16)
95
*length += t_size * pair->channels * 2;
96
else
97
*length += t_size * pair->channels * 3;
98
}
99
100
/* config dma channel */
101
static int asrc_dmaconfig(struct fsl_asrc_pair *pair,
102
struct dma_chan *chan,
103
u32 dma_addr, dma_addr_t buf_addr, u32 buf_len,
104
int dir, int width)
105
{
106
struct fsl_asrc *asrc = pair->asrc;
107
struct device *dev = &asrc->pdev->dev;
108
struct dma_slave_config slave_config;
109
enum dma_slave_buswidth buswidth;
110
unsigned int sg_len, max_period_size;
111
struct scatterlist *sg;
112
int ret, i;
113
114
switch (width) {
115
case 8:
116
buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
117
break;
118
case 16:
119
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
120
break;
121
case 24:
122
buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
123
break;
124
case 32:
125
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
126
break;
127
default:
128
dev_err(dev, "invalid word width\n");
129
return -EINVAL;
130
}
131
132
memset(&slave_config, 0, sizeof(slave_config));
133
if (dir == IN) {
134
slave_config.direction = DMA_MEM_TO_DEV;
135
slave_config.dst_addr = dma_addr;
136
slave_config.dst_addr_width = buswidth;
137
slave_config.dst_maxburst = asrc->m2m_get_maxburst(IN, pair);
138
} else {
139
slave_config.direction = DMA_DEV_TO_MEM;
140
slave_config.src_addr = dma_addr;
141
slave_config.src_addr_width = buswidth;
142
slave_config.src_maxburst = asrc->m2m_get_maxburst(OUT, pair);
143
}
144
145
ret = dmaengine_slave_config(chan, &slave_config);
146
if (ret) {
147
dev_err(dev, "failed to config dmaengine for %s task: %d\n",
148
DIR_STR(dir), ret);
149
return -EINVAL;
150
}
151
152
max_period_size = rounddown(ASRC_M2M_PERIOD_SIZE, width * pair->channels / 8);
153
/* scatter gather mode */
154
sg_len = buf_len / max_period_size;
155
if (buf_len % max_period_size)
156
sg_len += 1;
157
158
sg = kmalloc_array(sg_len, sizeof(*sg), GFP_KERNEL);
159
if (!sg)
160
return -ENOMEM;
161
162
sg_init_table(sg, sg_len);
163
for (i = 0; i < (sg_len - 1); i++) {
164
sg_dma_address(&sg[i]) = buf_addr + i * max_period_size;
165
sg_dma_len(&sg[i]) = max_period_size;
166
}
167
sg_dma_address(&sg[i]) = buf_addr + i * max_period_size;
168
sg_dma_len(&sg[i]) = buf_len - i * max_period_size;
169
170
pair->desc[dir] = dmaengine_prep_slave_sg(chan, sg, sg_len,
171
slave_config.direction,
172
DMA_PREP_INTERRUPT);
173
kfree(sg);
174
if (!pair->desc[dir]) {
175
dev_err(dev, "failed to prepare dmaengine for %s task\n", DIR_STR(dir));
176
return -EINVAL;
177
}
178
179
pair->desc[dir]->callback = ASRC_xPUT_DMA_CALLBACK(dir);
180
pair->desc[dir]->callback_param = pair;
181
182
return 0;
183
}
184
185
/* main function of converter */
186
static int asrc_m2m_device_run(struct fsl_asrc_pair *pair, struct snd_compr_task_runtime *task)
187
{
188
struct fsl_asrc *asrc = pair->asrc;
189
struct device *dev = &asrc->pdev->dev;
190
enum asrc_pair_index index = pair->index;
191
struct snd_dma_buffer *src_buf, *dst_buf;
192
unsigned int in_buf_len;
193
unsigned int out_dma_len;
194
unsigned int width;
195
u32 fifo_addr;
196
int ret = 0;
197
198
/* set ratio mod */
199
if (asrc->m2m_set_ratio_mod) {
200
if (pair->ratio_mod_flag) {
201
asrc->m2m_set_ratio_mod(pair, pair->ratio_mod);
202
pair->ratio_mod_flag = false;
203
}
204
}
205
206
src_buf = &pair->dma_buffer[IN];
207
dst_buf = &pair->dma_buffer[OUT];
208
209
width = snd_pcm_format_physical_width(pair->sample_format[IN]);
210
fifo_addr = asrc->paddr + asrc->get_fifo_addr(IN, index);
211
212
in_buf_len = task->input_size;
213
214
if (in_buf_len < width * pair->channels / 8 ||
215
in_buf_len > ASRC_M2M_BUFFER_SIZE ||
216
in_buf_len % (width * pair->channels / 8)) {
217
dev_err(dev, "out buffer size is error: [%d]\n", in_buf_len);
218
ret = -EINVAL;
219
goto end;
220
}
221
222
/* dma config for output dma channel */
223
ret = asrc_dmaconfig(pair,
224
pair->dma_chan[IN],
225
fifo_addr,
226
src_buf->addr,
227
in_buf_len, IN, width);
228
if (ret) {
229
dev_err(dev, "out dma config error\n");
230
goto end;
231
}
232
233
width = snd_pcm_format_physical_width(pair->sample_format[OUT]);
234
fifo_addr = asrc->paddr + asrc->get_fifo_addr(OUT, index);
235
out_dma_len = asrc->m2m_calc_out_len(pair, in_buf_len);
236
if (out_dma_len > 0 && out_dma_len <= ASRC_M2M_BUFFER_SIZE) {
237
/* dma config for capture dma channel */
238
ret = asrc_dmaconfig(pair,
239
pair->dma_chan[OUT],
240
fifo_addr,
241
dst_buf->addr,
242
out_dma_len, OUT, width);
243
if (ret) {
244
dev_err(dev, "cap dma config error\n");
245
goto end;
246
}
247
} else if (out_dma_len > ASRC_M2M_BUFFER_SIZE) {
248
dev_err(dev, "cap buffer size error\n");
249
ret = -EINVAL;
250
goto end;
251
}
252
253
reinit_completion(&pair->complete[IN]);
254
reinit_completion(&pair->complete[OUT]);
255
256
if (asrc->start_before_dma)
257
asrc->m2m_start(pair);
258
259
/* Submit DMA request */
260
dmaengine_submit(pair->desc[IN]);
261
dma_async_issue_pending(pair->desc[IN]->chan);
262
if (out_dma_len > 0) {
263
if (asrc->start_before_dma && asrc->m2m_output_ready)
264
asrc->m2m_output_ready(pair);
265
dmaengine_submit(pair->desc[OUT]);
266
dma_async_issue_pending(pair->desc[OUT]->chan);
267
}
268
269
if (!asrc->start_before_dma)
270
asrc->m2m_start(pair);
271
272
if (!wait_for_completion_interruptible_timeout(&pair->complete[IN], 10 * HZ)) {
273
dev_err(dev, "out DMA task timeout\n");
274
ret = -ETIMEDOUT;
275
goto end;
276
}
277
278
if (out_dma_len > 0) {
279
if (!wait_for_completion_interruptible_timeout(&pair->complete[OUT], 10 * HZ)) {
280
dev_err(dev, "cap DMA task timeout\n");
281
ret = -ETIMEDOUT;
282
goto end;
283
}
284
}
285
286
/* read the last words from FIFO */
287
asrc_read_last_fifo(pair, dst_buf->area, &out_dma_len);
288
/* update payload length for capture */
289
task->output_size = out_dma_len;
290
end:
291
return ret;
292
}
293
294
static int fsl_asrc_m2m_comp_open(struct snd_compr_stream *stream)
295
{
296
struct fsl_asrc *asrc = stream->private_data;
297
struct snd_compr_runtime *runtime = stream->runtime;
298
struct device *dev = &asrc->pdev->dev;
299
struct fsl_asrc_pair *pair;
300
int size, ret;
301
302
pair = kzalloc(sizeof(*pair) + asrc->pair_priv_size, GFP_KERNEL);
303
if (!pair)
304
return -ENOMEM;
305
306
pair->private = (void *)pair + sizeof(struct fsl_asrc_pair);
307
pair->asrc = asrc;
308
309
init_completion(&pair->complete[IN]);
310
init_completion(&pair->complete[OUT]);
311
312
runtime->private_data = pair;
313
314
size = ASRC_M2M_BUFFER_SIZE;
315
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[IN]);
316
if (ret)
317
goto error_alloc_in_buf;
318
319
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[OUT]);
320
if (ret)
321
goto error_alloc_out_buf;
322
323
ret = pm_runtime_get_sync(dev);
324
if (ret < 0) {
325
dev_err(dev, "Failed to power up asrc\n");
326
goto err_pm_runtime;
327
}
328
329
return 0;
330
331
err_pm_runtime:
332
snd_dma_free_pages(&pair->dma_buffer[OUT]);
333
error_alloc_out_buf:
334
snd_dma_free_pages(&pair->dma_buffer[IN]);
335
error_alloc_in_buf:
336
kfree(pair);
337
return ret;
338
}
339
340
static int fsl_asrc_m2m_comp_release(struct snd_compr_stream *stream)
341
{
342
struct fsl_asrc *asrc = stream->private_data;
343
struct snd_compr_runtime *runtime = stream->runtime;
344
struct fsl_asrc_pair *pair = runtime->private_data;
345
struct device *dev = &asrc->pdev->dev;
346
347
pm_runtime_put_sync(dev);
348
349
snd_dma_free_pages(&pair->dma_buffer[IN]);
350
snd_dma_free_pages(&pair->dma_buffer[OUT]);
351
352
kfree(runtime->private_data);
353
354
return 0;
355
}
356
357
static int fsl_asrc_m2m_comp_set_params(struct snd_compr_stream *stream,
358
struct snd_compr_params *params)
359
{
360
struct fsl_asrc *asrc = stream->private_data;
361
struct snd_compr_runtime *runtime = stream->runtime;
362
struct fsl_asrc_pair *pair = runtime->private_data;
363
struct fsl_asrc_m2m_cap cap;
364
int ret, i;
365
366
ret = asrc->m2m_get_cap(&cap);
367
if (ret)
368
return -EINVAL;
369
370
if (pcm_format_to_bits((__force snd_pcm_format_t)params->codec.format) & cap.fmt_in)
371
pair->sample_format[IN] = (__force snd_pcm_format_t)params->codec.format;
372
else
373
return -EINVAL;
374
375
if (pcm_format_to_bits((__force snd_pcm_format_t)params->codec.pcm_format) & cap.fmt_out)
376
pair->sample_format[OUT] = (__force snd_pcm_format_t)params->codec.pcm_format;
377
else
378
return -EINVAL;
379
380
/* check input rate is in scope */
381
for (i = 0; i < cap.rate_in_count; i++)
382
if (params->codec.sample_rate == cap.rate_in[i]) {
383
pair->rate[IN] = params->codec.sample_rate;
384
break;
385
}
386
if (i == cap.rate_in_count)
387
return -EINVAL;
388
389
/* check output rate is in scope */
390
for (i = 0; i < cap.rate_out_count; i++)
391
if (params->codec.options.src_d.out_sample_rate == cap.rate_out[i]) {
392
pair->rate[OUT] = params->codec.options.src_d.out_sample_rate;
393
break;
394
}
395
if (i == cap.rate_out_count)
396
return -EINVAL;
397
398
if (params->codec.ch_in != params->codec.ch_out ||
399
params->codec.ch_in < cap.chan_min ||
400
params->codec.ch_in > cap.chan_max)
401
return -EINVAL;
402
403
pair->channels = params->codec.ch_in;
404
pair->buf_len[IN] = params->buffer.fragment_size;
405
pair->buf_len[OUT] = params->buffer.fragment_size;
406
407
return 0;
408
}
409
410
static int fsl_asrc_m2m_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
411
{
412
struct snd_dma_buffer *dmab = dmabuf->priv;
413
414
return snd_dma_buffer_mmap(dmab, vma);
415
}
416
417
static struct sg_table *fsl_asrc_m2m_map_dma_buf(struct dma_buf_attachment *attachment,
418
enum dma_data_direction direction)
419
{
420
struct snd_dma_buffer *dmab = attachment->dmabuf->priv;
421
struct sg_table *sgt;
422
423
sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
424
if (!sgt)
425
return NULL;
426
427
if (dma_get_sgtable(attachment->dev, sgt, dmab->area, dmab->addr, dmab->bytes) < 0)
428
goto free;
429
430
if (dma_map_sgtable(attachment->dev, sgt, direction, 0))
431
goto free;
432
433
return sgt;
434
435
free:
436
sg_free_table(sgt);
437
kfree(sgt);
438
return NULL;
439
}
440
441
static void fsl_asrc_m2m_unmap_dma_buf(struct dma_buf_attachment *attachment,
442
struct sg_table *table,
443
enum dma_data_direction direction)
444
{
445
dma_unmap_sgtable(attachment->dev, table, direction, 0);
446
}
447
448
static void fsl_asrc_m2m_release(struct dma_buf *dmabuf)
449
{
450
/* buffer is released by fsl_asrc_m2m_comp_release() */
451
}
452
453
static const struct dma_buf_ops fsl_asrc_m2m_dma_buf_ops = {
454
.mmap = fsl_asrc_m2m_mmap,
455
.map_dma_buf = fsl_asrc_m2m_map_dma_buf,
456
.unmap_dma_buf = fsl_asrc_m2m_unmap_dma_buf,
457
.release = fsl_asrc_m2m_release,
458
};
459
460
static int fsl_asrc_m2m_comp_task_create(struct snd_compr_stream *stream,
461
struct snd_compr_task_runtime *task)
462
{
463
DEFINE_DMA_BUF_EXPORT_INFO(exp_info_in);
464
DEFINE_DMA_BUF_EXPORT_INFO(exp_info_out);
465
struct fsl_asrc *asrc = stream->private_data;
466
struct snd_compr_runtime *runtime = stream->runtime;
467
struct fsl_asrc_pair *pair = runtime->private_data;
468
struct device *dev = &asrc->pdev->dev;
469
int ret;
470
471
exp_info_in.ops = &fsl_asrc_m2m_dma_buf_ops;
472
exp_info_in.size = ASRC_M2M_BUFFER_SIZE;
473
exp_info_in.flags = O_RDWR;
474
exp_info_in.priv = &pair->dma_buffer[IN];
475
task->input = dma_buf_export(&exp_info_in);
476
if (IS_ERR(task->input)) {
477
ret = PTR_ERR(task->input);
478
return ret;
479
}
480
481
exp_info_out.ops = &fsl_asrc_m2m_dma_buf_ops;
482
exp_info_out.size = ASRC_M2M_BUFFER_SIZE;
483
exp_info_out.flags = O_RDWR;
484
exp_info_out.priv = &pair->dma_buffer[OUT];
485
task->output = dma_buf_export(&exp_info_out);
486
if (IS_ERR(task->output)) {
487
ret = PTR_ERR(task->output);
488
return ret;
489
}
490
491
/* Request asrc pair/context */
492
ret = asrc->request_pair(pair->channels, pair);
493
if (ret) {
494
dev_err(dev, "failed to request pair: %d\n", ret);
495
goto err_request_pair;
496
}
497
498
ret = asrc->m2m_prepare(pair);
499
if (ret) {
500
dev_err(dev, "failed to start pair part one: %d\n", ret);
501
goto err_start_part_one;
502
}
503
504
/* Request dma channels */
505
pair->dma_chan[IN] = asrc->get_dma_channel(pair, IN);
506
if (!pair->dma_chan[IN]) {
507
dev_err(dev, "[ctx%d] failed to get input DMA channel\n", pair->index);
508
ret = -EBUSY;
509
goto err_dma_channel_in;
510
}
511
512
pair->dma_chan[OUT] = asrc->get_dma_channel(pair, OUT);
513
if (!pair->dma_chan[OUT]) {
514
dev_err(dev, "[ctx%d] failed to get output DMA channel\n", pair->index);
515
ret = -EBUSY;
516
goto err_dma_channel_out;
517
}
518
519
return 0;
520
521
err_dma_channel_out:
522
dma_release_channel(pair->dma_chan[IN]);
523
err_dma_channel_in:
524
if (asrc->m2m_unprepare)
525
asrc->m2m_unprepare(pair);
526
err_start_part_one:
527
asrc->release_pair(pair);
528
err_request_pair:
529
return ret;
530
}
531
532
static int fsl_asrc_m2m_comp_task_start(struct snd_compr_stream *stream,
533
struct snd_compr_task_runtime *task)
534
{
535
struct snd_compr_runtime *runtime = stream->runtime;
536
struct fsl_asrc_pair *pair = runtime->private_data;
537
538
return asrc_m2m_device_run(pair, task);
539
}
540
541
static int fsl_asrc_m2m_comp_task_stop(struct snd_compr_stream *stream,
542
struct snd_compr_task_runtime *task)
543
{
544
return 0;
545
}
546
547
static int fsl_asrc_m2m_comp_task_free(struct snd_compr_stream *stream,
548
struct snd_compr_task_runtime *task)
549
{
550
struct fsl_asrc *asrc = stream->private_data;
551
struct snd_compr_runtime *runtime = stream->runtime;
552
struct fsl_asrc_pair *pair = runtime->private_data;
553
554
/* Stop & release pair/context */
555
if (asrc->m2m_stop)
556
asrc->m2m_stop(pair);
557
558
if (asrc->m2m_unprepare)
559
asrc->m2m_unprepare(pair);
560
asrc->release_pair(pair);
561
562
/* Release dma channel */
563
if (pair->dma_chan[IN])
564
dma_release_channel(pair->dma_chan[IN]);
565
if (pair->dma_chan[OUT])
566
dma_release_channel(pair->dma_chan[OUT]);
567
568
return 0;
569
}
570
571
static int fsl_asrc_m2m_get_caps(struct snd_compr_stream *cstream,
572
struct snd_compr_caps *caps)
573
{
574
caps->num_codecs = 1;
575
caps->min_fragment_size = 4096;
576
caps->max_fragment_size = 4096;
577
caps->min_fragments = 1;
578
caps->max_fragments = 1;
579
caps->codecs[0] = SND_AUDIOCODEC_PCM;
580
581
return 0;
582
}
583
584
static int fsl_asrc_m2m_fill_codec_caps(struct fsl_asrc *asrc,
585
struct snd_compr_codec_caps *codec)
586
{
587
struct fsl_asrc_m2m_cap cap;
588
snd_pcm_format_t k;
589
int j = 0;
590
int ret;
591
592
ret = asrc->m2m_get_cap(&cap);
593
if (ret)
594
return -EINVAL;
595
596
pcm_for_each_format(k) {
597
if (pcm_format_to_bits(k) & cap.fmt_in) {
598
codec->descriptor[j].max_ch = cap.chan_max;
599
memcpy(codec->descriptor[j].sample_rates,
600
cap.rate_in,
601
cap.rate_in_count * sizeof(__u32));
602
codec->descriptor[j].num_sample_rates = cap.rate_in_count;
603
codec->descriptor[j].formats = (__force __u32)k;
604
codec->descriptor[j].pcm_formats = cap.fmt_out;
605
codec->descriptor[j].src.out_sample_rate_min = cap.rate_out[0];
606
codec->descriptor[j].src.out_sample_rate_max =
607
cap.rate_out[cap.rate_out_count - 1];
608
j++;
609
}
610
}
611
612
codec->codec = SND_AUDIOCODEC_PCM;
613
codec->num_descriptors = j;
614
return 0;
615
}
616
617
static int fsl_asrc_m2m_get_codec_caps(struct snd_compr_stream *stream,
618
struct snd_compr_codec_caps *codec)
619
{
620
struct fsl_asrc *asrc = stream->private_data;
621
622
return fsl_asrc_m2m_fill_codec_caps(asrc, codec);
623
}
624
625
static struct snd_compr_ops fsl_asrc_m2m_compr_ops = {
626
.open = fsl_asrc_m2m_comp_open,
627
.free = fsl_asrc_m2m_comp_release,
628
.set_params = fsl_asrc_m2m_comp_set_params,
629
.get_caps = fsl_asrc_m2m_get_caps,
630
.get_codec_caps = fsl_asrc_m2m_get_codec_caps,
631
.task_create = fsl_asrc_m2m_comp_task_create,
632
.task_start = fsl_asrc_m2m_comp_task_start,
633
.task_stop = fsl_asrc_m2m_comp_task_stop,
634
.task_free = fsl_asrc_m2m_comp_task_free,
635
};
636
637
int fsl_asrc_m2m_suspend(struct fsl_asrc *asrc)
638
{
639
struct fsl_asrc_pair *pair;
640
int i;
641
642
for (i = 0; i < PAIR_CTX_NUM; i++) {
643
pair = asrc->pair[i];
644
if (!pair || !pair->dma_buffer[IN].area || !pair->dma_buffer[OUT].area)
645
continue;
646
if (!completion_done(&pair->complete[IN])) {
647
if (pair->dma_chan[IN])
648
dmaengine_terminate_all(pair->dma_chan[IN]);
649
asrc_input_dma_callback((void *)pair);
650
}
651
if (!completion_done(&pair->complete[OUT])) {
652
if (pair->dma_chan[OUT])
653
dmaengine_terminate_all(pair->dma_chan[OUT]);
654
asrc_output_dma_callback((void *)pair);
655
}
656
657
if (asrc->m2m_pair_suspend)
658
asrc->m2m_pair_suspend(pair);
659
}
660
661
return 0;
662
}
663
EXPORT_SYMBOL_GPL(fsl_asrc_m2m_suspend);
664
665
int fsl_asrc_m2m_resume(struct fsl_asrc *asrc)
666
{
667
struct fsl_asrc_pair *pair;
668
int i;
669
670
for (i = 0; i < PAIR_CTX_NUM; i++) {
671
pair = asrc->pair[i];
672
if (!pair)
673
continue;
674
if (asrc->m2m_pair_resume)
675
asrc->m2m_pair_resume(pair);
676
}
677
678
return 0;
679
}
680
EXPORT_SYMBOL_GPL(fsl_asrc_m2m_resume);
681
682
int fsl_asrc_m2m_init(struct fsl_asrc *asrc)
683
{
684
struct device *dev = &asrc->pdev->dev;
685
struct snd_card *card;
686
struct snd_compr *compr;
687
int ret;
688
689
ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
690
THIS_MODULE, 0, &card);
691
if (ret < 0)
692
return ret;
693
694
strscpy(card->driver, "fsl-asrc-m2m", sizeof(card->driver));
695
strscpy(card->shortname, "ASRC-M2M", sizeof(card->shortname));
696
strscpy(card->longname, "ASRC-M2M", sizeof(card->shortname));
697
698
asrc->card = card;
699
700
compr = devm_kzalloc(dev, sizeof(*compr), GFP_KERNEL);
701
if (!compr) {
702
ret = -ENOMEM;
703
goto err;
704
}
705
706
compr->ops = &fsl_asrc_m2m_compr_ops;
707
compr->private_data = asrc;
708
709
ret = snd_compress_new(card, 0, SND_COMPRESS_ACCEL, "ASRC M2M", compr);
710
if (ret < 0)
711
goto err;
712
713
ret = snd_card_register(card);
714
if (ret < 0)
715
goto err;
716
717
return 0;
718
err:
719
snd_card_free(card);
720
return ret;
721
}
722
EXPORT_SYMBOL_GPL(fsl_asrc_m2m_init);
723
724
void fsl_asrc_m2m_exit(struct fsl_asrc *asrc)
725
{
726
struct snd_card *card = asrc->card;
727
728
snd_card_free(card);
729
}
730
EXPORT_SYMBOL_GPL(fsl_asrc_m2m_exit);
731
732
MODULE_IMPORT_NS("DMA_BUF");
733
MODULE_AUTHOR("Shengjiu Wang <[email protected]>");
734
MODULE_DESCRIPTION("Freescale ASRC M2M driver");
735
MODULE_LICENSE("GPL");
736
737