File Index
Files and directories
Sign in
FILE

fsl_asrc_m2m.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/fsl/fsl_asrc_m2m.c C
  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 */
 31static 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 */
 39static 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 */
 52static 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;
 68retry:
 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;
 90end:
 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 */
101static 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 */
186static 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	/* Submit DMA request */
257	dmaengine_submit(pair->desc[IN]);
258	dma_async_issue_pending(pair->desc[IN]->chan);
259	if (out_dma_len > 0) {
260		dmaengine_submit(pair->desc[OUT]);
261		dma_async_issue_pending(pair->desc[OUT]->chan);
262	}
263
264	asrc->m2m_start(pair);
265
266	if (!wait_for_completion_interruptible_timeout(&pair->complete[IN], 10 * HZ)) {
267		dev_err(dev, "out DMA task timeout\n");
268		ret = -ETIMEDOUT;
269		goto end;
270	}
271
272	if (out_dma_len > 0) {
273		if (!wait_for_completion_interruptible_timeout(&pair->complete[OUT], 10 * HZ)) {
274			dev_err(dev, "cap DMA task timeout\n");
275			ret = -ETIMEDOUT;
276			goto end;
277		}
278	}
279
280	/* read the last words from FIFO */
281	asrc_read_last_fifo(pair, dst_buf->area, &out_dma_len);
282	/* update payload length for capture */
283	task->output_size = out_dma_len;
284end:
285	return ret;
286}
287
288static int fsl_asrc_m2m_comp_open(struct snd_compr_stream *stream)
289{
290	struct fsl_asrc *asrc = stream->private_data;
291	struct snd_compr_runtime *runtime = stream->runtime;
292	struct device *dev = &asrc->pdev->dev;
293	struct fsl_asrc_pair *pair;
294	int size, ret;
295
296	pair = kzalloc(sizeof(*pair) + asrc->pair_priv_size, GFP_KERNEL);
297	if (!pair)
298		return -ENOMEM;
299
300	pair->private = (void *)pair + sizeof(struct fsl_asrc_pair);
301	pair->asrc = asrc;
302
303	init_completion(&pair->complete[IN]);
304	init_completion(&pair->complete[OUT]);
305
306	runtime->private_data = pair;
307
308	size = ASRC_M2M_BUFFER_SIZE;
309	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[IN]);
310	if (ret)
311		goto error_alloc_in_buf;
312
313	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[OUT]);
314	if (ret)
315		goto error_alloc_out_buf;
316
317	ret = pm_runtime_get_sync(dev);
318	if (ret < 0) {
319		dev_err(dev, "Failed to power up asrc\n");
320		goto err_pm_runtime;
321	}
322
323	return 0;
324
325err_pm_runtime:
326	snd_dma_free_pages(&pair->dma_buffer[OUT]);
327error_alloc_out_buf:
328	snd_dma_free_pages(&pair->dma_buffer[IN]);
329error_alloc_in_buf:
330	kfree(pair);
331	return ret;
332}
333
334static int fsl_asrc_m2m_comp_release(struct snd_compr_stream *stream)
335{
336	struct fsl_asrc *asrc = stream->private_data;
337	struct snd_compr_runtime *runtime = stream->runtime;
338	struct fsl_asrc_pair *pair = runtime->private_data;
339	struct device *dev = &asrc->pdev->dev;
340
341	pm_runtime_put_sync(dev);
342
343	snd_dma_free_pages(&pair->dma_buffer[IN]);
344	snd_dma_free_pages(&pair->dma_buffer[OUT]);
345
346	kfree(runtime->private_data);
347
348	return 0;
349}
350
351static int fsl_asrc_m2m_comp_set_params(struct snd_compr_stream *stream,
352					struct snd_compr_params *params)
353{
354	struct fsl_asrc *asrc = stream->private_data;
355	struct snd_compr_runtime *runtime = stream->runtime;
356	struct fsl_asrc_pair *pair = runtime->private_data;
357	struct fsl_asrc_m2m_cap cap;
358	int ret, i;
359
360	ret = asrc->m2m_get_cap(&cap);
361	if (ret)
362		return -EINVAL;
363
364	if (pcm_format_to_bits((__force snd_pcm_format_t)params->codec.format) & cap.fmt_in)
365		pair->sample_format[IN] = (__force snd_pcm_format_t)params->codec.format;
366	else
367		return -EINVAL;
368
369	if (pcm_format_to_bits((__force snd_pcm_format_t)params->codec.pcm_format) & cap.fmt_out)
370		pair->sample_format[OUT] = (__force snd_pcm_format_t)params->codec.pcm_format;
371	else
372		return -EINVAL;
373
374	/* check input rate is in scope */
375	for (i = 0; i < cap.rate_in_count; i++)
376		if (params->codec.sample_rate == cap.rate_in[i]) {
377			pair->rate[IN] = params->codec.sample_rate;
378			break;
379		}
380	if (i == cap.rate_in_count)
381		return -EINVAL;
382
383	/* check output rate is in scope */
384	for (i = 0; i < cap.rate_out_count; i++)
385		if (params->codec.options.src_d.out_sample_rate == cap.rate_out[i]) {
386			pair->rate[OUT] = params->codec.options.src_d.out_sample_rate;
387			break;
388		}
389	if (i == cap.rate_out_count)
390		return -EINVAL;
391
392	if (params->codec.ch_in != params->codec.ch_out ||
393	    params->codec.ch_in < cap.chan_min ||
394	    params->codec.ch_in > cap.chan_max)
395		return -EINVAL;
396
397	pair->channels = params->codec.ch_in;
398	pair->buf_len[IN] = params->buffer.fragment_size;
399	pair->buf_len[OUT] = params->buffer.fragment_size;
400
401	return 0;
402}
403
404static int fsl_asrc_m2m_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
405{
406	struct snd_dma_buffer *dmab = dmabuf->priv;
407
408	return snd_dma_buffer_mmap(dmab, vma);
409}
410
411static struct sg_table *fsl_asrc_m2m_map_dma_buf(struct dma_buf_attachment *attachment,
412						 enum dma_data_direction direction)
413{
414	struct snd_dma_buffer *dmab = attachment->dmabuf->priv;
415	struct sg_table *sgt;
416
417	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
418	if (!sgt)
419		return NULL;
420
421	if (dma_get_sgtable(attachment->dev, sgt, dmab->area, dmab->addr, dmab->bytes) < 0)
422		goto free;
423
424	if (dma_map_sgtable(attachment->dev, sgt, direction, 0))
425		goto free;
426
427	return sgt;
428
429free:
430	sg_free_table(sgt);
431	kfree(sgt);
432	return NULL;
433}
434
435static void fsl_asrc_m2m_unmap_dma_buf(struct dma_buf_attachment *attachment,
436				       struct sg_table *table,
437				       enum dma_data_direction direction)
438{
439	dma_unmap_sgtable(attachment->dev, table, direction, 0);
440}
441
442static void fsl_asrc_m2m_release(struct dma_buf *dmabuf)
443{
444	/* buffer is released by fsl_asrc_m2m_comp_release() */
445}
446
447static const struct dma_buf_ops fsl_asrc_m2m_dma_buf_ops = {
448	.mmap = fsl_asrc_m2m_mmap,
449	.map_dma_buf = fsl_asrc_m2m_map_dma_buf,
450	.unmap_dma_buf = fsl_asrc_m2m_unmap_dma_buf,
451	.release = fsl_asrc_m2m_release,
452};
453
454static int fsl_asrc_m2m_comp_task_create(struct snd_compr_stream *stream,
455					 struct snd_compr_task_runtime *task)
456{
457	DEFINE_DMA_BUF_EXPORT_INFO(exp_info_in);
458	DEFINE_DMA_BUF_EXPORT_INFO(exp_info_out);
459	struct fsl_asrc *asrc = stream->private_data;
460	struct snd_compr_runtime *runtime = stream->runtime;
461	struct fsl_asrc_pair *pair = runtime->private_data;
462	struct device *dev = &asrc->pdev->dev;
463	int ret;
464
465	exp_info_in.ops = &fsl_asrc_m2m_dma_buf_ops;
466	exp_info_in.size = ASRC_M2M_BUFFER_SIZE;
467	exp_info_in.flags = O_RDWR;
468	exp_info_in.priv = &pair->dma_buffer[IN];
469	task->input = dma_buf_export(&exp_info_in);
470	if (IS_ERR(task->input)) {
471		ret = PTR_ERR(task->input);
472		return ret;
473	}
474
475	exp_info_out.ops = &fsl_asrc_m2m_dma_buf_ops;
476	exp_info_out.size = ASRC_M2M_BUFFER_SIZE;
477	exp_info_out.flags = O_RDWR;
478	exp_info_out.priv = &pair->dma_buffer[OUT];
479	task->output = dma_buf_export(&exp_info_out);
480	if (IS_ERR(task->output)) {
481		ret = PTR_ERR(task->output);
482		return ret;
483	}
484
485	/* Request asrc pair/context */
486	ret = asrc->request_pair(pair->channels, pair);
487	if (ret) {
488		dev_err(dev, "failed to request pair: %d\n", ret);
489		goto err_request_pair;
490	}
491
492	ret = asrc->m2m_prepare(pair);
493	if (ret) {
494		dev_err(dev, "failed to start pair part one: %d\n", ret);
495		goto err_start_part_one;
496	}
497
498	/* Request dma channels */
499	pair->dma_chan[IN] = asrc->get_dma_channel(pair, IN);
500	if (!pair->dma_chan[IN]) {
501		dev_err(dev, "[ctx%d] failed to get input DMA channel\n", pair->index);
502		ret = -EBUSY;
503		goto err_dma_channel_in;
504	}
505
506	pair->dma_chan[OUT] = asrc->get_dma_channel(pair, OUT);
507	if (!pair->dma_chan[OUT]) {
508		dev_err(dev, "[ctx%d] failed to get output DMA channel\n", pair->index);
509		ret = -EBUSY;
510		goto err_dma_channel_out;
511	}
512
513	return 0;
514
515err_dma_channel_out:
516	dma_release_channel(pair->dma_chan[IN]);
517err_dma_channel_in:
518	if (asrc->m2m_unprepare)
519		asrc->m2m_unprepare(pair);
520err_start_part_one:
521	asrc->release_pair(pair);
522err_request_pair:
523	return ret;
524}
525
526static int fsl_asrc_m2m_comp_task_start(struct snd_compr_stream *stream,
527					struct snd_compr_task_runtime *task)
528{
529	struct snd_compr_runtime *runtime = stream->runtime;
530	struct fsl_asrc_pair *pair = runtime->private_data;
531
532	return asrc_m2m_device_run(pair, task);
533}
534
535static int fsl_asrc_m2m_comp_task_stop(struct snd_compr_stream *stream,
536				       struct snd_compr_task_runtime *task)
537{
538	return 0;
539}
540
541static int fsl_asrc_m2m_comp_task_free(struct snd_compr_stream *stream,
542				       struct snd_compr_task_runtime *task)
543{
544	struct fsl_asrc *asrc = stream->private_data;
545	struct snd_compr_runtime *runtime = stream->runtime;
546	struct fsl_asrc_pair *pair = runtime->private_data;
547
548	/* Stop & release pair/context */
549	if (asrc->m2m_stop)
550		asrc->m2m_stop(pair);
551
552	if (asrc->m2m_unprepare)
553		asrc->m2m_unprepare(pair);
554	asrc->release_pair(pair);
555
556	/* Release dma channel */
557	if (pair->dma_chan[IN])
558		dma_release_channel(pair->dma_chan[IN]);
559	if (pair->dma_chan[OUT])
560		dma_release_channel(pair->dma_chan[OUT]);
561
562	return 0;
563}
564
565static int fsl_asrc_m2m_get_caps(struct snd_compr_stream *cstream,
566				 struct snd_compr_caps *caps)
567{
568	caps->num_codecs = 1;
569	caps->min_fragment_size = 4096;
570	caps->max_fragment_size = 4096;
571	caps->min_fragments = 1;
572	caps->max_fragments = 1;
573	caps->codecs[0] = SND_AUDIOCODEC_PCM;
574
575	return 0;
576}
577
578static int fsl_asrc_m2m_fill_codec_caps(struct fsl_asrc *asrc,
579					struct snd_compr_codec_caps *codec)
580{
581	struct fsl_asrc_m2m_cap cap;
582	snd_pcm_format_t k;
583	int j = 0;
584	int ret;
585
586	ret = asrc->m2m_get_cap(&cap);
587	if (ret)
588		return -EINVAL;
589
590	pcm_for_each_format(k) {
591		if (pcm_format_to_bits(k) & cap.fmt_in) {
592			codec->descriptor[j].max_ch = cap.chan_max;
593			memcpy(codec->descriptor[j].sample_rates,
594			       cap.rate_in,
595			       cap.rate_in_count * sizeof(__u32));
596			codec->descriptor[j].num_sample_rates = cap.rate_in_count;
597			codec->descriptor[j].formats = (__force __u32)k;
598			codec->descriptor[j].pcm_formats = cap.fmt_out;
599			codec->descriptor[j].src.out_sample_rate_min = cap.rate_out[0];
600			codec->descriptor[j].src.out_sample_rate_max =
601				cap.rate_out[cap.rate_out_count - 1];
602			j++;
603		}
604	}
605
606	codec->codec = SND_AUDIOCODEC_PCM;
607	codec->num_descriptors = j;
608	return 0;
609}
610
611static int fsl_asrc_m2m_get_codec_caps(struct snd_compr_stream *stream,
612				       struct snd_compr_codec_caps *codec)
613{
614	struct fsl_asrc *asrc = stream->private_data;
615
616	return fsl_asrc_m2m_fill_codec_caps(asrc, codec);
617}
618
619static struct snd_compr_ops fsl_asrc_m2m_compr_ops = {
620	.open = fsl_asrc_m2m_comp_open,
621	.free = fsl_asrc_m2m_comp_release,
622	.set_params = fsl_asrc_m2m_comp_set_params,
623	.get_caps = fsl_asrc_m2m_get_caps,
624	.get_codec_caps = fsl_asrc_m2m_get_codec_caps,
625	.task_create = fsl_asrc_m2m_comp_task_create,
626	.task_start = fsl_asrc_m2m_comp_task_start,
627	.task_stop = fsl_asrc_m2m_comp_task_stop,
628	.task_free = fsl_asrc_m2m_comp_task_free,
629};
630
631int fsl_asrc_m2m_suspend(struct fsl_asrc *asrc)
632{
633	struct fsl_asrc_pair *pair;
634	int i;
635
636	for (i = 0; i < PAIR_CTX_NUM; i++) {
637		pair = asrc->pair[i];
638		if (!pair || !pair->dma_buffer[IN].area || !pair->dma_buffer[OUT].area)
639			continue;
640		if (!completion_done(&pair->complete[IN])) {
641			if (pair->dma_chan[IN])
642				dmaengine_terminate_all(pair->dma_chan[IN]);
643			asrc_input_dma_callback((void *)pair);
644		}
645		if (!completion_done(&pair->complete[OUT])) {
646			if (pair->dma_chan[OUT])
647				dmaengine_terminate_all(pair->dma_chan[OUT]);
648			asrc_output_dma_callback((void *)pair);
649		}
650
651		if (asrc->m2m_pair_suspend)
652			asrc->m2m_pair_suspend(pair);
653	}
654
655	return 0;
656}
657EXPORT_SYMBOL_GPL(fsl_asrc_m2m_suspend);
658
659int fsl_asrc_m2m_resume(struct fsl_asrc *asrc)
660{
661	struct fsl_asrc_pair *pair;
662	int i;
663
664	for (i = 0; i < PAIR_CTX_NUM; i++) {
665		pair = asrc->pair[i];
666		if (!pair)
667			continue;
668		if (asrc->m2m_pair_resume)
669			asrc->m2m_pair_resume(pair);
670	}
671
672	return 0;
673}
674EXPORT_SYMBOL_GPL(fsl_asrc_m2m_resume);
675
676int fsl_asrc_m2m_init(struct fsl_asrc *asrc)
677{
678	struct device *dev = &asrc->pdev->dev;
679	struct snd_card *card;
680	struct snd_compr *compr;
681	int ret;
682
683	ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
684			   THIS_MODULE, 0, &card);
685	if (ret < 0)
686		return ret;
687
688	strscpy(card->driver, "fsl-asrc-m2m", sizeof(card->driver));
689	strscpy(card->shortname, "ASRC-M2M", sizeof(card->shortname));
690	strscpy(card->longname, "ASRC-M2M", sizeof(card->shortname));
691
692	asrc->card = card;
693
694	compr = devm_kzalloc(dev, sizeof(*compr), GFP_KERNEL);
695	if (!compr) {
696		ret = -ENOMEM;
697		goto err;
698	}
699
700	compr->ops = &fsl_asrc_m2m_compr_ops;
701	compr->private_data = asrc;
702
703	ret = snd_compress_new(card, 0, SND_COMPRESS_ACCEL, "ASRC M2M", compr);
704	if (ret < 0)
705		goto err;
706
707	ret = snd_card_register(card);
708	if (ret < 0)
709		goto err;
710
711	return 0;
712err:
713	snd_card_free(card);
714	return ret;
715}
716EXPORT_SYMBOL_GPL(fsl_asrc_m2m_init);
717
718void fsl_asrc_m2m_exit(struct fsl_asrc *asrc)
719{
720	struct snd_card *card = asrc->card;
721
722	snd_card_free(card);
723}
724EXPORT_SYMBOL_GPL(fsl_asrc_m2m_exit);
725
726MODULE_IMPORT_NS("DMA_BUF");
727MODULE_AUTHOR("Shengjiu Wang <Shengjiu.Wang@nxp.com>");
728MODULE_DESCRIPTION("Freescale ASRC M2M driver");
729MODULE_LICENSE("GPL");
~/ Read-only file preview.