[Sound-open-firmware] [PATCH v3 12/27] host: add a completion work to notify host side
Keyon Jie
yang.jie at linux.intel.com
Sat Feb 11 03:17:52 CET 2017
We need to wait until the last bytes/period is finished in dai,
before we can notify host side about that, otherwise, host side
will trigger stop too early, and we will miss rendering them.
Signed-off-by: Keyon Jie <yang.jie at linux.intel.com>
---
src/audio/host.c | 38 +++++++++++++++++++++++
src/audio/pipeline.c | 1 +
src/include/reef/audio/pipeline.h | 2 ++
src/platform/baytrail/include/platform/platform.h | 6 ++++
4 files changed, 47 insertions(+)
diff --git a/src/audio/host.c b/src/audio/host.c
index e8265df..6a4c669 100644
--- a/src/audio/host.c
+++ b/src/audio/host.c
@@ -64,6 +64,7 @@ struct host_data {
completion_t complete;
struct period_desc *period;
struct comp_buffer *dma_buffer;
+ struct work work;
/* local and host DMA buffer info */
struct hc_buf host;
@@ -220,6 +221,10 @@ static void host_dma_cb_playback(struct comp_dev *dev,
/* end of stream, stop */
next->size = 0;
need_copy = 0;
+
+ /* will notify host side once dai tell us */
+ wait_init(&dev->pipeline->complete);
+ work_schedule_default(&hd->work, PLATFORM_HOST_FINISH_DELAY);
goto next_copy;
}
@@ -354,6 +359,38 @@ static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next)
host_dma_cb_capture(dev, next);
}
+/* We need to wait until the last bytes/period is finished in dai, before we
+ * can notify host side about that, otherwise, host side will trigger stop too
+ * early, and we will miss rendering them.
+ * This work should be scheduled once the copy for host component is finished,
+ * and wait a timeout inside the work for pipeline->complete, which should be
+ * set in the endpoint(dai) rendering finishing callback.
+ */
+static uint32_t host_finish_work(void *data, uint32_t udelay)
+{
+ struct comp_dev *dev = (struct comp_dev *)data;
+ struct host_data *hd = comp_get_drvdata(dev);
+ int ret;
+
+ dev->pipeline->complete.timeout = PLATFORM_HOST_FINISH_TIMEOUT;
+ ret = wait_for_completion_timeout(&dev->pipeline->complete);
+ if (ret < 0)
+ trace_comp_error("eHf");
+ else {
+ trace_comp("hFw");
+ /* update for host side */
+ if (hd->host_pos) {
+ *hd->host_pos = hd->host_pos_read;
+ /* send the last notification to host */
+ ipc_stream_send_notification(dev, &hd->cp);
+ }
+ }
+
+ return 0;
+}
+
+
+
static struct comp_dev *host_new(uint32_t type, uint32_t index,
uint32_t direction)
{
@@ -389,6 +426,7 @@ static struct comp_dev *host_new(uint32_t type, uint32_t index,
hd->source = NULL;
hd->sink = NULL;
hd->split_remaining = 0;
+ work_init(&hd->work, host_finish_work, dev, WORK_ASYNC);
/* init buffer elems */
list_init(&hd->config.elem_list);
diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c
index 9d74e37..41693ae 100644
--- a/src/audio/pipeline.c
+++ b/src/audio/pipeline.c
@@ -141,6 +141,7 @@ struct pipeline *pipeline_new(uint32_t id)
list_init(&p->host_ep_list);
list_init(&p->dai_ep_list);
list_init(&p->buffer_list);
+ wait_init(&p->complete);
spinlock_init(&p->lock);
list_item_prepend(&p->list, &pipe_data->pipeline_list);
diff --git a/src/include/reef/audio/pipeline.h b/src/include/reef/audio/pipeline.h
index 26c1dd6..e7de501 100644
--- a/src/include/reef/audio/pipeline.h
+++ b/src/include/reef/audio/pipeline.h
@@ -39,6 +39,7 @@
#include <reef/dma.h>
#include <reef/audio/component.h>
#include <reef/trace.h>
+#include <reef/wait.h>
#define trace_pipe(__e) trace_event(TRACE_CLASS_PIPE, __e)
#define trace_pipe_error(__e) trace_error(TRACE_CLASS_PIPE, __e)
@@ -50,6 +51,7 @@
struct pipeline {
uint32_t id; /* id */
spinlock_t lock;
+ completion_t complete; /* indicate if the pipeline data is finished*/
/* lists */
struct list_item host_ep_list; /* list of host endpoints */
diff --git a/src/platform/baytrail/include/platform/platform.h b/src/platform/baytrail/include/platform/platform.h
index f86019d..7df65b8 100644
--- a/src/platform/baytrail/include/platform/platform.h
+++ b/src/platform/baytrail/include/platform/platform.h
@@ -86,6 +86,12 @@
/* WorkQ window size in microseconds */
#define PLATFORM_WORKQ_WINDOW 2000
+/* Host finish work schedule delay in microseconds */
+#define PLATFORM_HOST_FINISH_DELAY 100
+
+/* Host finish work(drain from host to dai) timeout in microseconds */
+#define PLATFORM_HOST_FINISH_TIMEOUT 50000
+
/* Platform defined panic code */
#define platform_panic(__x) \
shim_write(SHIM_IPCXL, ((shim_read(SHIM_IPCXL) & 0xc0000000) |\
--
2.7.4
More information about the Sound-open-firmware
mailing list