It is possible that we may don't like check host side buffer and assume there are always datas/room for playback/capture, so here we add a config item HOST_SIDE_BUFFER_CHECK to make it configurable, and disable this buffer check may save about 0.6KB to the firmware binary size.
Signed-off-by: Keyon Jie yang.jie@linux.intel.com --- src/audio/host.c | 50 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-)
diff --git a/src/audio/host.c b/src/audio/host.c index 195cd6c..80ee3fe 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -50,6 +50,8 @@ #define tracev_host(__e) tracev_event(TRACE_CLASS_HOST, __e) #define trace_host_error(__e) trace_error(TRACE_CLASS_HOST, __e)
+//#define HOST_SIDE_BUFFER_CHECK + struct hc_buf { /* host buffer info */ struct list_item elem_list; @@ -65,19 +67,23 @@ 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; struct hc_buf local; uint32_t host_size; + /* host possition reporting related */ volatile uint32_t *host_pos; /* read/write pos, update to mailbox for host side */ - uint32_t buff_w_off; /* the host side buffer write offset in bytes */ - uint32_t buff_r_off; /* the host side buffer read offset in bytes */ - uint32_t report_period; /* host_pos report/update to host side period, in bytes */ - uint32_t report_pos; /* position in current report period */ - uint32_t buff_avail; /* host side buffer available size */ - uint32_t buff_free; /* host side buffer free size */ + uint32_t report_period; /* host_pos report/update to host side period, in bytes */ + uint32_t report_pos; /* position in current report period */ + uint32_t buff_w_off; /* the host side buffer write offset in bytes */ + uint32_t buff_r_off; /* the host side buffer read offset in bytes */ +#ifdef HOST_SIDE_BUFFER_CHECK + struct work work; + /* host side buffer management related */ + uint32_t buff_avail; /* host side buffer available size */ + uint32_t buff_free; /* host side buffer free size */ +#endif /* pointers set during params to host or local above */ struct hc_buf *source; struct hc_buf *sink; @@ -89,6 +95,7 @@ struct host_data { struct comp_position cp; };
+#ifdef HOST_SIDE_BUFFER_CHECK static void host_update_buffer(struct host_data *hd, uint32_t produce) { if (hd->buff_r_off < hd->buff_w_off) @@ -99,7 +106,11 @@ static void host_update_buffer(struct host_data *hd, uint32_t produce) hd->buff_avail = hd->host_size -hd->buff_r_off + hd->buff_w_off; hd->buff_free = hd->host_size - hd->buff_avail; } - +#else +static void host_update_buffer(struct host_data *hd, uint32_t produce) +{ +} +#endif static inline struct dma_sg_elem *next_buffer(struct hc_buf *hc) { struct dma_sg_elem *elem; @@ -161,6 +172,7 @@ static void host_dma_cb_playback(struct comp_dev *dev, hd->report_pos += local_elem->size; if (hd->report_pos >= hd->report_period) { hd->report_pos = 0; +#ifdef HOST_SIDE_BUFFER_CHECK /* for the last bytes/period, send notification later */ if (hd->buff_avail) { /* update for host side */ @@ -169,6 +181,13 @@ static void host_dma_cb_playback(struct comp_dev *dev, ipc_stream_send_notification(dev, &hd->cp); } } +#else + /* update for host side */ + if (hd->host_pos) { + *hd->host_pos = hd->buff_r_off; + ipc_stream_send_notification(dev, &hd->cp); + } +#endif }
local_elem->src += local_elem->size; @@ -203,6 +222,7 @@ static void host_dma_cb_playback(struct comp_dev *dev, } local_elem->size = next_size;
+#ifdef HOST_SIDE_BUFFER_CHECK /* check if avail is enough, otherwise, drain the last bytes and stop */ if (hd->buff_avail < local_elem->size) { if (hd->buff_avail == 0) { @@ -226,6 +246,7 @@ static void host_dma_cb_playback(struct comp_dev *dev, }
next_copy: +#endif if (need_copy) { next->src = local_elem->src; next->dest = local_elem->dest; @@ -347,6 +368,7 @@ static void host_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) host_dma_cb_capture(dev, next); }
+#ifdef HOST_SIDE_BUFFER_CHECK /* 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. @@ -378,8 +400,7 @@ static uint32_t host_finish_work(void *data, uint32_t udelay)
return 0; } - - +#endif
static struct comp_dev *host_new(uint32_t type, uint32_t index, uint32_t direction) @@ -410,8 +431,9 @@ static struct comp_dev *host_new(uint32_t type, uint32_t index, hd->dma = dma_get(DMA_ID_DMAC0); if (hd->dma == NULL) goto error; +#ifdef HOST_SIDE_BUFFER_CHECK work_init(&hd->work, host_finish_work, dev, WORK_ASYNC); - +#endif /* init buffer elems */ list_init(&hd->config.elem_list); list_init(&hd->host.elem_list); @@ -694,7 +716,9 @@ static int host_cmd(struct comp_dev *dev, int cmd, void *data) { struct host_data *hd = comp_get_drvdata(dev); struct comp_dev *vol_dev = NULL; +#ifdef HOST_SIDE_BUFFER_CHECK struct ipc_intel_ipc_stream_set_position *app_pos; +#endif int ret = 0;
// TODO: align cmd macros. @@ -723,6 +747,7 @@ static int host_cmd(struct comp_dev *dev, int cmd, void *data) case COMP_CMD_IPC_MMAP_RPOS: hd->host_pos = data; break; +#ifdef HOST_SIDE_BUFFER_CHECK case COMP_CMD_AVAIL_UPDATE: app_pos = (struct ipc_intel_ipc_stream_set_position *)data;
@@ -735,6 +760,7 @@ static int host_cmd(struct comp_dev *dev, int cmd, void *data) host_update_buffer(hd, 0); /* consume */ } break; +#endif case COMP_CMD_VOLUME: vol_dev = host_volume_component(dev); if (vol_dev != NULL) @@ -810,6 +836,7 @@ static int host_copy(struct comp_dev *dev) if (dev->state != COMP_STATE_RUNNING) return 0;
+#ifdef HOST_SIDE_BUFFER_CHECK /* don't copy if the host side buffer is not ready */ if ((hd->params.direction == STREAM_DIRECTION_PLAYBACK) && (hd->buff_avail == 0)) @@ -817,6 +844,7 @@ static int host_copy(struct comp_dev *dev) if ((hd->params.direction == STREAM_DIRECTION_CAPTURE) && (hd->buff_free == 0)) return 0; +#endif
/* do DMA transfer */ wait_init(&hd->complete);