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 */ 35 typedef struct ia_css_circbuf_s ia_css_circbuf_t; 36 struct 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 */ 48 void 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 */ 58 void 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 */ 71 uint32_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 */ 85 uint32_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 */ 100 static 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 */ 114 static 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 */ 127 static 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 */ 146 static 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 */ 179 static 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 */ 204 static 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 */ 220 static 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 */ 242 static 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 */ 260 static 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 */ 277 static 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 */ 301 static 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 */ 324 static 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 */ 341 uint32_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 */ 353 uint32_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 */ 372 bool 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