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:
Родитель
6c5e6a3990
Коммит
2518d1d1fc
|
@ -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:
|
||||||
|
|
Загрузка…
Ссылка в новой задаче