/* SPDX-License-Identifier: GPL-2.0 */
|
/*
|
* Support for Intel Camera Imaging ISP subsystem.
|
* Copyright (c) 2015, Intel Corporation.
|
*
|
* This program is free software; you can redistribute it and/or modify it
|
* under the terms and conditions of the GNU General Public License,
|
* version 2, as published by the Free Software Foundation.
|
*
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
* more details.
|
*/
|
|
#ifndef _IA_CSS_CIRCBUF_H
|
#define _IA_CSS_CIRCBUF_H
|
|
#include <sp.h>
|
#include <type_support.h>
|
#include <math_support.h>
|
#include <assert_support.h>
|
#include <platform_support.h>
|
#include "ia_css_circbuf_comm.h"
|
#include "ia_css_circbuf_desc.h"
|
|
/****************************************************************
|
*
|
* Data structures.
|
*
|
****************************************************************/
|
/**
|
* @brief Data structure for the circular buffer.
|
*/
|
typedef struct ia_css_circbuf_s ia_css_circbuf_t;
|
struct ia_css_circbuf_s {
|
ia_css_circbuf_desc_t *desc; /* Pointer to the descriptor of the circbuf */
|
ia_css_circbuf_elem_t *elems; /* an array of elements */
|
};
|
|
/**
|
* @brief Create the circular buffer.
|
*
|
* @param cb The pointer to the circular buffer.
|
* @param elems An array of elements.
|
* @param desc The descriptor set to the size using ia_css_circbuf_desc_init().
|
*/
|
void ia_css_circbuf_create(
|
ia_css_circbuf_t *cb,
|
ia_css_circbuf_elem_t *elems,
|
ia_css_circbuf_desc_t *desc);
|
|
/**
|
* @brief Destroy the circular buffer.
|
*
|
* @param cb The pointer to the circular buffer.
|
*/
|
void ia_css_circbuf_destroy(
|
ia_css_circbuf_t *cb);
|
|
/**
|
* @brief Pop a value out of the circular buffer.
|
* Get a value at the head of the circular buffer.
|
* The user should call "ia_css_circbuf_is_empty()"
|
* to avoid accessing to an empty buffer.
|
*
|
* @param cb The pointer to the circular buffer.
|
*
|
* @return the pop-out value.
|
*/
|
uint32_t ia_css_circbuf_pop(
|
ia_css_circbuf_t *cb);
|
|
/**
|
* @brief Extract a value out of the circular buffer.
|
* Get a value at an arbitrary poistion in the circular
|
* buffer. The user should call "ia_css_circbuf_is_empty()"
|
* to avoid accessing to an empty buffer.
|
*
|
* @param cb The pointer to the circular buffer.
|
* @param offset The offset from "start" to the target position.
|
*
|
* @return the extracted value.
|
*/
|
uint32_t ia_css_circbuf_extract(
|
ia_css_circbuf_t *cb,
|
int offset);
|
|
/****************************************************************
|
*
|
* Inline functions.
|
*
|
****************************************************************/
|
/**
|
* @brief Set the "val" field in the element.
|
*
|
* @param elem The pointer to the element.
|
* @param val The value to be set.
|
*/
|
static inline void ia_css_circbuf_elem_set_val(
|
ia_css_circbuf_elem_t *elem,
|
uint32_t val)
|
{
|
OP___assert(elem);
|
|
elem->val = val;
|
}
|
|
/**
|
* @brief Initialize the element.
|
*
|
* @param elem The pointer to the element.
|
*/
|
static inline void ia_css_circbuf_elem_init(
|
ia_css_circbuf_elem_t *elem)
|
{
|
OP___assert(elem);
|
ia_css_circbuf_elem_set_val(elem, 0);
|
}
|
|
/**
|
* @brief Copy an element.
|
*
|
* @param src The element as the copy source.
|
* @param dest The element as the copy destination.
|
*/
|
static inline void ia_css_circbuf_elem_cpy(
|
ia_css_circbuf_elem_t *src,
|
ia_css_circbuf_elem_t *dest)
|
{
|
OP___assert(src);
|
OP___assert(dest);
|
|
ia_css_circbuf_elem_set_val(dest, src->val);
|
}
|
|
/**
|
* @brief Get position in the circular buffer.
|
*
|
* @param cb The pointer to the circular buffer.
|
* @param base The base position.
|
* @param offset The offset.
|
*
|
* @return the position at offset.
|
*/
|
static inline uint8_t ia_css_circbuf_get_pos_at_offset(
|
ia_css_circbuf_t *cb,
|
u32 base,
|
int offset)
|
{
|
u8 dest;
|
|
OP___assert(cb);
|
OP___assert(cb->desc);
|
OP___assert(cb->desc->size > 0);
|
|
/* step 1: adjudst the offset */
|
while (offset < 0) {
|
offset += cb->desc->size;
|
}
|
|
/* step 2: shift and round by the upper limit */
|
dest = OP_std_modadd(base, offset, cb->desc->size);
|
|
return dest;
|
}
|
|
/**
|
* @brief Get the offset between two positions in the circular buffer.
|
* Get the offset from the source position to the terminal position,
|
* along the direction in which the new elements come in.
|
*
|
* @param cb The pointer to the circular buffer.
|
* @param src_pos The source position.
|
* @param dest_pos The terminal position.
|
*
|
* @return the offset.
|
*/
|
static inline int ia_css_circbuf_get_offset(
|
ia_css_circbuf_t *cb,
|
u32 src_pos,
|
uint32_t dest_pos)
|
{
|
int offset;
|
|
OP___assert(cb);
|
OP___assert(cb->desc);
|
|
offset = (int)(dest_pos - src_pos);
|
offset += (offset < 0) ? cb->desc->size : 0;
|
|
return offset;
|
}
|
|
/**
|
* @brief Get the maximum number of elements.
|
*
|
* @param cb The pointer to the circular buffer.
|
*
|
* @return the maximum number of elements.
|
*
|
* TODO: Test this API.
|
*/
|
static inline uint32_t ia_css_circbuf_get_size(
|
ia_css_circbuf_t *cb)
|
{
|
OP___assert(cb);
|
OP___assert(cb->desc);
|
|
return cb->desc->size;
|
}
|
|
/**
|
* @brief Get the number of available elements.
|
*
|
* @param cb The pointer to the circular buffer.
|
*
|
* @return the number of available elements.
|
*/
|
static inline uint32_t ia_css_circbuf_get_num_elems(
|
ia_css_circbuf_t *cb)
|
{
|
int num;
|
|
OP___assert(cb);
|
OP___assert(cb->desc);
|
|
num = ia_css_circbuf_get_offset(cb, cb->desc->start, cb->desc->end);
|
|
return (uint32_t)num;
|
}
|
|
/**
|
* @brief Test if the circular buffer is empty.
|
*
|
* @param cb The pointer to the circular buffer.
|
*
|
* @return
|
* - true when it is empty.
|
* - false when it is not empty.
|
*/
|
static inline bool ia_css_circbuf_is_empty(
|
ia_css_circbuf_t *cb)
|
{
|
OP___assert(cb);
|
OP___assert(cb->desc);
|
|
return ia_css_circbuf_desc_is_empty(cb->desc);
|
}
|
|
/**
|
* @brief Test if the circular buffer is full.
|
*
|
* @param cb The pointer to the circular buffer.
|
*
|
* @return
|
* - true when it is full.
|
* - false when it is not full.
|
*/
|
static inline bool ia_css_circbuf_is_full(ia_css_circbuf_t *cb)
|
{
|
OP___assert(cb);
|
OP___assert(cb->desc);
|
|
return ia_css_circbuf_desc_is_full(cb->desc);
|
}
|
|
/**
|
* @brief Write a new element into the circular buffer.
|
* Write a new element WITHOUT checking whether the
|
* circular buffer is full or not. So it also overwrites
|
* the oldest element when the buffer is full.
|
*
|
* @param cb The pointer to the circular buffer.
|
* @param elem The new element.
|
*/
|
static inline void ia_css_circbuf_write(
|
ia_css_circbuf_t *cb,
|
ia_css_circbuf_elem_t elem)
|
{
|
OP___assert(cb);
|
OP___assert(cb->desc);
|
|
/* Cannot continue as the queue is full*/
|
assert(!ia_css_circbuf_is_full(cb));
|
|
ia_css_circbuf_elem_cpy(&elem, &cb->elems[cb->desc->end]);
|
|
cb->desc->end = ia_css_circbuf_get_pos_at_offset(cb, cb->desc->end, 1);
|
}
|
|
/**
|
* @brief Push a value in the circular buffer.
|
* Put a new value at the tail of the circular buffer.
|
* The user should call "ia_css_circbuf_is_full()"
|
* to avoid accessing to a full buffer.
|
*
|
* @param cb The pointer to the circular buffer.
|
* @param val The value to be pushed in.
|
*/
|
static inline void ia_css_circbuf_push(
|
ia_css_circbuf_t *cb,
|
uint32_t val)
|
{
|
ia_css_circbuf_elem_t elem;
|
|
OP___assert(cb);
|
|
/* set up an element */
|
ia_css_circbuf_elem_init(&elem);
|
ia_css_circbuf_elem_set_val(&elem, val);
|
|
/* write the element into the buffer */
|
ia_css_circbuf_write(cb, elem);
|
}
|
|
/**
|
* @brief Get the number of free elements.
|
*
|
* @param cb The pointer to the circular buffer.
|
*
|
* @return: The number of free elements.
|
*/
|
static inline uint32_t ia_css_circbuf_get_free_elems(
|
ia_css_circbuf_t *cb)
|
{
|
OP___assert(cb);
|
OP___assert(cb->desc);
|
|
return ia_css_circbuf_desc_get_free_elems(cb->desc);
|
}
|
|
/**
|
* @brief Peek an element in Circular Buffer.
|
*
|
* @param cb The pointer to the circular buffer.
|
* @param offset Offset to the element.
|
*
|
* @return the elements value.
|
*/
|
uint32_t ia_css_circbuf_peek(
|
ia_css_circbuf_t *cb,
|
int offset);
|
|
/**
|
* @brief Get an element in Circular Buffer.
|
*
|
* @param cb The pointer to the circular buffer.
|
* @param offset Offset to the element.
|
*
|
* @return the elements value.
|
*/
|
uint32_t ia_css_circbuf_peek_from_start(
|
ia_css_circbuf_t *cb,
|
int offset);
|
|
/**
|
* @brief Increase Size of a Circular Buffer.
|
* Use 'CAUTION' before using this function, This was added to
|
* support / fix issue with increasing size for tagger only
|
*
|
* @param cb The pointer to the circular buffer.
|
* @param sz_delta delta increase for new size
|
* @param elems (optional) pointers to new additional elements
|
* cb element array size will not be increased dynamically,
|
* but new elements should be added at the end to existing
|
* cb element array which if of max_size >= new size
|
*
|
* @return true on successfully increasing the size
|
* false on failure
|
*/
|
bool ia_css_circbuf_increase_size(
|
ia_css_circbuf_t *cb,
|
unsigned int sz_delta,
|
ia_css_circbuf_elem_t *elems);
|
|
#endif /*_IA_CSS_CIRCBUF_H */
|