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>
This commit is contained in:
Barry Song 2012-12-14 10:59:22 +00:00 коммит произвёл Vinod Koul
Родитель 6c5e6a3990
Коммит 2518d1d1fc
1 изменённых файлов: 46 добавлений и 0 удалений

Просмотреть файл

@ -313,6 +313,48 @@ static int sirfsoc_dma_terminate_all(struct sirfsoc_dma_chan *schan)
return 0; return 0;
} }
static int sirfsoc_dma_pause_chan(struct sirfsoc_dma_chan *schan)
{
struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
int cid = schan->chan.chan_id;
unsigned long flags;
spin_lock_irqsave(&schan->lock, flags);
if (!sdma->is_marco)
writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL)
& ~((1 << cid) | 1 << (cid + 16)),
sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
else
writel_relaxed((1 << cid) | 1 << (cid + 16),
sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL_CLR);
spin_unlock_irqrestore(&schan->lock, flags);
return 0;
}
static int sirfsoc_dma_resume_chan(struct sirfsoc_dma_chan *schan)
{
struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
int cid = schan->chan.chan_id;
unsigned long flags;
spin_lock_irqsave(&schan->lock, flags);
if (!sdma->is_marco)
writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL)
| ((1 << cid) | 1 << (cid + 16)),
sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
else
writel_relaxed((1 << cid) | 1 << (cid + 16),
sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
spin_unlock_irqrestore(&schan->lock, flags);
return 0;
}
static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
unsigned long arg) unsigned long arg)
{ {
@ -320,6 +362,10 @@ static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
switch (cmd) { switch (cmd) {
case DMA_PAUSE:
return sirfsoc_dma_pause_chan(schan);
case DMA_RESUME:
return sirfsoc_dma_resume_chan(schan);
case DMA_TERMINATE_ALL: case DMA_TERMINATE_ALL:
return sirfsoc_dma_terminate_all(schan); return sirfsoc_dma_terminate_all(schan);
case DMA_SLAVE_CONFIG: case DMA_SLAVE_CONFIG: