Lines Matching +full:asrc +full:- +full:width
1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
4 // Copyright (C) 2019-2024 NXP
6 // Freescale ASRC Memory to Memory (M2M) driver
8 #include <linux/dma/imx-dma.h>
9 #include <linux/dma-buf.h>
10 #include <linux/dma-mapping.h>
35 complete(&pair->complete[IN]); in asrc_input_dma_callback()
43 complete(&pair->complete[OUT]); in asrc_output_dma_callback()
54 struct fsl_asrc *asrc = pair->asrc; in asrc_read_last_fifo() local
55 enum asrc_pair_index index = pair->index; in asrc_read_last_fifo()
56 u32 i, reg, size, t_size = 0, width; in asrc_read_last_fifo() local
61 width = snd_pcm_format_physical_width(pair->sample_format[OUT]); in asrc_read_last_fifo()
62 if (width == 32) in asrc_read_last_fifo()
64 else if (width == 16) in asrc_read_last_fifo()
69 size = asrc->get_output_fifo_size(pair); in asrc_read_last_fifo()
73 for (i = 0; i < size * pair->channels; i++) { in asrc_read_last_fifo()
74 regmap_read(asrc->regmap, asrc->get_fifo_addr(OUT, index), ®); in asrc_read_last_fifo()
93 *length += t_size * pair->channels * 4; in asrc_read_last_fifo()
95 *length += t_size * pair->channels * 2; in asrc_read_last_fifo()
97 *length += t_size * pair->channels * 3; in asrc_read_last_fifo()
104 int dir, int width) in asrc_dmaconfig() argument
106 struct fsl_asrc *asrc = pair->asrc; in asrc_dmaconfig() local
107 struct device *dev = &asrc->pdev->dev; in asrc_dmaconfig()
114 switch (width) { in asrc_dmaconfig()
128 dev_err(dev, "invalid word width\n"); in asrc_dmaconfig()
129 return -EINVAL; in asrc_dmaconfig()
137 slave_config.dst_maxburst = asrc->m2m_get_maxburst(IN, pair); in asrc_dmaconfig()
142 slave_config.src_maxburst = asrc->m2m_get_maxburst(OUT, pair); in asrc_dmaconfig()
149 return -EINVAL; in asrc_dmaconfig()
152 max_period_size = rounddown(ASRC_M2M_PERIOD_SIZE, width * pair->channels / 8); in asrc_dmaconfig()
160 return -ENOMEM; in asrc_dmaconfig()
163 for (i = 0; i < (sg_len - 1); i++) { in asrc_dmaconfig()
168 sg_dma_len(&sg[i]) = buf_len - i * max_period_size; in asrc_dmaconfig()
170 pair->desc[dir] = dmaengine_prep_slave_sg(chan, sg, sg_len, in asrc_dmaconfig()
174 if (!pair->desc[dir]) { in asrc_dmaconfig()
176 return -EINVAL; in asrc_dmaconfig()
179 pair->desc[dir]->callback = ASRC_xPUT_DMA_CALLBACK(dir); in asrc_dmaconfig()
180 pair->desc[dir]->callback_param = pair; in asrc_dmaconfig()
188 struct fsl_asrc *asrc = pair->asrc; in asrc_m2m_device_run() local
189 struct device *dev = &asrc->pdev->dev; in asrc_m2m_device_run()
190 enum asrc_pair_index index = pair->index; in asrc_m2m_device_run()
194 unsigned int width; in asrc_m2m_device_run() local
199 if (asrc->m2m_set_ratio_mod) { in asrc_m2m_device_run()
200 if (pair->ratio_mod_flag) { in asrc_m2m_device_run()
201 asrc->m2m_set_ratio_mod(pair, pair->ratio_mod); in asrc_m2m_device_run()
202 pair->ratio_mod_flag = false; in asrc_m2m_device_run()
206 src_buf = &pair->dma_buffer[IN]; in asrc_m2m_device_run()
207 dst_buf = &pair->dma_buffer[OUT]; in asrc_m2m_device_run()
209 width = snd_pcm_format_physical_width(pair->sample_format[IN]); in asrc_m2m_device_run()
210 fifo_addr = asrc->paddr + asrc->get_fifo_addr(IN, index); in asrc_m2m_device_run()
212 in_buf_len = task->input_size; in asrc_m2m_device_run()
214 if (in_buf_len < width * pair->channels / 8 || in asrc_m2m_device_run()
216 in_buf_len % (width * pair->channels / 8)) { in asrc_m2m_device_run()
218 ret = -EINVAL; in asrc_m2m_device_run()
224 pair->dma_chan[IN], in asrc_m2m_device_run()
226 src_buf->addr, in asrc_m2m_device_run()
227 in_buf_len, IN, width); in asrc_m2m_device_run()
233 width = snd_pcm_format_physical_width(pair->sample_format[OUT]); in asrc_m2m_device_run()
234 fifo_addr = asrc->paddr + asrc->get_fifo_addr(OUT, index); in asrc_m2m_device_run()
235 out_dma_len = asrc->m2m_calc_out_len(pair, in_buf_len); in asrc_m2m_device_run()
239 pair->dma_chan[OUT], in asrc_m2m_device_run()
241 dst_buf->addr, in asrc_m2m_device_run()
242 out_dma_len, OUT, width); in asrc_m2m_device_run()
249 ret = -EINVAL; in asrc_m2m_device_run()
253 reinit_completion(&pair->complete[IN]); in asrc_m2m_device_run()
254 reinit_completion(&pair->complete[OUT]); in asrc_m2m_device_run()
257 dmaengine_submit(pair->desc[IN]); in asrc_m2m_device_run()
258 dma_async_issue_pending(pair->desc[IN]->chan); in asrc_m2m_device_run()
260 dmaengine_submit(pair->desc[OUT]); in asrc_m2m_device_run()
261 dma_async_issue_pending(pair->desc[OUT]->chan); in asrc_m2m_device_run()
264 asrc->m2m_start(pair); in asrc_m2m_device_run()
266 if (!wait_for_completion_interruptible_timeout(&pair->complete[IN], 10 * HZ)) { in asrc_m2m_device_run()
268 ret = -ETIMEDOUT; in asrc_m2m_device_run()
273 if (!wait_for_completion_interruptible_timeout(&pair->complete[OUT], 10 * HZ)) { in asrc_m2m_device_run()
275 ret = -ETIMEDOUT; in asrc_m2m_device_run()
281 asrc_read_last_fifo(pair, dst_buf->area, &out_dma_len); in asrc_m2m_device_run()
283 task->output_size = out_dma_len; in asrc_m2m_device_run()
290 struct fsl_asrc *asrc = stream->private_data; in fsl_asrc_m2m_comp_open() local
291 struct snd_compr_runtime *runtime = stream->runtime; in fsl_asrc_m2m_comp_open()
292 struct device *dev = &asrc->pdev->dev; in fsl_asrc_m2m_comp_open()
296 pair = kzalloc(sizeof(*pair) + asrc->pair_priv_size, GFP_KERNEL); in fsl_asrc_m2m_comp_open()
298 return -ENOMEM; in fsl_asrc_m2m_comp_open()
300 pair->private = (void *)pair + sizeof(struct fsl_asrc_pair); in fsl_asrc_m2m_comp_open()
301 pair->asrc = asrc; in fsl_asrc_m2m_comp_open()
303 init_completion(&pair->complete[IN]); in fsl_asrc_m2m_comp_open()
304 init_completion(&pair->complete[OUT]); in fsl_asrc_m2m_comp_open()
306 runtime->private_data = pair; in fsl_asrc_m2m_comp_open()
309 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[IN]); in fsl_asrc_m2m_comp_open()
313 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &pair->dma_buffer[OUT]); in fsl_asrc_m2m_comp_open()
319 dev_err(dev, "Failed to power up asrc\n"); in fsl_asrc_m2m_comp_open()
326 snd_dma_free_pages(&pair->dma_buffer[OUT]); in fsl_asrc_m2m_comp_open()
328 snd_dma_free_pages(&pair->dma_buffer[IN]); in fsl_asrc_m2m_comp_open()
336 struct fsl_asrc *asrc = stream->private_data; in fsl_asrc_m2m_comp_release() local
337 struct snd_compr_runtime *runtime = stream->runtime; in fsl_asrc_m2m_comp_release()
338 struct fsl_asrc_pair *pair = runtime->private_data; in fsl_asrc_m2m_comp_release()
339 struct device *dev = &asrc->pdev->dev; in fsl_asrc_m2m_comp_release()
343 snd_dma_free_pages(&pair->dma_buffer[IN]); in fsl_asrc_m2m_comp_release()
344 snd_dma_free_pages(&pair->dma_buffer[OUT]); in fsl_asrc_m2m_comp_release()
346 kfree(runtime->private_data); in fsl_asrc_m2m_comp_release()
354 struct fsl_asrc *asrc = stream->private_data; in fsl_asrc_m2m_comp_set_params() local
355 struct snd_compr_runtime *runtime = stream->runtime; in fsl_asrc_m2m_comp_set_params()
356 struct fsl_asrc_pair *pair = runtime->private_data; in fsl_asrc_m2m_comp_set_params()
360 ret = asrc->m2m_get_cap(&cap); in fsl_asrc_m2m_comp_set_params()
362 return -EINVAL; in fsl_asrc_m2m_comp_set_params()
364 if (pcm_format_to_bits((__force snd_pcm_format_t)params->codec.format) & cap.fmt_in) in fsl_asrc_m2m_comp_set_params()
365 pair->sample_format[IN] = (__force snd_pcm_format_t)params->codec.format; in fsl_asrc_m2m_comp_set_params()
367 return -EINVAL; in fsl_asrc_m2m_comp_set_params()
369 if (pcm_format_to_bits((__force snd_pcm_format_t)params->codec.pcm_format) & cap.fmt_out) in fsl_asrc_m2m_comp_set_params()
370 pair->sample_format[OUT] = (__force snd_pcm_format_t)params->codec.pcm_format; in fsl_asrc_m2m_comp_set_params()
372 return -EINVAL; in fsl_asrc_m2m_comp_set_params()
376 if (params->codec.sample_rate == cap.rate_in[i]) { in fsl_asrc_m2m_comp_set_params()
377 pair->rate[IN] = params->codec.sample_rate; in fsl_asrc_m2m_comp_set_params()
381 return -EINVAL; in fsl_asrc_m2m_comp_set_params()
385 if (params->codec.options.src_d.out_sample_rate == cap.rate_out[i]) { in fsl_asrc_m2m_comp_set_params()
386 pair->rate[OUT] = params->codec.options.src_d.out_sample_rate; in fsl_asrc_m2m_comp_set_params()
390 return -EINVAL; in fsl_asrc_m2m_comp_set_params()
392 if (params->codec.ch_in != params->codec.ch_out || in fsl_asrc_m2m_comp_set_params()
393 params->codec.ch_in < cap.chan_min || in fsl_asrc_m2m_comp_set_params()
394 params->codec.ch_in > cap.chan_max) in fsl_asrc_m2m_comp_set_params()
395 return -EINVAL; in fsl_asrc_m2m_comp_set_params()
397 pair->channels = params->codec.ch_in; in fsl_asrc_m2m_comp_set_params()
398 pair->buf_len[IN] = params->buffer.fragment_size; in fsl_asrc_m2m_comp_set_params()
399 pair->buf_len[OUT] = params->buffer.fragment_size; in fsl_asrc_m2m_comp_set_params()
406 struct snd_dma_buffer *dmab = dmabuf->priv; in fsl_asrc_m2m_mmap()
414 struct snd_dma_buffer *dmab = attachment->dmabuf->priv; in fsl_asrc_m2m_map_dma_buf()
421 if (dma_get_sgtable(attachment->dev, sgt, dmab->area, dmab->addr, dmab->bytes) < 0) in fsl_asrc_m2m_map_dma_buf()
424 if (dma_map_sgtable(attachment->dev, sgt, direction, 0)) in fsl_asrc_m2m_map_dma_buf()
439 dma_unmap_sgtable(attachment->dev, table, direction, 0); in fsl_asrc_m2m_unmap_dma_buf()
459 struct fsl_asrc *asrc = stream->private_data; in fsl_asrc_m2m_comp_task_create() local
460 struct snd_compr_runtime *runtime = stream->runtime; in fsl_asrc_m2m_comp_task_create()
461 struct fsl_asrc_pair *pair = runtime->private_data; in fsl_asrc_m2m_comp_task_create()
462 struct device *dev = &asrc->pdev->dev; in fsl_asrc_m2m_comp_task_create()
468 exp_info_in.priv = &pair->dma_buffer[IN]; in fsl_asrc_m2m_comp_task_create()
469 task->input = dma_buf_export(&exp_info_in); in fsl_asrc_m2m_comp_task_create()
470 if (IS_ERR(task->input)) { in fsl_asrc_m2m_comp_task_create()
471 ret = PTR_ERR(task->input); in fsl_asrc_m2m_comp_task_create()
478 exp_info_out.priv = &pair->dma_buffer[OUT]; in fsl_asrc_m2m_comp_task_create()
479 task->output = dma_buf_export(&exp_info_out); in fsl_asrc_m2m_comp_task_create()
480 if (IS_ERR(task->output)) { in fsl_asrc_m2m_comp_task_create()
481 ret = PTR_ERR(task->output); in fsl_asrc_m2m_comp_task_create()
485 /* Request asrc pair/context */ in fsl_asrc_m2m_comp_task_create()
486 ret = asrc->request_pair(pair->channels, pair); in fsl_asrc_m2m_comp_task_create()
492 ret = asrc->m2m_prepare(pair); in fsl_asrc_m2m_comp_task_create()
499 pair->dma_chan[IN] = asrc->get_dma_channel(pair, IN); in fsl_asrc_m2m_comp_task_create()
500 if (!pair->dma_chan[IN]) { in fsl_asrc_m2m_comp_task_create()
501 dev_err(dev, "[ctx%d] failed to get input DMA channel\n", pair->index); in fsl_asrc_m2m_comp_task_create()
502 ret = -EBUSY; in fsl_asrc_m2m_comp_task_create()
506 pair->dma_chan[OUT] = asrc->get_dma_channel(pair, OUT); in fsl_asrc_m2m_comp_task_create()
507 if (!pair->dma_chan[OUT]) { in fsl_asrc_m2m_comp_task_create()
508 dev_err(dev, "[ctx%d] failed to get output DMA channel\n", pair->index); in fsl_asrc_m2m_comp_task_create()
509 ret = -EBUSY; in fsl_asrc_m2m_comp_task_create()
516 dma_release_channel(pair->dma_chan[IN]); in fsl_asrc_m2m_comp_task_create()
518 if (asrc->m2m_unprepare) in fsl_asrc_m2m_comp_task_create()
519 asrc->m2m_unprepare(pair); in fsl_asrc_m2m_comp_task_create()
521 asrc->release_pair(pair); in fsl_asrc_m2m_comp_task_create()
529 struct snd_compr_runtime *runtime = stream->runtime; in fsl_asrc_m2m_comp_task_start()
530 struct fsl_asrc_pair *pair = runtime->private_data; in fsl_asrc_m2m_comp_task_start()
544 struct fsl_asrc *asrc = stream->private_data; in fsl_asrc_m2m_comp_task_free() local
545 struct snd_compr_runtime *runtime = stream->runtime; in fsl_asrc_m2m_comp_task_free()
546 struct fsl_asrc_pair *pair = runtime->private_data; in fsl_asrc_m2m_comp_task_free()
549 if (asrc->m2m_stop) in fsl_asrc_m2m_comp_task_free()
550 asrc->m2m_stop(pair); in fsl_asrc_m2m_comp_task_free()
552 if (asrc->m2m_unprepare) in fsl_asrc_m2m_comp_task_free()
553 asrc->m2m_unprepare(pair); in fsl_asrc_m2m_comp_task_free()
554 asrc->release_pair(pair); in fsl_asrc_m2m_comp_task_free()
557 if (pair->dma_chan[IN]) in fsl_asrc_m2m_comp_task_free()
558 dma_release_channel(pair->dma_chan[IN]); in fsl_asrc_m2m_comp_task_free()
559 if (pair->dma_chan[OUT]) in fsl_asrc_m2m_comp_task_free()
560 dma_release_channel(pair->dma_chan[OUT]); in fsl_asrc_m2m_comp_task_free()
568 caps->num_codecs = 1; in fsl_asrc_m2m_get_caps()
569 caps->min_fragment_size = 4096; in fsl_asrc_m2m_get_caps()
570 caps->max_fragment_size = 4096; in fsl_asrc_m2m_get_caps()
571 caps->min_fragments = 1; in fsl_asrc_m2m_get_caps()
572 caps->max_fragments = 1; in fsl_asrc_m2m_get_caps()
573 caps->codecs[0] = SND_AUDIOCODEC_PCM; in fsl_asrc_m2m_get_caps()
578 static int fsl_asrc_m2m_fill_codec_caps(struct fsl_asrc *asrc, in fsl_asrc_m2m_fill_codec_caps() argument
586 ret = asrc->m2m_get_cap(&cap); in fsl_asrc_m2m_fill_codec_caps()
588 return -EINVAL; in fsl_asrc_m2m_fill_codec_caps()
592 codec->descriptor[j].max_ch = cap.chan_max; in fsl_asrc_m2m_fill_codec_caps()
593 memcpy(codec->descriptor[j].sample_rates, in fsl_asrc_m2m_fill_codec_caps()
596 codec->descriptor[j].num_sample_rates = cap.rate_in_count; in fsl_asrc_m2m_fill_codec_caps()
597 codec->descriptor[j].formats = (__force __u32)k; in fsl_asrc_m2m_fill_codec_caps()
598 codec->descriptor[j].pcm_formats = cap.fmt_out; in fsl_asrc_m2m_fill_codec_caps()
599 codec->descriptor[j].src.out_sample_rate_min = cap.rate_out[0]; in fsl_asrc_m2m_fill_codec_caps()
600 codec->descriptor[j].src.out_sample_rate_max = in fsl_asrc_m2m_fill_codec_caps()
601 cap.rate_out[cap.rate_out_count - 1]; in fsl_asrc_m2m_fill_codec_caps()
606 codec->codec = SND_AUDIOCODEC_PCM; in fsl_asrc_m2m_fill_codec_caps()
607 codec->num_descriptors = j; in fsl_asrc_m2m_fill_codec_caps()
614 struct fsl_asrc *asrc = stream->private_data; in fsl_asrc_m2m_get_codec_caps() local
616 return fsl_asrc_m2m_fill_codec_caps(asrc, codec); in fsl_asrc_m2m_get_codec_caps()
631 int fsl_asrc_m2m_suspend(struct fsl_asrc *asrc) in fsl_asrc_m2m_suspend() argument
637 pair = asrc->pair[i]; in fsl_asrc_m2m_suspend()
638 if (!pair || !pair->dma_buffer[IN].area || !pair->dma_buffer[OUT].area) in fsl_asrc_m2m_suspend()
640 if (!completion_done(&pair->complete[IN])) { in fsl_asrc_m2m_suspend()
641 if (pair->dma_chan[IN]) in fsl_asrc_m2m_suspend()
642 dmaengine_terminate_all(pair->dma_chan[IN]); in fsl_asrc_m2m_suspend()
645 if (!completion_done(&pair->complete[OUT])) { in fsl_asrc_m2m_suspend()
646 if (pair->dma_chan[OUT]) in fsl_asrc_m2m_suspend()
647 dmaengine_terminate_all(pair->dma_chan[OUT]); in fsl_asrc_m2m_suspend()
651 if (asrc->m2m_pair_suspend) in fsl_asrc_m2m_suspend()
652 asrc->m2m_pair_suspend(pair); in fsl_asrc_m2m_suspend()
659 int fsl_asrc_m2m_resume(struct fsl_asrc *asrc) in fsl_asrc_m2m_resume() argument
665 pair = asrc->pair[i]; in fsl_asrc_m2m_resume()
668 if (asrc->m2m_pair_resume) in fsl_asrc_m2m_resume()
669 asrc->m2m_pair_resume(pair); in fsl_asrc_m2m_resume()
676 int fsl_asrc_m2m_init(struct fsl_asrc *asrc) in fsl_asrc_m2m_init() argument
678 struct device *dev = &asrc->pdev->dev; in fsl_asrc_m2m_init()
688 strscpy(card->driver, "fsl-asrc-m2m", sizeof(card->driver)); in fsl_asrc_m2m_init()
689 strscpy(card->shortname, "ASRC-M2M", sizeof(card->shortname)); in fsl_asrc_m2m_init()
690 strscpy(card->longname, "ASRC-M2M", sizeof(card->shortname)); in fsl_asrc_m2m_init()
692 asrc->card = card; in fsl_asrc_m2m_init()
696 ret = -ENOMEM; in fsl_asrc_m2m_init()
700 compr->ops = &fsl_asrc_m2m_compr_ops; in fsl_asrc_m2m_init()
701 compr->private_data = asrc; in fsl_asrc_m2m_init()
703 ret = snd_compress_new(card, 0, SND_COMPRESS_ACCEL, "ASRC M2M", compr); in fsl_asrc_m2m_init()
718 void fsl_asrc_m2m_exit(struct fsl_asrc *asrc) in fsl_asrc_m2m_exit() argument
720 struct snd_card *card = asrc->card; in fsl_asrc_m2m_exit()
728 MODULE_DESCRIPTION("Freescale ASRC M2M driver");