diff options
Diffstat (limited to 'sound/soc/soc-dmaengine-pcm.c')
-rw-r--r-- | sound/soc/soc-dmaengine-pcm.c | 72 |
1 files changed, 49 insertions, 23 deletions
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 | } |
255 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); | 255 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); |
256 | 256 | ||
257 | static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd, | 257 | static 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 | */ |
289 | int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, | 280 | int 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, | |||
314 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open); | 304 | EXPORT_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 | */ | ||
319 | int 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 | } | ||
325 | EXPORT_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 | } |
329 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); | 339 | EXPORT_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 | */ | ||
347 | int 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 | } | ||
355 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan); | ||
356 | |||
331 | MODULE_LICENSE("GPL"); | 357 | MODULE_LICENSE("GPL"); |