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 "assert_support.h" /* assert */
16 #include "ia_css_buffer.h"
18 #include "ia_css_bufq.h" /* Bufq API's */
19 #include "ia_css_queue.h" /* ia_css_queue_t */
20 #include "sw_event_global.h" /* Event IDs.*/
21 #include "ia_css_eventq.h" /* ia_css_eventq_recv()*/
22 #include "ia_css_debug.h" /* ia_css_debug_dtrace*/
23 #include "sh_css_internal.h" /* sh_css_queue_type */
24 #include "sp_local.h" /* sp_address_of */
25 #include "ia_css_util.h" /* ia_css_convert_errno()*/
26 #include "sh_css_firmware.h" /* sh_css_sp_fw*/
28 #define BUFQ_DUMP_FILE_NAME_PREFIX_SIZE 256
30 static char prefix[BUFQ_DUMP_FILE_NAME_PREFIX_SIZE] = {0};
32 /*********************************************************/
33 /* Global Queue objects used by CSS */
34 /*********************************************************/
38 struct sh_css_queues {
39 /* Host2SP buffer queue */
40 ia_css_queue_t host2sp_buffer_queue_handles
41 [SH_CSS_MAX_SP_THREADS][SH_CSS_MAX_NUM_QUEUES];
42 /* SP2Host buffer queue */
43 ia_css_queue_t sp2host_buffer_queue_handles
44 [SH_CSS_MAX_NUM_QUEUES];
46 /* Host2SP event queue */
47 ia_css_queue_t host2sp_psys_event_queue_handle;
49 /* SP2Host event queue */
50 ia_css_queue_t sp2host_psys_event_queue_handle;
52 #if !defined(HAS_NO_INPUT_SYSTEM)
53 /* Host2SP ISYS event queue */
54 ia_css_queue_t host2sp_isys_event_queue_handle;
56 /* SP2Host ISYS event queue */
57 ia_css_queue_t sp2host_isys_event_queue_handle;
59 /* Tagger command queue */
60 ia_css_queue_t host2sp_tag_cmd_queue_handle;
65 struct sh_css_queues {
66 /* Host2SP buffer queue */
67 ia_css_queue_t host2sp_buffer_queue_handles
68 [SH_CSS_MAX_SP_THREADS][SH_CSS_MAX_NUM_QUEUES];
69 /* SP2Host buffer queue */
70 ia_css_queue_t sp2host_buffer_queue_handles
71 [SH_CSS_MAX_NUM_QUEUES];
73 /* Host2SP event queue */
74 ia_css_queue_t host2sp_psys_event_queue_handle;
76 /* SP2Host event queue */
77 ia_css_queue_t sp2host_psys_event_queue_handle;
79 #if !defined(HAS_NO_INPUT_SYSTEM)
80 /* Host2SP ISYS event queue */
81 ia_css_queue_t host2sp_isys_event_queue_handle;
83 /* SP2Host ISYS event queue */
84 ia_css_queue_t sp2host_isys_event_queue_handle;
86 /* Tagger command queue */
87 ia_css_queue_t host2sp_tag_cmd_queue_handle;
93 struct sh_css_queues css_queues;
96 /*******************************************************
98 ********************************************************/
99 static int buffer_type_to_queue_id_map[SH_CSS_MAX_SP_THREADS][IA_CSS_NUM_DYNAMIC_BUFFER_TYPE];
100 static bool queue_availability[SH_CSS_MAX_SP_THREADS][SH_CSS_MAX_NUM_QUEUES];
102 /*******************************************************
104 ********************************************************/
105 static void map_buffer_type_to_queue_id(
106 unsigned int thread_id,
107 enum ia_css_buffer_type buf_type
109 static void unmap_buffer_type_to_queue_id(
110 unsigned int thread_id,
111 enum ia_css_buffer_type buf_type
114 static ia_css_queue_t *bufq_get_qhandle(
115 enum sh_css_queue_type type,
116 enum sh_css_queue_id id,
120 /*******************************************************
122 ********************************************************/
123 void ia_css_queue_map_init(void)
127 for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
128 for (j = 0; j < SH_CSS_MAX_NUM_QUEUES; j++)
129 queue_availability[i][j] = true;
132 for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
133 for (j = 0; j < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE; j++)
134 buffer_type_to_queue_id_map[i][j] = SH_CSS_INVALID_QUEUE_ID;
138 void ia_css_queue_map(
139 unsigned int thread_id,
140 enum ia_css_buffer_type buf_type,
143 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
144 assert(thread_id < SH_CSS_MAX_SP_THREADS);
146 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
147 "ia_css_queue_map() enter: buf_type=%d, thread_id=%d\n", buf_type, thread_id);
150 map_buffer_type_to_queue_id(thread_id, buf_type);
152 unmap_buffer_type_to_queue_id(thread_id, buf_type);
156 * @brief Query the internal queue ID.
158 bool ia_css_query_internal_queue_id(
159 enum ia_css_buffer_type buf_type,
160 unsigned int thread_id,
161 enum sh_css_queue_id *val)
163 IA_CSS_ENTER("buf_type=%d, thread_id=%d, val = %p", buf_type, thread_id, val);
165 if ((val == NULL) || (thread_id >= SH_CSS_MAX_SP_THREADS) || (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE)) {
166 IA_CSS_LEAVE("return_val = false");
170 *val = buffer_type_to_queue_id_map[thread_id][buf_type];
171 if ((*val == SH_CSS_INVALID_QUEUE_ID) || (*val >= SH_CSS_MAX_NUM_QUEUES)) {
172 IA_CSS_LOG("INVALID queue ID MAP = %d\n", *val);
173 IA_CSS_LEAVE("return_val = false");
176 IA_CSS_LEAVE("return_val = true");
180 /*******************************************************
182 ********************************************************/
183 static void map_buffer_type_to_queue_id(
184 unsigned int thread_id,
185 enum ia_css_buffer_type buf_type)
189 assert(thread_id < SH_CSS_MAX_SP_THREADS);
190 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
191 assert(buffer_type_to_queue_id_map[thread_id][buf_type] == SH_CSS_INVALID_QUEUE_ID);
193 /* queue 0 is reserved for parameters because it doesn't depend on events */
194 if (buf_type == IA_CSS_BUFFER_TYPE_PARAMETER_SET) {
195 assert(queue_availability[thread_id][IA_CSS_PARAMETER_SET_QUEUE_ID]);
196 queue_availability[thread_id][IA_CSS_PARAMETER_SET_QUEUE_ID] = false;
197 buffer_type_to_queue_id_map[thread_id][buf_type] = IA_CSS_PARAMETER_SET_QUEUE_ID;
201 /* queue 1 is reserved for per frame parameters because it doesn't depend on events */
202 if (buf_type == IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET) {
203 assert(queue_availability[thread_id][IA_CSS_PER_FRAME_PARAMETER_SET_QUEUE_ID]);
204 queue_availability[thread_id][IA_CSS_PER_FRAME_PARAMETER_SET_QUEUE_ID] = false;
205 buffer_type_to_queue_id_map[thread_id][buf_type] = IA_CSS_PER_FRAME_PARAMETER_SET_QUEUE_ID;
209 for (i = SH_CSS_QUEUE_C_ID; i < SH_CSS_MAX_NUM_QUEUES; i++) {
210 if (queue_availability[thread_id][i] == true) {
211 queue_availability[thread_id][i] = false;
212 buffer_type_to_queue_id_map[thread_id][buf_type] = i;
217 assert(i != SH_CSS_MAX_NUM_QUEUES);
221 static void unmap_buffer_type_to_queue_id(
222 unsigned int thread_id,
223 enum ia_css_buffer_type buf_type)
227 assert(thread_id < SH_CSS_MAX_SP_THREADS);
228 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
229 assert(buffer_type_to_queue_id_map[thread_id][buf_type] != SH_CSS_INVALID_QUEUE_ID);
231 queue_id = buffer_type_to_queue_id_map[thread_id][buf_type];
232 buffer_type_to_queue_id_map[thread_id][buf_type] = SH_CSS_INVALID_QUEUE_ID;
233 queue_availability[thread_id][queue_id] = true;
237 static ia_css_queue_t *bufq_get_qhandle(
238 enum sh_css_queue_type type,
239 enum sh_css_queue_id id,
242 ia_css_queue_t *q = NULL;
245 case sh_css_host2sp_buffer_queue:
246 if ((thread >= SH_CSS_MAX_SP_THREADS) || (thread < 0) ||
247 (id == SH_CSS_INVALID_QUEUE_ID))
249 q = &css_queues.host2sp_buffer_queue_handles[thread][id];
251 case sh_css_sp2host_buffer_queue:
252 if (id == SH_CSS_INVALID_QUEUE_ID)
254 q = &css_queues.sp2host_buffer_queue_handles[id];
256 case sh_css_host2sp_psys_event_queue:
257 q = &css_queues.host2sp_psys_event_queue_handle;
259 case sh_css_sp2host_psys_event_queue:
260 q = &css_queues.sp2host_psys_event_queue_handle;
262 #if !defined(HAS_NO_INPUT_SYSTEM)
263 case sh_css_host2sp_isys_event_queue:
264 q = &css_queues.host2sp_isys_event_queue_handle;
266 case sh_css_sp2host_isys_event_queue:
267 q = &css_queues.sp2host_isys_event_queue_handle;
270 case sh_css_host2sp_tag_cmd_queue:
271 q = &css_queues.host2sp_tag_cmd_queue_handle;
280 /* Local function to initialize a buffer queue. This reduces
281 * the chances of copy-paste errors or typos.
284 init_bufq(unsigned int desc_offset,
285 unsigned int elems_offset,
286 ia_css_queue_t *handle)
288 const struct ia_css_fw_info *fw;
289 unsigned int q_base_addr;
290 ia_css_queue_remote_t remoteq;
293 q_base_addr = fw->info.sp.host_sp_queue;
295 /* Setup queue location as SP and proc id as SP0_ID */
296 remoteq.location = IA_CSS_QUEUE_LOC_SP;
297 remoteq.proc_id = SP0_ID;
298 remoteq.cb_desc_addr = q_base_addr + desc_offset;
299 remoteq.cb_elems_addr = q_base_addr + elems_offset;
300 /* Initialize the queue instance and obtain handle */
301 ia_css_queue_remote_init(handle, &remoteq);
304 void ia_css_bufq_init(void)
308 IA_CSS_ENTER_PRIVATE("");
310 /* Setup all the local queue descriptors for Host2SP Buffer Queues */
311 for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++)
312 for (j = 0; j < SH_CSS_MAX_NUM_QUEUES; j++) {
313 init_bufq((uint32_t)offsetof(struct host_sp_queues, host2sp_buffer_queues_desc[i][j]),
314 (uint32_t)offsetof(struct host_sp_queues, host2sp_buffer_queues_elems[i][j]),
315 &css_queues.host2sp_buffer_queue_handles[i][j]);
318 /* Setup all the local queue descriptors for SP2Host Buffer Queues */
319 for (i = 0; i < SH_CSS_MAX_NUM_QUEUES; i++) {
320 init_bufq(offsetof(struct host_sp_queues, sp2host_buffer_queues_desc[i]),
321 offsetof(struct host_sp_queues, sp2host_buffer_queues_elems[i]),
322 &css_queues.sp2host_buffer_queue_handles[i]);
325 /* Host2SP event queue*/
326 init_bufq((uint32_t)offsetof(struct host_sp_queues, host2sp_psys_event_queue_desc),
327 (uint32_t)offsetof(struct host_sp_queues, host2sp_psys_event_queue_elems),
328 &css_queues.host2sp_psys_event_queue_handle);
330 /* SP2Host event queue */
331 init_bufq((uint32_t)offsetof(struct host_sp_queues, sp2host_psys_event_queue_desc),
332 (uint32_t)offsetof(struct host_sp_queues, sp2host_psys_event_queue_elems),
333 &css_queues.sp2host_psys_event_queue_handle);
335 #if !defined(HAS_NO_INPUT_SYSTEM)
336 /* Host2SP ISYS event queue */
337 init_bufq((uint32_t)offsetof(struct host_sp_queues, host2sp_isys_event_queue_desc),
338 (uint32_t)offsetof(struct host_sp_queues, host2sp_isys_event_queue_elems),
339 &css_queues.host2sp_isys_event_queue_handle);
341 /* SP2Host ISYS event queue*/
342 init_bufq((uint32_t)offsetof(struct host_sp_queues, sp2host_isys_event_queue_desc),
343 (uint32_t)offsetof(struct host_sp_queues, sp2host_isys_event_queue_elems),
344 &css_queues.sp2host_isys_event_queue_handle);
346 /* Host2SP tagger command queue */
347 init_bufq((uint32_t)offsetof(struct host_sp_queues, host2sp_tag_cmd_queue_desc),
348 (uint32_t)offsetof(struct host_sp_queues, host2sp_tag_cmd_queue_elems),
349 &css_queues.host2sp_tag_cmd_queue_handle);
352 IA_CSS_LEAVE_PRIVATE("");
355 enum ia_css_err ia_css_bufq_enqueue_buffer(
360 enum ia_css_err return_err = IA_CSS_SUCCESS;
364 IA_CSS_ENTER_PRIVATE("queue_id=%d", queue_id);
365 if ((thread_index >= SH_CSS_MAX_SP_THREADS) || (thread_index < 0) ||
366 (queue_id == SH_CSS_INVALID_QUEUE_ID))
367 return IA_CSS_ERR_INVALID_ARGUMENTS;
369 /* Get the queue for communication */
370 q = bufq_get_qhandle(sh_css_host2sp_buffer_queue,
374 error = ia_css_queue_enqueue(q, item);
375 return_err = ia_css_convert_errno(error);
377 IA_CSS_ERROR("queue is not initialized");
378 return_err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
381 IA_CSS_LEAVE_ERR_PRIVATE(return_err);
385 enum ia_css_err ia_css_bufq_dequeue_buffer(
389 enum ia_css_err return_err;
393 IA_CSS_ENTER_PRIVATE("queue_id=%d", queue_id);
394 if ((item == NULL) ||
395 (queue_id <= SH_CSS_INVALID_QUEUE_ID) ||
396 (queue_id >= SH_CSS_MAX_NUM_QUEUES)
398 return IA_CSS_ERR_INVALID_ARGUMENTS;
400 q = bufq_get_qhandle(sh_css_sp2host_buffer_queue,
404 error = ia_css_queue_dequeue(q, item);
405 return_err = ia_css_convert_errno(error);
407 IA_CSS_ERROR("queue is not initialized");
408 return_err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
411 IA_CSS_LEAVE_ERR_PRIVATE(return_err);
415 enum ia_css_err ia_css_bufq_enqueue_psys_event(
417 uint8_t evt_payload_0,
418 uint8_t evt_payload_1,
419 uint8_t evt_payload_2)
421 enum ia_css_err return_err;
425 IA_CSS_ENTER_PRIVATE("evt_id=%d", evt_id);
426 q = bufq_get_qhandle(sh_css_host2sp_psys_event_queue, -1, -1);
428 IA_CSS_ERROR("queue is not initialized");
429 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
432 error = ia_css_eventq_send(q,
433 evt_id, evt_payload_0, evt_payload_1, evt_payload_2);
435 return_err = ia_css_convert_errno(error);
436 IA_CSS_LEAVE_ERR_PRIVATE(return_err);
440 enum ia_css_err ia_css_bufq_dequeue_psys_event(
441 uint8_t item[BUFQ_EVENT_SIZE])
447 /* No ENTER/LEAVE in this function since this is polled
448 * by some test apps. Enablign logging here floods the log
449 * files which may cause timeouts. */
451 return IA_CSS_ERR_INVALID_ARGUMENTS;
453 q = bufq_get_qhandle(sh_css_sp2host_psys_event_queue, -1, -1);
455 IA_CSS_ERROR("queue is not initialized");
456 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
458 error = ia_css_eventq_recv(q, item);
460 return ia_css_convert_errno(error);
464 enum ia_css_err ia_css_bufq_dequeue_isys_event(
465 uint8_t item[BUFQ_EVENT_SIZE])
467 #if !defined(HAS_NO_INPUT_SYSTEM)
472 /* No ENTER/LEAVE in this function since this is polled
473 * by some test apps. Enablign logging here floods the log
474 * files which may cause timeouts. */
476 return IA_CSS_ERR_INVALID_ARGUMENTS;
478 q = bufq_get_qhandle(sh_css_sp2host_isys_event_queue, -1, -1);
480 IA_CSS_ERROR("queue is not initialized");
481 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
483 error = ia_css_eventq_recv(q, item);
484 return ia_css_convert_errno(error);
487 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
491 enum ia_css_err ia_css_bufq_enqueue_isys_event(uint8_t evt_id)
493 #if !defined(HAS_NO_INPUT_SYSTEM)
494 enum ia_css_err return_err;
498 IA_CSS_ENTER_PRIVATE("event_id=%d", evt_id);
499 q = bufq_get_qhandle(sh_css_host2sp_isys_event_queue, -1, -1);
501 IA_CSS_ERROR("queue is not initialized");
502 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
505 error = ia_css_eventq_send(q, evt_id, 0, 0, 0);
506 return_err = ia_css_convert_errno(error);
507 IA_CSS_LEAVE_ERR_PRIVATE(return_err);
511 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
515 enum ia_css_err ia_css_bufq_enqueue_tag_cmd(
518 #if !defined(HAS_NO_INPUT_SYSTEM)
519 enum ia_css_err return_err;
523 IA_CSS_ENTER_PRIVATE("item=%d", item);
524 q = bufq_get_qhandle(sh_css_host2sp_tag_cmd_queue, -1, -1);
526 IA_CSS_ERROR("queue is not initialized");
527 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
529 error = ia_css_queue_enqueue(q, item);
531 return_err = ia_css_convert_errno(error);
532 IA_CSS_LEAVE_ERR_PRIVATE(return_err);
536 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
540 enum ia_css_err ia_css_bufq_deinit(void)
542 return IA_CSS_SUCCESS;
545 static void bufq_dump_queue_info(const char *prefix, ia_css_queue_t *qhandle)
547 uint32_t free = 0, used = 0;
548 assert(prefix != NULL && qhandle != NULL);
549 ia_css_queue_get_used_space(qhandle, &used);
550 ia_css_queue_get_free_space(qhandle, &free);
551 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s: used=%u free=%u\n",
556 void ia_css_bufq_dump_queue_info(void)
560 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "Queue Information:\n");
562 for (i = 0; i < SH_CSS_MAX_SP_THREADS; i++) {
563 for (j = 0; j < SH_CSS_MAX_NUM_QUEUES; j++) {
564 snprintf(prefix, BUFQ_DUMP_FILE_NAME_PREFIX_SIZE,
565 "host2sp_buffer_queue[%u][%u]", i, j);
566 bufq_dump_queue_info(prefix,
567 &css_queues.host2sp_buffer_queue_handles[i][j]);
571 for (i = 0; i < SH_CSS_MAX_NUM_QUEUES; i++) {
572 snprintf(prefix, BUFQ_DUMP_FILE_NAME_PREFIX_SIZE,
573 "sp2host_buffer_queue[%u]", i);
574 bufq_dump_queue_info(prefix,
575 &css_queues.sp2host_buffer_queue_handles[i]);
577 bufq_dump_queue_info("host2sp_psys_event",
578 &css_queues.host2sp_psys_event_queue_handle);
579 bufq_dump_queue_info("sp2host_psys_event",
580 &css_queues.sp2host_psys_event_queue_handle);
582 #if !defined(HAS_NO_INPUT_SYSTEM)
583 bufq_dump_queue_info("host2sp_isys_event",
584 &css_queues.host2sp_isys_event_queue_handle);
585 bufq_dump_queue_info("sp2host_isys_event",
586 &css_queues.sp2host_isys_event_queue_handle);
587 bufq_dump_queue_info("host2sp_tag_cmd",
588 &css_queues.host2sp_tag_cmd_queue_handle);