summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorGary Zhang <b13634@freescale.com>2013-01-04 10:09:00 +0800
committerGary Zhang <b13634@freescale.com>2013-01-05 10:15:40 +0800
commit724fef3a8cbeac64b03c934d5a46f3249e30e404 (patch)
tree25dd0d960caf2b5c1be731002db73a79d3b12755 /sound
parent36b611f5e8c751a882f35eb6ec3647367e204d93 (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/Kconfig6
-rw-r--r--sound/soc/imx/imx-ssi.c96
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;
}
}