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>
20 #include <hive_isp_css_sp_api_modified.h>
21 #include <ia_css_sp_file_id.sp.h>
23 #define SP_FILE_ID SP_FILE_ID_CIRCBUF /* overrule default in ia_css_sp_assert_level.sp.h */
25 #include <ia_css_sp_assert_level.sp.h>
28 /**********************************************************************
30 * Forward declarations.
32 **********************************************************************/
34 * @brief Read the oldest element from the circular buffer.
35 * Read the oldest element WITHOUT checking whehter the
36 * circular buffer is empty or not. The oldest element is
37 * also removed out from the circular buffer.
39 * @param cb The pointer to the circular buffer.
41 * @return the oldest element.
43 static inline ia_css_circbuf_elem_t
44 ia_css_circbuf_read(ia_css_circbuf_t
*cb
);
47 * @brief Shift a chunk of elements in the circular buffer.
48 * A chunk of elements (i.e. the ones from the "start" position
49 * to the "chunk_src" position) are shifted in the circular buffer,
50 * along the direction of new elements coming.
52 * @param cb The pointer to the circular buffer.
53 * @param chunk_src The position at which the first element in the chunk is.
54 * @param chunk_dest The position to which the first element in the chunk would be shift.
56 static inline void ia_css_circbuf_shift_chunk(ia_css_circbuf_t
*cb
,
61 * @brief Get the "val" field in the element.
63 * @param elem The pointer to the element.
65 * @return the "val" field.
67 static inline uint32_t
68 ia_css_circbuf_elem_get_val(ia_css_circbuf_elem_t
*elem
);
70 /**********************************************************************
72 * Non-inline functions.
74 **********************************************************************/
76 * @brief Create the circular buffer.
77 * Refer to "ia_css_circbuf.h" for details.
80 ia_css_circbuf_create(ia_css_circbuf_t
*cb
,
81 ia_css_circbuf_elem_t
*elems
,
82 ia_css_circbuf_desc_t
*desc
)
89 /* Initialize to defaults */
94 for (i
= 0; i
< cb
->desc
->size
; i
++)
95 ia_css_circbuf_elem_init(&elems
[i
]);
101 * @brief Destroy the circular buffer.
102 * Refer to "ia_css_circbuf.h" for details.
104 void ia_css_circbuf_destroy(ia_css_circbuf_t
*cb
)
112 * @brief Pop a value out of the circular buffer.
113 * Refer to "ia_css_circbuf.h" for details.
115 uint32_t ia_css_circbuf_pop(ia_css_circbuf_t
*cb
)
118 ia_css_circbuf_elem_t elem
;
121 SP_ASSERT_FATAL(!ia_css_circbuf_is_empty(cb
));
123 assert(!ia_css_circbuf_is_empty(cb
));
126 /* read an element from the buffer */
127 elem
= ia_css_circbuf_read(cb
);
128 ret
= ia_css_circbuf_elem_get_val(&elem
);
133 * @brief Extract a value out of the circular buffer.
134 * Refer to "ia_css_circbuf.h" for details.
136 uint32_t ia_css_circbuf_extract(ia_css_circbuf_t
*cb
, int offset
)
144 /* get the maximum offest */
145 max_offset
= ia_css_circbuf_get_offset(cb
, cb
->desc
->start
, cb
->desc
->end
);
149 * Step 1: When the target element is at the "start" position.
152 val
= ia_css_circbuf_pop(cb
);
157 * Step 2: When the target element is out of the range.
159 if (offset
> max_offset
) {
165 * Step 3: When the target element is between the "start" and
168 /* get the position of the target element */
169 pos
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->start
, offset
);
171 /* get the value from the target element */
172 val
= ia_css_circbuf_elem_get_val(&cb
->elems
[pos
]);
174 /* shift the elements */
175 src_pos
= ia_css_circbuf_get_pos_at_offset(cb
, pos
, -1);
177 ia_css_circbuf_shift_chunk(cb
, src_pos
, dest_pos
);
183 * @brief Peek an element from the circular buffer.
184 * Refer to "ia_css_circbuf.h" for details.
186 uint32_t ia_css_circbuf_peek(ia_css_circbuf_t
*cb
, int offset
)
190 pos
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->end
, offset
);
192 /* get the value at the position */
193 return cb
->elems
[pos
].val
;
197 * @brief Get the value of an element from the circular buffer.
198 * Refer to "ia_css_circbuf.h" for details.
200 uint32_t ia_css_circbuf_peek_from_start(ia_css_circbuf_t
*cb
, int offset
)
204 pos
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->start
, offset
);
206 /* get the value at the position */
207 return cb
->elems
[pos
].val
;
210 /** @brief increase size of a circular buffer.
211 * Use 'CAUTION' before using this function. This was added to
212 * support / fix issue with increasing size for tagger only
213 * Please refer to "ia_css_circbuf.h" for details.
215 bool ia_css_circbuf_increase_size(
216 ia_css_circbuf_t
*cb
,
217 unsigned int sz_delta
,
218 ia_css_circbuf_elem_t
*elems
)
224 if (!cb
|| sz_delta
== 0)
227 curr_size
= cb
->desc
->size
;
228 curr_end
= cb
->desc
->end
;
229 /* We assume cb was pre defined as global to allow
230 * increase in size */
231 /* FM: are we sure this cannot cause size to become too big? */
232 if (((uint8_t)(cb
->desc
->size
+ (uint8_t)sz_delta
) > cb
->desc
->size
) && ((uint8_t)sz_delta
== sz_delta
))
233 cb
->desc
->size
+= (uint8_t)sz_delta
;
235 return false; /* overflow in size */
237 /* If elems are passed update them else we assume its been taken
238 * care before calling this function */
240 /* cb element array size will not be increased dynamically,
241 * but pointers to new elements can be added at the end
242 * of existing pre defined cb element array of
243 * size >= new size if not already added */
244 for (i
= curr_size
; i
< cb
->desc
->size
; i
++)
245 cb
->elems
[i
] = elems
[i
- curr_size
];
247 /* Fix Start / End */
248 if (curr_end
< cb
->desc
->start
) {
251 cb
->desc
->end
= curr_size
;
253 /* Move elements and fix Start*/
254 ia_css_circbuf_shift_chunk(cb
,
256 curr_size
+ sz_delta
- 1);
263 /****************************************************************
267 ****************************************************************/
269 * @brief Get the "val" field in the element.
270 * Refer to "Forward declarations" for details.
272 static inline uint32_t
273 ia_css_circbuf_elem_get_val(ia_css_circbuf_elem_t
*elem
)
279 * @brief Read the oldest element from the circular buffer.
280 * Refer to "Forward declarations" for details.
282 static inline ia_css_circbuf_elem_t
283 ia_css_circbuf_read(ia_css_circbuf_t
*cb
)
285 ia_css_circbuf_elem_t elem
;
287 /* get the element from the target position */
288 elem
= cb
->elems
[cb
->desc
->start
];
290 /* clear the target position */
291 ia_css_circbuf_elem_init(&cb
->elems
[cb
->desc
->start
]);
293 /* adjust the "start" position */
294 cb
->desc
->start
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->start
, 1);
299 * @brief Shift a chunk of elements in the circular buffer.
300 * Refer to "Forward declarations" for details.
303 ia_css_circbuf_shift_chunk(ia_css_circbuf_t
*cb
,
304 uint32_t chunk_src
, uint32_t chunk_dest
)
310 /* get the chunk offset and size */
311 chunk_offset
= ia_css_circbuf_get_offset(cb
,
312 chunk_src
, chunk_dest
);
313 chunk_sz
= ia_css_circbuf_get_offset(cb
, cb
->desc
->start
, chunk_src
) + 1;
315 /* shift each element to its terminal position */
316 for (i
= 0; i
< chunk_sz
; i
++) {
318 /* copy the element from the source to the destination */
319 ia_css_circbuf_elem_cpy(&cb
->elems
[chunk_src
],
320 &cb
->elems
[chunk_dest
]);
322 /* clear the source position */
323 ia_css_circbuf_elem_init(&cb
->elems
[chunk_src
]);
325 /* adjust the source/terminal positions */
326 chunk_src
= ia_css_circbuf_get_pos_at_offset(cb
, chunk_src
, -1);
327 chunk_dest
= ia_css_circbuf_get_pos_at_offset(cb
, chunk_dest
, -1);
331 /* adjust the index "start" */
332 cb
->desc
->start
= ia_css_circbuf_get_pos_at_offset(cb
, cb
->desc
->start
, chunk_offset
);