[Sound-open-firmware] [PATCH 24/25] dw-dma: handle different cases in irq handler
Keyon Jie
yang.jie at linux.intel.com
Tue Feb 7 15:03:11 CET 2017
After finished a transfer copy, check for reload channel:
1. if next.size is 0xFFFFFFFF, stop this dma copy;
2. if next.size > 0 but not 0xFFFFFFFF, use next element
for next copy
3. if we are waiting for pause, pause it;
4. otherwise, reload lli.
Signed-off-by: Keyon Jie <yang.jie at 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)
- p->chan[channel].cb(p->chan[channel].cb_data, DMA_IRQ_TYPE_LLIST, &next);
dw_dma_chan_reload_lli(dma, channel);
}
@@ -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
+
struct dma;
struct dma_sg_elem {
--
2.7.4
More information about the Sound-open-firmware
mailing list