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 position 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 */
ia_css_circbuf_elem_set_val(ia_css_circbuf_elem_t * elem,uint32_t val)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 */
ia_css_circbuf_elem_init(ia_css_circbuf_elem_t * elem)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 */
ia_css_circbuf_elem_cpy(ia_css_circbuf_elem_t * src,ia_css_circbuf_elem_t * dest)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 */
ia_css_circbuf_get_pos_at_offset(ia_css_circbuf_t * cb,u32 base,int offset)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 */
ia_css_circbuf_get_offset(ia_css_circbuf_t * cb,u32 src_pos,uint32_t dest_pos)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 */
ia_css_circbuf_get_size(ia_css_circbuf_t * cb)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 */
ia_css_circbuf_get_num_elems(ia_css_circbuf_t * cb)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 */
ia_css_circbuf_is_empty(ia_css_circbuf_t * cb)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 */
ia_css_circbuf_is_full(ia_css_circbuf_t * cb)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 */
ia_css_circbuf_write(ia_css_circbuf_t * cb,ia_css_circbuf_elem_t elem)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 */
ia_css_circbuf_push(ia_css_circbuf_t * cb,uint32_t val)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 */
ia_css_circbuf_get_free_elems(ia_css_circbuf_t * cb)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