Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 40 additions & 68 deletions src/audio/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,94 +7,99 @@

#include <sof/audio/buffer.h>
#include <sof/audio/component.h>
#include <sof/debug/panic.h>
#include <sof/drivers/interrupt.h>
#include <sof/lib/alloc.h>
#include <sof/lib/cache.h>
#include <sof/lib/memory.h>
#include <sof/list.h>
#include <sof/string.h>
#include <ipc/topology.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>

/* create a new component in the pipeline */
struct comp_buffer *buffer_new(struct sof_ipc_buffer *desc)
struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t align)
{
struct comp_buffer *buffer;

trace_buffer("buffer_new()");
trace_buffer("buffer_alloc()");

/* validate request */
if (desc->size == 0 || desc->size > HEAP_BUFFER_SIZE) {
trace_buffer_error("buffer_new() error: "
"new size = %u is invalid", desc->size);
if (size == 0 || size > HEAP_BUFFER_SIZE) {
trace_buffer_error("buffer_alloc() error: "
"new size = %u is invalid", size);
return NULL;
}

/* allocate new buffer */
buffer = rzalloc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, sizeof(*buffer));
if (!buffer) {
trace_buffer_error("buffer_new() error: "
trace_buffer_error("buffer_alloc() error: "
"could not alloc structure");
return NULL;
}

buffer->addr = rballoc(RZONE_BUFFER, desc->caps, desc->size);
buffer->addr = rballoc_align(RZONE_BUFFER, caps, size, align);
if (!buffer->addr) {
rfree(buffer);
trace_buffer_error("buffer_new() error: "
trace_buffer_error("buffer_alloc() error: "
"could not alloc size = %u "
"bytes of type = %u",
desc->size, desc->caps);
size, caps);
return NULL;
}

assert(!memcpy_s(&buffer->ipc_buffer, sizeof(buffer->ipc_buffer),
desc, sizeof(*desc)));
buffer_init(buffer, size, caps);

buffer_init(buffer, desc->size);
list_init(&buffer->source_list);
list_init(&buffer->sink_list);

return buffer;
}

/* create a new component in the pipeline */
struct comp_buffer *buffer_new(struct sof_ipc_buffer *desc)
{
struct comp_buffer *buffer;

trace_buffer("buffer_new()");

/* allocate buffer */
buffer = buffer_alloc(desc->size, desc->caps, PLATFORM_DCACHE_ALIGN);
if (buffer) {
buffer->id = desc->comp.id;
buffer->pipeline_id = desc->comp.pipeline_id;
}

return buffer;
}

int buffer_set_size(struct comp_buffer *buffer, uint32_t size)
{
void *new_ptr = NULL;
struct sof_ipc_buffer *desc = NULL;

/* validate request */
if (size == 0 || size > HEAP_BUFFER_SIZE) {
trace_buffer_error("resize error: size = %u is invalid", size);
return -EINVAL;
}

desc = &buffer->ipc_buffer;
if (!desc) {
trace_buffer_error("resize error: invalid buffer desc");
return -EINVAL;
}

if (size == desc->size)
if (size == buffer->size)
return 0;

new_ptr = rbrealloc(buffer->addr, RZONE_BUFFER, desc->caps, size);
new_ptr = rbrealloc(buffer->addr, RZONE_BUFFER, buffer->caps, size);

/* we couldn't allocate bigger chunk */
if (!new_ptr && size > desc->size) {
if (!new_ptr && size > buffer->size) {
trace_buffer_error("resize error: can't alloc %u bytes type %u",
desc->size, desc->caps);
buffer->size, buffer->caps);
return -ENOMEM;
}

/* use bigger chunk, else just use the old chunk but set smaller */
if (new_ptr)
buffer->addr = new_ptr;

desc->size = size;

buffer_init(buffer, desc->size);
buffer_init(buffer, size, buffer->caps);

return 0;
}
Expand All @@ -113,8 +118,6 @@ void buffer_free(struct comp_buffer *buffer)
void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes)
{
uint32_t flags;
uint32_t head = bytes;
uint32_t tail = 0;

/* return if no bytes */
if (!bytes) {
Expand All @@ -129,33 +132,6 @@ void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes)

irq_local_disable(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:
* 1. source(DMA) --> buffer --> sink(non-DMA): invalidate cache.
* 2. source(non-DMA) --> buffer --> sink(DMA): write back to memory.
* 3. source(DMA) --> buffer --> sink(DMA): do nothing.
* 4. source(non-DMA) --> buffer --> sink(non-DMA): do nothing.
*/
if (buffer->source->is_dma_connected &&
!buffer->sink->is_dma_connected) {
/* need invalidate cache for sink component to use */
dcache_invalidate_region(buffer->w_ptr, head);
if (tail)
dcache_invalidate_region(buffer->addr, tail);
} else if (!buffer->source->is_dma_connected &&
buffer->sink->is_dma_connected) {
/* need write back to memory for sink component to use */
dcache_writeback_region(buffer->w_ptr, head);
if (tail)
dcache_writeback_region(buffer->addr, tail);
}

buffer->w_ptr += bytes;

/* check for pointer wrap */
Expand Down Expand Up @@ -184,10 +160,10 @@ void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes)
irq_local_enable(flags);

tracev_buffer("comp_update_buffer_produce(), ((buffer->avail << 16) | "
"buffer->free) = %08x, ((buffer->ipc_buffer.comp.id << "
"16) | buffer->size) = %08x",
"buffer->free) = %08x, ((buffer->id << 16) | "
"buffer->size) = %08x",
(buffer->avail << 16) | buffer->free,
(buffer->ipc_buffer.comp.id << 16) | buffer->size);
(buffer->id << 16) | buffer->size);
tracev_buffer("comp_update_buffer_produce(), ((buffer->r_ptr - buffer"
"->addr) << 16 | (buffer->w_ptr - buffer->addr)) = %08x",
(buffer->r_ptr - buffer->addr) << 16 |
Expand Down Expand Up @@ -229,22 +205,18 @@ void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes)
/* calculate free bytes */
buffer->free = buffer->size - buffer->avail;

