Skip to content

Commit

Permalink
ASoC: dmaengine-pcm: Make requesting the DMA channel at PCM open opti…
Browse files Browse the repository at this point in the history
…onal

Refactor the dmaengine PCM library to allow the DMA channel to be requested
before opening a PCM substream. snd_dmaengine_pcm_open() now expects a DMA
channel instead of a filter function and filter parameter as its parameters.
snd_dmaengine_pcm_close() is updated to not release the DMA channel. This allows
a dmaengine based PCM driver to request its channels before the substream is
opened.

The patch also introduces two new functions, snd_dmaengine_pcm_open_request_chan()
and snd_dmaengine_pcm_close_release_chan(), which have the same signature and
behaviour of the old snd_dmaengine_pcm_{open,close}() and internally use the new
variants of these functions. All users of snd_dmaengine_pcm_{open,close}() are
updated to use snd_dmaengine_pcm_open_request_chan() and
snd_dmaengine_pcm_close_release_chan().

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Tested-by: Stephen Warren <swarren@nvidia.com>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Lars-Peter Clausen authored and Mark Brown committed Apr 17, 2013
1 parent 69b6f19 commit 7c1c1d4
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 44 deletions.
6 changes: 5 additions & 1 deletion include/sound/dmaengine_pcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream);

int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
dma_filter_fn filter_fn, void *filter_data);
struct dma_chan *chan);
int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);

int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
dma_filter_fn filter_fn, void *filter_data);
int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream);

struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);

