From aa5d0cdc64e9109333fa5c36608a0e56f3a08c0f Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 10 Jan 2017 17:10:17 -0800 Subject: [PATCH] ANDROID: GKI: 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. Test: build Bug: 151372815 Change-Id: I8947f1ad2c4a7013e92e21078b35e3cad332cf6f Signed-off-by: Liam Girdwood Signed-off-by: Patrick Lai Git-commit: b77e8f4fb684f8afd45d4276e3dba9edd4a0c4e0 Git-repo: https://source.codeaurora.org/quic/la/kernel/msm/log/?h=msm-2.6.38 [bgoswami@codeaurora.org: fix merge conflict by moving code to the right source file. Fix checkpatch errors for line over 80 character. Fix compilation errors.] Signed-off-by: Banajit Goswami Signed-off-by: Meng Wang (cherry picked from commit c009f70138e1b66c6ae9597947b56a761f92bc0d) Signed-off-by: Hridya Valsaraju --- include/sound/soc.h | 10 +++++++++ sound/soc/soc-pcm.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index dc3dcad05929..f213d39d7c3c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -380,6 +380,10 @@ #define SND_SOC_COMP_ORDER_LATE 1 #define SND_SOC_COMP_ORDER_LAST 2 +/* DAI Link Host Mode Support */ +#define SND_SOC_DAI_LINK_NO_HOST 0x1 +#define SND_SOC_DAI_LINK_OPT_HOST 0x2 + /* * Bias levels * @@ -976,6 +980,12 @@ struct snd_soc_dai_link { /* This DAI link can route to other DAI links at runtime (Frontend)*/ unsigned int dynamic:1; + /* + * This DAI can support no host IO (no pcm data is + * copied to from host) + */ + unsigned int no_host_mode:2; + /* DPCM capture and Playback support */ unsigned int dpcm_capture:1; unsigned int dpcm_playback:1; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 356d4e754561..d07d323d8dcb 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -28,6 +28,25 @@ #define DPCM_MAX_BE_USERS 8 +/* + * 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, +}; + /* * snd_soc_dai_stream_valid() - check if a DAI supports the given stream * @@ -493,6 +512,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); @@ -1007,6 +1029,20 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, ret = soc_pcm_params_symmetry(substream, params); if (ret) goto component_err; + + /* 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.private_data = NULL; + + ret = snd_pcm_lib_malloc_pages(substream, PAGE_SIZE); + if (ret < 0) + goto component_err; + } out: mutex_unlock(&rtd->pcm_mutex); return ret; @@ -1089,6 +1125,8 @@ 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; } @@ -3150,6 +3188,18 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) goto out; } + /* setup any hostless PCMs - i.e. no host IO is performed */ + if (rtd->dai_link->no_host_mode) { + pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->hw_no_buffer = 1; + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->hw_no_buffer = 1; + snd_soc_set_runtime_hwparams( + pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, + &no_host_hardware); + snd_soc_set_runtime_hwparams( + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, + &no_host_hardware); + } + /* ASoC PCM operations */ if (rtd->dai_link->dynamic) { rtd->ops.open = dpcm_fe_dai_open;