From 0de64fbea026e5f62860e217a42c574774e30722 Mon Sep 17 00:00:00 2001 From: Gopikrishnaiah Anandan Date: Fri, 15 Feb 2013 14:26:52 -0500 Subject: [PATCH] ASoC: pcm: Add support for Hostless pcm Hostless PCM nodes will not exchange data with the userspace clients.Control paths will be setup by userspace clients. Signed-off-by: Gopikrishnaiah Anandan --- include/sound/pcm.h | 1 + sound/soc/soc-core.c | 27 ++++++++++++++++++--------- sound/soc/soc-pcm.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 41e708e6c865..6cb456e8da11 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -413,6 +413,7 @@ struct snd_pcm_substream { #endif /* misc flags */ unsigned int hw_opened: 1; + unsigned int hw_no_buffer: 1; /* substream may not have a buffer */ }; #define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3231dfe47fbc..f9a5b527a6ba 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -567,7 +567,8 @@ int snd_soc_suspend(struct device *dev) struct snd_soc_dai *dai = card->rtd[i].codec_dai; struct snd_soc_dai_driver *drv = dai->driver; - if (card->rtd[i].dai_link->ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend || + card->rtd[i].dai_link->no_pcm) continue; if (card->rtd[i].dai_link->dynamic) @@ -580,7 +581,8 @@ int snd_soc_suspend(struct device *dev) /* suspend all pcms */ for (i = 0; i < card->num_rtd; i++) { - if (card->rtd[i].dai_link->ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend || + card->rtd[i].dai_link->no_pcm) continue; snd_pcm_suspend_all(card->rtd[i].pcm); @@ -593,7 +595,8 @@ int snd_soc_suspend(struct device *dev) struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; struct snd_soc_platform *platform = card->rtd[i].platform; - if (card->rtd[i].dai_link->ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend || + card->rtd[i].dai_link->no_pcm) continue; if (card->rtd[i].dai_link->dynamic) { @@ -618,7 +621,8 @@ int snd_soc_suspend(struct device *dev) for (i = 0; i < card->num_rtd; i++) { struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver; - if (card->rtd[i].dai_link->ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend || + card->rtd[i].dai_link->no_pcm) continue; if (driver->playback.stream_name != NULL) @@ -652,7 +656,8 @@ int snd_soc_suspend(struct device *dev) for (i = 0; i < card->num_rtd; i++) { struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; - if (card->rtd[i].dai_link->ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend || + card->rtd[i].dai_link->no_pcm) continue; if (card->rtd[i].dai_link->dynamic) @@ -695,7 +700,8 @@ static void soc_resume_deferred(struct work_struct *work) for (i = 0; i < card->num_rtd; i++) { struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; - if (card->rtd[i].dai_link->ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend || + card->rtd[i].dai_link->no_pcm) continue; if (card->rtd[i].dai_link->dynamic) @@ -727,7 +733,8 @@ static void soc_resume_deferred(struct work_struct *work) for (i = 0; i < card->num_rtd; i++) { struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver; - if (card->rtd[i].dai_link->ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend || + card->rtd[i].dai_link->no_pcm) continue; if (driver->playback.stream_name != NULL) @@ -744,7 +751,8 @@ static void soc_resume_deferred(struct work_struct *work) struct snd_soc_dai *dai = card->rtd[i].codec_dai; struct snd_soc_dai_driver *drv = dai->driver; - if (card->rtd[i].dai_link->ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend || + card->rtd[i].dai_link->no_pcm) continue; if (card->rtd[i].dai_link->dynamic) @@ -759,7 +767,8 @@ static void soc_resume_deferred(struct work_struct *work) struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; struct snd_soc_platform *platform = card->rtd[i].platform; - if (card->rtd[i].dai_link->ignore_suspend) + if (card->rtd[i].dai_link->ignore_suspend || + card->rtd[i].dai_link->no_pcm) continue; if (card->rtd[i].dai_link->dynamic) { diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 9d8c02a8db08..e45166f10c43 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -31,9 +31,29 @@ #include #include #include + #define MAX_BE_USERS 8 /* adjust if too low for everday use */ static int soc_dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream); + +/* 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, +}; + /* * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE * are not running, paused or suspended for the specified stream direction. @@ -194,6 +214,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); @@ -606,6 +629,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; @@ -658,6 +695,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; }