Date:2013-04-15 19:19:48 (9 years 5 months ago)
Author:Lars C.
Commit:e836ae0a9e7a76bb1a8a776851cb0b32b458d24f
Message:ASoC: dmaengine-pcm: Make requesting the DMA channel at PCM open optional

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>
Files: include/sound/dmaengine_pcm.h (1 diff)
sound/soc/atmel/atmel-pcm-dma.c (3 diffs)
sound/soc/cirrus/ep93xx-pcm.c (2 diffs)
sound/soc/fsl/imx-pcm-dma.c (1 diff)
sound/soc/mxs/mxs-pcm.c (2 diffs)
sound/soc/omap/omap-pcm.c (2 diffs)
sound/soc/pxa/mmp-pcm.c (2 diffs)
sound/soc/soc-dmaengine-pcm.c (4 diffs)
sound/soc/spear/spear_pcm.c (2 diffs)
sound/soc/tegra/tegra_pcm.c (2 diffs)
sound/soc/ux500/ux500_pcm.c (2 diffs)

Change Details

include/sound/dmaengine_pcm.h
3939snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream);
4040
4141int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
42    dma_filter_fn filter_fn, void *filter_data);
42    struct dma_chan *chan);
4343int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
4444
45int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
46    dma_filter_fn filter_fn, void *filter_data);
47int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream);
48
4549struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
4650
4751/**
sound/soc/atmel/atmel-pcm-dma.c
155155    if (ssc->pdev)
156156        sdata = ssc->pdev->dev.platform_data;
157157
158    ret = snd_dmaengine_pcm_open(substream, filter, sdata);
158    ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
159159    if (ret) {
160160        pr_err("atmel-pcm: dmaengine pcm open failed\n");
161161        return -EINVAL;
...... 
171171
172172    return 0;
173173err:
174    snd_dmaengine_pcm_close(substream);
174    snd_dmaengine_pcm_close_release_chan(substream);
175175    return ret;
176176}
177177
...... 
197197
198198static struct snd_pcm_ops atmel_pcm_ops = {
199199    .open = atmel_pcm_open,
200    .close = snd_dmaengine_pcm_close,
200    .close = snd_dmaengine_pcm_close_release_chan,
201201    .ioctl = snd_pcm_lib_ioctl,
202202    .hw_params = atmel_pcm_hw_params,
203203    .prepare = atmel_pcm_dma_prepare,
sound/soc/cirrus/ep93xx-pcm.c
6969
7070    snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
7171
72    return snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter,
72    return snd_dmaengine_pcm_open_request_chan(substream,
73            ep93xx_pcm_dma_filter,
7374            snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
7475}
7576
...... 
100101
101102static struct snd_pcm_ops ep93xx_pcm_ops = {
102103    .open = ep93xx_pcm_open,
103    .close = snd_dmaengine_pcm_close,
104    .close = snd_dmaengine_pcm_close_release_chan,
104105    .ioctl = snd_pcm_lib_ioctl,
105106    .hw_params = ep93xx_pcm_hw_params,
106107    .hw_free = ep93xx_pcm_hw_free,
sound/soc/fsl/imx-pcm-dma.c
100100
101101static struct snd_pcm_ops imx_pcm_ops = {
102102    .open = snd_imx_open,
103    .close = snd_dmaengine_pcm_close,
103    .close = snd_dmaengine_pcm_close_release_chan,
104104    .ioctl = snd_pcm_lib_ioctl,
105105    .hw_params = snd_imx_pcm_hw_params,
106106    .trigger = snd_dmaengine_pcm_trigger,
sound/soc/mxs/mxs-pcm.c
8787
8888    snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
8989
90    return snd_dmaengine_pcm_open(substream, filter,
90    return snd_dmaengine_pcm_open_request_chan(substream, filter,
9191        snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
9292}
9393
...... 
104104
105105static struct snd_pcm_ops mxs_pcm_ops = {
106106    .open = snd_mxs_open,
107    .close = snd_dmaengine_pcm_close,
107    .close = snd_dmaengine_pcm_close_release_chan,
108108    .ioctl = snd_pcm_lib_ioctl,
109109    .hw_params = snd_mxs_pcm_hw_params,
110110    .trigger = snd_dmaengine_pcm_trigger,
sound/soc/omap/omap-pcm.c
118118
119119    dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
120120
121    return snd_dmaengine_pcm_open(substream, omap_dma_filter_fn,
122                      dma_data->filter_data);
121    return snd_dmaengine_pcm_open_request_chan(substream,
122                           omap_dma_filter_fn,
123                           dma_data->filter_data);
123124}
124125
125126static int omap_pcm_mmap(struct snd_pcm_substream *substream,
...... 
135136
136137static struct snd_pcm_ops omap_pcm_ops = {
137138    .open = omap_pcm_open,
138    .close = snd_dmaengine_pcm_close,
139    .close = snd_dmaengine_pcm_close_release_chan,
139140    .ioctl = snd_pcm_lib_ioctl,
140141    .hw_params = omap_pcm_hw_params,
141142    .hw_free = omap_pcm_hw_free,
sound/soc/pxa/mmp-pcm.c
131131    dma_data.dma_res = r;
132132    dma_data.ssp_id = cpu_dai->id;
133133
134    return snd_dmaengine_pcm_open(substream, filter, &dma_data);
134    return snd_dmaengine_pcm_open_request_chan(substream, filter,
135            &dma_data);
135136}
136137
137138static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
...... 
148149
149150struct snd_pcm_ops mmp_pcm_ops = {
150151    .open = mmp_pcm_open,
151    .close = snd_dmaengine_pcm_close,
152    .close = snd_dmaengine_pcm_close_release_chan,
152153    .ioctl = snd_pcm_lib_ioctl,
153154    .hw_params = mmp_pcm_hw_params,
154155    .trigger = snd_dmaengine_pcm_trigger,
sound/soc/soc-dmaengine-pcm.c
254254}
255255EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
256256
257static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd,
258    dma_filter_fn filter_fn, void *filter_data)
257static struct dma_chan *dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
258    void *filter_data)
259259{
260260    dma_cap_mask_t mask;
261261
262262    dma_cap_zero(mask);
263263    dma_cap_set(DMA_SLAVE, mask);
264264    dma_cap_set(DMA_CYCLIC, mask);
265    prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data);
266
267    if (!prtd->dma_chan)
268        return -ENXIO;
269265
270    return 0;
266    return dma_request_channel(mask, filter_fn, filter_data);
271267}
272268
273269/**
274270 * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
275271 * @substream: PCM substream
276 * @filter_fn: Filter function used to request the DMA channel
277 * @filter_data: Data passed to the DMA filter function
272 * @chan: DMA channel to use for data transfers
278273 *
279274 * Returns 0 on success, a negative error code otherwise.
280275 *
281 * This function will request a DMA channel using the passed filter function and
282 * data. The function should usually be called from the pcm open callback.
283 *
284 * Note that this function will use private_data field of the substream's
285 * runtime. So it is not availabe to your pcm driver implementation. If you need
286 * to keep additional data attached to a substream use
287 * snd_dmaengine_pcm_{set,get}_data.
276 * The function should usually be called from the pcm open callback. Note that
277 * this function will use private_data field of the substream's runtime. So it
278 * is not availabe to your pcm driver implementation.
288279 */
289280int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
290    dma_filter_fn filter_fn, void *filter_data)
281    struct dma_chan *chan)
291282{
292283    struct dmaengine_pcm_runtime_data *prtd;
293284    int ret;
294285
286    if (!chan)
287        return -ENXIO;
288
295289    ret = snd_pcm_hw_constraint_integer(substream->runtime,
296290                        SNDRV_PCM_HW_PARAM_PERIODS);
297291    if (ret < 0)
...... 
301295    if (!prtd)
302296        return -ENOMEM;
303297
304    ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data);
305    if (ret < 0) {
306        kfree(prtd);
307        return ret;
308    }
298    prtd->dma_chan = chan;
309299
310300    substream->runtime->private_data = prtd;
311301
...... 
314304EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
315305
316306/**
307 * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel
308 * @substream: PCM substream
309 * @filter_fn: Filter function used to request the DMA channel
310 * @filter_data: Data passed to the DMA filter function
311 *
312 * Returns 0 on success, a negative error code otherwise.
313 *
314 * This function will request a DMA channel using the passed filter function and
315 * data. The function should usually be called from the pcm open callback. Note
316 * that this function will use private_data field of the substream's runtime. So
317 * it is not availabe to your pcm driver implementation.
318 */
319int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
320    dma_filter_fn filter_fn, void *filter_data)
321{
322    return snd_dmaengine_pcm_open(substream,
323            dmaengine_pcm_request_channel(filter_fn, filter_data));
324}
325EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
326
327/**
317328 * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
318329 * @substream: PCM substream
319330 */
...... 
321332{
322333    struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
323334
324    dma_release_channel(prtd->dma_chan);
325335    kfree(prtd);
326336
327337    return 0;
328338}
329339EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
330340
341/**
342 * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel
343 * @substream: PCM substream
344 *
345 * Releases the DMA channel associated with the PCM substream.
346 */
347int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream)
348{
349    struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
350
351    dma_release_channel(prtd->dma_chan);
352
353    return snd_dmaengine_pcm_close(substream);
354}
355EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan);
356
331357MODULE_LICENSE("GPL");
sound/soc/spear/spear_pcm.c
6464    if (ret)
6565        return ret;
6666
67    return snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data)
67    return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter,
68                dma_data);
6869}
6970
7071static int spear_pcm_mmap(struct snd_pcm_substream *substream,
...... 
7980
8081static struct snd_pcm_ops spear_pcm_ops = {
8182    .open = spear_pcm_open,
82    .close = snd_dmaengine_pcm_close,
83    .close = snd_dmaengine_pcm_close_release_chan,
8384    .ioctl = snd_pcm_lib_ioctl,
8485    .hw_params = spear_pcm_hw_params,
8586    .hw_free = spear_pcm_hw_free,
sound/soc/tegra/tegra_pcm.c
6464    /* Set HW params now that initialization is complete */
6565    snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
6666
67    ret = snd_dmaengine_pcm_open(substream, NULL, NULL);
67    ret = snd_dmaengine_pcm_open_request_chan(substream, NULL, NULL);
6868    if (ret) {
6969        dev_err(dev, "dmaengine pcm open failed with err %d\n", ret);
7070        return ret;
...... 
122122
123123static struct snd_pcm_ops tegra_pcm_ops = {
124124    .open = tegra_pcm_open,
125    .close = snd_dmaengine_pcm_close,
125    .close = snd_dmaengine_pcm_close_release_chan,
126126    .ioctl = snd_pcm_lib_ioctl,
127127    .hw_params = tegra_pcm_hw_params,
128128    .hw_free = tegra_pcm_hw_free,
sound/soc/ux500/ux500_pcm.c
146146        dma_cfg->dst_info.data_width = mem_data_width;
147147    }
148148
149
150    ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg);
149    ret = snd_dmaengine_pcm_open_request_chan(substream, stedma40_filter,
150            dma_cfg);
151151    if (ret) {
152152        dev_dbg(dai->dev,
153153            "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n",
...... 
232232
233233static struct snd_pcm_ops ux500_pcm_ops = {
234234    .open = ux500_pcm_open,
235    .close = snd_dmaengine_pcm_close,
235    .close = snd_dmaengine_pcm_close_release_chan,
236236    .ioctl = snd_pcm_lib_ioctl,
237237    .hw_params = ux500_pcm_hw_params,
238238    .hw_free = ux500_pcm_hw_free,

Archive Download the corresponding diff file



interactive