aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2013-04-15 13:19:48 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-17 09:17:54 -0400
commit7c1c1d4a7b4ca1266057a3632d27450f5575caf9 (patch)
tree39e53ebd108b551ba939fd13ca9e3c2f8f869400 /sound
parent69b6f19622ce0aef41df884b75e3f789c64b89c0 (diff)
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>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/atmel/atmel-pcm-dma.c6
-rw-r--r--sound/soc/cirrus/ep93xx-pcm.c5
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c2
-rw-r--r--sound/soc/mxs/mxs-pcm.c4
-rw-r--r--sound/soc/omap/omap-pcm.c7
-rw-r--r--sound/soc/pxa/mmp-pcm.c5
-rw-r--r--sound/soc/soc-dmaengine-pcm.c72
-rw-r--r--sound/soc/spear/spear_pcm.c5
-rw-r--r--sound/soc/tegra/tegra_pcm.c4
-rw-r--r--sound/soc/ux500/ux500_pcm.c6
10 files changed, 73 insertions, 43 deletions
diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c
index bb07989762d5..1d38fd0bc4e2 100644
--- a/sound/soc/atmel/atmel-pcm-dma.c
+++ b/sound/soc/atmel/atmel-pcm-dma.c
@@ -155,7 +155,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
155 if (ssc->pdev) 155 if (ssc->pdev)
156 sdata = ssc->pdev->dev.platform_data; 156 sdata = ssc->pdev->dev.platform_data;
157 157
158 ret = snd_dmaengine_pcm_open(substream, filter, sdata); 158 ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
159 if (ret) { 159 if (ret) {
160 pr_err("atmel-pcm: dmaengine pcm open failed\n"); 160 pr_err("atmel-pcm: dmaengine pcm open failed\n");
161 return -EINVAL; 161 return -EINVAL;
@@ -171,7 +171,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
171 171
172 return 0; 172 return 0;
173err: 173err:
174 snd_dmaengine_pcm_close(substream); 174 snd_dmaengine_pcm_close_release_chan(substream);
175 return ret; 175 return ret;
176} 176}
177 177
@@ -197,7 +197,7 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
197 197
198static struct snd_pcm_ops atmel_pcm_ops = { 198static struct snd_pcm_ops atmel_pcm_ops = {
199 .open = atmel_pcm_open, 199 .open = atmel_pcm_open,
200 .close = snd_dmaengine_pcm_close, 200 .close = snd_dmaengine_pcm_close_release_chan,
201 .ioctl = snd_pcm_lib_ioctl, 201 .ioctl = snd_pcm_lib_ioctl,
202 .hw_params = atmel_pcm_hw_params, 202 .hw_params = atmel_pcm_hw_params,
203 .prepare = atmel_pcm_dma_prepare, 203 .prepare = atmel_pcm_dma_prepare,
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c
index 298946f790eb..488032690378 100644
--- a/sound/soc/cirrus/ep93xx-pcm.c
+++ b/sound/soc/cirrus/ep93xx-pcm.c
@@ -69,7 +69,8 @@ static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
69 69
70 snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); 70 snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
71 71
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,
73 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); 74 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
74} 75}
75 76
@@ -100,7 +101,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
100 101
101static struct snd_pcm_ops ep93xx_pcm_ops = { 102static struct snd_pcm_ops ep93xx_pcm_ops = {
102 .open = ep93xx_pcm_open, 103 .open = ep93xx_pcm_open,
103 .close = snd_dmaengine_pcm_close, 104 .close = snd_dmaengine_pcm_close_release_chan,
104 .ioctl = snd_pcm_lib_ioctl, 105 .ioctl = snd_pcm_lib_ioctl,
105 .hw_params = ep93xx_pcm_hw_params, 106 .hw_params = ep93xx_pcm_hw_params,
106 .hw_free = ep93xx_pcm_hw_free, 107 .hw_free = ep93xx_pcm_hw_free,
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index ee838c8a3b11..c6647825bdd5 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -100,7 +100,7 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
100 100
101static struct snd_pcm_ops imx_pcm_ops = { 101static struct snd_pcm_ops imx_pcm_ops = {
102 .open = snd_imx_open, 102 .open = snd_imx_open,
103 .close = snd_dmaengine_pcm_close, 103 .close = snd_dmaengine_pcm_close_release_chan,
104 .ioctl = snd_pcm_lib_ioctl, 104 .ioctl = snd_pcm_lib_ioctl,
105 .hw_params = snd_imx_pcm_hw_params, 105 .hw_params = snd_imx_pcm_hw_params,
106 .trigger = snd_dmaengine_pcm_trigger, 106 .trigger = snd_dmaengine_pcm_trigger,
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index ebbef8597554..7bceb16d0fd9 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -87,7 +87,7 @@ static int snd_mxs_open(struct snd_pcm_substream *substream)
87 87
88 snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); 88 snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
89 89
90 return snd_dmaengine_pcm_open(substream, filter, 90 return snd_dmaengine_pcm_open_request_chan(substream, filter,
91 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); 91 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
92} 92}
93 93
@@ -104,7 +104,7 @@ static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
104 104
105static struct snd_pcm_ops mxs_pcm_ops = { 105static struct snd_pcm_ops mxs_pcm_ops = {
106 .open = snd_mxs_open, 106 .open = snd_mxs_open,
107 .close = snd_dmaengine_pcm_close, 107 .close = snd_dmaengine_pcm_close_release_chan,
108 .ioctl = snd_pcm_lib_ioctl, 108 .ioctl = snd_pcm_lib_ioctl,
109 .hw_params = snd_mxs_pcm_hw_params, 109 .hw_params = snd_mxs_pcm_hw_params,
110 .trigger = snd_dmaengine_pcm_trigger, 110 .trigger = snd_dmaengine_pcm_trigger,
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index c8e272f9c2de..c28e042f2208 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -118,8 +118,9 @@ static int omap_pcm_open(struct snd_pcm_substream *substream)
118 118
119 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 119 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
120 120
121 return snd_dmaengine_pcm_open(substream, omap_dma_filter_fn, 121 return snd_dmaengine_pcm_open_request_chan(substream,
122 dma_data->filter_data); 122 omap_dma_filter_fn,
123 dma_data->filter_data);
123} 124}
124 125
125static int omap_pcm_mmap(struct snd_pcm_substream *substream, 126static int omap_pcm_mmap(struct snd_pcm_substream *substream,
@@ -135,7 +136,7 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,
135 136
136static struct snd_pcm_ops omap_pcm_ops = { 137static struct snd_pcm_ops omap_pcm_ops = {
137 .open = omap_pcm_open, 138 .open = omap_pcm_open,
138 .close = snd_dmaengine_pcm_close, 139 .close = snd_dmaengine_pcm_close_release_chan,
139 .ioctl = snd_pcm_lib_ioctl, 140 .ioctl = snd_pcm_lib_ioctl,
140 .hw_params = omap_pcm_hw_params, 141 .hw_params = omap_pcm_hw_params,
141 .hw_free = omap_pcm_hw_free, 142 .hw_free = omap_pcm_hw_free,
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 6c3980252bf6..349930015264 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -131,7 +131,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
131 dma_data.dma_res = r; 131 dma_data.dma_res = r;
132 dma_data.ssp_id = cpu_dai->id; 132 dma_data.ssp_id = cpu_dai->id;
133 133
134 return snd_dmaengine_pcm_open(substream, filter, &dma_data); 134 return snd_dmaengine_pcm_open_request_chan(substream, filter,
135 &dma_data);
135} 136}
136 137
137static int mmp_pcm_mmap(struct snd_pcm_substream *substream, 138static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
@@ -148,7 +149,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
148 149
149struct snd_pcm_ops mmp_pcm_ops = { 150struct snd_pcm_ops mmp_pcm_ops = {
150 .open = mmp_pcm_open, 151 .open = mmp_pcm_open,
151 .close = snd_dmaengine_pcm_close, 152 .close = snd_dmaengine_pcm_close_release_chan,
152 .ioctl = snd_pcm_lib_ioctl, 153 .ioctl = snd_pcm_lib_ioctl,
153 .hw_params = mmp_pcm_hw_params, 154 .hw_params = mmp_pcm_hw_params,
154 .trigger = snd_dmaengine_pcm_trigger, 155 .trigger = snd_dmaengine_pcm_trigger,
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
index a9a300acb506..b0420a75f412 100644
--- a/sound/soc/soc-dmaengine-pcm.c
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -254,44 +254,38 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
254} 254}
255EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); 255EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
256 256
257static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd, 257static struct dma_chan *dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
258 dma_filter_fn filter_fn, void *filter_data) 258 void *filter_data)
259{ 259{
260 dma_cap_mask_t mask; 260 dma_cap_mask_t mask;
261 261
262 dma_cap_zero(mask); 262 dma_cap_zero(mask);
263 dma_cap_set(DMA_SLAVE, mask); 263 dma_cap_set(DMA_SLAVE, mask);
264 dma_cap_set(DMA_CYCLIC, mask); 264 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;
269 265
270 return 0; 266 return dma_request_channel(mask, filter_fn, filter_data);
271} 267}
272 268
273/** 269/**
274 * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream 270 * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
275 * @substream: PCM substream 271 * @substream: PCM substream
276 * @filter_fn: Filter function used to request the DMA channel 272 * @chan: DMA channel to use for data transfers
277 * @filter_data: Data passed to the DMA filter function
278 * 273 *
279 * Returns 0 on success, a negative error code otherwise. 274 * Returns 0 on success, a negative error code otherwise.
280 * 275 *
281 * This function will request a DMA channel using the passed filter function and 276 * The function should usually be called from the pcm open callback. Note that
282 * data. The function should usually be called from the pcm open callback. 277 * this function will use private_data field of the substream's runtime. So it
283 * 278 * is not availabe to your pcm driver implementation.
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.
288 */ 279 */
289int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, 280int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
290 dma_filter_fn filter_fn, void *filter_data) 281 struct dma_chan *chan)
291{ 282{
292 struct dmaengine_pcm_runtime_data *prtd; 283 struct dmaengine_pcm_runtime_data *prtd;
293 int ret; 284 int ret;
294 285
286 if (!chan)
287 return -ENXIO;
288
295 ret = snd_pcm_hw_constraint_integer(substream->runtime, 289 ret = snd_pcm_hw_constraint_integer(substream->runtime,
296 SNDRV_PCM_HW_PARAM_PERIODS); 290 SNDRV_PCM_HW_PARAM_PERIODS);
297 if (ret < 0) 291 if (ret < 0)
@@ -301,11 +295,7 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
301 if (!prtd) 295 if (!prtd)
302 return -ENOMEM; 296 return -ENOMEM;
303 297
304 ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data); 298 prtd->dma_chan = chan;
305 if (ret < 0) {
306 kfree(prtd);
307 return ret;
308 }
309 299
310 substream->runtime->private_data = prtd; 300 substream->runtime->private_data = prtd;
311 301
@@ -314,6 +304,27 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
314EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); 304EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
315 305
316/** 306/**
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/**
317 * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream 328 * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
318 * @substream: PCM substream 329 * @substream: PCM substream
319 */ 330 */
@@ -321,11 +332,26 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
321{ 332{
322 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); 333 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
323 334
324 dma_release_channel(prtd->dma_chan);
325 kfree(prtd); 335 kfree(prtd);
326 336
327 return 0; 337 return 0;
328} 338}
329EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); 339EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
330 340
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
331MODULE_LICENSE("GPL"); 357MODULE_LICENSE("GPL");
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
index db75d72c4805..ba66a3f370a3 100644
--- a/sound/soc/spear/spear_pcm.c
+++ b/sound/soc/spear/spear_pcm.c
@@ -64,7 +64,8 @@ static int spear_pcm_open(struct snd_pcm_substream *substream)
64 if (ret) 64 if (ret)
65 return ret; 65 return ret;
66 66
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);
68} 69}
69 70
70static int spear_pcm_mmap(struct snd_pcm_substream *substream, 71static int spear_pcm_mmap(struct snd_pcm_substream *substream,
@@ -79,7 +80,7 @@ static int spear_pcm_mmap(struct snd_pcm_substream *substream,
79 80
80static struct snd_pcm_ops spear_pcm_ops = { 81static struct snd_pcm_ops spear_pcm_ops = {
81 .open = spear_pcm_open, 82 .open = spear_pcm_open,
82 .close = snd_dmaengine_pcm_close, 83 .close = snd_dmaengine_pcm_close_release_chan,
83 .ioctl = snd_pcm_lib_ioctl, 84 .ioctl = snd_pcm_lib_ioctl,
84 .hw_params = spear_pcm_hw_params, 85 .hw_params = spear_pcm_hw_params,
85 .hw_free = spear_pcm_hw_free, 86 .hw_free = spear_pcm_hw_free,
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index f91d08bc1753..32d08119dd87 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -66,7 +66,7 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
66 /* Set HW params now that initialization is complete */ 66 /* Set HW params now that initialization is complete */
67 snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); 67 snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
68 68
69 ret = snd_dmaengine_pcm_open(substream, NULL, NULL); 69 ret = snd_dmaengine_pcm_open_request_chan(substream, NULL, NULL);
70 if (ret) { 70 if (ret) {
71 dev_err(dev, "dmaengine pcm open failed with err %d\n", ret); 71 dev_err(dev, "dmaengine pcm open failed with err %d\n", ret);
72 return ret; 72 return ret;
@@ -144,7 +144,7 @@ static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
144 144
145static struct snd_pcm_ops tegra_pcm_ops = { 145static struct snd_pcm_ops tegra_pcm_ops = {
146 .open = tegra_pcm_open, 146 .open = tegra_pcm_open,
147 .close = snd_dmaengine_pcm_close, 147 .close = snd_dmaengine_pcm_close_release_chan,
148 .ioctl = snd_pcm_lib_ioctl, 148 .ioctl = snd_pcm_lib_ioctl,
149 .hw_params = tegra_pcm_hw_params, 149 .hw_params = tegra_pcm_hw_params,
150 .hw_free = tegra_pcm_hw_free, 150 .hw_free = tegra_pcm_hw_free,
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
index 09b5364e5095..a7d4f04e5964 100644
--- a/sound/soc/ux500/ux500_pcm.c
+++ b/sound/soc/ux500/ux500_pcm.c
@@ -125,8 +125,8 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
125 dma_cfg->dst_info.data_width = mem_data_width; 125 dma_cfg->dst_info.data_width = mem_data_width;
126 } 126 }
127 127
128 128 ret = snd_dmaengine_pcm_open_request_chan(substream, stedma40_filter,
129 ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg); 129 dma_cfg);
130 if (ret) { 130 if (ret) {
131 dev_dbg(dai->dev, 131 dev_dbg(dai->dev,
132 "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n", 132 "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n",
@@ -211,7 +211,7 @@ static int ux500_pcm_mmap(struct snd_pcm_substream *substream,
211 211
212static struct snd_pcm_ops ux500_pcm_ops = { 212static struct snd_pcm_ops ux500_pcm_ops = {
213 .open = ux500_pcm_open, 213 .open = ux500_pcm_open,
214 .close = snd_dmaengine_pcm_close, 214 .close = snd_dmaengine_pcm_close_release_chan,
215 .ioctl = snd_pcm_lib_ioctl, 215 .ioctl = snd_pcm_lib_ioctl,
216 .hw_params = ux500_pcm_hw_params, 216 .hw_params = ux500_pcm_hw_params,
217 .hw_free = ux500_pcm_hw_free, 217 .hw_free = ux500_pcm_hw_free,