diff options
author | Gary Zhang <b13634@freescale.com> | 2013-01-04 10:09:00 +0800 |
---|---|---|
committer | Gary Zhang <b13634@freescale.com> | 2013-01-05 10:15:40 +0800 |
commit | 724fef3a8cbeac64b03c934d5a46f3249e30e404 (patch) | |
tree | 25dd0d960caf2b5c1be731002db73a79d3b12755 /sound | |
parent | 36b611f5e8c751a882f35eb6ec3647367e204d93 (diff) |
ENGR00238809-2 mx6sl: ssi: add IRAM support
locate SSI playback buffer into IRAM in mx6sl.
because left IRAM room is not enough to contain record
buffer, if IRAM allocation for record fails, record
buffer will use external ram
Signed-off-by: Gary Zhang <b13634@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/imx/Kconfig | 6 | ||||
-rw-r--r-- | sound/soc/imx/imx-ssi.c | 96 |
2 files changed, 99 insertions, 3 deletions
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 72d85503d495..e30ebbe7e131 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -124,4 +124,10 @@ config SND_SOC_IMX_HDMI help Say Y if you want to add support for SoC audio through IMX HDMI. +config SND_MXC_SOC_IRAM + bool "Locate SSI Audio DMA playback buffers in IRAM" + depends on MACH_MX6SL_EVK && MACH_MX6SL_ARM2 + help + Say Y if you don't want Audio playback buffers in external ram + endif # SND_IMX_SOC diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 060d093a0aa9..d398307873bf 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -1,7 +1,7 @@ /* * imx-ssi.c -- ALSA Soc Audio Layer * - * Copyright 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2010-2013 Freescale Semiconductor, Inc. All Rights Reserved. * * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> * @@ -53,6 +53,7 @@ #include <sound/soc.h> #include <mach/ssi.h> +#include <mach/iram.h> #include <mach/hardware.h> #include "imx-ssi.h" @@ -62,6 +63,9 @@ #define IMX_SSI_FORMATS \ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE) +#ifdef CONFIG_SND_MXC_SOC_IRAM +static int UseIRAM; +#endif /* * SSI Network Mode or TDM slots configuration. @@ -419,15 +423,61 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { .shutdown = imx_ssi_shutdown, }; +#ifdef CONFIG_SND_MXC_SOC_IRAM + +static struct vm_operations_struct snd_mxc_audio_playback_vm_ops = { + .open = snd_pcm_mmap_data_open, + .close = snd_pcm_mmap_data_close, +}; + +/* + enable user space access to iram buffer +*/ +static int imx_iram_audio_playback_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *area) +{ + struct snd_dma_buffer *buf = &substream->dma_buffer; + unsigned long off; + unsigned long phys; + unsigned long size; + int ret = 0; + + area->vm_ops = &snd_mxc_audio_playback_vm_ops; + area->vm_private_data = substream; + + off = area->vm_pgoff << PAGE_SHIFT; + phys = buf->addr + off; + size = area->vm_end - area->vm_start; + + area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); + area->vm_flags |= VM_IO; + ret = + remap_pfn_range(area, area->vm_start, phys >> PAGE_SHIFT, + size, area->vm_page_prot); + + return ret; +} +#endif + int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) { struct snd_pcm_runtime *runtime = substream->runtime; int ret; +#ifdef CONFIG_SND_MXC_SOC_IRAM + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + if ((!strncmp(rtd->cpu_dai->name, "imx-ssi", strlen("imx-ssi"))) + && (UseIRAM & (1<<substream->stream))) + ret = imx_iram_audio_playback_mmap(substream, vma); + else + ret = dma_mmap_coherent(NULL, vma, runtime->dma_area, + runtime->dma_addr, runtime->dma_bytes); +#else ret = dma_mmap_coherent(NULL, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); - +#endif pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, runtime->dma_area, runtime->dma_addr, @@ -442,6 +492,9 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) struct snd_soc_pcm_runtime *rtd = pcm->private_data; struct snd_dma_buffer *buf = &substream->dma_buffer; size_t size; +#ifdef CONFIG_SND_MXC_SOC_IRAM + unsigned long buf_paddr; +#endif if (!strncmp(rtd->cpu_dai->name, "imx-ssi", strlen("imx-ssi"))) size = IMX_SSI_DMABUF_SIZE; @@ -455,11 +508,34 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) buf->dev.type = SNDRV_DMA_TYPE_DEV; buf->dev.dev = pcm->card->dev; buf->private_data = NULL; + buf->bytes = size; + +#ifdef CONFIG_SND_MXC_SOC_IRAM + if (!strncmp(rtd->cpu_dai->name, "imx-ssi", strlen("imx-ssi"))) { + buf->area = iram_alloc(size, &buf_paddr); + if (!buf->area) { + buf->area = + dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + } else { + buf->addr = buf_paddr; + UseIRAM |= 1<<substream->stream; + } + } else { + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + + } +#else buf->area = dma_alloc_writecombine(pcm->card->dev, size, &buf->addr, GFP_KERNEL); if (!buf->area) return -ENOMEM; - buf->bytes = size; +#endif return 0; } @@ -500,6 +576,9 @@ void imx_pcm_free(struct snd_pcm *pcm) struct snd_pcm_substream *substream; struct snd_dma_buffer *buf; int stream; +#ifdef CONFIG_SND_MXC_SOC_IRAM + struct snd_soc_pcm_runtime *rtd = pcm->private_data; +#endif for (stream = 0; stream < 2; stream++) { substream = pcm->streams[stream].substream; @@ -510,8 +589,19 @@ void imx_pcm_free(struct snd_pcm *pcm) if (!buf->area) continue; +#ifdef CONFIG_SND_MXC_SOC_IRAM + if ((!strncmp(rtd->cpu_dai->name, "imx-ssi", strlen("imx-ssi"))) + && (UseIRAM & (1<<substream->stream))) { + iram_free(buf->addr, IMX_SSI_DMABUF_SIZE); + UseIRAM &= ~(1<<substream->stream); + } else { + dma_free_writecombine(pcm->card->dev, buf->bytes, + buf->area, buf->addr); + } +#else dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, buf->addr); +#endif buf->area = NULL; } } |