blob: 4e2c43a930c9b51344b27b137af304e7aba1c620 [file] [log] [blame]
/*
* Copyright (c) 2017, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Intel Corporation nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/
#ifndef __INCLUDE_AUDIO_BUFFER_H__
#define __INCLUDE_AUDIO_BUFFER_H__
#include <stdint.h>
#include <stddef.h>
#include <sof/lock.h>
#include <sof/list.h>
#include <sof/stream.h>
#include <sof/dma.h>
#include <sof/audio/component.h>
#include <sof/trace.h>
#include <sof/schedule.h>
#include <uapi/ipc.h>
/* pipeline tracing */
#define trace_buffer(__e) trace_event(TRACE_CLASS_BUFFER, __e)
#define trace_buffer_error(__e) trace_error(TRACE_CLASS_BUFFER, __e)
#define tracev_buffer(__e) tracev_event(TRACE_CLASS_BUFFER, __e)
/* audio component buffer - connects 2 audio components together in pipeline */
struct comp_buffer {
/* runtime data */
uint32_t connected; /* connected in path */
uint32_t size; /* runtime buffer size in bytes (period multiple) */
uint32_t alloc_size; /* allocated size in bytes */
uint32_t avail; /* available bytes for reading */
uint32_t free; /* free bytes for writing */
void *w_ptr; /* buffer write pointer */
void *r_ptr; /* buffer read position */
void *addr; /* buffer base address */
void *end_addr; /* buffer end address */
/* IPC configuration */
struct sof_ipc_buffer ipc_buffer;
/* connected components */
struct comp_dev *source; /* source component */
struct comp_dev *sink; /* sink component */
/* lists */
struct list_item source_list; /* list in comp buffers */
struct list_item sink_list; /* list in comp buffers */
spinlock_t lock;
};
/* pipeline buffer creation and destruction */
struct comp_buffer *buffer_new(struct sof_ipc_buffer *desc);
void buffer_free(struct comp_buffer *buffer);
/* called by a component after producing data into this buffer */
void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes);
/* called by a component after consuming data from this buffer */
void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes);
static inline void buffer_zero(struct comp_buffer *buffer)
{
tracev_buffer("BZr");
bzero(buffer->addr, buffer->size);
if (buffer->ipc_buffer.caps & SOF_MEM_CAPS_DMA)
dcache_writeback_region(buffer->addr, buffer->size);
}
/* get the max number of bytes that can be copied between sink and source */
static inline int comp_buffer_can_copy_bytes(struct comp_buffer *source,
struct comp_buffer *sink, uint32_t bytes)
{
/* check for underrun */
if (source->avail < bytes)
return -1;
/* check for overrun */
if (sink->free < bytes)
return 1;
/* we are good to copy */
return 0;
}
static inline uint32_t comp_buffer_get_copy_bytes(struct comp_buffer *source,
struct comp_buffer *sink)
{
if (source->avail > sink->free)
return sink->free;
else
return source->avail;
}
static inline void buffer_reset_pos(struct comp_buffer *buffer)
{
/* reset read and write pointer to buffer bas */
buffer->w_ptr = buffer->r_ptr = buffer->addr;
/* free space is buffer size */
buffer->free = buffer->size;
/* ther are no avail samples at reset */
buffer->avail = 0;
/* clear buffer contents */
buffer_zero(buffer);
}
/* set the runtime size of a buffer in bytes and improve the data cache */
/* performance by only using minimum space needed for runtime params */
static inline int buffer_set_size(struct comp_buffer *buffer, uint32_t size)
{
if (size > buffer->alloc_size)
return -ENOMEM;
if (size == 0)
return -EINVAL;
buffer->end_addr = buffer->addr + size;
buffer->size = size;
return 0;
}
#endif