1
0
Fork 0

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)
pull/10/head
Shengjiu Wang 2018-08-14 17:06:08 +08:00 committed by Jason Liu
parent 22bbd9f2a3
commit e4a97e60b7
1 changed files with 39 additions and 63 deletions

View File

@ -122,6 +122,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;
@ -208,6 +230,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)
@ -227,9 +253,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,
@ -238,82 +275,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_platform_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)