buffer: fix buffer produce dcache circular wrap

dcache_writeback is called for dma connected
buffers, however it doesn't take into account
the possible circular wrap if bytes size is
not exact multiple of frames period.

Signed-off-by: Jaska Uimonen <jaska.uimonen@intel.com>
This commit is contained in:
Jaska Uimonen 2018-12-14 09:19:47 +02:00 committed by Liam Girdwood
parent fd084b765c
commit 0dad013067
1 changed files with 18 additions and 4 deletions

View File

@ -108,9 +108,17 @@ void buffer_free(struct comp_buffer *buffer)
void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes) void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes)
{ {
uint32_t flags; uint32_t flags;
uint32_t head = bytes;
uint32_t tail = 0;
spin_lock_irq(&buffer->lock, flags); spin_lock_irq(&buffer->lock, flags);
/* calculate head and tail size for dcache circular wrap ops */
if (buffer->w_ptr + bytes > buffer->end_addr) {
head = buffer->end_addr - buffer->w_ptr;
tail = bytes - head;
}
/* /*
* new data produce, handle consistency for buffer and cache: * new data produce, handle consistency for buffer and cache:
* 1. source(DMA) --> buffer --> sink(non-DMA): invalidate cache. * 1. source(DMA) --> buffer --> sink(non-DMA): invalidate cache.
@ -119,13 +127,19 @@ void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes)
* 4. source(non-DMA) --> buffer --> sink(non-DMA): do nothing. * 4. source(non-DMA) --> buffer --> sink(non-DMA): do nothing.
*/ */
if (buffer->source->is_dma_connected && if (buffer->source->is_dma_connected &&
!buffer->sink->is_dma_connected) !buffer->sink->is_dma_connected) {
/* need invalidate cache for sink component to use */ /* need invalidate cache for sink component to use */
dcache_invalidate_region(buffer->w_ptr, bytes); dcache_invalidate_region(buffer->w_ptr, head);
if (tail)
dcache_invalidate_region(buffer->addr, tail);
}
else if (!buffer->source->is_dma_connected && else if (!buffer->source->is_dma_connected &&
buffer->sink->is_dma_connected) buffer->sink->is_dma_connected) {
/* need write back to memory for sink component to use */ /* need write back to memory for sink component to use */
dcache_writeback_region(buffer->w_ptr, bytes); dcache_writeback_region(buffer->w_ptr, head);
if (tail)
dcache_writeback_region(buffer->addr, tail);
}
buffer->w_ptr += bytes; buffer->w_ptr += bytes;