summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@ti.com>2011-12-02 09:57:52 +0800
committerSebastien Jan <s-jan@ti.com>2011-12-05 11:20:23 +0100
commitc14dc6545b2acb3ac719040d966780fdc6610b3b (patch)
treea64c44e5aef0ce8ecca1f6be94d82f70686bb286 /sound
parent6309ecdd4429e851553d250d9c7f9372b21eac7b (diff)
ASoC: core - add hostless DAI support
Allow DAI's to be hostless so that no PCM data is sent between DAI and CPU. This allows for power savings as there is no DMA or CPU interaction required. TODO: we shouldn't need to allocate a PAGE for a dummy DMA buffer. Signed-off-by: Liam Girdwood <lrg@ti.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/soc-pcm.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 5895bae24956..875847621231 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -31,6 +32,24 @@
#include <sound/soc-dsp.h>
#include <sound/initval.h>
+/* ASoC no host IO hardware.
+ * TODO: fine tune these values for all host less transfers.
+ */
+static const struct snd_pcm_hardware no_host_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .period_bytes_min = PAGE_SIZE >> 2,
+ .period_bytes_max = PAGE_SIZE >> 1,
+ .periods_min = 2,
+ .periods_max = 4,
+ .buffer_bytes_max = PAGE_SIZE,
+};
+
/* count the number of FE clients in a particular state */
int soc_dsp_fe_state_count(struct snd_soc_pcm_runtime *be, int stream,
enum snd_soc_dsp_state state)
@@ -99,6 +118,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
+ if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
+ snd_soc_set_runtime_hwparams(substream, &no_host_hardware);
+
/* startup the audio subsystem */
if (cpu_dai->driver->ops->startup) {
ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
@@ -491,6 +513,20 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
cpu_dai->rate = params_rate(params);
codec_dai->rate = params_rate(params);
+ /* malloc a page for hostless IO.
+ * FIXME: rework with alsa-lib changes so that this malloc is not required.
+ */
+ if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) {
+ substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV;
+ substream->dma_buffer.dev.dev = &rtd->dev;
+ substream->dma_buffer.dev.dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ substream->dma_buffer.private_data = NULL;
+
+ ret = snd_pcm_lib_malloc_pages(substream, PAGE_SIZE);
+ if (ret < 0)
+ goto platform_err;
+ }
+
out:
mutex_unlock(&rtd->pcm_mutex);
return ret;
@@ -543,6 +579,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
if (cpu_dai->driver->ops->hw_free)
cpu_dai->driver->ops->hw_free(substream, cpu_dai);
+ if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST)
+ snd_pcm_lib_free_pages(substream);
+
mutex_unlock(&rtd->pcm_mutex);
return 0;
}
@@ -2159,7 +2198,6 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
&no_host_hardware);
}
-
/* ASoC PCM operations */
if (rtd->dai_link->dynamic) {
rtd->ops.open = soc_dsp_fe_dai_open;