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.

Change-Id: I8947f1ad2c4a7013e92e21078b35e3cad332cf6f
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Patrick Lai <plai@codeaurora.org>
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 <bgoswami@codeaurora.org>
Signed-off-by: Meng Wang <mwang@codeaurora.org>
This commit is contained in:
Liam Girdwood 2017-01-10 17:10:17 -08:00 committed by Gerrit - the friendly Code Review server
parent 563a50719c
commit c009f70138
2 changed files with 60 additions and 0 deletions

View file

@ -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
*
@ -968,6 +972,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;

View file

@ -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);
@ -1004,6 +1026,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;
@ -1086,6 +1122,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;
}
@ -3105,6 +3143,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;