[Sound-open-firmware] [PATCH v2] dw-dma: fix hardware link list mode

Keyon Jie yang.jie at linux.intel.com
Mon Jan 29 02:39:18 CET 2018


For hardware link list mode, we also need to configure address
and config registers for the first link list, here fix it.

Signed-off-by: Keyon Jie <yang.jie at linux.intel.com>
---
update on v2:
Fix checkpatch.pl issues.

Tested on minnow turbot rt5651, 
SOF Master: f7beb51118e6e8463a864b9416c773a508930e06, 
SOF Tool Master: 59d81995f682876bd34f939332e8838c76f714ec, 
https://github.com/plbossart/sound/tree/topic/sof-v4.14:
5a91e6776d41b0e97828882294cdc00b5c0bafd6

 src/audio/dai.c      |  3 ++-
 src/drivers/dw-dma.c | 50 ++++++++++++++++++++++----------------------------
 2 files changed, 24 insertions(+), 29 deletions(-)

diff --git a/src/audio/dai.c b/src/audio/dai.c
index d19e18a..3a6b9f7 100644
--- a/src/audio/dai.c
+++ b/src/audio/dai.c
@@ -226,7 +226,8 @@ static struct comp_dev *dai_new(struct sof_ipc_comp *comp)
 	}
 
 	/* set up callback */
-	dma_set_cb(dd->dma, dd->chan, DMA_IRQ_TYPE_LLIST, dai_dma_cb, dev);
+	dma_set_cb(dd->dma, dd->chan, DMA_IRQ_TYPE_BLOCK |
+				DMA_IRQ_TYPE_LLIST, dai_dma_cb, dev);
 	dev->state = COMP_STATE_READY;
 	return dev;
 
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c
index 8248461..5501f8e 100644
--- a/src/drivers/dw-dma.c
+++ b/src/drivers/dw-dma.c
@@ -396,22 +396,11 @@ static int dw_dma_start(struct dma *dma, int channel)
 
 #if DW_USE_HW_LLI
 	/* TODO: Revisit: are we using LLP mode or single transfer ? */
-	if (p->chan[channel].lli->llp) {
-		/* LLP mode - only write LLP pointer */
+	if (p->chan[channel].lli) {
+		/* LLP mode - write LLP pointer */
 		dw_write(dma, DW_LLP(channel), (uint32_t)p->chan[channel].lli);
-	} else {
-		/* single transfer */
-		dw_write(dma, DW_LLP(channel), 0);
-
-		/* channel needs started from scratch, so write SARn, DARn */
-		dw_write(dma, DW_SAR(channel), p->chan[channel].lli->sar);
-		dw_write(dma, DW_DAR(channel), p->chan[channel].lli->dar);
-
-		/* program CTLn */
-		dw_write(dma, DW_CTRL_LOW(channel), p->chan[channel].lli->ctrl_lo);
-		dw_write(dma, DW_CTRL_HIGH(channel), p->chan[channel].lli->ctrl_hi);
 	}
-#else
+#endif
 	/* channel needs started from scratch, so write SARn, DARn */
 	dw_write(dma, DW_SAR(channel), p->chan[channel].lli->sar);
 	dw_write(dma, DW_DAR(channel), p->chan[channel].lli->dar);
@@ -419,7 +408,6 @@ static int dw_dma_start(struct dma *dma, int channel)
 	/* program CTLn */
 	dw_write(dma, DW_CTRL_LOW(channel), p->chan[channel].lli->ctrl_lo);
 	dw_write(dma, DW_CTRL_HIGH(channel), p->chan[channel].lli->ctrl_hi);
-#endif
 
 	/* write channel config */
 	dw_write(dma, DW_CFG_LOW(channel), p->chan[channel].cfg_lo);
@@ -829,6 +817,7 @@ static void dw_dma_irq_handler(void *data)
 	struct dma_sg_elem next;
 	uint32_t status_tfr = 0;
 	uint32_t status_block = 0;
+	uint32_t status_block_new = 0;
 	uint32_t status_err = 0;
 	uint32_t status_intr;
 	uint32_t mask;
@@ -861,10 +850,10 @@ static void dw_dma_irq_handler(void *data)
 	platform_interrupt_clear(dma_irq(dma), pmask);
 
 	/* confirm IRQ cleared */
-	status_block = dw_read(dma, DW_STATUS_BLOCK);
-	if (status_block) {
+	status_block_new = dw_read(dma, DW_STATUS_BLOCK);
+	if (status_block_new) {
 		trace_dma_error("eI2");
-		trace_value(status_block);
+		trace_value(status_block_new);
 	}
 
 	for (i = 0; i < DW_MAX_CHAN; i++) {
@@ -875,12 +864,25 @@ static void dw_dma_irq_handler(void *data)
 
 		mask = 0x1 << i;
 
+#if DW_USE_HW_LLI
+		/* end of a LLI block */
+		if (status_block & mask &&
+		    p->chan[i].cb_type & DMA_IRQ_TYPE_BLOCK) {
+			next.src = DMA_RELOAD_LLI;
+			next.dest = DMA_RELOAD_LLI;
+			next.size = DMA_RELOAD_LLI;
+			p->chan[i].cb(p->chan[i].cb_data,
+					DMA_IRQ_TYPE_BLOCK, &next);
+		}
+#endif
 		/* end of a transfer */
 		if ((status_tfr & mask) &&
 			(p->chan[i].cb_type & DMA_IRQ_TYPE_LLIST)) {
 
-			next.src = next.dest = DMA_RELOAD_LLI;
-			next.size = DMA_RELOAD_LLI; /* will reload lli by default */
+			next.src = DMA_RELOAD_LLI;
+			next.dest = DMA_RELOAD_LLI;
+			/* will reload lli by default */
+			next.size = DMA_RELOAD_LLI;
 			if (p->chan[i].cb)
 				p->chan[i].cb(p->chan[i].cb_data,
 					DMA_IRQ_TYPE_LLIST, &next);
@@ -904,14 +906,6 @@ static void dw_dma_irq_handler(void *data)
 				break;
 			}
 		}
-#if DW_USE_HW_LLI
-		/* end of a LLI block */
-		if (status_block & mask &&
-			p->chan[i].cb_type & DMA_IRQ_TYPE_BLOCK) {
-			p->chan[i].cb(p->chan[i].cb_data,
-					DMA_IRQ_TYPE_BLOCK);
-		}
-#endif
 	}
 }
 
-- 
2.11.0



More information about the Sound-open-firmware mailing list