[Sound-open-firmware] [PATCH] component: fix comp_update_buffer() when buffer full
It will treat full buffer as empty one at current comp_update_buffer(), as w_ptr is equal to r_ptr, this will make us missing those datas or at least the buffer->avail/free are not correct.
Here spit comp_update_buffer() into consuming one and producing one, for consuming, 'r_ptr == w_ptr' update means buffer is becoming empty, and for producing, 'w_ptr == r_ptr' means buffer is becoming full.
Signed-off-by: Keyon Jie yang.jie@linux.intel.com --- src/audio/dai.c | 8 +++++--- src/audio/host.c | 4 ++-- src/audio/mixer.c | 4 ++-- src/audio/volume.c | 4 ++-- src/include/reef/audio/component.h | 18 ++++++++++++++++-- 5 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 64e4761..ab0164c 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -98,6 +98,8 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) *dd->dai_pos = dd->dai_pos_blks + dma_buffer->r_ptr - dma_buffer->addr;
+ /* recalc available buffer space */ + comp_update_buffer_consume(dma_buffer); } else { dma_buffer = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); @@ -119,10 +121,10 @@ static void dai_dma_cb(void *data, uint32_t type, struct dma_sg_elem *next) if (dd->dai_pos) *dd->dai_pos = dd->dai_pos_blks + dma_buffer->w_ptr - dma_buffer->addr; - }
- /* recalc available buffer space */ - comp_update_buffer(dma_buffer); + /* recalc available buffer space */ + comp_update_buffer_produce(dma_buffer); + }
/* notify pipeline that DAI needs it's buffer filled */ // if (dev->state == COMP_STATE_RUNNING) diff --git a/src/audio/host.c b/src/audio/host.c index fe43cf8..217ad4f 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -130,7 +130,7 @@ static void host_dma_cb_playback(struct comp_dev *dev, #endif
/* recalc available buffer space */ - comp_update_buffer(hd->dma_buffer); + comp_update_buffer_consume(hd->dma_buffer);
/* new local period, update host buffer position blks */ hd->host_pos_blks += local_elem->size; @@ -236,7 +236,7 @@ static void host_dma_cb_capture(struct comp_dev *dev, *hd->host_pos = hd->host_pos_blks;
/* recalc available buffer space */ - comp_update_buffer(hd->dma_buffer); + comp_update_buffer_produce(hd->dma_buffer);
/* send IPC message to driver if needed */ hd->host_period_pos += local_elem->size; diff --git a/src/audio/mixer.c b/src/audio/mixer.c index b996dae..3a8d12f 100644 --- a/src/audio/mixer.c +++ b/src/audio/mixer.c @@ -230,13 +230,13 @@ static int mixer_copy(struct comp_dev *dev) for(; i > 0; i--) { if (sources[i-1]->r_ptr >= sources[i-1]->end_addr) sources[i-1]->r_ptr = sources[i-1]->addr; - comp_update_buffer(sources[i-1]); + comp_update_buffer_consume(sources[i-1]); } if (sink->w_ptr >= sink->end_addr) sink->w_ptr = sink->addr;
/* calc new free and available */ - comp_update_buffer(sink); + comp_update_buffer_produce(sink);
/* number of frames sent downstream */ return cframes; diff --git a/src/audio/volume.c b/src/audio/volume.c index e2badb8..75a48f9 100644 --- a/src/audio/volume.c +++ b/src/audio/volume.c @@ -460,8 +460,8 @@ static int volume_copy(struct comp_dev *dev) sink->w_ptr = sink->addr;
/* calc new free and available */ - comp_update_buffer(sink); - comp_update_buffer(source); + comp_update_buffer_produce(sink); + comp_update_buffer_consume(source);
/* number of frames sent downstream */ return cframes; diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h index fbd29e4..e521753 100644 --- a/src/include/reef/audio/component.h +++ b/src/include/reef/audio/component.h @@ -311,10 +311,24 @@ void sys_comp_mux_init(void); void sys_comp_switch_init(void); void sys_comp_volume_init(void);
-static inline void comp_update_buffer(struct comp_buffer *buffer) +static inline void comp_update_buffer_produce(struct comp_buffer *buffer) { - if (buffer->r_ptr <= buffer->w_ptr) + if (buffer->r_ptr < buffer->w_ptr) buffer->avail = buffer->w_ptr - buffer->r_ptr; + else if (buffer->r_ptr == buffer->w_ptr) + buffer->avail = buffer->end_addr - buffer->addr; /* full */ + else + buffer->avail = buffer->end_addr - buffer->r_ptr + + buffer->w_ptr - buffer->addr; + buffer->free = buffer->desc.size - buffer->avail; +} + +static inline void comp_update_buffer_consume(struct comp_buffer *buffer) +{ + if (buffer->r_ptr < buffer->w_ptr) + buffer->avail = buffer->w_ptr - buffer->r_ptr; + else if (buffer->r_ptr == buffer->w_ptr) + buffer->avail = 0; /* empty */ else buffer->avail = buffer->end_addr - buffer->r_ptr + buffer->w_ptr - buffer->addr;
On Tue, 2017-01-10 at 17:06 +0800, Keyon Jie wrote:
It will treat full buffer as empty one at current comp_update_buffer(), as w_ptr is equal to r_ptr, this will make us missing those datas or at least the buffer->avail/free are not correct.
Here spit comp_update_buffer() into consuming one and producing one, for consuming, 'r_ptr == w_ptr' update means buffer is becoming empty, and for producing, 'w_ptr == r_ptr' means buffer is becoming full.
Signed-off-by: Keyon Jie yang.jie@linux.intel.com
Applied
participants (2)
-
Keyon Jie
-
Liam Girdwood