On Tue, 2017-02-07 at 22:03 +0800, Keyon Jie wrote:
After finished a transfer copy, check for reload channel:
- if next.size is 0xFFFFFFFF, stop this dma copy;
- if next.size > 0 but not 0xFFFFFFFF, use next element
magic numbers.
for next copy 3. if we are waiting for pause, pause it; 4. otherwise, reload lli.
Signed-off-by: Keyon Jie yang.jie@linux.intel.com
src/audio/dai.c | 2 +- src/drivers/dw-dma.c | 25 ++++++++++++++----------- src/include/reef/dma.h | 6 ++++++ 3 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index a9b46a5..e365ed9 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -140,7 +140,7 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) if (dma_buffer->avail == 0) { dai_cmd(dev, COMP_CMD_STOP, NULL); /* stop dma immediatly */
next->size = 0xFFFFFFFF;
next->size = DMA_RELOAD_STOP_SIZE; /* let any waiters know we have completed */ wait_completed(&dev->pipeline->complete); return;
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index c073ed5..baa773e 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -387,7 +387,6 @@ out: static int dw_dma_release(struct dma *dma, int channel) { struct dma_pdata *p = dma_get_drvdata(dma);
struct dma_sg_elem next; uint32_t flags;
spin_lock_irq(&dma->lock, flags);
@@ -395,8 +394,6 @@ static int dw_dma_release(struct dma *dma, int channel) trace_dma("Dpr");
if (p->chan[channel].status == DMA_STATUS_PAUSED) {
if (p->chan[channel].cb && p->chan[channel].cb_type & DMA_IRQ_TYPE_LLIST)
dw_dma_chan_reload_lli(dma, channel); }p->chan[channel].cb(p->chan[channel].cb_data, DMA_IRQ_TYPE_LLIST, &next);
@@ -834,20 +831,26 @@ static void dw_dma_irq_handler(void *data) if ((status_tfr & mask) && (p->chan[i].cb_type & DMA_IRQ_TYPE_LLIST)) {
if (p->chan[i].status == DMA_STATUS_PAUSING) {
p->chan[i].status = DMA_STATUS_PAUSED;
continue;
}
next.size = 0; if (p->chan[i].cb) p->chan[i].cb(p->chan[i].cb_data, DMA_IRQ_TYPE_LLIST, &next);
/* check for reload channel */
if (next.size > 0)
/* check for reload channel:
* next.size is DMA_RELOAD_STOP_SIZE, stop this dma copy;
* next.size > 0 but not DMA_RELOAD_STOP_SIZE, use next
* element for next copy;
* if we are waiting for pause, pause it;
* otherwise, reload lli
*/
if (next.size == DMA_RELOAD_STOP_SIZE)
continue;
else if (next.size > 0) dw_dma_chan_reload_next(dma, i, &next);
else
else if (p->chan[i].status == DMA_STATUS_PAUSING) {
p->chan[i].status = DMA_STATUS_PAUSED;
continue;
}} else dw_dma_chan_reload_lli(dma, i);
#if DW_USE_HW_LLI diff --git a/src/include/reef/dma.h b/src/include/reef/dma.h index 6de2ede..273371e 100644 --- a/src/include/reef/dma.h +++ b/src/include/reef/dma.h @@ -59,6 +59,12 @@ #define DMA_IRQ_TYPE_BLOCK (1 << 0) #define DMA_IRQ_TYPE_LLIST (1 << 1)
+/* We will use this macro in cb handler to inform dma that
- we need to stop the reload for specail purpose
- */
+#define DMA_RELOAD_STOP_SIZE 0xFFFFFFFF
if we are using the size variable then it makes more sense to use 0 here to indicate end of transfer.
#define DMA_RELOAD_END 0
struct dma;
struct dma_sg_elem {