diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2012-09-14 08:05:45 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-09-22 11:12:40 -0400 |
commit | 2dcdf570936168d488acf90be9b04a3d32dafce7 (patch) | |
tree | db98bbd4b10906b6148510f6719d479e635a889f /drivers | |
parent | ccffa3870a7ec2b59cf051b745220c56f423d182 (diff) |
dmaengine: omap: Add support for pause/resume in cyclic dma mode
The audio stack used omap_stop_dma/omap_start_dma to pause/resume the DMA.
This method has been used for years on OMAP based products.
We only allow pause/resume when the DMA has been configured in cyclic mode
which is used by the audio stack.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Acked-by: Vinod Koul <vinod.koul@linux.intel.com>
Tested-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/omap-dma.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index b77a40db2856..71d786973dfd 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c | |||
@@ -34,6 +34,7 @@ struct omap_chan { | |||
34 | struct dma_slave_config cfg; | 34 | struct dma_slave_config cfg; |
35 | unsigned dma_sig; | 35 | unsigned dma_sig; |
36 | bool cyclic; | 36 | bool cyclic; |
37 | bool paused; | ||
37 | 38 | ||
38 | int dma_ch; | 39 | int dma_ch; |
39 | struct omap_desc *desc; | 40 | struct omap_desc *desc; |
@@ -470,11 +471,14 @@ static int omap_dma_terminate_all(struct omap_chan *c) | |||
470 | */ | 471 | */ |
471 | if (c->desc) { | 472 | if (c->desc) { |
472 | c->desc = NULL; | 473 | c->desc = NULL; |
473 | omap_stop_dma(c->dma_ch); | 474 | /* Avoid stopping the dma twice */ |
475 | if (!c->paused) | ||
476 | omap_stop_dma(c->dma_ch); | ||
474 | } | 477 | } |
475 | 478 | ||
476 | if (c->cyclic) { | 479 | if (c->cyclic) { |
477 | c->cyclic = false; | 480 | c->cyclic = false; |
481 | c->paused = false; | ||
478 | omap_dma_unlink_lch(c->dma_ch, c->dma_ch); | 482 | omap_dma_unlink_lch(c->dma_ch, c->dma_ch); |
479 | } | 483 | } |
480 | 484 | ||
@@ -487,14 +491,30 @@ static int omap_dma_terminate_all(struct omap_chan *c) | |||
487 | 491 | ||
488 | static int omap_dma_pause(struct omap_chan *c) | 492 | static int omap_dma_pause(struct omap_chan *c) |
489 | { | 493 | { |
490 | /* FIXME: not supported by platform private API */ | 494 | /* Pause/Resume only allowed with cyclic mode */ |
491 | return -EINVAL; | 495 | if (!c->cyclic) |
496 | return -EINVAL; | ||
497 | |||
498 | if (!c->paused) { | ||
499 | omap_stop_dma(c->dma_ch); | ||
500 | c->paused = true; | ||
501 | } | ||
502 | |||
503 | return 0; | ||
492 | } | 504 | } |
493 | 505 | ||
494 | static int omap_dma_resume(struct omap_chan *c) | 506 | static int omap_dma_resume(struct omap_chan *c) |
495 | { | 507 | { |
496 | /* FIXME: not supported by platform private API */ | 508 | /* Pause/Resume only allowed with cyclic mode */ |
497 | return -EINVAL; | 509 | if (!c->cyclic) |
510 | return -EINVAL; | ||
511 | |||
512 | if (c->paused) { | ||
513 | omap_start_dma(c->dma_ch); | ||
514 | c->paused = false; | ||
515 | } | ||
516 | |||
517 | return 0; | ||
498 | } | 518 | } |
499 | 519 | ||
500 | static int omap_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 520 | static int omap_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, |