linux/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf.h
<<
>>
Prefs
   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