diff options
author | Shengjiu Wang <shengjiu.wang@nxp.com> | 2018-08-14 17:06:08 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2019-11-25 15:51:27 +0800 |
commit | 6ee22f9f6d6cd427d2b4ba4446d9de9858daaf8a (patch) | |
tree | 1c14e0aec29e1050f2371b2de76ab35dc5b14135 /sound/soc/fsl/imx-pcm-dma-v2.c | |
parent | 7047fb026bdb3128e2f8d5407210f66eb85623ed (diff) |
MLK-18947: ASoC: imx-pcm-dma: alloc buffer from IRAM
In some platform, the low power audio playback should be
supported, which need the audio buffer allocated from
OCRAM/IRAM. So move the buffer allocation to .open
function at that time the dma chan is allocated.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
(cherry picked from commit 85c59acfc5c8d17aa0f369dbe30e4a5fb128c25f)
Diffstat (limited to 'sound/soc/fsl/imx-pcm-dma-v2.c')
-rw-r--r-- | sound/soc/fsl/imx-pcm-dma-v2.c | 102 |
1 files changed, 39 insertions, 63 deletions
diff --git a/sound/soc/fsl/imx-pcm-dma-v2.c b/sound/soc/fsl/imx-pcm-dma-v2.c index f8e89588b8e2..4c38efbbf907 100644 --- a/sound/soc/fsl/imx-pcm-dma-v2.c +++ b/sound/soc/fsl/imx-pcm-dma-v2.c @@ -99,6 +99,28 @@ static snd_pcm_uframes_t imx_pcm_pointer(struct snd_pcm_substream *substream) return snd_dmaengine_pcm_pointer(substream); } +static int imx_pcm_preallocate_dma_buffer(struct snd_pcm_substream *substream, + struct device *dev) +{ + size_t size = imx_pcm_hardware.buffer_bytes_max; + int ret; + + ret = snd_pcm_lib_preallocate_pages(substream, + SNDRV_DMA_TYPE_DEV_IRAM, + dev, + size, + size); + if (ret) + return ret; + + return 0; +} + +static int imx_pcm_free_dma_buffers(struct snd_pcm_substream *substream) +{ + return snd_pcm_lib_preallocate_free(substream); +} + static int imx_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -185,6 +207,10 @@ static int imx_pcm_open(struct snd_pcm_substream *substream) snd_soc_set_runtime_hwparams(substream, &imx_pcm_hardware); + ret = imx_pcm_preallocate_dma_buffer(substream, chan->device->dev); + if (ret) + return ret; + ret = snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) @@ -204,9 +230,20 @@ static int imx_pcm_mmap(struct snd_pcm_substream *substream, runtime->dma_bytes); } +static int imx_pcm_close(struct snd_pcm_substream *substream) +{ + int ret; + + ret = imx_pcm_free_dma_buffers(substream); + if (ret) + return ret; + + return snd_dmaengine_pcm_close_release_chan(substream); +} + static struct snd_pcm_ops imx_pcm_ops = { .open = imx_pcm_open, - .close = snd_dmaengine_pcm_close_release_chan, + .close = imx_pcm_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = imx_pcm_hw_params, .hw_free = imx_pcm_hw_free, @@ -215,82 +252,21 @@ static struct snd_pcm_ops imx_pcm_ops = { .mmap = imx_pcm_mmap, }; -static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, - int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = imx_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - - buf->bytes = size; - return 0; -} - -static void imx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = SNDRV_PCM_STREAM_PLAYBACK; stream < SNDRV_PCM_STREAM_LAST; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret; + int ret = 0; ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); if (ret) return ret; - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = imx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = imx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - -out: - /* free preallocated buffers in case of error */ - if (ret) - imx_pcm_free_dma_buffers(pcm); - return ret; } static struct snd_soc_component_driver imx_soc_platform = { .ops = &imx_pcm_ops, .pcm_new = imx_pcm_new, - .pcm_free = imx_pcm_free_dma_buffers, }; int imx_pcm_platform_register(struct device *dev) |