Lines Matching +full:pcm +full:- +full:platform

1 // SPDX-License-Identifier: GPL-2.0
4 #include <linux/dma-mapping.h>
6 #include <linux/dma/sprd-dma.h>
11 #include <sound/pcm.h>
15 #include "sprd-pcm-dma.h"
52 struct snd_pcm_runtime *runtime = substream->runtime; in sprd_pcm_open()
53 struct device *dev = component->dev; in sprd_pcm_open()
79 return -ENOMEM; in sprd_pcm_open()
81 size = runtime->hw.periods_max * SPRD_PCM_DMA_LINKLIST_SIZE; in sprd_pcm_open()
84 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_open()
86 data->virt = dmam_alloc_coherent(dev, size, &data->phys, in sprd_pcm_open()
88 if (!data->virt) { in sprd_pcm_open()
89 ret = -ENOMEM; in sprd_pcm_open()
94 dma_private->hw_chan = hw_chan; in sprd_pcm_open()
95 runtime->private_data = dma_private; in sprd_pcm_open()
96 dma_private->substream = substream; in sprd_pcm_open()
102 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_open()
104 if (data->virt) in sprd_pcm_open()
105 dmam_free_coherent(dev, size, data->virt, data->phys); in sprd_pcm_open()
115 struct snd_pcm_runtime *runtime = substream->runtime; in sprd_pcm_close()
116 struct sprd_pcm_dma_private *dma_private = runtime->private_data; in sprd_pcm_close()
117 struct device *dev = component->dev; in sprd_pcm_close()
118 int size = runtime->hw.periods_max * SPRD_PCM_DMA_LINKLIST_SIZE; in sprd_pcm_close()
121 for (i = 0; i < dma_private->hw_chan; i++) { in sprd_pcm_close()
122 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_close()
124 dmam_free_coherent(dev, size, data->virt, data->phys); in sprd_pcm_close()
135 struct snd_pcm_substream *substream = dma_private->substream; in sprd_pcm_dma_complete()
142 struct snd_pcm_runtime *runtime = substream->runtime; in sprd_pcm_release_dma_channel()
143 struct sprd_pcm_dma_private *dma_private = runtime->private_data; in sprd_pcm_release_dma_channel()
147 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_release_dma_channel()
149 if (data->chan) { in sprd_pcm_release_dma_channel()
150 dma_release_channel(data->chan); in sprd_pcm_release_dma_channel()
151 data->chan = NULL; in sprd_pcm_release_dma_channel()
160 struct snd_pcm_runtime *runtime = substream->runtime; in sprd_pcm_request_dma_channel()
161 struct sprd_pcm_dma_private *dma_private = runtime->private_data; in sprd_pcm_request_dma_channel()
162 struct device *dev = component->dev; in sprd_pcm_request_dma_channel()
163 struct sprd_pcm_dma_params *dma_params = dma_private->params; in sprd_pcm_request_dma_channel()
168 return -EINVAL; in sprd_pcm_request_dma_channel()
172 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_request_dma_channel()
174 data->chan = dma_request_slave_channel(dev, in sprd_pcm_request_dma_channel()
175 dma_params->chan_name[i]); in sprd_pcm_request_dma_channel()
176 if (!data->chan) { in sprd_pcm_request_dma_channel()
178 dma_params->chan_name[i]); in sprd_pcm_request_dma_channel()
180 return -ENODEV; in sprd_pcm_request_dma_channel()
191 struct snd_pcm_runtime *runtime = substream->runtime; in sprd_pcm_hw_params()
192 struct sprd_pcm_dma_private *dma_private = runtime->private_data; in sprd_pcm_hw_params()
198 int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; in sprd_pcm_hw_params()
205 dev_warn(component->dev, "no dma parameters setting\n"); in sprd_pcm_hw_params()
206 dma_private->params = NULL; in sprd_pcm_hw_params()
210 if (!dma_private->params) { in sprd_pcm_hw_params()
211 dma_private->params = dma_params; in sprd_pcm_hw_params()
219 dma_private->dma_addr_offset = totsize / channels; in sprd_pcm_hw_params()
221 sg = devm_kcalloc(component->dev, sg_num, sizeof(*sg), GFP_KERNEL); in sprd_pcm_hw_params()
223 ret = -ENOMEM; in sprd_pcm_hw_params()
228 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_hw_params()
229 struct dma_chan *chan = data->chan; in sprd_pcm_hw_params()
235 config.src_maxburst = dma_params->fragment_len[i]; in sprd_pcm_hw_params()
236 config.src_addr_width = dma_params->datawidth[i]; in sprd_pcm_hw_params()
237 config.dst_addr_width = dma_params->datawidth[i]; in sprd_pcm_hw_params()
239 config.src_addr = runtime->dma_addr + in sprd_pcm_hw_params()
240 i * dma_private->dma_addr_offset; in sprd_pcm_hw_params()
241 config.dst_addr = dma_params->dev_phys[i]; in sprd_pcm_hw_params()
244 config.src_addr = dma_params->dev_phys[i]; in sprd_pcm_hw_params()
245 config.dst_addr = runtime->dma_addr + in sprd_pcm_hw_params()
246 i * dma_private->dma_addr_offset; in sprd_pcm_hw_params()
255 sg_dma_address(sgt) = runtime->dma_addr + in sprd_pcm_hw_params()
256 i * dma_private->dma_addr_offset + sg_len * j; in sprd_pcm_hw_params()
260 * Configure the link-list address for the DMA engine link-list in sprd_pcm_hw_params()
263 link.virt_addr = (unsigned long)data->virt; in sprd_pcm_hw_params()
264 link.phy_addr = data->phys; in sprd_pcm_hw_params()
268 dev_err(component->dev, in sprd_pcm_hw_params()
279 data->desc = chan->device->device_prep_slave_sg(chan, sg, in sprd_pcm_hw_params()
282 if (!data->desc) { in sprd_pcm_hw_params()
283 dev_err(component->dev, "failed to prepare slave sg\n"); in sprd_pcm_hw_params()
284 ret = -ENOMEM; in sprd_pcm_hw_params()
288 if (!runtime->no_period_wakeup) { in sprd_pcm_hw_params()
289 data->desc->callback = sprd_pcm_dma_complete; in sprd_pcm_hw_params()
290 data->desc->callback_param = dma_private; in sprd_pcm_hw_params()
294 devm_kfree(component->dev, sg); in sprd_pcm_hw_params()
299 devm_kfree(component->dev, sg); in sprd_pcm_hw_params()
317 substream->runtime->private_data; in sprd_pcm_trigger()
322 for (i = 0; i < dma_private->hw_chan; i++) { in sprd_pcm_trigger()
323 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_trigger()
325 if (!data->desc) in sprd_pcm_trigger()
328 data->cookie = dmaengine_submit(data->desc); in sprd_pcm_trigger()
329 ret = dma_submit_error(data->cookie); in sprd_pcm_trigger()
331 dev_err(component->dev, in sprd_pcm_trigger()
337 dma_async_issue_pending(data->chan); in sprd_pcm_trigger()
343 for (i = 0; i < dma_private->hw_chan; i++) { in sprd_pcm_trigger()
344 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_trigger()
346 if (data->chan) in sprd_pcm_trigger()
347 dmaengine_resume(data->chan); in sprd_pcm_trigger()
352 for (i = 0; i < dma_private->hw_chan; i++) { in sprd_pcm_trigger()
353 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_trigger()
355 if (data->chan) in sprd_pcm_trigger()
356 dmaengine_terminate_async(data->chan); in sprd_pcm_trigger()
362 for (i = 0; i < dma_private->hw_chan; i++) { in sprd_pcm_trigger()
363 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_trigger()
365 if (data->chan) in sprd_pcm_trigger()
366 dmaengine_pause(data->chan); in sprd_pcm_trigger()
371 ret = -EINVAL; in sprd_pcm_trigger()
380 struct snd_pcm_runtime *runtime = substream->runtime; in sprd_pcm_pointer()
381 struct sprd_pcm_dma_private *dma_private = runtime->private_data; in sprd_pcm_pointer()
388 for (i = 0; i < dma_private->hw_chan; i++) { in sprd_pcm_pointer()
389 struct sprd_pcm_dma_data *data = &dma_private->data[i]; in sprd_pcm_pointer()
391 if (!data->chan) in sprd_pcm_pointer()
394 status = dmaengine_tx_status(data->chan, data->cookie, &state); in sprd_pcm_pointer()
396 dev_err(component->dev, in sprd_pcm_pointer()
405 pointer[i] = state.residue - runtime->dma_addr - in sprd_pcm_pointer()
406 i * dma_private->dma_addr_offset; in sprd_pcm_pointer()
410 sel_max = pointer[i] < data->pre_pointer ? 1 : 0; in sprd_pcm_pointer()
412 sel_max ^= pointer[i] < data->pre_pointer ? 1 : 0; in sprd_pcm_pointer()
416 max(pointer[i], pointer[i - 1]) << 1; in sprd_pcm_pointer()
419 min(pointer[i], pointer[i - 1]) << 1; in sprd_pcm_pointer()
422 data->pre_pointer = pointer[i]; in sprd_pcm_pointer()
426 if (x == runtime->buffer_size) in sprd_pcm_pointer()
435 struct snd_card *card = rtd->card->snd_card; in sprd_pcm_new()
436 struct snd_pcm *pcm = rtd->pcm; in sprd_pcm_new() local
439 ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); in sprd_pcm_new()
443 return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, in sprd_pcm_new()
444 card->dev, in sprd_pcm_new()
462 struct device_node *np = pdev->dev.of_node; in sprd_soc_platform_probe()
465 ret = of_reserved_mem_device_init_by_idx(&pdev->dev, np, 0); in sprd_soc_platform_probe()
467 dev_warn(&pdev->dev, in sprd_soc_platform_probe()
468 "no reserved DMA memory for audio platform device\n"); in sprd_soc_platform_probe()
470 ret = devm_snd_soc_register_component(&pdev->dev, &sprd_soc_component, in sprd_soc_platform_probe()
473 dev_err(&pdev->dev, "could not register platform:%d\n", ret); in sprd_soc_platform_probe()
479 { .compatible = "sprd,pcm-platform", },
486 .name = "sprd-pcm-audio",
495 MODULE_DESCRIPTION("Spreadtrum ASoC PCM DMA");
497 MODULE_ALIAS("platform:sprd-audio");