On 12.08.2013 10:42, Daniel Mack wrote:
For the PXA DMA rework, we need the generic dmaengine implementation that currently lives in sound/soc for standalone (non-ASoC) AC'97 support.
Sorry, I forgot to copy Lars in this one.
Move it to sound/core, and rename the Kconfig symbol.
Signed-off-by: Daniel Mack zonque@gmail.com
sound/core/Kconfig | 3 + sound/core/Makefile | 3 + sound/core/pcm_dmaengine.c | 367 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/Kconfig | 5 +- sound/soc/Makefile | 4 - sound/soc/omap/Kconfig | 2 +- sound/soc/pxa/Kconfig | 2 +- sound/soc/soc-dmaengine-pcm.c | 367 ------------------------------------------ sound/soc/spear/Kconfig | 2 +- 9 files changed, 377 insertions(+), 378 deletions(-) create mode 100644 sound/core/pcm_dmaengine.c delete mode 100644 sound/soc/soc-dmaengine-pcm.c
diff --git a/sound/core/Kconfig b/sound/core/Kconfig index c0c2f57..94ce1c4 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -6,6 +6,9 @@ config SND_PCM tristate select SND_TIMER
+config SND_DMAENGINE_PCM
- bool
config SND_HWDEP tristate
diff --git a/sound/core/Makefile b/sound/core/Makefile index 43d4117..5e890cf 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -13,6 +13,8 @@ snd-$(CONFIG_SND_JACK) += jack.o snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ pcm_memory.o
+snd-pcm-dmaengine-objs := pcm_dmaengine.o
snd-page-alloc-y := memalloc.o snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
@@ -30,6 +32,7 @@ obj-$(CONFIG_SND_TIMER) += snd-timer.o obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o +obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
obj-$(CONFIG_SND_OSSEMUL) += oss/ diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c new file mode 100644 index 0000000..aa924d9 --- /dev/null +++ b/sound/core/pcm_dmaengine.c @@ -0,0 +1,367 @@ +/*
- Copyright (C) 2012, Analog Devices Inc.
- Author: Lars-Peter Clausen lars@metafoo.de
- Based on:
- imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer s.hauer@pengutronix.de
- mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc.
- ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek buytenh@wantstofly.org
Copyright (C) 2006 Applied Data Systems
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+#include <linux/module.h> +#include <linux/init.h> +#include <linux/dmaengine.h> +#include <linux/slab.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+struct dmaengine_pcm_runtime_data {
- struct dma_chan *dma_chan;
- dma_cookie_t cookie;
- unsigned int pos;
+};
+static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
- const struct snd_pcm_substream *substream)
+{
- return substream->runtime->private_data;
+}
+struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) +{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- return prtd->dma_chan;
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan);
+/**
- snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config
- @substream: PCM substream
- @params: hw_params
- @slave_config: DMA slave config
- This function can be used to initialize a dma_slave_config from a substream
- and hw_params in a dmaengine based PCM driver implementation.
- */
+int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
- const struct snd_pcm_hw_params *params,
- struct dma_slave_config *slave_config)
+{
- enum dma_slave_buswidth buswidth;
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
break;
- case SNDRV_PCM_FORMAT_S16_LE:
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
- case SNDRV_PCM_FORMAT_S18_3LE:
- case SNDRV_PCM_FORMAT_S20_3LE:
- case SNDRV_PCM_FORMAT_S24_LE:
- case SNDRV_PCM_FORMAT_S32_LE:
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
- default:
return -EINVAL;
- }
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config->direction = DMA_MEM_TO_DEV;
slave_config->dst_addr_width = buswidth;
- } else {
slave_config->direction = DMA_DEV_TO_MEM;
slave_config->src_addr_width = buswidth;
- }
- slave_config->device_fc = false;
- return 0;
+} +EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config);
+/**
- snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config
- using DAI DMA data.
- @substream: PCM substream
- @dma_data: DAI DMA data
- @slave_config: DMA slave configuration
- Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and
- slave_id fields of the DMA slave config from the same fields of the DAI DMA
- data struct. The src and dst fields will be initialized depending on the
- direction of the substream. If the substream is a playback stream the dst
- fields will be initialized, if it is a capture stream the src fields will be
- initialized. The {dst,src}_addr_width field will only be initialized if the
- addr_width field of the DAI DMA data struct is not equal to
- DMA_SLAVE_BUSWIDTH_UNDEFINED.
- */
+void snd_dmaengine_pcm_set_config_from_dai_data(
- const struct snd_pcm_substream *substream,
- const struct snd_dmaengine_dai_dma_data *dma_data,
- struct dma_slave_config *slave_config)
+{
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config->dst_addr = dma_data->addr;
slave_config->dst_maxburst = dma_data->maxburst;
if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
slave_config->dst_addr_width = dma_data->addr_width;
- } else {
slave_config->src_addr = dma_data->addr;
slave_config->src_maxburst = dma_data->maxburst;
if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
slave_config->src_addr_width = dma_data->addr_width;
- }
- slave_config->slave_id = dma_data->slave_id;
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
+static void dmaengine_pcm_dma_complete(void *arg) +{
- struct snd_pcm_substream *substream = arg;
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- prtd->pos += snd_pcm_lib_period_bytes(substream);
- if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
prtd->pos = 0;
- snd_pcm_period_elapsed(substream);
+}
+static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) +{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- struct dma_chan *chan = prtd->dma_chan;
- struct dma_async_tx_descriptor *desc;
- enum dma_transfer_direction direction;
- unsigned long flags = DMA_CTRL_ACK;
- direction = snd_pcm_substream_to_dma_direction(substream);
- if (!substream->runtime->no_period_wakeup)
flags |= DMA_PREP_INTERRUPT;
- prtd->pos = 0;
- desc = dmaengine_prep_dma_cyclic(chan,
substream->runtime->dma_addr,
snd_pcm_lib_buffer_bytes(substream),
snd_pcm_lib_period_bytes(substream), direction, flags);
- if (!desc)
return -ENOMEM;
- desc->callback = dmaengine_pcm_dma_complete;
- desc->callback_param = substream;
- prtd->cookie = dmaengine_submit(desc);
- return 0;
+}
+/**
- snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation
- @substream: PCM substream
- @cmd: Trigger command
- Returns 0 on success, a negative error code otherwise.
- This function can be used as the PCM trigger callback for dmaengine based PCM
- driver implementations.
- */
+int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- int ret;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
ret = dmaengine_pcm_prepare_and_submit(substream);
if (ret)
return ret;
dma_async_issue_pending(prtd->dma_chan);
break;
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
dmaengine_resume(prtd->dma_chan);
break;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
dmaengine_pause(prtd->dma_chan);
break;
- case SNDRV_PCM_TRIGGER_STOP:
dmaengine_terminate_all(prtd->dma_chan);
break;
- default:
return -EINVAL;
- }
- return 0;
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
+/**
- snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation
- @substream: PCM substream
- This function is deprecated and should not be used by new drivers, as its
- results may be unreliable.
- */
+snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) +{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- return bytes_to_frames(substream->runtime, prtd->pos);
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue);
+/**
- snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation
- @substream: PCM substream
- This function can be used as the PCM pointer callback for dmaengine based PCM
- driver implementations.
- */
+snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) +{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- struct dma_tx_state state;
- enum dma_status status;
- unsigned int buf_size;
- unsigned int pos = 0;
- status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state);
- if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) {
buf_size = snd_pcm_lib_buffer_bytes(substream);
if (state.residue > 0 && state.residue <= buf_size)
pos = buf_size - state.residue;
- }
- return bytes_to_frames(substream->runtime, pos);
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
+/**
- snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM
- @filter_fn: Filter function used to request the DMA channel
- @filter_data: Data passed to the DMA filter function
- Returns NULL or the requested DMA channel.
- This function request a DMA channel for usage with dmaengine PCM.
- */
+struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
- void *filter_data)
+{
- dma_cap_mask_t mask;
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- dma_cap_set(DMA_CYCLIC, mask);
- return dma_request_channel(mask, filter_fn, filter_data);
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel);
+/**
- snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
- @substream: PCM substream
- @chan: DMA channel to use for data transfers
- Returns 0 on success, a negative error code otherwise.
- The function should usually be called from the pcm open callback. Note that
- this function will use private_data field of the substream's runtime. So it
- is not availabe to your pcm driver implementation.
- */
+int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
- struct dma_chan *chan)
+{
- struct dmaengine_pcm_runtime_data *prtd;
- int ret;
- if (!chan)
return -ENXIO;
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
return ret;
- prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
- if (!prtd)
return -ENOMEM;
- prtd->dma_chan = chan;
- substream->runtime->private_data = prtd;
- return 0;
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
+/**
- snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel
- @substream: PCM substream
- @filter_fn: Filter function used to request the DMA channel
- @filter_data: Data passed to the DMA filter function
- Returns 0 on success, a negative error code otherwise.
- This function will request a DMA channel using the passed filter function and
- data. The function should usually be called from the pcm open callback. Note
- that this function will use private_data field of the substream's runtime. So
- it is not availabe to your pcm driver implementation.
- */
+int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
- dma_filter_fn filter_fn, void *filter_data)
+{
- return snd_dmaengine_pcm_open(substream,
snd_dmaengine_pcm_request_channel(filter_fn, filter_data));
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
+/**
- snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
- @substream: PCM substream
- */
+int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) +{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- kfree(prtd);
- return 0;
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
+/**
- snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel
- @substream: PCM substream
- Releases the DMA channel associated with the PCM substream.
- */
+int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) +{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- dma_release_channel(prtd->dma_chan);
- return snd_dmaengine_pcm_close(substream);
+} +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan);
+MODULE_LICENSE("GPL"); diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 45eeaa9..5138b84 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -26,12 +26,9 @@ if SND_SOC config SND_SOC_AC97_BUS bool
-config SND_SOC_DMAENGINE_PCM
- bool
config SND_SOC_GENERIC_DMAENGINE_PCM bool
- select SND_SOC_DMAENGINE_PCM
- select SND_DMAENGINE_PCM
# All the supported SoCs source "sound/soc/atmel/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index bc02614..61a64d2 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,10 +1,6 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o
-ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),) -snd-soc-core-objs += soc-dmaengine-pcm.o -endif
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) snd-soc-core-objs += soc-generic-dmaengine-pcm.o endif diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 9f5d55e..accd0ff 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -1,7 +1,7 @@ config SND_OMAP_SOC tristate "SoC Audio for the Texas Instruments OMAP chips" depends on ARCH_OMAP && DMA_OMAP
- select SND_SOC_DMAENGINE_PCM
- select SND_DMAENGINE_PCM
config SND_OMAP_SOC_DMIC tristate diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index b358094..4db74a0 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -11,7 +11,7 @@ config SND_PXA2XX_SOC config SND_MMP_SOC bool "Soc Audio for Marvell MMP chips" depends on ARCH_MMP
- select SND_SOC_DMAENGINE_PCM
- select SND_DMAENGINE_PCM select SND_ARM help Say Y if you want to add support for codecs attached to
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c deleted file mode 100644 index aa924d9..0000000 --- a/sound/soc/soc-dmaengine-pcm.c +++ /dev/null @@ -1,367 +0,0 @@ -/*
- Copyright (C) 2012, Analog Devices Inc.
- Author: Lars-Peter Clausen lars@metafoo.de
- Based on:
- imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer s.hauer@pengutronix.de
- mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc.
- ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek buytenh@wantstofly.org
Copyright (C) 2006 Applied Data Systems
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/module.h> -#include <linux/init.h> -#include <linux/dmaengine.h> -#include <linux/slab.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h>
-#include <sound/dmaengine_pcm.h>
-struct dmaengine_pcm_runtime_data {
- struct dma_chan *dma_chan;
- dma_cookie_t cookie;
- unsigned int pos;
-};
-static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
- const struct snd_pcm_substream *substream)
-{
- return substream->runtime->private_data;
-}
-struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) -{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- return prtd->dma_chan;
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan);
-/**
- snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config
- @substream: PCM substream
- @params: hw_params
- @slave_config: DMA slave config
- This function can be used to initialize a dma_slave_config from a substream
- and hw_params in a dmaengine based PCM driver implementation.
- */
-int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
- const struct snd_pcm_hw_params *params,
- struct dma_slave_config *slave_config)
-{
- enum dma_slave_buswidth buswidth;
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
break;
- case SNDRV_PCM_FORMAT_S16_LE:
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
- case SNDRV_PCM_FORMAT_S18_3LE:
- case SNDRV_PCM_FORMAT_S20_3LE:
- case SNDRV_PCM_FORMAT_S24_LE:
- case SNDRV_PCM_FORMAT_S32_LE:
buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
- default:
return -EINVAL;
- }
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config->direction = DMA_MEM_TO_DEV;
slave_config->dst_addr_width = buswidth;
- } else {
slave_config->direction = DMA_DEV_TO_MEM;
slave_config->src_addr_width = buswidth;
- }
- slave_config->device_fc = false;
- return 0;
-} -EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config);
-/**
- snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config
- using DAI DMA data.
- @substream: PCM substream
- @dma_data: DAI DMA data
- @slave_config: DMA slave configuration
- Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and
- slave_id fields of the DMA slave config from the same fields of the DAI DMA
- data struct. The src and dst fields will be initialized depending on the
- direction of the substream. If the substream is a playback stream the dst
- fields will be initialized, if it is a capture stream the src fields will be
- initialized. The {dst,src}_addr_width field will only be initialized if the
- addr_width field of the DAI DMA data struct is not equal to
- DMA_SLAVE_BUSWIDTH_UNDEFINED.
- */
-void snd_dmaengine_pcm_set_config_from_dai_data(
- const struct snd_pcm_substream *substream,
- const struct snd_dmaengine_dai_dma_data *dma_data,
- struct dma_slave_config *slave_config)
-{
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
slave_config->dst_addr = dma_data->addr;
slave_config->dst_maxburst = dma_data->maxburst;
if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
slave_config->dst_addr_width = dma_data->addr_width;
- } else {
slave_config->src_addr = dma_data->addr;
slave_config->src_maxburst = dma_data->maxburst;
if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
slave_config->src_addr_width = dma_data->addr_width;
- }
- slave_config->slave_id = dma_data->slave_id;
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
-static void dmaengine_pcm_dma_complete(void *arg) -{
- struct snd_pcm_substream *substream = arg;
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- prtd->pos += snd_pcm_lib_period_bytes(substream);
- if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
prtd->pos = 0;
- snd_pcm_period_elapsed(substream);
-}
-static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) -{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- struct dma_chan *chan = prtd->dma_chan;
- struct dma_async_tx_descriptor *desc;
- enum dma_transfer_direction direction;
- unsigned long flags = DMA_CTRL_ACK;
- direction = snd_pcm_substream_to_dma_direction(substream);
- if (!substream->runtime->no_period_wakeup)
flags |= DMA_PREP_INTERRUPT;
- prtd->pos = 0;
- desc = dmaengine_prep_dma_cyclic(chan,
substream->runtime->dma_addr,
snd_pcm_lib_buffer_bytes(substream),
snd_pcm_lib_period_bytes(substream), direction, flags);
- if (!desc)
return -ENOMEM;
- desc->callback = dmaengine_pcm_dma_complete;
- desc->callback_param = substream;
- prtd->cookie = dmaengine_submit(desc);
- return 0;
-}
-/**
- snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation
- @substream: PCM substream
- @cmd: Trigger command
- Returns 0 on success, a negative error code otherwise.
- This function can be used as the PCM trigger callback for dmaengine based PCM
- driver implementations.
- */
-int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- int ret;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
ret = dmaengine_pcm_prepare_and_submit(substream);
if (ret)
return ret;
dma_async_issue_pending(prtd->dma_chan);
break;
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
dmaengine_resume(prtd->dma_chan);
break;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
dmaengine_pause(prtd->dma_chan);
break;
- case SNDRV_PCM_TRIGGER_STOP:
dmaengine_terminate_all(prtd->dma_chan);
break;
- default:
return -EINVAL;
- }
- return 0;
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
-/**
- snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation
- @substream: PCM substream
- This function is deprecated and should not be used by new drivers, as its
- results may be unreliable.
- */
-snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream) -{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- return bytes_to_frames(substream->runtime, prtd->pos);
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue);
-/**
- snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation
- @substream: PCM substream
- This function can be used as the PCM pointer callback for dmaengine based PCM
- driver implementations.
- */
-snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) -{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- struct dma_tx_state state;
- enum dma_status status;
- unsigned int buf_size;
- unsigned int pos = 0;
- status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state);
- if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) {
buf_size = snd_pcm_lib_buffer_bytes(substream);
if (state.residue > 0 && state.residue <= buf_size)
pos = buf_size - state.residue;
- }
- return bytes_to_frames(substream->runtime, pos);
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
-/**
- snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM
- @filter_fn: Filter function used to request the DMA channel
- @filter_data: Data passed to the DMA filter function
- Returns NULL or the requested DMA channel.
- This function request a DMA channel for usage with dmaengine PCM.
- */
-struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
- void *filter_data)
-{
- dma_cap_mask_t mask;
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- dma_cap_set(DMA_CYCLIC, mask);
- return dma_request_channel(mask, filter_fn, filter_data);
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel);
-/**
- snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
- @substream: PCM substream
- @chan: DMA channel to use for data transfers
- Returns 0 on success, a negative error code otherwise.
- The function should usually be called from the pcm open callback. Note that
- this function will use private_data field of the substream's runtime. So it
- is not availabe to your pcm driver implementation.
- */
-int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
- struct dma_chan *chan)
-{
- struct dmaengine_pcm_runtime_data *prtd;
- int ret;
- if (!chan)
return -ENXIO;
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
return ret;
- prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
- if (!prtd)
return -ENOMEM;
- prtd->dma_chan = chan;
- substream->runtime->private_data = prtd;
- return 0;
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
-/**
- snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel
- @substream: PCM substream
- @filter_fn: Filter function used to request the DMA channel
- @filter_data: Data passed to the DMA filter function
- Returns 0 on success, a negative error code otherwise.
- This function will request a DMA channel using the passed filter function and
- data. The function should usually be called from the pcm open callback. Note
- that this function will use private_data field of the substream's runtime. So
- it is not availabe to your pcm driver implementation.
- */
-int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
- dma_filter_fn filter_fn, void *filter_data)
-{
- return snd_dmaengine_pcm_open(substream,
snd_dmaengine_pcm_request_channel(filter_fn, filter_data));
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
-/**
- snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
- @substream: PCM substream
- */
-int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) -{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- kfree(prtd);
- return 0;
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
-/**
- snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel
- @substream: PCM substream
- Releases the DMA channel associated with the PCM substream.
- */
-int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) -{
- struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
- dma_release_channel(prtd->dma_chan);
- return snd_dmaengine_pcm_close(substream);
-} -EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan);
-MODULE_LICENSE("GPL"); diff --git a/sound/soc/spear/Kconfig b/sound/soc/spear/Kconfig index 3567d73..0a53053 100644 --- a/sound/soc/spear/Kconfig +++ b/sound/soc/spear/Kconfig @@ -1,6 +1,6 @@ config SND_SPEAR_SOC tristate
- select SND_SOC_DMAENGINE_PCM
- select SND_DMAENGINE_PCM
config SND_SPEAR_SPDIF_OUT tristate