summaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/atomisp/pci/atomisp2/css2400/base/circbuf/interface/ia_css_circbuf.h
blob: 766218ed3649f2c17a515b81c736900ff7f172e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/*
 * Support for Intel Camera Imaging ISP subsystem.
 * Copyright (c) 2015, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 */

#ifndef _IA_CSS_CIRCBUF_H
#define _IA_CSS_CIRCBUF_H

#include <sp.h>
#include <type_support.h>
#include <math_support.h>
#include <storage_class.h>
#include <assert_support.h>
#include <platform_support.h>
#include "ia_css_circbuf_comm.h"
#include "ia_css_circbuf_desc.h"

/****************************************************************
 *
 * Data structures.
 *
 ****************************************************************/
/**
 * @brief Data structure for the circular buffer.
 */
typedef struct ia_css_circbuf_s ia_css_circbuf_t;
struct ia_css_circbuf_s {
	ia_css_circbuf_desc_t *desc;    /* Pointer to the descriptor of the circbuf */
	ia_css_circbuf_elem_t *elems;	/* an array of elements    */
};

/**
 * @brief Create the circular buffer.
 *
 * @param cb	The pointer to the circular buffer.
 * @param elems	An array of elements.
 * @param desc	The descriptor set to the size using ia_css_circbuf_desc_init().
 */
STORAGE_CLASS_EXTERN void ia_css_circbuf_create(
	ia_css_circbuf_t *cb,
	ia_css_circbuf_elem_t *elems,
	ia_css_circbuf_desc_t *desc);

/**
 * @brief Destroy the circular buffer.
 *
 * @param cb The pointer to the circular buffer.
 */
STORAGE_CLASS_EXTERN void ia_css_circbuf_destroy(
		ia_css_circbuf_t *cb);

/**
 * @brief Pop a value out of the circular buffer.
 * Get a value at the head of the circular buffer.
 * The user should call "ia_css_circbuf_is_empty()"
 * to avoid accessing to an empty buffer.
 *
 * @param cb	The pointer to the circular buffer.
 *
 * @return the pop-out value.
 */
STORAGE_CLASS_EXTERN uint32_t ia_css_circbuf_pop(
		ia_css_circbuf_t *cb);

/**
 * @brief Extract a value out of the circular buffer.
 * Get a value at an arbitrary poistion in the circular
 * buffer. The user should call "ia_css_circbuf_is_empty()"
 * to avoid accessing to an empty buffer.
 *
 * @param cb	 The pointer to the circular buffer.
 * @param offset The offset from "start" to the target position.
 *
 * @return the extracted value.
 */
STORAGE_CLASS_EXTERN uint32_t ia_css_circbuf_extract(
	ia_css_circbuf_t *cb,
	int offset);

/****************************************************************
 *
 * Inline functions.
 *
 ****************************************************************/
/**
 * @brief Set the "val" field in the element.
 *
 * @param elem The pointer to the element.
 * @param val  The value to be set.
 */
STORAGE_CLASS_INLINE void ia_css_circbuf_elem_set_val(
	ia_css_circbuf_elem_t *elem,
	uint32_t val)
{
	OP___assert(elem != NULL);

	elem->val = val;
}

/**
 * @brief Initialize the element.
 *
 * @param elem The pointer to the element.
 */
STORAGE_CLASS_INLINE void ia_css_circbuf_elem_init(
		ia_css_circbuf_elem_t *elem)
{
	OP___assert(elem != NULL);
	ia_css_circbuf_elem_set_val(elem, 0);
}

/**
 * @brief Copy an element.
 *
 * @param src  The element as the copy source.
 * @param dest The element as the copy destination.
 */
STORAGE_CLASS_INLINE void ia_css_circbuf_elem_cpy(
	ia_css_circbuf_elem_t *src,
	ia_css_circbuf_elem_t *dest)
{
	OP___assert(src != NULL);
	OP___assert(dest != NULL);

	ia_css_circbuf_elem_set_val(dest, src->val);
}

/**
 * @brief Get position in the circular buffer.
 *
 * @param cb		The pointer to the circular buffer.
 * @param base		The base position.
 * @param offset	The offset.
 *
 * @return the position at offset.
 */
STORAGE_CLASS_INLINE uint8_t ia_css_circbuf_get_pos_at_offset(
	ia_css_circbuf_t *cb,
	uint32_t base,
	int offset)
{
	uint8_t dest;

	OP___assert(cb != NULL);
	OP___assert(cb->desc != NULL);
	OP___assert(cb->desc->size > 0);

	/* step 1: adjudst the offset  */
	while (offset < 0) {
		offset += cb->desc->size;
	}

	/* step 2: shift and round by the upper limit */
	dest = OP_std_modadd(base, offset, cb->desc->size);

	return dest;
}

/**
 * @brief Get the offset between two positions in the circular buffer.
 * Get the offset from the source position to the terminal position,
 * along the direction in which the new elements come in.
 *
 * @param cb		The pointer to the circular buffer.
 * @param src_pos	The source position.
 * @param dest_pos	The terminal position.
 *
 * @return the offset.
 */
STORAGE_CLASS_INLINE int ia_css_circbuf_get_offset(
	ia_css_circbuf_t *cb,
	uint32_t src_pos,
	uint32_t dest_pos)
{
	int offset;

	OP___assert(cb != NULL);
	OP___assert(cb->desc != NULL);

	offset = (int)(dest_pos - src_pos);
	offset += (offset < 0) ? cb->desc->size : 0;

	return offset;
}

