Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2518d1d1 authored by Barry Song's avatar Barry Song Committed by Vinod Koul
Browse files

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: default avatarBarry Song <Baohua.Song@csr.com>
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent 6c5e6a39
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -313,6 +313,48 @@ static int sirfsoc_dma_terminate_all(struct sirfsoc_dma_chan *schan)
	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,
	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);

	switch (cmd) {
	case DMA_PAUSE:
		return sirfsoc_dma_pause_chan(schan);
	case DMA_RESUME:
		return sirfsoc_dma_resume_chan(schan);
	case DMA_TERMINATE_ALL:
		return sirfsoc_dma_terminate_all(schan);
	case DMA_SLAVE_CONFIG: