[Sound-open-firmware] [RFC PATCH v2 4/5] APL/CNL: Implement host DMA setting and position update on APL/CNL.
yan.wang at linux.intel.com
yan.wang at linux.intel.com
Wed Mar 14 07:51:14 CET 2018
From: Yan Wang <yan.wang at linux.intel.com>
The host DMA has the different config method:
1. Get DMA channel based on stream tag.
2. Prepare DMA elem list based on local DMA trace buffer which make
sure that one trace record data can be transferred at least.
3. Need start DMA on firmware side before trigger start on kernel side.
4. Because no DMA callback in host DMA, add position update
calling at the end of trace_work().
Signed-off-by: Yan Wang <yan.wang at linux.intel.com>
---
src/lib/dma-trace.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/src/lib/dma-trace.c b/src/lib/dma-trace.c
index b08e7fb..1ff2bd4 100644
--- a/src/lib/dma-trace.c
+++ b/src/lib/dma-trace.c
@@ -120,6 +120,14 @@ out:
spin_unlock_irq(&d->lock, flags);
+#if defined CONFIG_DMA_GW
+ /*
+ * there isn't DMA completion callback in GW DMA copying
+ * so we send position IPC message after DMA copying API calling
+ */
+ ipc_dma_trace_send_position();
+#endif
+
/* reschedule the trace copying work */
return DMA_TRACE_PERIOD;
}
@@ -195,8 +203,77 @@ int dma_trace_host_buffer(struct dma_trace_data *d, struct dma_sg_elem *elem,
return 0;
}
+#if defined CONFIG_DMA_GW
+
+static int dma_trace_start(struct dma_trace_data *d)
+{
+ struct dma_sg_config config;
+ struct dma_sg_elem *e;
+ uint32_t elem_size, elem_addr, elem_num;
+ int err = 0;
+ int i;
+
+ err = dma_copy_set_stream_tag(&d->dc, d->stream_tag);
+ if (err < 0)
+ return err;
+
+ /* size of every trace record */
+ elem_size = sizeof(uint64_t) * 2;
+
+ /* Initialize address of local elem */
+ elem_addr = (uint32_t)d->dmatb.addr;
+
+ /* the number of elem list */
+ elem_num = DMA_TRACE_LOCAL_SIZE / elem_size;
+
+ config.direction = DMA_DIR_LMEM_TO_HMEM;
+ config.src_width = sizeof(uint32_t);
+ config.dest_width = sizeof(uint32_t);
+ config.cyclic = 0;
+ list_init(&config.elem_list);
+
+ /* generate local elem list for local trace buffer */
+ e = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(*e) * elem_num);
+ if (!e)
+ return -ENOMEM;
+
+ for (i = 0; i < elem_num; i++) {
+ e[i].dest = 0;
+ e[i].src = elem_addr;
+ e[i].size = elem_size; /* the minimum size of DMA copy */
+
+ list_item_append(&e[i].list, &config.elem_list);
+ elem_addr += elem_size;
+ }
+
+ err = dma_set_config(d->dc.dmac, d->dc.chan, &config);
+ if (err < 0) {
+ rfree(e);
+ return err;
+ }
+
+ err = dma_start(d->dc.dmac, d->dc.chan);
+
+ rfree(e);
+ return err;
+}
+
+#endif
+
int dma_trace_enable(struct dma_trace_data *d)
{
+#if defined CONFIG_DMA_GW
+ int err;
+
+ /*
+ * GW DMA need finish DMA config and start before
+ * host driver trigger start DMA
+ */
+ err = dma_trace_start(d);
+ if (err < 0)
+ return err;
+#endif
+
/* validate DMA context */
if (d->dc.dmac == NULL || d->dc.chan < 0) {
trace_error_atomic(TRACE_CLASS_BUFFER, "eem");
--
2.14.3
More information about the Sound-open-firmware
mailing list