/**
 * @brief Get the maximum number of elements.
 *
 * @param cb The pointer to the circular buffer.
 *
 * @return the maximum number of elements.
 *
 * TODO: Test this API.
 */
STORAGE_CLASS_INLINE uint32_t ia_css_circbuf_get_size(
		ia_css_circbuf_t *cb)
{
	OP___assert(cb != NULL);
	OP___assert(cb->desc != NULL);

	return cb->desc->size;
}

/**
 * @brief Get the number of available elements.
 *
 * @param cb The pointer to the circular buffer.
 *
 * @return the number of available elements.
 */
STORAGE_CLASS_INLINE uint32_t ia_css_circbuf_get_num_elems(
		ia_css_circbuf_t *cb)
{
	int num;

	OP___assert(cb != NULL);
	OP___assert(cb->desc != NULL);

	num = ia_css_circbuf_get_offset(cb, cb->desc->start, cb->desc->end);

	return (uint32_t)num;
}

/**
 * @brief Test if the circular buffer is empty.
 *
 * @param cb	The pointer to the circular buffer.
 *
 * @return
 *	- true when it is empty.
 *	- false when it is not empty.
 */
STORAGE_CLASS_INLINE bool ia_css_circbuf_is_empty(
		ia_css_circbuf_t *cb)
{
	OP___assert(cb != NULL);
	OP___assert(cb->desc != NULL);

	return ia_css_circbuf_desc_is_empty(cb->desc);
}

/**
 * @brief Test if the circular buffer is full.
 *
 * @param cb	The pointer to the circular buffer.
 *
 * @return
 *	- true when it is full.
 *	- false when it is not full.
 */
STORAGE_CLASS_INLINE bool ia_css_circbuf_is_full(ia_css_circbuf_t *cb)
{
	OP___assert(cb != NULL);
	OP___assert(cb->desc != NULL);

	return ia_css_circbuf_desc_is_full(cb->desc);
}

/**
 * @brief Write a new element into the circular buffer.
 * Write a new element WITHOUT checking whether the
 * circular buffer is full or not. So it also overwrites
 * the oldest element when the buffer is full.
 *
 * @param cb	The pointer to the circular buffer.
 * @param elem	The new element.
 */
STORAGE_CLASS_INLINE void ia_css_circbuf_write(
	ia_css_circbuf_t *cb,
	ia_css_circbuf_elem_t elem)
{
	OP___assert(cb != NULL);
	OP___assert(cb->desc != NULL);

	/* Cannot continue as the queue is full*/
	assert(!ia_css_circbuf_is_full(cb));

	ia_css_circbuf_elem_cpy(&elem, &cb->elems[cb->desc->end]);

	cb->desc->end = ia_css_circbuf_get_pos_at_offset(cb, cb->desc->end, 1);
}

/**
 * @brief Push a value in the circular buffer.
 * Put a new value at the tail of the circular buffer.
 * The user should call "ia_css_circbuf_is_full()"
 * to avoid accessing to a full buffer.
 *
 * @param cb	The pointer to the circular buffer.
 * @param val	The value to be pushed in.
 */
STORAGE_CLASS_INLINE void ia_css_circbuf_push(
	ia_css_circbuf_t *cb,
	uint32_t val)
{
	ia_css_circbuf_elem_t elem;

	OP___assert(cb != NULL);

	/* set up an element */
	ia_css_circbuf_elem_init(&elem);
	ia_css_circbuf_elem_set_val(&elem, val);

	/* write the element into the buffer */
	ia_css_circbuf_write(cb, elem);
}

/**
 * @brief Get the number of free elements.
 *
 * @param cb The pointer to the circular buffer.
 *
 * @return: The number of free elements.
 */
STORAGE_CLASS_INLINE uint32_t ia_css_circbuf_get_free_elems(
		ia_css_circbuf_t *cb)
{
	OP___assert(cb != NULL);
	OP___assert(cb->desc != NULL);

	return ia_css_circbuf_desc_get_free_elems(cb->desc);
}

/**
 * @brief Peek an element in Circular Buffer.
 *
 * @param cb	 The pointer to the circular buffer.
 * @param offset Offset to the element.
 *
 * @return the elements value.
 */
STORAGE_CLASS_EXTERN uint32_t ia_css_circbuf_peek(
	ia_css_circbuf_t *cb,
	int offset);

/**
 * @brief Get an element in Circular Buffer.
 *
 * @param cb	 The pointer to the circular buffer.
 * @param offset Offset to the element.
 *
 * @return the elements value.
 */
STORAGE_CLASS_EXTERN uint32_t ia_css_circbuf_peek_from_start(
	ia_css_circbuf_t *cb,
	int offset);

/**
 * @brief Increase Size of a Circular Buffer.
 * Use 'CAUTION' before using this function, This was added to
 * support / fix issue with increasing size for tagger only
 *
 * @param cb The pointer to the circular buffer.
 * @param sz_delta delta increase for new size
 * @param elems (optional) pointers to new additional elements
 *		cb element array size will not be increased dynamically,
 * 		but new elements should be added at the end to existing
 * 		cb element array which if of max_size >= new size
 *
 * @return	true on succesfully increasing the size
 * 			false on failure
 */
STORAGE_CLASS_EXTERN bool ia_css_circbuf_increase_size(
		ia_css_circbuf_t *cb,
		unsigned int sz_delta,
		ia_css_circbuf_elem_t *elems);

#endif /*_IA_CSS_CIRCBUF_H */
OpenPOWER on IntegriCloud