2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 2015, Intel Corporation.
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.
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
15 #include "ia_css_circbuf.h"
17 #include <assert_support.h>
19 /**********************************************************************
21 * Forward declarations.
23 **********************************************************************/
25 * @brief Read the oldest element from the circular buffer.
26 * Read the oldest element WITHOUT checking whehter the
27 * circular buffer is empty or not. The oldest element is
28 * also removed out from the circular buffer.
30 * @param cb The pointer to the circular buffer.
32 * @return the oldest element.
34 static inline ia_css_circbuf_elem_t
35 ia_css_circbuf_read(ia_css_circbuf_t
*cb
);
38 * @brief Shift a chunk of elements in the circular buffer.
39 * A chunk of elements (i.e. the ones from the "start" position
40 * to the "chunk_src" position) are shifted in the circular buffer,
41 * along the direction of new elements coming.
43 * @param cb The pointer to the circular buffer.
44 * @param chunk_src The position at which the first element in the chunk is.
45 * @param chunk_dest The position to which the first element in the chunk would be shift.
47 static inline void ia_css_circbuf_shift_chunk(ia_css_circbuf_t
*cb
,
52 * @brief Get the "val" field in the element.
54 * @param elem The pointer to the element.
56 * @return the "val" field.
58 static inline uint32_t
59 ia_css_circbuf_elem_get_val(ia_css_circbuf_elem_t
*elem
);
61 /**********************************************************************
63 * Non-inline functions.
65 **********************************************************************/
67 * @brief Create the circular buffer.
68 * Refer to "ia_css_circbuf.h" for details.
71 ia_css_circbuf_create(ia_css_circbuf_t
*cb
,
72 ia_css_circbuf_elem_t
*elems
,
73 ia_css_circbuf_desc_t
*desc
)
80 /* Initialize to defaults */
85 for (i
= 0; i
< cb
->desc
->size
; i
++)
86 ia_css_circbuf_elem_init(&elems
[i
]);
92 * @brief Destroy the circular buffer.
93 * Refer to "ia_css_circbuf.h" for details.
95 void ia_css_circbuf_destroy(ia_css_circbuf_t
*cb
)
103 * @brief Pop a value out of the circular buffer.
104 * Refer to "ia_css_circbuf.h" for details.
106 uint32_t ia_css_circbuf_pop(ia_css_circbuf_t
*cb
)
109 ia_css_circbuf_elem_t elem
;
111 assert(!ia_css_circbuf_is_empty(cb
));
113 /* read an element from the buffer */
114 elem
= ia_css_circbuf_read(cb
);
115 ret
= ia_css_circbuf_elem_get_val(&elem
);
120 * @brief Extract a value out of the circular buffer.
121 * Refer to "ia_css_circbuf.h" for details.
123 uint32_t ia_css_circbuf_extract(ia_css_circbuf_t
*cb
, int offset
)
131 /* get the maximum offest */
132 max_offset
= ia_css_circbuf_get_offset(cb
, cb
->desc
->start
, cb
->desc
->end
);
136 * Step 1: When the target element is at the "start" position.
139 val
= ia_css_circbuf_pop(cb
);
144 * Step 2: When the target element is out of the range.
146 if (offset
> max_offset
) {
152 * Step 3: When the target element is between the "start" and
155 /* get the position of the target element */
156 pos
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->start
, offset
);
158 /* get the value from the target element */
159 val
= ia_css_circbuf_elem_get_val(&cb
->elems
[pos
]);
161 /* shift the elements */
162 src_pos
= ia_css_circbuf_get_pos_at_offset(cb
, pos
, -1);
164 ia_css_circbuf_shift_chunk(cb
, src_pos
, dest_pos
);
170 * @brief Peek an element from the circular buffer.
171 * Refer to "ia_css_circbuf.h" for details.
173 uint32_t ia_css_circbuf_peek(ia_css_circbuf_t
*cb
, int offset
)
177 pos
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->end
, offset
);
179 /* get the value at the position */
180 return cb
->elems
[pos
].val
;
184 * @brief Get the value of an element from the circular buffer.
185 * Refer to "ia_css_circbuf.h" for details.
187 uint32_t ia_css_circbuf_peek_from_start(ia_css_circbuf_t
*cb
, int offset
)
191 pos
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->start
, offset
);
193 /* get the value at the position */
194 return cb
->elems
[pos
].val
;
197 /** @brief increase size of a circular buffer.
198 * Use 'CAUTION' before using this function. This was added to
199 * support / fix issue with increasing size for tagger only
200 * Please refer to "ia_css_circbuf.h" for details.
202 bool ia_css_circbuf_increase_size(
203 ia_css_circbuf_t
*cb
,
204 unsigned int sz_delta
,
205 ia_css_circbuf_elem_t
*elems
)
211 if (!cb
|| sz_delta
== 0)
214 curr_size
= cb
->desc
->size
;
215 curr_end
= cb
->desc
->end
;
216 /* We assume cb was pre defined as global to allow
217 * increase in size */
218 /* FM: are we sure this cannot cause size to become too big? */
219 if (((uint8_t)(cb
->desc
->size
+ (uint8_t)sz_delta
) > cb
->desc
->size
) && ((uint8_t)sz_delta
== sz_delta
))
220 cb
->desc
->size
+= (uint8_t)sz_delta
;
222 return false; /* overflow in size */
224 /* If elems are passed update them else we assume its been taken
225 * care before calling this function */
227 /* cb element array size will not be increased dynamically,
228 * but pointers to new elements can be added at the end
229 * of existing pre defined cb element array of
230 * size >= new size if not already added */
231 for (i
= curr_size
; i
< cb
->desc
->size
; i
++)
232 cb
->elems
[i
] = elems
[i
- curr_size
];
234 /* Fix Start / End */
235 if (curr_end
< cb
->desc
->start
) {
238 cb
->desc
->end
= curr_size
;
240 /* Move elements and fix Start*/
241 ia_css_circbuf_shift_chunk(cb
,
243 curr_size
+ sz_delta
- 1);
250 /****************************************************************
254 ****************************************************************/
256 * @brief Get the "val" field in the element.
257 * Refer to "Forward declarations" for details.
259 static inline uint32_t
260 ia_css_circbuf_elem_get_val(ia_css_circbuf_elem_t
*elem
)
266 * @brief Read the oldest element from the circular buffer.
267 * Refer to "Forward declarations" for details.
269 static inline ia_css_circbuf_elem_t
270 ia_css_circbuf_read(ia_css_circbuf_t
*cb
)
272 ia_css_circbuf_elem_t elem
;
274 /* get the element from the target position */
275 elem
= cb
->elems
[cb
->desc
->start
];
277 /* clear the target position */
278 ia_css_circbuf_elem_init(&cb
->elems
[cb
->desc
->start
]);
280 /* adjust the "start" position */
281 cb
->desc
->start
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->start
, 1);
286 * @brief Shift a chunk of elements in the circular buffer.
287 * Refer to "Forward declarations" for details.
290 ia_css_circbuf_shift_chunk(ia_css_circbuf_t
*cb
,
291 uint32_t chunk_src
, uint32_t chunk_dest
)
297 /* get the chunk offset and size */
298 chunk_offset
= ia_css_circbuf_get_offset(cb
,
299 chunk_src
, chunk_dest
);
300 chunk_sz
= ia_css_circbuf_get_offset(cb
, cb
->desc
->start
, chunk_src
) + 1;
302 /* shift each element to its terminal position */
303 for (i
= 0; i
< chunk_sz
; i
++) {
305 /* copy the element from the source to the destination */
306 ia_css_circbuf_elem_cpy(&cb
->elems
[chunk_src
],
307 &cb
->elems
[chunk_dest
]);
309 /* clear the source position */
310 ia_css_circbuf_elem_init(&cb
->elems
[chunk_src
]);
312 /* adjust the source/terminal positions */
313 chunk_src
= ia_css_circbuf_get_pos_at_offset(cb
, chunk_src
, -1);
314 chunk_dest
= ia_css_circbuf_get_pos_at_offset(cb
, chunk_dest
, -1);
318 /* adjust the index "start" */
319 cb
->desc
->start
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->start
, chunk_offset
);