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 */
asrc_input_dma_callback(void * data)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 */
asrc_output_dma_callback(void * data)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 */
asrc_read_last_fifo(struct fsl_asrc_pair * pair,void * dma_vaddr,u32 * length)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), ®);
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 */
asrc_dmaconfig(struct fsl_asrc_pair * pair,struct dma_chan * chan,u32 dma_addr,dma_addr_t buf_addr,u32 buf_len,int dir,int width)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_objs(*sg, sg_len);
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 */
asrc_m2m_device_run(struct fsl_asrc_pair * pair,struct snd_compr_task_runtime * task)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
fsl_asrc_m2m_comp_open(struct snd_compr_stream * stream)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
fsl_asrc_m2m_comp_release(struct snd_compr_stream * stream)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
fsl_asrc_m2m_comp_set_params(struct snd_compr_stream * stream,struct snd_compr_params * params)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
fsl_asrc_m2m_mmap(struct dma_buf * dmabuf,struct vm_area_struct * vma)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
fsl_asrc_m2m_map_dma_buf(struct dma_buf_attachment * attachment,enum dma_data_direction direction)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_obj(*sgt);
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
fsl_asrc_m2m_unmap_dma_buf(struct dma_buf_attachment * attachment,struct sg_table * table,enum dma_data_direction direction)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
fsl_asrc_m2m_release(struct dma_buf * dmabuf)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
fsl_asrc_m2m_comp_task_create(struct snd_compr_stream * stream,struct snd_compr_task_runtime * task)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
fsl_asrc_m2m_comp_task_start(struct snd_compr_stream * stream,struct snd_compr_task_runtime * task)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
fsl_asrc_m2m_comp_task_stop(struct snd_compr_stream * stream,struct snd_compr_task_runtime * task)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
fsl_asrc_m2m_comp_task_free(struct snd_compr_stream * stream,struct snd_compr_task_runtime * task)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
fsl_asrc_m2m_get_caps(struct snd_compr_stream * cstream,struct snd_compr_caps * caps)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
fsl_asrc_m2m_fill_codec_caps(struct fsl_asrc * asrc,struct snd_compr_codec_caps * codec)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
fsl_asrc_m2m_get_codec_caps(struct snd_compr_stream * stream,struct snd_compr_codec_caps * codec)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
fsl_asrc_m2m_suspend(struct fsl_asrc * asrc)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
fsl_asrc_m2m_resume(struct fsl_asrc * asrc)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
fsl_asrc_m2m_init(struct fsl_asrc * asrc)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
fsl_asrc_m2m_exit(struct fsl_asrc * asrc)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 <Shengjiu.Wang@nxp.com>");
734 MODULE_DESCRIPTION("Freescale ASRC M2M driver");
735 MODULE_LICENSE("GPL");
736