1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Support for Intel Camera Imaging ISP subsystem. 4 * Copyright (c) 2015, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 */ 15 16#ifndef _IA_CSS_CIRCBUF_H 17#define _IA_CSS_CIRCBUF_H 18 19#include <sp.h> 20#include <type_support.h> 21#include <math_support.h> 22#include <assert_support.h> 23#include <platform_support.h> 24#include "ia_css_circbuf_comm.h" 25#include "ia_css_circbuf_desc.h" 26 27/**************************************************************** 28 * 29 * Data structures. 30 * 31 ****************************************************************/ 32/** 33 * @brief Data structure for the circular buffer. 34 */ 35typedef struct ia_css_circbuf_s ia_css_circbuf_t; 36struct ia_css_circbuf_s { 37 ia_css_circbuf_desc_t *desc; /* Pointer to the descriptor of the circbuf */ 38 ia_css_circbuf_elem_t *elems; /* an array of elements */ 39}; 40 41/** 42 * @brief Create the circular buffer. 43 * 44 * @param cb The pointer to the circular buffer. 45 * @param elems An array of elements. 46 * @param desc The descriptor set to the size using ia_css_circbuf_desc_init(). 47 */ 48void ia_css_circbuf_create( 49 ia_css_circbuf_t *cb, 50 ia_css_circbuf_elem_t *elems, 51 ia_css_circbuf_desc_t *desc); 52 53/** 54 * @brief Destroy the circular buffer. 55 * 56 * @param cb The pointer to the circular buffer. 57 */ 58void ia_css_circbuf_destroy( 59 ia_css_circbuf_t *cb); 60 61/** 62 * @brief Pop a value out of the circular buffer. 63 * Get a value at the head of the circular buffer. 64 * The user should call "ia_css_circbuf_is_empty()" 65 * to avoid accessing to an empty buffer. 66 * 67 * @param cb The pointer to the circular buffer. 68 * 69 * @return the pop-out value. 70 */ 71uint32_t ia_css_circbuf_pop( 72 ia_css_circbuf_t *cb); 73 74/** 75 * @brief Extract a value out of the circular buffer. 76 * Get a value at an arbitrary poistion in the circular 77 * buffer. The user should call "ia_css_circbuf_is_empty()" 78 * to avoid accessing to an empty buffer. 79 * 80 * @param cb The pointer to the circular buffer. 81 * @param offset The offset from "start" to the target position. 82 * 83 * @return the extracted value. 84 */ 85uint32_t ia_css_circbuf_extract( 86 ia_css_circbuf_t *cb, 87 int offset); 88 89/**************************************************************** 90 * 91 * Inline functions. 92 * 93 ****************************************************************/ 94/** 95 * @brief Set the "val" field in the element. 96 * 97 * @param elem The pointer to the element. 98 * @param val The value to be set. 99 */ 100static inline void ia_css_circbuf_elem_set_val( 101 ia_css_circbuf_elem_t *elem, 102 uint32_t val) 103{ 104 OP___assert(elem); 105 106 elem->val = val; 107} 108 109/** 110 * @brief Initialize the element. 111 * 112 * @param elem The pointer to the element. 113 */ 114static inline void ia_css_circbuf_elem_init( 115 ia_css_circbuf_elem_t *elem) 116{ 117 OP___assert(elem); 118 ia_css_circbuf_elem_set_val(elem, 0); 119} 120 121/** 122 * @brief Copy an element. 123 * 124 * @param src The element as the copy source. 125 * @param dest The element as the copy destination. 126 */ 127static inline void ia_css_circbuf_elem_cpy( 128 ia_css_circbuf_elem_t *src, 129 ia_css_circbuf_elem_t *dest) 130{ 131 OP___assert(src); 132 OP___assert(dest); 133 134 ia_css_circbuf_elem_set_val(dest, src->val); 135} 136 137/** 138 * @brief Get position in the circular buffer. 139 * 140 * @param cb The pointer to the circular buffer. 141 * @param base The base position. 142 * @param offset The offset. 143 * 144 * @return the position at offset. 145 */ 146static inline uint8_t ia_css_circbuf_get_pos_at_offset( 147 ia_css_circbuf_t *cb, 148 u32 base, 149 int offset) 150{ 151 u8 dest; 152 153 OP___assert(cb); 154 OP___assert(cb->desc); 155 OP___assert(cb->desc->size > 0); 156 157 /* step 1: adjudst the offset */ 158 while (offset < 0) { 159 offset += cb->desc->size; 160 } 161 162 /* step 2: shift and round by the upper limit */ 163 dest = OP_std_modadd(base, offset, cb->desc->size); 164 165 return dest; 166} 167 168/** 169 * @brief Get the offset between two positions in the circular buffer. 170 * Get the offset from the source position to the terminal position, 171 * along the direction in which the new elements come in. 172 * 173 * @param cb The pointer to the circular buffer. 174 * @param src_pos The source position. 175 * @param dest_pos The terminal position. 176 * 177 * @return the offset. 178 */ 179static inline int ia_css_circbuf_get_offset( 180 ia_css_circbuf_t *cb, 181 u32 src_pos, 182 uint32_t dest_pos) 183{ 184 int offset; 185 186 OP___assert(cb); 187 OP___assert(cb->desc); 188 189 offset = (int)(dest_pos - src_pos); 190 offset += (offset < 0) ? cb->desc->size : 0; 191 192 return offset; 193} 194 195/** 196 * @brief Get the maximum number of elements. 197 * 198 * @param cb The pointer to the circular buffer. 199 * 200 * @return the maximum number of elements. 201 * 202 * TODO: Test this API. 203 */ 204static inline uint32_t ia_css_circbuf_get_size( 205 ia_css_circbuf_t *cb) 206{ 207 OP___assert(cb); 208 OP___assert(cb->desc); 209 210 return cb->desc->size; 211} 212 213/** 214 * @brief Get the number of available elements. 215 * 216 * @param cb The pointer to the circular buffer. 217 * 218 * @return the number of available elements. 219 */ 220static inline uint32_t ia_css_circbuf_get_num_elems( 221 ia_css_circbuf_t *cb) 222{ 223 int num; 224 225 OP___assert(cb); 226 OP___assert(cb->desc); 227 228 num = ia_css_circbuf_get_offset(cb, cb->desc->start, cb->desc->end); 229 230 return (uint32_t)num; 231} 232 233/** 234 * @brief Test if the circular buffer is empty. 235 * 236 * @param cb The pointer to the circular buffer. 237 * 238 * @return 239 * - true when it is empty. 240 * - false when it is not empty. 241 */ 242static inline bool ia_css_circbuf_is_empty( 243 ia_css_circbuf_t *cb) 244{ 245 OP___assert(cb); 246 OP___assert(cb->desc); 247 248 return ia_css_circbuf_desc_is_empty(cb->desc); 249} 250 251/** 252 * @brief Test if the circular buffer is full. 253 * 254 * @param cb The pointer to the circular buffer. 255 * 256 * @return 257 * - true when it is full. 258 * - false when it is not full. 259 */ 260static inline bool ia_css_circbuf_is_full(ia_css_circbuf_t *cb) 261{ 262 OP___assert(cb); 263 OP___assert(cb->desc); 264 265 return ia_css_circbuf_desc_is_full(cb->desc); 266} 267 268/** 269 * @brief Write a new element into the circular buffer. 270 * Write a new element WITHOUT checking whether the 271 * circular buffer is full or not. So it also overwrites 272 * the oldest element when the buffer is full. 273 * 274 * @param cb The pointer to the circular buffer. 275 * @param elem The new element. 276 */ 277static inline void ia_css_circbuf_write( 278 ia_css_circbuf_t *cb, 279 ia_css_circbuf_elem_t elem) 280{ 281 OP___assert(cb); 282 OP___assert(cb->desc); 283 284 /* Cannot continue as the queue is full*/ 285 assert(!ia_css_circbuf_is_full(cb)); 286 287 ia_css_circbuf_elem_cpy(&elem, &cb->elems[cb->desc->end]); 288 289 cb->desc->end = ia_css_circbuf_get_pos_at_offset(cb, cb->desc->end, 1); 290} 291 292/** 293 * @brief Push a value in the circular buffer. 294 * Put a new value at the tail of the circular buffer. 295 * The user should call "ia_css_circbuf_is_full()" 296 * to avoid accessing to a full buffer. 297 * 298 * @param cb The pointer to the circular buffer. 299 * @param val The value to be pushed in. 300 */ 301static inline void ia_css_circbuf_push( 302 ia_css_circbuf_t *cb, 303 uint32_t val) 304{ 305 ia_css_circbuf_elem_t elem; 306 307 OP___assert(cb); 308 309 /* set up an element */ 310 ia_css_circbuf_elem_init(&elem); 311 ia_css_circbuf_elem_set_val(&elem, val); 312 313 /* write the element into the buffer */ 314 ia_css_circbuf_write(cb, elem); 315} 316 317/** 318 * @brief Get the number of free elements. 319 * 320 * @param cb The pointer to the circular buffer. 321 * 322 * @return: The number of free elements. 323 */ 324static inline uint32_t ia_css_circbuf_get_free_elems( 325 ia_css_circbuf_t *cb) 326{ 327 OP___assert(cb); 328 OP___assert(cb->desc); 329 330 return ia_css_circbuf_desc_get_free_elems(cb->desc); 331} 332 333/** 334 * @brief Peek an element in Circular Buffer. 335 * 336 * @param cb The pointer to the circular buffer. 337 * @param offset Offset to the element. 338 * 339 * @return the elements value. 340 */ 341uint32_t ia_css_circbuf_peek( 342 ia_css_circbuf_t *cb, 343 int offset); 344 345/** 346 * @brief Get an element in Circular Buffer. 347 * 348 * @param cb The pointer to the circular buffer. 349 * @param offset Offset to the element. 350 * 351 * @return the elements value. 352 */ 353uint32_t ia_css_circbuf_peek_from_start( 354 ia_css_circbuf_t *cb, 355 int offset); 356 357/** 358 * @brief Increase Size of a Circular Buffer. 359 * Use 'CAUTION' before using this function, This was added to 360 * support / fix issue with increasing size for tagger only 361 * 362 * @param cb The pointer to the circular buffer. 363 * @param sz_delta delta increase for new size 364 * @param elems (optional) pointers to new additional elements 365 * cb element array size will not be increased dynamically, 366 * but new elements should be added at the end to existing 367 * cb element array which if of max_size >= new size 368 * 369 * @return true on successfully increasing the size 370 * false on failure 371 */ 372bool ia_css_circbuf_increase_size( 373 ia_css_circbuf_t *cb, 374 unsigned int sz_delta, 375 ia_css_circbuf_elem_t *elems); 376 377#endif /*_IA_CSS_CIRCBUF_H */ 378