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