diff options
| author | Barry Song <Baohua.Song@csr.com> | 2012-12-14 05:59:22 -0500 |
|---|---|---|
| committer | Vinod Koul <vinod.koul@intel.com> | 2013-01-28 04:44:40 -0500 |
| commit | 2518d1d1fc0ba7ef781bac97132bcfd6d7466c4b (patch) | |
| tree | 7c38d76cbf4f92fc81dea18073f66f53027ce946 | |
| parent | 6c5e6a3990ce64192b56ffafa5ffa5af129751d5 (diff) | |
DMAEngine: sirf: add DMA pause/resume support
pause/resume are important for users like ALSA sound drivers,
this patches make the sirf prima2/marco support DMA commands
DMA_PAUSE and DMA_RESUME.
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
| -rw-r--r-- | drivers/dma/sirf-dma.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 3c210ba9f938..7d78cf7bb7f1 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c | |||
| @@ -313,6 +313,48 @@ static int sirfsoc_dma_terminate_all(struct sirfsoc_dma_chan *schan) | |||
| 313 | return 0; | 313 | return 0; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | static int sirfsoc_dma_pause_chan(struct sirfsoc_dma_chan *schan) | ||
| 317 | { | ||
| 318 | struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan); | ||
| 319 | int cid = schan->chan.chan_id; | ||
| 320 | unsigned long flags; | ||
| 321 | |||
| 322 | spin_lock_irqsave(&schan->lock, flags); | ||
| 323 | |||
| 324 | if (!sdma->is_marco) | ||
| 325 | writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL) | ||
| 326 | & ~((1 << cid) | 1 << (cid + 16)), | ||
| 327 | sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL); | ||
| 328 | else | ||
| 329 | writel_relaxed((1 << cid) | 1 << (cid + 16), | ||
| 330 | sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL_CLR); | ||
| 331 | |||
| 332 | spin_unlock_irqrestore(&schan->lock, flags); | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | static int sirfsoc_dma_resume_chan(struct sirfsoc_dma_chan *schan) | ||
| 338 | { | ||
| 339 | struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan); | ||
| 340 | int cid = schan->chan.chan_id; | ||
| 341 | unsigned long flags; | ||
| 342 | |||
| 343 | spin_lock_irqsave(&schan->lock, flags); | ||
| 344 | |||
| 345 | if (!sdma->is_marco) | ||
| 346 | writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL) | ||
| 347 | | ((1 << cid) | 1 << (cid + 16)), | ||
| 348 | sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL); | ||
| 349 | else | ||
| 350 | writel_relaxed((1 << cid) | 1 << (cid + 16), | ||
| 351 | sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL); | ||
| 352 | |||
| 353 | spin_unlock_irqrestore(&schan->lock, flags); | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 316 | static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 358 | static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, |
| 317 | unsigned long arg) | 359 | unsigned long arg) |
| 318 | { | 360 | { |
| @@ -320,6 +362,10 @@ static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
| 320 | struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); | 362 | struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); |
| 321 | 363 | ||
| 322 | switch (cmd) { | 364 | switch (cmd) { |
| 365 | case DMA_PAUSE: | ||
| 366 | return sirfsoc_dma_pause_chan(schan); | ||
| 367 | case DMA_RESUME: | ||
| 368 | return sirfsoc_dma_resume_chan(schan); | ||
| 323 | case DMA_TERMINATE_ALL: | 369 | case DMA_TERMINATE_ALL: |
| 324 | return sirfsoc_dma_terminate_all(schan); | 370 | return sirfsoc_dma_terminate_all(schan); |
| 325 | case DMA_SLAVE_CONFIG: | 371 | case DMA_SLAVE_CONFIG: |
