GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / base / circbuf / interface / ia_css_circbuf.h
1 /*
2  * Support for Intel Camera Imaging ISP subsystem.
3  * Copyright (c) 2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14
15 #ifndef _IA_CSS_CIRCBUF_H
16 #define _IA_CSS_CIRCBUF_H
17
18 #include <sp.h>
19 #include <type_support.h>
20 #include <math_support.h>
21 #include <storage_class.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 STORAGE_CLASS_EXTERN 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 STORAGE_CLASS_EXTERN 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 STORAGE_CLASS_EXTERN 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 STORAGE_CLASS_EXTERN 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 STORAGE_CLASS_INLINE void ia_css_circbuf_elem_set_val(
101         ia_css_circbuf_elem_t *elem,
102         uint32_t val)
103 {
104         OP___assert(elem != NULL);
105
106         elem->val = val;
107 }
108
109 /**
110  * @brief Initialize the element.
111  *
112  * @param elem The pointer to the element.
113  */
114 STORAGE_CLASS_INLINE void ia_css_circbuf_elem_init(
115                 ia_css_circbuf_elem_t *elem)
116 {
117         OP___assert(elem != NULL);
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 STORAGE_CLASS_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 != NULL);
132         OP___assert(dest != NULL);
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 STORAGE_CLASS_INLINE uint8_t ia_css_circbuf_get_pos_at_offset(
147         ia_css_circbuf_t *cb,
148         uint32_t base,
149         int offset)
150 {
151         uint8_t dest;
152
153         OP___assert(cb != NULL);
154         OP___assert(cb->desc != NULL);
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 STORAGE_CLASS_INLINE int ia_css_circbuf_get_offset(
180         ia_css_circbuf_t *cb,
181         uint32_t src_pos,
182         uint32_t dest_pos)
183 {
184         int offset;
185
186         OP___assert(cb != NULL);
187         OP___assert(cb->desc != NULL);
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 STORAGE_CLASS_INLINE uint32_t ia_css_circbuf_get_size(
205                 ia_css_circbuf_t *cb)
206 {
207         OP___assert(cb != NULL);
208         OP___assert(cb->desc != NULL);
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 STORAGE_CLASS_INLINE uint32_t ia_css_circbuf_get_num_elems(
221                 ia_css_circbuf_t *cb)
222 {
223         int num;
224
225         OP___assert(cb != NULL);
226         OP___assert(cb->desc != NULL);
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 STORAGE_CLASS_INLINE bool ia_css_circbuf_is_empty(
243                 ia_css_circbuf_t *cb)
244 {
245         OP___assert(cb != NULL);
246         OP___assert(cb->desc != NULL);
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 STORAGE_CLASS_INLINE bool ia_css_circbuf_is_full(ia_css_circbuf_t *cb)
261 {
262         OP___assert(cb != NULL);
263         OP___assert(cb->desc != NULL);
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 STORAGE_CLASS_INLINE void ia_css_circbuf_write(
278         ia_css_circbuf_t *cb,
279         ia_css_circbuf_elem_t elem)
280 {
281         OP___assert(cb != NULL);
282         OP___assert(cb->desc != NULL);
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 STORAGE_CLASS_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 != NULL);
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 STORAGE_CLASS_INLINE uint32_t ia_css_circbuf_get_free_elems(
325                 ia_css_circbuf_t *cb)
326 {
327         OP___assert(cb != NULL);
328         OP___assert(cb->desc != NULL);
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 STORAGE_CLASS_EXTERN 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 STORAGE_CLASS_EXTERN 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 succesfully increasing the size
370  *                      false on failure
371  */
372 STORAGE_CLASS_EXTERN 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 */