if (buffer->sink->is_dma_connected &&
!buffer->source->is_dma_connected)
dcache_writeback_region(buffer->r_ptr, bytes);

if (buffer->cb && buffer->cb_type & BUFF_CB_TYPE_CONSUME)
buffer->cb(buffer->cb_data, bytes);

irq_local_enable(flags);

tracev_buffer("comp_update_buffer_consume(), "
"(buffer->avail << 16) | buffer->free = %08x, "
"(buffer->ipc_buffer.comp.id << 16) | buffer->size = "
" %08x, (buffer->r_ptr - buffer->addr) << 16 | "
"(buffer->id << 16) | buffer->size = %08x, "
"(buffer->r_ptr - buffer->addr) << 16 | "
"(buffer->w_ptr - buffer->addr)) = %08x",
(buffer->avail << 16) | buffer->free,
(buffer->ipc_buffer.comp.id << 16) | buffer->size,
(buffer->id << 16) | buffer->size,
(buffer->r_ptr - buffer->addr) << 16 |
(buffer->w_ptr - buffer->addr));
}
27 changes: 0 additions & 27 deletions src/audio/component.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,33 +98,6 @@ void comp_unregister(struct comp_driver *drv)
irq_local_enable(flags);
}

int comp_set_sink_buffer(struct comp_dev *dev, uint32_t period_bytes,
uint32_t periods)
{
struct comp_buffer *sinkb;
int ret = 0;

sinkb = list_first_item(&dev->bsink_list, struct comp_buffer,
source_list);

/* components connected to dma configure buffer independently */
if (!sinkb->sink->is_dma_connected) {
ret = buffer_set_size(sinkb, period_bytes * periods);
if (ret < 0) {
trace_comp_error("comp_set_sink_buffer() error: "
"buffer_set_size() failed");
return ret;
}
} else if (sinkb->size < period_bytes * periods) {
trace_comp_error("comp_set_sink_buffer() error: "
"sink buffer size is not sufficient");
ret = -EINVAL;
return ret;
}

return ret;
}

int comp_set_state(struct comp_dev *dev, int cmd)
{
int requested_state = comp_get_requested_state(cmd);
Expand Down
Loading