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);
/**
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;
return 0;
err:
- snd_dmaengine_pcm_close(substream);
+ snd_dmaengine_pcm_close_release_chan(substream);
return ret;
}
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,
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));
}
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,
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,
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));
}
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,
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,
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,
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,
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,
}
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)
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;
}
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
{
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");
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,
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,
/* 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;
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,
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",
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,