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@xxxxxxxxx> > --- > 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@xxxxxxxxxx> > + * > + * Based on: > + * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> > + * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. > + * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@xxxxxxxxxxxxxx> > + * 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@xxxxxxxxxx> > - * > - * Based on: > - * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> > - * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc. > - * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@xxxxxxxxxxxxxx> > - * 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 > -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html