Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2837197 authored by Gopikrishnaiah Anandan's avatar Gopikrishnaiah Anandan Committed by Stephen Boyd
Browse files

ASoC: core: Add support for hostless playback/capture



For capture/playback usecases in which host doesn't exchange
PCM data, audio driver creates hostless pcm devices.
Change adds support for hostless pcm devices.

Change-Id: I33c24381fffea569acd16763e1e196234d5b5466
Signed-off-by: default avatarGopikrishnaiah Anandan <agopik@codeaurora.org>
parent ff4e2069
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2237,6 +2237,8 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
	const struct snd_pcm_hardware *hw)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (!runtime)
		return 0;
	runtime->hw.info = hw->info;
	runtime->hw.formats = hw->formats;
	runtime->hw.period_bytes_min = hw->period_bytes_min;
+49 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/workqueue.h>
#include <linux/export.h>
#include <linux/debugfs.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -33,6 +34,21 @@

#define DPCM_MAX_BE_USERS	8

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,
};

/* DPCM stream event, send event to FE and all active BEs. */
static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
	int event)
@@ -148,7 +164,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
	pm_runtime_get_sync(platform->dev);

	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);
@@ -552,7 +569,19 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
	/* store the rate for each DAIs */
	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;
@@ -605,6 +634,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;
}
@@ -2069,6 +2101,22 @@ 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) {
		if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
			pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->hw_no_buffer = 1;
			snd_soc_set_runtime_hwparams(
				pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
				&no_host_hardware);
		}
		if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
			pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->hw_no_buffer = 1;
			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;