/**
Expand Down
6 changes: 3 additions & 3 deletions sound/soc/atmel/atmel-pcm-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
if (ssc->pdev)
sdata = ssc->pdev->dev.platform_data;

ret = snd_dmaengine_pcm_open(substream, filter, sdata);
ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
if (ret) {
pr_err("atmel-pcm: dmaengine pcm open failed\n");
return -EINVAL;
Expand All @@ -171,7 +171,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,

return 0;
err:
snd_dmaengine_pcm_close(substream);
snd_dmaengine_pcm_close_release_chan(substream);
return ret;
}

Expand All @@ -197,7 +197,7 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)

static struct snd_pcm_ops atmel_pcm_ops = {
.open = atmel_pcm_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = atmel_pcm_hw_params,
.prepare = atmel_pcm_dma_prepare,
Expand Down
5 changes: 3 additions & 2 deletions sound/soc/cirrus/ep93xx-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ static int ep93xx_pcm_open(struct snd_pcm_substream *substream)

snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);

return snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter,
return snd_dmaengine_pcm_open_request_chan(substream,
ep93xx_pcm_dma_filter,
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
}

Expand Down Expand Up @@ -100,7 +101,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,

static struct snd_pcm_ops ep93xx_pcm_ops = {
.open = ep93xx_pcm_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = ep93xx_pcm_hw_params,
.hw_free = ep93xx_pcm_hw_free,
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/fsl/imx-pcm-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ static int snd_imx_open(struct snd_pcm_substream *substream)

static struct snd_pcm_ops imx_pcm_ops = {
.open = snd_imx_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params,
.trigger = snd_dmaengine_pcm_trigger,
Expand Down
4 changes: 2 additions & 2 deletions sound/soc/mxs/mxs-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ static int snd_mxs_open(struct snd_pcm_substream *substream)

snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);

return snd_dmaengine_pcm_open(substream, filter,
return snd_dmaengine_pcm_open_request_chan(substream, filter,
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
}

Expand All @@ -104,7 +104,7 @@ static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,

static struct snd_pcm_ops mxs_pcm_ops = {
.open = snd_mxs_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_mxs_pcm_hw_params,
.trigger = snd_dmaengine_pcm_trigger,
Expand Down
7 changes: 4 additions & 3 deletions sound/soc/omap/omap-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,9 @@ static int omap_pcm_open(struct snd_pcm_substream *substream)

dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);

return snd_dmaengine_pcm_open(substream, omap_dma_filter_fn,
dma_data->filter_data);
return snd_dmaengine_pcm_open_request_chan(substream,
omap_dma_filter_fn,
dma_data->filter_data);
}

static int omap_pcm_mmap(struct snd_pcm_substream *substream,
Expand All @@ -135,7 +136,7 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,

static struct snd_pcm_ops omap_pcm_ops = {
.open = omap_pcm_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = omap_pcm_hw_params,
.hw_free = omap_pcm_hw_free,
Expand Down
5 changes: 3 additions & 2 deletions sound/soc/pxa/mmp-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
dma_data.dma_res = r;
dma_data.ssp_id = cpu_dai->id;

return snd_dmaengine_pcm_open(substream, filter, &dma_data);
return snd_dmaengine_pcm_open_request_chan(substream, filter,
&dma_data);
}

static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
Expand All @@ -148,7 +149,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream,

struct snd_pcm_ops mmp_pcm_ops = {
.open = mmp_pcm_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = mmp_pcm_hw_params,
.trigger = snd_dmaengine_pcm_trigger,
Expand Down
72 changes: 49 additions & 23 deletions sound/soc/soc-dmaengine-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,44 +254,38 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);

static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd,
dma_filter_fn filter_fn, void *filter_data)
static struct dma_chan *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);
prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data);

if (!prtd->dma_chan)
return -ENXIO;

return 0;
return dma_request_channel(mask, filter_fn, filter_data);
}

/**
* snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
* @substream: PCM substream
* @filter_fn: Filter function used to request the DMA channel
* @filter_data: Data passed to the DMA filter function
* @chan: DMA channel to use for data transfers
*
* 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. If you need
* to keep additional data attached to a substream use
* snd_dmaengine_pcm_{set,get}_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(struct snd_pcm_substream *substream,
dma_filter_fn filter_fn, void *filter_data)
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)
Expand All @@ -301,18 +295,35 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
if (!prtd)
return -ENOMEM;

ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data);
if (ret < 0) {
kfree(prtd);
return ret;
}
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,
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
Expand All @@ -321,11 +332,26 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);

dma_release_channel(prtd->dma_chan);
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");
5 changes: 3 additions & 2 deletions sound/soc/spear/spear_pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ static int spear_pcm_open(struct snd_pcm_substream *substream)
if (ret)
return ret;

return snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data)
return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter,
dma_data);
}

static int spear_pcm_mmap(struct snd_pcm_substream *substream,
Expand All @@ -79,7 +80,7 @@ static int spear_pcm_mmap(struct snd_pcm_substream *substream,

static struct snd_pcm_ops spear_pcm_ops = {
.open = spear_pcm_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = spear_pcm_hw_params,
.hw_free = spear_pcm_hw_free,
Expand Down
4 changes: 2 additions & 2 deletions sound/soc/tegra/tegra_pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
/* Set HW params now that initialization is complete */
snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);

ret = snd_dmaengine_pcm_open(substream, NULL, NULL);
ret = snd_dmaengine_pcm_open_request_chan(substream, NULL, NULL);
if (ret) {
dev_err(dev, "dmaengine pcm open failed with err %d\n", ret);
return ret;
Expand Down Expand Up @@ -144,7 +144,7 @@ static int tegra_pcm_mmap(struct snd_pcm_substream *substream,

static struct snd_pcm_ops tegra_pcm_ops = {
.open = tegra_pcm_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = tegra_pcm_hw_params,
.hw_free = tegra_pcm_hw_free,
Expand Down
6 changes: 3 additions & 3 deletions sound/soc/ux500/ux500_pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
dma_cfg->dst_info.data_width = mem_data_width;
}


ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg);
ret = snd_dmaengine_pcm_open_request_chan(substream, stedma40_filter,
dma_cfg);
if (ret) {
dev_dbg(dai->dev,
"%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n",
Expand Down Expand Up @@ -211,7 +211,7 @@ static int ux500_pcm_mmap(struct snd_pcm_substream *substream,

static struct snd_pcm_ops ux500_pcm_ops = {
.open = ux500_pcm_open,
.close = snd_dmaengine_pcm_close,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = ux500_pcm_hw_params,
.hw_free = ux500_pcm_hw_free,
Expand Down

0 comments on commit 7c1c1d4

Please sign in to comment.