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
17 #include "sh_css_sp.h"
19 #if !defined(HAS_NO_INPUT_FORMATTER)
20 #include "input_formatter.h"
23 #include "dma.h" /* N_DMA_CHANNEL_ID */
25 #include "ia_css_buffer.h"
26 #include "ia_css_binary.h"
27 #include "sh_css_hrt.h"
28 #include "sh_css_defs.h"
29 #include "sh_css_internal.h"
30 #include "ia_css_control.h"
31 #include "ia_css_debug.h"
32 #include "ia_css_debug_pipe.h"
33 #include "ia_css_event_public.h"
34 #include "ia_css_mmu.h"
35 #include "ia_css_stream.h"
36 #include "ia_css_isp_param.h"
37 #include "sh_css_params.h"
38 #include "sh_css_legacy.h"
39 #include "ia_css_frame_comm.h"
40 #if !defined(HAS_NO_INPUT_SYSTEM)
41 #include "ia_css_isys.h"
44 #include "gdc_device.h" /* HRT_GDC_N */
46 /*#include "sp.h"*/ /* host2sp_enqueue_frame_data() */
49 #include "assert_support.h"
50 #include "platform_support.h" /* hrt_sleep() */
52 #include "sw_event_global.h" /* Event IDs.*/
53 #include "ia_css_event.h"
54 #include "mmu_device.h"
55 #include "ia_css_spctrl.h"
58 #define offsetof(T, x) ((unsigned int)&(((T *)0)->x))
61 #define IA_CSS_INCLUDE_CONFIGURATIONS
62 #include "ia_css_isp_configs.h"
63 #define IA_CSS_INCLUDE_STATES
64 #include "ia_css_isp_states.h"
66 #include "isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h"
68 struct sh_css_sp_group sh_css_sp_group;
69 struct sh_css_sp_stage sh_css_sp_stage;
70 struct sh_css_isp_stage sh_css_isp_stage;
71 static struct sh_css_sp_output sh_css_sp_output;
72 static struct sh_css_sp_per_frame_data per_frame_data;
74 /* true if SP supports frame loop and host2sp_commands */
75 /* For the moment there is only code that sets this bool to true */
76 /* TODO: add code that sets this bool to false */
77 static bool sp_running;
79 static enum ia_css_err
80 set_output_frame_buffer(const struct ia_css_frame *frame,
84 sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf,
85 const enum sh_css_queue_id queue_id,
86 const ia_css_ptr xmem_addr,
87 const enum ia_css_buffer_type buf_type);
90 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr);
93 initialize_stage_frames(struct ia_css_frames_sp *frames);
95 /* This data is stored every frame */
97 store_sp_group_data(void)
99 per_frame_data.sp_group_addr = sh_css_store_sp_group_to_ddr();
103 copy_isp_stage_to_sp_stage(void)
105 /* [WW07.5]type casting will cause potential issues */
106 sh_css_sp_stage.num_stripes = (uint8_t)
107 sh_css_isp_stage.binary_info.iterator.num_stripes;
108 sh_css_sp_stage.row_stripes_height = (uint16_t)
109 sh_css_isp_stage.binary_info.iterator.row_stripes_height;
110 sh_css_sp_stage.row_stripes_overlap_lines = (uint16_t)
111 sh_css_isp_stage.binary_info.iterator.row_stripes_overlap_lines;
112 sh_css_sp_stage.top_cropping = (uint16_t)
113 sh_css_isp_stage.binary_info.pipeline.top_cropping;
114 /* moved to sh_css_sp_init_stage
115 sh_css_sp_stage.enable.vf_output =
116 sh_css_isp_stage.binary_info.enable.vf_veceven ||
117 sh_css_isp_stage.binary_info.num_output_pins > 1;
119 sh_css_sp_stage.enable.sdis = sh_css_isp_stage.binary_info.enable.dis;
120 sh_css_sp_stage.enable.s3a = sh_css_isp_stage.binary_info.enable.s3a;
124 store_sp_stage_data(enum ia_css_pipe_id id, unsigned int pipe_num,
127 unsigned int thread_id;
129 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
130 copy_isp_stage_to_sp_stage();
131 if (id != IA_CSS_PIPE_ID_COPY)
132 sh_css_sp_stage.isp_stage_addr =
133 sh_css_store_isp_stage_to_ddr(pipe_num, stage);
134 sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] =
135 sh_css_store_sp_stage_to_ddr(pipe_num, stage);
137 /* Clear for next frame */
138 sh_css_sp_stage.program_input_circuit = false;
142 store_sp_per_frame_data(const struct ia_css_fw_info *fw)
144 unsigned int HIVE_ADDR_sp_per_frame_data = 0;
149 case ia_css_sp_firmware:
150 HIVE_ADDR_sp_per_frame_data = fw->info.sp.per_frame_data;
152 case ia_css_acc_firmware:
153 HIVE_ADDR_sp_per_frame_data = fw->info.acc.per_frame_data;
155 case ia_css_isp_firmware:
159 sp_dmem_store(SP0_ID,
160 (unsigned int)sp_address_of(sp_per_frame_data),
162 sizeof(per_frame_data));
166 sh_css_store_sp_per_frame_data(enum ia_css_pipe_id pipe_id,
167 unsigned int pipe_num,
168 const struct ia_css_fw_info *sp_fw)
171 sp_fw = &sh_css_sp_fw;
173 store_sp_stage_data(pipe_id, pipe_num, 0);
174 store_sp_group_data();
175 store_sp_per_frame_data(sp_fw);
178 #if SP_DEBUG != SP_DEBUG_NONE
181 sh_css_sp_get_debug_state(struct sh_css_sp_debug_state *state)
183 const struct ia_css_fw_info *fw = &sh_css_sp_fw;
184 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
186 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
187 debug) / sizeof(int);
191 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
192 for (i = 0; i < sizeof(*state) / sizeof(int); i++)
193 ((unsigned *)state)[i] = load_sp_array_uint(sp_output, i + offset);
199 sh_css_sp_start_binary_copy(unsigned int pipe_num,
200 struct ia_css_frame *out_frame,
201 unsigned int two_ppc)
203 enum ia_css_pipe_id pipe_id;
204 unsigned int thread_id;
205 struct sh_css_sp_pipeline *pipe;
209 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
210 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
211 pipe = &sh_css_sp_group.pipe[thread_id];
213 pipe->copy.bin.bytes_available = out_frame->data_bytes;
214 pipe->num_stages = 1;
215 pipe->pipe_id = pipe_id;
216 pipe->pipe_num = pipe_num;
217 pipe->thread_id = thread_id;
218 pipe->pipe_config = 0x0; /* No parameters */
219 pipe->pipe_qos_config = QOS_INVALID;
221 if (pipe->inout_port_config == 0) {
222 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
223 (uint8_t)SH_CSS_PORT_INPUT,
224 (uint8_t)SH_CSS_HOST_TYPE, 1);
225 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
226 (uint8_t)SH_CSS_PORT_OUTPUT,
227 (uint8_t)SH_CSS_HOST_TYPE, 1);
229 IA_CSS_LOG("pipe_id %d port_config %08x",
230 pipe->pipe_id, pipe->inout_port_config);
232 #if !defined(HAS_NO_INPUT_FORMATTER)
233 sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc;
238 sh_css_sp_stage.num = stage_num;
239 sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
240 sh_css_sp_stage.func =
241 (unsigned int)IA_CSS_PIPELINE_BIN_COPY;
243 set_output_frame_buffer(out_frame, 0);
245 /* sp_bin_copy_init on the SP does not deal with dynamica/static yet */
246 /* For now always update the dynamic data from out frames. */
247 sh_css_store_sp_per_frame_data(pipe_id, pipe_num, &sh_css_sp_fw);
251 sh_css_sp_start_raw_copy(struct ia_css_frame *out_frame,
252 unsigned int pipe_num,
253 unsigned int two_ppc,
254 unsigned int max_input_width,
255 enum sh_css_pipe_config_override pipe_conf_override,
256 unsigned int if_config_index)
258 enum ia_css_pipe_id pipe_id;
259 unsigned int thread_id;
261 struct sh_css_sp_pipeline *pipe;
267 * Clear sh_css_sp_stage for easy debugging.
268 * program_input_circuit must be saved as it is set outside
271 u8 program_input_circuit;
273 program_input_circuit = sh_css_sp_stage.program_input_circuit;
274 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
275 sh_css_sp_stage.program_input_circuit = program_input_circuit;
278 pipe_id = IA_CSS_PIPE_ID_COPY;
279 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
280 pipe = &sh_css_sp_group.pipe[thread_id];
282 pipe->copy.raw.height = out_frame->info.res.height;
283 pipe->copy.raw.width = out_frame->info.res.width;
284 pipe->copy.raw.padded_width = out_frame->info.padded_width;
285 pipe->copy.raw.raw_bit_depth = out_frame->info.raw_bit_depth;
286 pipe->copy.raw.max_input_width = max_input_width;
287 pipe->num_stages = 1;
288 pipe->pipe_id = pipe_id;
289 /* TODO: next indicates from which queues parameters need to be
290 sampled, needs checking/improvement */
291 if (pipe_conf_override == SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD)
293 (SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id);
295 pipe->pipe_config = pipe_conf_override;
297 pipe->pipe_qos_config = QOS_INVALID;
299 if (pipe->inout_port_config == 0) {
300 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
301 (uint8_t)SH_CSS_PORT_INPUT,
302 (uint8_t)SH_CSS_HOST_TYPE, 1);
303 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
304 (uint8_t)SH_CSS_PORT_OUTPUT,
305 (uint8_t)SH_CSS_HOST_TYPE, 1);
307 IA_CSS_LOG("pipe_id %d port_config %08x",
308 pipe->pipe_id, pipe->inout_port_config);
310 #if !defined(HAS_NO_INPUT_FORMATTER)
311 sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc;
316 sh_css_sp_stage.num = stage_num;
317 sh_css_sp_stage.xmem_bin_addr = 0x0;
318 sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
319 sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_RAW_COPY;
320 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
321 set_output_frame_buffer(out_frame, 0);
323 ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame);
327 sh_css_sp_start_isys_copy(struct ia_css_frame *out_frame,
328 unsigned int pipe_num, unsigned int max_input_width,
329 unsigned int if_config_index)
331 enum ia_css_pipe_id pipe_id;
332 unsigned int thread_id;
334 struct sh_css_sp_pipeline *pipe;
335 #if defined SH_CSS_ENABLE_METADATA
336 enum sh_css_queue_id queue_id;
343 * Clear sh_css_sp_stage for easy debugging.
344 * program_input_circuit must be saved as it is set outside
347 u8 program_input_circuit;
349 program_input_circuit = sh_css_sp_stage.program_input_circuit;
350 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
351 sh_css_sp_stage.program_input_circuit = program_input_circuit;
354 pipe_id = IA_CSS_PIPE_ID_COPY;
355 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
356 pipe = &sh_css_sp_group.pipe[thread_id];
358 pipe->copy.raw.height = out_frame->info.res.height;
359 pipe->copy.raw.width = out_frame->info.res.width;
360 pipe->copy.raw.padded_width = out_frame->info.padded_width;
361 pipe->copy.raw.raw_bit_depth = out_frame->info.raw_bit_depth;
362 pipe->copy.raw.max_input_width = max_input_width;
363 pipe->num_stages = 1;
364 pipe->pipe_id = pipe_id;
365 pipe->pipe_config = 0x0; /* No parameters */
366 pipe->pipe_qos_config = QOS_INVALID;
368 initialize_stage_frames(&sh_css_sp_stage.frames);
369 sh_css_sp_stage.num = stage_num;
370 sh_css_sp_stage.xmem_bin_addr = 0x0;
371 sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
372 sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_ISYS_COPY;
373 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
375 set_output_frame_buffer(out_frame, 0);
377 #if defined SH_CSS_ENABLE_METADATA
378 if (pipe->metadata.height > 0) {
379 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id,
381 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf,
382 queue_id, mmgr_EXCEPTION,
383 IA_CSS_BUFFER_TYPE_METADATA);
387 ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame);
391 sh_css_sp_get_binary_copy_size(void)
393 const struct ia_css_fw_info *fw = &sh_css_sp_fw;
394 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
395 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
396 bin_copy_bytes_copied) / sizeof(int);
397 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
398 return load_sp_array_uint(sp_output, offset);
402 sh_css_sp_get_sw_interrupt_value(unsigned int irq)
404 const struct ia_css_fw_info *fw = &sh_css_sp_fw;
405 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
406 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
409 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
410 return load_sp_array_uint(sp_output, offset + irq);
414 sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf,
415 const enum sh_css_queue_id queue_id,
416 const ia_css_ptr xmem_addr,
417 const enum ia_css_buffer_type buf_type)
419 assert(buf_type < IA_CSS_NUM_BUFFER_TYPE);
420 if (queue_id > SH_CSS_INVALID_QUEUE_ID) {
422 * value >=0 indicates that function init_frame_pointers()
423 * should use the dynamic data address
425 assert(queue_id < SH_CSS_MAX_NUM_QUEUES);
427 /* Klocwork assumes assert can be disabled;
428 Since we can get there with any type, and it does not
429 know that frame_in->dynamic_data_index can only be set
430 for one of the types in the assert) it has to assume we
431 can get here for any type. however this could lead to an
432 out of bounds reference when indexing buf_type about 10
433 lines below. In order to satisfy KW an additional if
434 has been added. This one will always yield true.
436 if ((queue_id < SH_CSS_MAX_NUM_QUEUES)) {
437 dest_buf->buf_src.queue_id = queue_id;
440 assert(xmem_addr != mmgr_EXCEPTION);
441 dest_buf->buf_src.xmem_addr = xmem_addr;
443 dest_buf->buf_type = buf_type;
447 sh_css_copy_frame_to_spframe(struct ia_css_frame_sp *sp_frame_out,
448 const struct ia_css_frame *frame_in)
452 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
453 "sh_css_copy_frame_to_spframe():\n");
455 sh_css_copy_buffer_attr_to_spbuffer(&sp_frame_out->buf_attr,
456 frame_in->dynamic_queue_id,
460 ia_css_frame_info_to_frame_sp_info(&sp_frame_out->info, &frame_in->info);
462 switch (frame_in->info.format) {
463 case IA_CSS_FRAME_FORMAT_RAW_PACKED:
464 case IA_CSS_FRAME_FORMAT_RAW:
465 sp_frame_out->planes.raw.offset = frame_in->planes.raw.offset;
467 case IA_CSS_FRAME_FORMAT_RGB565:
468 case IA_CSS_FRAME_FORMAT_RGBA888:
469 sp_frame_out->planes.rgb.offset = frame_in->planes.rgb.offset;
471 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
472 sp_frame_out->planes.planar_rgb.r.offset =
473 frame_in->planes.planar_rgb.r.offset;
474 sp_frame_out->planes.planar_rgb.g.offset =
475 frame_in->planes.planar_rgb.g.offset;
476 sp_frame_out->planes.planar_rgb.b.offset =
477 frame_in->planes.planar_rgb.b.offset;
479 case IA_CSS_FRAME_FORMAT_YUYV:
480 case IA_CSS_FRAME_FORMAT_UYVY:
481 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
482 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
483 case IA_CSS_FRAME_FORMAT_YUV_LINE:
484 sp_frame_out->planes.yuyv.offset = frame_in->planes.yuyv.offset;
486 case IA_CSS_FRAME_FORMAT_NV11:
487 case IA_CSS_FRAME_FORMAT_NV12:
488 case IA_CSS_FRAME_FORMAT_NV12_16:
489 case IA_CSS_FRAME_FORMAT_NV12_TILEY:
490 case IA_CSS_FRAME_FORMAT_NV21:
491 case IA_CSS_FRAME_FORMAT_NV16:
492 case IA_CSS_FRAME_FORMAT_NV61:
493 sp_frame_out->planes.nv.y.offset =
494 frame_in->planes.nv.y.offset;
495 sp_frame_out->planes.nv.uv.offset =
496 frame_in->planes.nv.uv.offset;
498 case IA_CSS_FRAME_FORMAT_YUV420:
499 case IA_CSS_FRAME_FORMAT_YUV422:
500 case IA_CSS_FRAME_FORMAT_YUV444:
501 case IA_CSS_FRAME_FORMAT_YUV420_16:
502 case IA_CSS_FRAME_FORMAT_YUV422_16:
503 case IA_CSS_FRAME_FORMAT_YV12:
504 case IA_CSS_FRAME_FORMAT_YV16:
505 sp_frame_out->planes.yuv.y.offset =
506 frame_in->planes.yuv.y.offset;
507 sp_frame_out->planes.yuv.u.offset =
508 frame_in->planes.yuv.u.offset;
509 sp_frame_out->planes.yuv.v.offset =
510 frame_in->planes.yuv.v.offset;
512 case IA_CSS_FRAME_FORMAT_QPLANE6:
513 sp_frame_out->planes.plane6.r.offset =
514 frame_in->planes.plane6.r.offset;
515 sp_frame_out->planes.plane6.r_at_b.offset =
516 frame_in->planes.plane6.r_at_b.offset;
517 sp_frame_out->planes.plane6.gr.offset =
518 frame_in->planes.plane6.gr.offset;
519 sp_frame_out->planes.plane6.gb.offset =
520 frame_in->planes.plane6.gb.offset;
521 sp_frame_out->planes.plane6.b.offset =
522 frame_in->planes.plane6.b.offset;
523 sp_frame_out->planes.plane6.b_at_r.offset =
524 frame_in->planes.plane6.b_at_r.offset;
526 case IA_CSS_FRAME_FORMAT_BINARY_8:
527 sp_frame_out->planes.binary.data.offset =
528 frame_in->planes.binary.data.offset;
531 /* This should not happen, but in case it does,
534 memset(&sp_frame_out->planes, 0, sizeof(sp_frame_out->planes));
539 static enum ia_css_err
540 set_input_frame_buffer(const struct ia_css_frame *frame) {
542 return IA_CSS_ERR_INVALID_ARGUMENTS;
544 switch (frame->info.format)
546 case IA_CSS_FRAME_FORMAT_QPLANE6:
547 case IA_CSS_FRAME_FORMAT_YUV420_16:
548 case IA_CSS_FRAME_FORMAT_RAW_PACKED:
549 case IA_CSS_FRAME_FORMAT_RAW:
550 case IA_CSS_FRAME_FORMAT_YUV420:
551 case IA_CSS_FRAME_FORMAT_YUYV:
552 case IA_CSS_FRAME_FORMAT_YUV_LINE:
553 case IA_CSS_FRAME_FORMAT_NV12:
554 case IA_CSS_FRAME_FORMAT_NV12_16:
555 case IA_CSS_FRAME_FORMAT_NV12_TILEY:
556 case IA_CSS_FRAME_FORMAT_NV21:
557 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
558 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
559 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_10:
562 return IA_CSS_ERR_INVALID_ARGUMENTS;
564 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.in, frame);
566 return IA_CSS_SUCCESS;
569 static enum ia_css_err
570 set_output_frame_buffer(const struct ia_css_frame *frame,
573 return IA_CSS_ERR_INVALID_ARGUMENTS;
575 switch (frame->info.format)
577 case IA_CSS_FRAME_FORMAT_YUV420:
578 case IA_CSS_FRAME_FORMAT_YUV422:
579 case IA_CSS_FRAME_FORMAT_YUV444:
580 case IA_CSS_FRAME_FORMAT_YV12:
581 case IA_CSS_FRAME_FORMAT_YV16:
582 case IA_CSS_FRAME_FORMAT_YUV420_16:
583 case IA_CSS_FRAME_FORMAT_YUV422_16:
584 case IA_CSS_FRAME_FORMAT_NV11:
585 case IA_CSS_FRAME_FORMAT_NV12:
586 case IA_CSS_FRAME_FORMAT_NV12_16:
587 case IA_CSS_FRAME_FORMAT_NV12_TILEY:
588 case IA_CSS_FRAME_FORMAT_NV16:
589 case IA_CSS_FRAME_FORMAT_NV21:
590 case IA_CSS_FRAME_FORMAT_NV61:
591 case IA_CSS_FRAME_FORMAT_YUYV:
592 case IA_CSS_FRAME_FORMAT_UYVY:
593 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
594 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
595 case IA_CSS_FRAME_FORMAT_YUV_LINE:
596 case IA_CSS_FRAME_FORMAT_RGB565:
597 case IA_CSS_FRAME_FORMAT_RGBA888:
598 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
599 case IA_CSS_FRAME_FORMAT_RAW:
600 case IA_CSS_FRAME_FORMAT_RAW_PACKED:
601 case IA_CSS_FRAME_FORMAT_QPLANE6:
602 case IA_CSS_FRAME_FORMAT_BINARY_8:
605 return IA_CSS_ERR_INVALID_ARGUMENTS;
607 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out[idx], frame);
608 return IA_CSS_SUCCESS;
611 static enum ia_css_err
612 set_view_finder_buffer(const struct ia_css_frame *frame) {
614 return IA_CSS_ERR_INVALID_ARGUMENTS;
616 switch (frame->info.format)
618 /* the dual output pin */
619 case IA_CSS_FRAME_FORMAT_NV12:
620 case IA_CSS_FRAME_FORMAT_NV12_16:
621 case IA_CSS_FRAME_FORMAT_NV21:
622 case IA_CSS_FRAME_FORMAT_YUYV:
623 case IA_CSS_FRAME_FORMAT_UYVY:
624 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
625 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
626 case IA_CSS_FRAME_FORMAT_YUV420:
627 case IA_CSS_FRAME_FORMAT_YV12:
628 case IA_CSS_FRAME_FORMAT_NV12_TILEY:
631 case IA_CSS_FRAME_FORMAT_YUV_LINE:
634 return IA_CSS_ERR_INVALID_ARGUMENTS;
637 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out_vf, frame);
638 return IA_CSS_SUCCESS;
641 #if !defined(HAS_NO_INPUT_FORMATTER)
642 void sh_css_sp_set_if_configs(
643 const input_formatter_cfg_t *config_a,
644 const input_formatter_cfg_t *config_b,
645 const uint8_t if_config_index
648 assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
651 sh_css_sp_group.config.input_formatter.set[if_config_index].config_a =
653 sh_css_sp_group.config.input_formatter.a_changed = true;
656 sh_css_sp_group.config.input_formatter.set[if_config_index].config_b =
658 sh_css_sp_group.config.input_formatter.b_changed = true;
665 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
667 sh_css_sp_program_input_circuit(int fmt_type,
669 enum ia_css_input_mode input_mode)
671 sh_css_sp_group.config.input_circuit.no_side_band = false;
672 sh_css_sp_group.config.input_circuit.fmt_type = fmt_type;
673 sh_css_sp_group.config.input_circuit.ch_id = ch_id;
674 sh_css_sp_group.config.input_circuit.input_mode = input_mode;
676 * The SP group is only loaded at SP boot time and is read once
677 * change flags as "input_circuit_cfg_changed" must be reset on the SP
679 sh_css_sp_group.config.input_circuit_cfg_changed = true;
680 sh_css_sp_stage.program_input_circuit = true;
684 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
686 sh_css_sp_configure_sync_gen(int width, int height,
690 sh_css_sp_group.config.sync_gen.width = width;
691 sh_css_sp_group.config.sync_gen.height = height;
692 sh_css_sp_group.config.sync_gen.hblank_cycles = hblank_cycles;
693 sh_css_sp_group.config.sync_gen.vblank_cycles = vblank_cycles;
697 sh_css_sp_configure_tpg(int x_mask,
703 sh_css_sp_group.config.tpg.x_mask = x_mask;
704 sh_css_sp_group.config.tpg.y_mask = y_mask;
705 sh_css_sp_group.config.tpg.x_delta = x_delta;
706 sh_css_sp_group.config.tpg.y_delta = y_delta;
707 sh_css_sp_group.config.tpg.xy_mask = xy_mask;
711 sh_css_sp_configure_prbs(int seed)
713 sh_css_sp_group.config.prbs.seed = seed;
718 sh_css_sp_configure_enable_raw_pool_locking(bool lock_all)
720 sh_css_sp_group.config.enable_raw_pool_locking = true;
721 sh_css_sp_group.config.lock_all = lock_all;
725 sh_css_sp_enable_isys_event_queue(bool enable)
727 #if !defined(HAS_NO_INPUT_SYSTEM)
728 sh_css_sp_group.config.enable_isys_event_queue = enable;
735 sh_css_sp_set_disable_continuous_viewfinder(bool flag)
737 sh_css_sp_group.config.disable_cont_vf = flag;
740 static enum ia_css_err
741 sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args) {
742 enum ia_css_err err = IA_CSS_SUCCESS;
748 err = set_input_frame_buffer(args->in_frame);
749 if (err == IA_CSS_SUCCESS && args->out_vf_frame)
750 err = set_view_finder_buffer(args->out_vf_frame);
751 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
753 if (err == IA_CSS_SUCCESS && args->out_frame[i])
754 err = set_output_frame_buffer(args->out_frame[i], i);
757 /* we don't pass this error back to the upper layer, so we add a assert here
758 because we actually hit the error here but it still works by accident... */
759 if (err != IA_CSS_SUCCESS) assert(false);
764 sh_css_sp_init_group(bool two_ppc,
765 enum atomisp_input_format input_format,
767 uint8_t if_config_index)
769 #if !defined(HAS_NO_INPUT_FORMATTER)
770 sh_css_sp_group.config.input_formatter.isp_2ppc = two_ppc;
775 sh_css_sp_group.config.no_isp_sync = (uint8_t)no_isp_sync;
776 /* decide whether the frame is processed online or offline */
777 if (if_config_index == SH_CSS_IF_CONFIG_NOT_NEEDED) return;
778 #if !defined(HAS_NO_INPUT_FORMATTER)
779 assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
780 sh_css_sp_group.config.input_formatter.set[if_config_index].stream_format =
788 sh_css_stage_write_binary_info(struct ia_css_binary_info *info)
791 sh_css_isp_stage.binary_info = *info;
794 static enum ia_css_err
795 copy_isp_mem_if_to_ddr(struct ia_css_binary *binary) {
798 err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
801 IA_CSS_PARAM_CLASS_CONFIG);
802 if (err != IA_CSS_SUCCESS)
804 err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
807 IA_CSS_PARAM_CLASS_STATE);
808 if (err != IA_CSS_SUCCESS)
810 return IA_CSS_SUCCESS;
814 is_sp_stage(struct ia_css_pipeline_stage *stage)
817 return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC;
820 static enum ia_css_err
821 configure_isp_from_args(
822 const struct sh_css_sp_pipeline *pipeline,
823 const struct ia_css_binary *binary,
824 const struct sh_css_binary_args *args,
826 bool deinterleaved) {
827 ia_css_fpn_configure(binary, &binary->in_frame_info);
828 ia_css_crop_configure(binary, &args->delay_frames[0]->info);
829 ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info);
830 ia_css_output0_configure(binary, &args->out_frame[0]->info);
831 ia_css_output1_configure(binary, &args->out_vf_frame->info);
832 ia_css_copy_output_configure(binary, args->copy_output);
833 ia_css_output0_configure(binary, &args->out_frame[0]->info);
835 ia_css_sc_configure(binary, pipeline->shading.internal_frame_origin_x_bqs_on_sctbl,
836 pipeline->shading.internal_frame_origin_y_bqs_on_sctbl);
838 ia_css_iterator_configure(binary, &args->in_frame->info);
839 ia_css_dvs_configure(binary, &args->out_frame[0]->info);
840 ia_css_output_configure(binary, &args->out_frame[0]->info);
841 ia_css_raw_configure(pipeline, binary, &args->in_frame->info, &binary->in_frame_info, two_ppc, deinterleaved);
844 * FIXME: args->delay_frames can be NULL here
846 * Somehow, the driver at the Intel Atom Yocto tree doesn't seem to
847 * suffer from the same issue.
849 * Anyway, the function below should now handle a NULL delay_frames
850 * without crashing, but the pipeline should likely be built without
851 * adding it at the first place (or there are a hidden bug somewhere)
853 ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay);
854 ia_css_tnr_configure(binary, args->tnr_frames);
855 ia_css_bayer_io_config(binary, args);
856 return IA_CSS_SUCCESS;
860 initialize_isp_states(const struct ia_css_binary *binary)
864 if (!binary->info->mem_offsets.offsets.state)
866 for (i = 0; i < IA_CSS_NUM_STATE_IDS; i++) {
867 ia_css_kernel_init_state[i](binary);
872 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr)
874 buf_attr->buf_src.queue_id = SH_CSS_INVALID_QUEUE_ID;
875 buf_attr->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
879 initialize_stage_frames(struct ia_css_frames_sp *frames)
883 initialize_frame_buffer_attribute(&frames->in.buf_attr);
884 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
885 initialize_frame_buffer_attribute(&frames->out[i].buf_attr);
887 initialize_frame_buffer_attribute(&frames->out_vf.buf_attr);
888 initialize_frame_buffer_attribute(&frames->s3a_buf);
889 initialize_frame_buffer_attribute(&frames->dvs_buf);
890 #if defined SH_CSS_ENABLE_METADATA
891 initialize_frame_buffer_attribute(&frames->metadata_buf);
895 static enum ia_css_err
896 sh_css_sp_init_stage(struct ia_css_binary *binary,
897 const char *binary_name,
898 const struct ia_css_blob_info *blob_info,
899 const struct sh_css_binary_args *args,
900 unsigned int pipe_num,
903 const struct ia_css_isp_param_css_segments *isp_mem_if,
904 unsigned int if_config_index,
906 const struct ia_css_binary_xinfo *xinfo;
907 const struct ia_css_binary_info *info;
908 enum ia_css_err err = IA_CSS_SUCCESS;
910 struct ia_css_pipe *pipe = NULL;
911 unsigned int thread_id;
912 enum sh_css_queue_id queue_id;
913 bool continuous = sh_css_continuous_is_enabled((uint8_t)pipe_num);
920 xinfo = binary->info;
924 * Clear sh_css_sp_stage for easy debugging.
925 * program_input_circuit must be saved as it is set outside
928 u8 program_input_circuit;
930 program_input_circuit = sh_css_sp_stage.program_input_circuit;
931 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
932 sh_css_sp_stage.program_input_circuit = (uint8_t)program_input_circuit;
935 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
939 sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL;
940 return IA_CSS_SUCCESS;
943 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
945 sh_css_sp_stage.deinterleaved = 0;
947 sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous);
950 initialize_stage_frames(&sh_css_sp_stage.frames);
952 * TODO: Make the Host dynamically determine
955 sh_css_sp_stage.stage_type = SH_CSS_ISP_STAGE_TYPE;
956 sh_css_sp_stage.num = (uint8_t)stage;
957 sh_css_sp_stage.isp_online = (uint8_t)binary->online;
958 sh_css_sp_stage.isp_copy_vf = (uint8_t)args->copy_vf;
959 sh_css_sp_stage.isp_copy_output = (uint8_t)args->copy_output;
960 sh_css_sp_stage.enable.vf_output = (args->out_vf_frame != NULL);
962 /* Copy the frame infos first, to be overwritten by the frames,
963 if these are present.
965 sh_css_sp_stage.frames.effective_in_res.width = binary->effective_in_frame_res.width;
966 sh_css_sp_stage.frames.effective_in_res.height = binary->effective_in_frame_res.height;
968 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.in.info,
969 &binary->in_frame_info);
970 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
972 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.out[i].info,
973 &binary->out_frame_info[i]);
975 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.internal_frame_info,
976 &binary->internal_frame_info);
977 sh_css_sp_stage.dvs_envelope.width = binary->dvs_envelope.width;
978 sh_css_sp_stage.dvs_envelope.height = binary->dvs_envelope.height;
979 sh_css_sp_stage.isp_pipe_version = (uint8_t)info->pipeline.isp_pipe_version;
980 sh_css_sp_stage.isp_deci_log_factor = (uint8_t)binary->deci_factor_log2;
981 sh_css_sp_stage.isp_vf_downscale_bits = (uint8_t)binary->vf_downscale_log2;
983 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
985 sh_css_sp_stage.sp_enable_xnr = (uint8_t)xnr;
986 sh_css_sp_stage.xmem_bin_addr = xinfo->xmem_addr;
987 sh_css_sp_stage.xmem_map_addr = sh_css_params_ddr_address_map();
988 sh_css_isp_stage.blob_info = *blob_info;
989 sh_css_stage_write_binary_info((struct ia_css_binary_info *)info);
991 /* Make sure binary name is smaller than allowed string size */
992 assert(strlen(binary_name) < SH_CSS_MAX_BINARY_NAME - 1);
993 strncpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME - 1);
994 sh_css_isp_stage.binary_name[SH_CSS_MAX_BINARY_NAME - 1] = 0;
995 sh_css_isp_stage.mem_initializers = *isp_mem_if;
998 * Even when a stage does not need uds and does not params,
999 * ia_css_uds_sp_scale_params() seems to be called (needs
1000 * further investigation). This function can not deal with
1004 err = sh_css_sp_write_frame_pointers(args);
1005 /* TODO: move it to a better place */
1006 if (binary->info->sp.enable.s3a)
1008 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_3A_STATISTICS, thread_id,
1010 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.s3a_buf, queue_id,
1012 IA_CSS_BUFFER_TYPE_3A_STATISTICS);
1014 if (binary->info->sp.enable.dis)
1016 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id,
1018 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id,
1020 IA_CSS_BUFFER_TYPE_DIS_STATISTICS);
1022 #if defined SH_CSS_ENABLE_METADATA
1023 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id);
1024 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA);
1026 if (err != IA_CSS_SUCCESS)
1029 #ifdef USE_INPUT_SYSTEM_VERSION_2401
1033 pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num);
1035 return IA_CSS_ERR_INTERNAL_ERROR;
1036 ia_css_get_crop_offsets(pipe, &args->in_frame->info);
1037 } else if (&binary->in_frame_info)
1039 pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num);
1041 return IA_CSS_ERR_INTERNAL_ERROR;
1042 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1046 if (args->in_frame) {
1047 pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num);
1049 return IA_CSS_ERR_INTERNAL_ERROR;
1050 ia_css_get_crop_offsets(pipe, &args->in_frame->info);
1051 } else if (&binary->in_frame_info) {
1052 pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num);
1054 return IA_CSS_ERR_INTERNAL_ERROR;
1055 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1060 (void)pipe; /*avoid build warning*/
1063 err = configure_isp_from_args(&sh_css_sp_group.pipe[thread_id],
1064 binary, args, two_ppc, sh_css_sp_stage.deinterleaved);
1065 if (err != IA_CSS_SUCCESS)
1068 initialize_isp_states(binary);
1070 /* we do this only for preview pipe because in fill_binary_info function
1071 * we assign vf_out res to out res, but for ISP internal processing, we need
1072 * the original out res. for video pipe, it has two output pins --- out and
1073 * vf_out, so it can keep these two resolutions already. */
1074 if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW &&
1075 (binary->vf_downscale_log2 > 0))
1077 /* TODO: Remove this after preview output decimation is fixed
1078 * by configuring out&vf info fiels properly */
1079 sh_css_sp_stage.frames.out[0].info.padded_width
1080 <<= binary->vf_downscale_log2;
1081 sh_css_sp_stage.frames.out[0].info.res.width
1082 <<= binary->vf_downscale_log2;
1083 sh_css_sp_stage.frames.out[0].info.res.height
1084 <<= binary->vf_downscale_log2;
1086 err = copy_isp_mem_if_to_ddr(binary);
1087 if (err != IA_CSS_SUCCESS)
1090 return IA_CSS_SUCCESS;
1093 static enum ia_css_err
1094 sp_init_stage(struct ia_css_pipeline_stage *stage,
1095 unsigned int pipe_num,
1097 unsigned int if_config_index,
1099 struct ia_css_binary *binary;
1100 const struct ia_css_fw_info *firmware;
1101 const struct sh_css_binary_args *args;
1102 unsigned int stage_num;
1104 * Initialiser required because of the "else" path below.
1105 * Is this a valid path ?
1107 const char *binary_name = "";
1108 const struct ia_css_binary_xinfo *info = NULL;
1109 /* note: the var below is made static as it is quite large;
1110 if it is not static it ends up on the stack which could
1111 cause issues for drivers
1113 static struct ia_css_binary tmp_binary;
1114 const struct ia_css_blob_info *blob_info = NULL;
1115 struct ia_css_isp_param_css_segments isp_mem_if;
1116 /* LA: should be ia_css_data, should not contain host pointer.
1117 However, CSS/DDR pointer is not available yet.
1118 Hack is to store it in params->ddr_ptrs and then copy it late in the SP just before vmem init.
1119 TODO: Call this after CSS/DDR allocation and store that pointer.
1120 Best is to allocate it at stage creation time together with host pointer.
1121 Remove vmem from params.
1123 struct ia_css_isp_param_css_segments *mem_if = &isp_mem_if;
1125 enum ia_css_err err = IA_CSS_SUCCESS;
1129 binary = stage->binary;
1130 firmware = stage->firmware;
1131 args = &stage->args;
1132 stage_num = stage->stage_num;
1136 info = binary->info;
1137 binary_name = (const char *)(info->blob->name);
1138 blob_info = &info->blob->header.blob;
1139 ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params);
1140 } else if (firmware)
1142 const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
1144 if (args->out_frame[0])
1145 out_infos[0] = &args->out_frame[0]->info;
1146 info = &firmware->info.isp;
1147 ia_css_binary_fill_info(info, false, false,
1148 ATOMISP_INPUT_FORMAT_RAW_10,
1149 args->in_frame ? &args->in_frame->info : NULL,
1152 args->out_vf_frame ? &args->out_vf_frame->info
1157 binary = &tmp_binary;
1158 binary->info = info;
1159 binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware);
1160 blob_info = &firmware->blob;
1161 mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers;
1165 assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC);
1166 /* binary and blob_info are now NULL.
1167 These will be passed to sh_css_sp_init_stage
1168 and dereferenced there, so passing a NULL
1169 pointer is no good. return an error */
1170 return IA_CSS_ERR_INTERNAL_ERROR;
1173 err = sh_css_sp_init_stage(binary,
1174 (const char *)binary_name,
1187 sp_init_sp_stage(struct ia_css_pipeline_stage *stage,
1188 unsigned int pipe_num,
1190 enum sh_css_pipe_config_override copy_ovrd,
1191 unsigned int if_config_index)
1193 const struct sh_css_binary_args *args = &stage->args;
1196 switch (stage->sp_func) {
1197 case IA_CSS_PIPELINE_RAW_COPY:
1198 sh_css_sp_start_raw_copy(args->out_frame[0],
1200 stage->max_input_width,
1201 copy_ovrd, if_config_index);
1203 case IA_CSS_PIPELINE_BIN_COPY:
1204 assert(false); /* TBI */
1205 case IA_CSS_PIPELINE_ISYS_COPY:
1206 sh_css_sp_start_isys_copy(args->out_frame[0],
1207 pipe_num, stage->max_input_width, if_config_index);
1209 case IA_CSS_PIPELINE_NO_FUNC:
1215 sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
1216 enum ia_css_pipe_id id,
1222 unsigned int required_bds_factor,
1223 enum sh_css_pipe_config_override copy_ovrd,
1224 enum ia_css_input_mode input_mode,
1225 const struct ia_css_metadata_config *md_config,
1226 const struct ia_css_metadata_info *md_info,
1227 #if !defined(HAS_NO_INPUT_SYSTEM)
1228 const enum mipi_port_id port_id,
1230 const struct ia_css_coordinate
1231 *internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame
1232 positioned on shading table at shading correction in ISP. */
1233 const struct ia_css_isp_parameters *params
1235 /* Get first stage */
1236 struct ia_css_pipeline_stage *stage = NULL;
1237 struct ia_css_binary *first_binary = NULL;
1238 struct ia_css_pipe *pipe = NULL;
1241 enum ia_css_pipe_id pipe_id = id;
1242 unsigned int thread_id;
1243 u8 if_config_index, tmp_if_config_index;
1247 #if !defined(HAS_NO_INPUT_SYSTEM)
1250 first_binary = me->stages->binary;
1252 if (input_mode == IA_CSS_INPUT_MODE_SENSOR ||
1253 input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1255 assert(port_id < N_MIPI_PORT_ID);
1256 if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */
1257 return; /* we should be able to return an error */
1258 if_config_index = (uint8_t)(port_id - MIPI_PORT0_ID);
1259 } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY)
1261 if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1264 if_config_index = 0x0;
1268 if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1271 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1272 memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));
1275 for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
1277 stage->stage_num = num;
1278 ia_css_debug_pipe_graph_dump_stage(stage, id);
1280 me->num_stages = num;
1284 /* Init pipeline data */
1285 sh_css_sp_init_group(two_ppc, first_binary->input_format,
1286 offline, if_config_index);
1287 } /* if (first_binary != NULL) */
1289 #if defined(USE_INPUT_SYSTEM_VERSION_2401) || defined(USE_INPUT_SYSTEM_VERSION_2)
1290 /* Signal the host immediately after start for SP_ISYS_COPY only */
1291 if ((me->num_stages == 1) && me->stages &&
1292 (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY))
1293 sh_css_sp_group.config.no_isp_sync = true;
1296 /* Init stage data */
1297 sh_css_init_host2sp_frame_data();
1299 sh_css_sp_group.pipe[thread_id].num_stages = 0;
1300 sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id;
1301 sh_css_sp_group.pipe[thread_id].thread_id = thread_id;
1302 sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num;
1303 sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs;
1304 sh_css_sp_group.pipe[thread_id].pipe_qos_config = me->pipe_qos_config;
1305 sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor;
1306 #if !defined(HAS_NO_INPUT_SYSTEM)
1307 sh_css_sp_group.pipe[thread_id].input_system_mode
1308 = (uint32_t)input_mode;
1309 sh_css_sp_group.pipe[thread_id].port_id = port_id;
1311 sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay;
1313 /* TODO: next indicates from which queues parameters need to be
1314 sampled, needs checking/improvement */
1315 if (ia_css_pipeline_uses_params(me))
1317 sh_css_sp_group.pipe[thread_id].pipe_config =
1318 SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id;
1321 /* For continuous use-cases, SP copy is responsible for sampling the
1324 sh_css_sp_group.pipe[thread_id].pipe_config = 0;
1326 sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config;
1328 pipe = find_pipe_by_num(pipe_num);
1334 sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe);
1336 #if defined(SH_CSS_ENABLE_METADATA)
1337 if (md_info && md_info->size > 0)
1339 sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width;
1340 sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height;
1341 sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride;
1342 sh_css_sp_group.pipe[thread_id].metadata.size = md_info->size;
1343 ia_css_isys_convert_stream_format_to_mipi_format(
1344 md_config->data_type, MIPI_PREDICTOR_NONE,
1345 &sh_css_sp_group.pipe[thread_id].metadata.format);
1352 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
1353 sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID;
1354 if (pipe_id != IA_CSS_PIPE_ID_COPY)
1356 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id,
1357 (enum sh_css_queue_id *)(
1358 &sh_css_sp_group.pipe[thread_id].output_frame_queue_id));
1362 if (atomisp_hw_is_isp2401) {
1363 /* For the shading correction type 1 (the legacy shading table conversion in css is not used),
1364 * the parameters are passed to the isp for the shading table centering.
1366 if (internal_frame_origin_bqs_on_sctbl &&
1367 params && params->shading_settings.enable_shading_table_conversion == 0)
1369 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl
1370 = (uint32_t)internal_frame_origin_bqs_on_sctbl->x;
1371 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl
1372 = (uint32_t)internal_frame_origin_bqs_on_sctbl->y;
1375 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl =
1377 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl =
1382 IA_CSS_LOG("pipe_id %d port_config %08x",
1383 pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config);
1385 for (stage = me->stages, num = 0; stage; stage = stage->next, num++)
1387 sh_css_sp_group.pipe[thread_id].num_stages++;
1388 if (is_sp_stage(stage)) {
1389 sp_init_sp_stage(stage, pipe_num, two_ppc,
1390 copy_ovrd, if_config_index);
1392 if ((stage->stage_num != 0) ||
1393 SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config))
1394 tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1396 tmp_if_config_index = if_config_index;
1397 sp_init_stage(stage, pipe_num,
1398 xnr, tmp_if_config_index, two_ppc);
1401 store_sp_stage_data(pipe_id, pipe_num, num);
1403 sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t)
1404 (me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS);
1405 store_sp_group_data();
1409 sh_css_sp_uninit_pipeline(unsigned int pipe_num)
1411 unsigned int thread_id;
1413 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1414 /*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/
1415 sh_css_sp_group.pipe[thread_id].num_stages = 0;
1418 bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command)
1420 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1421 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication,
1424 enum host2sp_commands last_cmd = host2sp_cmd_error;
1425 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1427 /* Previous command must be handled by SP (by design) */
1428 last_cmd = load_sp_array_uint(host_sp_com, offset);
1429 if (last_cmd != host2sp_cmd_ready)
1430 IA_CSS_ERROR("last host command not handled by SP(%d)", last_cmd);
1432 store_sp_array_uint(host_sp_com, offset, host2sp_command);
1434 return (last_cmd == host2sp_cmd_ready);
1437 enum host2sp_commands
1438 sh_css_read_host2sp_command(void) {
1439 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1440 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command)
1442 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1443 return (enum host2sp_commands)load_sp_array_uint(host_sp_com, offset);
1447 * Frame data is no longer part of the sp_stage structure but part of a
1448 * separate structure. The aim is to make the sp_data struct static
1449 * (it defines a pipeline) and that the dynamic (per frame) data is stored
1452 * This function must be called first every where were you start constructing
1453 * a new pipeline by defining one or more stages with use of variable
1454 * sh_css_sp_stage. Even the special cases like accelerator and copy_frame
1455 * These have a pipeline of just 1 stage.
1458 sh_css_init_host2sp_frame_data(void)
1461 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1463 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1465 * rvanimme: don't clean it to save static frame info line ref_in
1466 * ref_out, and tnr_frames. Once this static data is in a
1467 * separate data struct, this may be enable (but still, there is
1473 * @brief Update the offline frame information in host_sp_communication.
1474 * Refer to "sh_css_sp.h" for more details.
1477 sh_css_update_host2sp_offline_frame(
1478 unsigned int frame_num,
1479 struct ia_css_frame *frame,
1480 struct ia_css_metadata *metadata)
1482 unsigned int HIVE_ADDR_host_sp_com;
1483 unsigned int offset;
1485 assert(frame_num < NUM_CONTINUOUS_FRAMES);
1487 /* Write new frame data into SP DMEM */
1488 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1489 offset = (unsigned int)offsetof(struct host_sp_communication,
1490 host2sp_offline_frames)
1492 offset += frame_num;
1493 store_sp_array_uint(host_sp_com, offset, frame ? frame->data : 0);
1495 /* Write metadata buffer into SP DMEM */
1496 offset = (unsigned int)offsetof(struct host_sp_communication,
1497 host2sp_offline_metadata)
1499 offset += frame_num;
1500 store_sp_array_uint(host_sp_com, offset, metadata ? metadata->address : 0);
1503 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
1505 * @brief Update the mipi frame information in host_sp_communication.
1506 * Refer to "sh_css_sp.h" for more details.
1509 sh_css_update_host2sp_mipi_frame(
1510 unsigned int frame_num,
1511 struct ia_css_frame *frame)
1513 unsigned int HIVE_ADDR_host_sp_com;
1514 unsigned int offset;
1516 /* MIPI buffers are dedicated to port, so now there are more of them. */
1517 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1519 /* Write new frame data into SP DMEM */
1520 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1521 offset = (unsigned int)offsetof(struct host_sp_communication,
1522 host2sp_mipi_frames)
1524 offset += frame_num;
1526 store_sp_array_uint(host_sp_com, offset,
1527 frame ? frame->data : 0);
1531 * @brief Update the mipi metadata information in host_sp_communication.
1532 * Refer to "sh_css_sp.h" for more details.
1535 sh_css_update_host2sp_mipi_metadata(
1536 unsigned int frame_num,
1537 struct ia_css_metadata *metadata)
1539 unsigned int HIVE_ADDR_host_sp_com;
1542 /* MIPI buffers are dedicated to port, so now there are more of them. */
1543 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1545 /* Write new frame data into SP DMEM */
1546 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1547 o = offsetof(struct host_sp_communication, host2sp_mipi_metadata)
1550 store_sp_array_uint(host_sp_com, o,
1551 metadata ? metadata->address : 0);
1555 sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames)
1557 unsigned int HIVE_ADDR_host_sp_com;
1558 unsigned int offset;
1560 /* Write new frame data into SP DMEM */
1561 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1562 offset = (unsigned int)offsetof(struct host_sp_communication,
1563 host2sp_num_mipi_frames)
1566 store_sp_array_uint(host_sp_com, offset, num_frames);
1571 sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames,
1574 const struct ia_css_fw_info *fw;
1575 unsigned int HIVE_ADDR_host_sp_com;
1576 unsigned int extra_num_frames, avail_num_frames;
1577 unsigned int offset, offset_extra;
1579 /* Write new frame data into SP DMEM */
1581 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
1583 offset = (unsigned int)offsetof(struct host_sp_communication,
1584 host2sp_cont_avail_num_raw_frames)
1586 avail_num_frames = load_sp_array_uint(host_sp_com, offset);
1587 extra_num_frames = num_frames - avail_num_frames;
1588 offset_extra = (unsigned int)offsetof(struct host_sp_communication,
1589 host2sp_cont_extra_num_raw_frames)
1591 store_sp_array_uint(host_sp_com, offset_extra, extra_num_frames);
1593 offset = (unsigned int)offsetof(struct host_sp_communication,
1594 host2sp_cont_target_num_raw_frames)
1597 store_sp_array_uint(host_sp_com, offset, num_frames);
1601 sh_css_event_init_irq_mask(void)
1604 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1605 unsigned int offset;
1606 struct sh_css_event_irq_mask event_irq_mask_init;
1608 event_irq_mask_init.or_mask = IA_CSS_EVENT_TYPE_ALL;
1609 event_irq_mask_init.and_mask = IA_CSS_EVENT_TYPE_NONE;
1610 (void)HIVE_ADDR_host_sp_com; /* Suppress warnings in CRUN */
1612 assert(sizeof(event_irq_mask_init) % HRT_BUS_BYTES == 0);
1613 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
1614 offset = (unsigned int)offsetof(struct host_sp_communication,
1615 host2sp_event_irq_mask[i]);
1616 assert(offset % HRT_BUS_BYTES == 0);
1617 sp_dmem_store(SP0_ID,
1618 (unsigned int)sp_address_of(host_sp_com) + offset,
1619 &event_irq_mask_init, sizeof(event_irq_mask_init));
1624 ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe,
1625 unsigned int or_mask,
1626 unsigned int and_mask) {
1627 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1628 unsigned int offset;
1629 struct sh_css_event_irq_mask event_irq_mask;
1630 unsigned int pipe_num;
1634 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1635 /* Linux kernel does not have UINT16_MAX
1636 * Therefore decided to comment out these 2 asserts for Linux
1637 * Alternatives that were not chosen:
1638 * - add a conditional #define for UINT16_MAX
1639 * - compare with (uint16_t)~0 or 0xffff
1640 * - different assert for Linux and Windows
1643 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1645 IA_CSS_LOG("or_mask=%x, and_mask=%x", or_mask, and_mask);
1646 event_irq_mask.or_mask = (uint16_t)or_mask;
1647 event_irq_mask.and_mask = (uint16_t)and_mask;
1649 pipe_num = ia_css_pipe_get_pipe_num(pipe);
1650 if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1651 return IA_CSS_ERR_INTERNAL_ERROR;
1652 offset = (unsigned int)offsetof(struct host_sp_communication,
1653 host2sp_event_irq_mask[pipe_num]);
1654 assert(offset % HRT_BUS_BYTES == 0);
1655 sp_dmem_store(SP0_ID,
1656 (unsigned int)sp_address_of(host_sp_com) + offset,
1657 &event_irq_mask, sizeof(event_irq_mask));
1659 return IA_CSS_SUCCESS;
1663 ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe,
1664 unsigned int *or_mask,
1665 unsigned int *and_mask) {
1666 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1667 unsigned int offset;
1668 struct sh_css_event_irq_mask event_irq_mask;
1669 unsigned int pipe_num;
1671 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1673 IA_CSS_ENTER_LEAVE("");
1676 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1678 pipe_num = ia_css_pipe_get_pipe_num(pipe);
1679 if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1680 return IA_CSS_ERR_INTERNAL_ERROR;
1681 offset = (unsigned int)offsetof(struct host_sp_communication,
1682 host2sp_event_irq_mask[pipe_num]);
1683 assert(offset % HRT_BUS_BYTES == 0);
1684 sp_dmem_load(SP0_ID,
1685 (unsigned int)sp_address_of(host_sp_com) + offset,
1686 &event_irq_mask, sizeof(event_irq_mask));
1689 *or_mask = event_irq_mask.or_mask;
1692 *and_mask = event_irq_mask.and_mask;
1694 return IA_CSS_SUCCESS;
1698 sh_css_sp_set_sp_running(bool flag)
1704 sh_css_sp_is_running(void)
1710 sh_css_sp_start_isp(void)
1712 const struct ia_css_fw_info *fw;
1713 unsigned int HIVE_ADDR_sp_sw_state;
1716 HIVE_ADDR_sp_sw_state = fw->info.sp.sw_state;
1721 (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */
1723 /* no longer here, sp started immediately */
1724 /*ia_css_debug_pipe_graph_dump_epilogue();*/
1726 store_sp_group_data();
1727 store_sp_per_frame_data(fw);
1729 sp_dmem_store_uint32(SP0_ID,
1730 (unsigned int)sp_address_of(sp_sw_state),
1731 (uint32_t)(IA_CSS_SP_SW_TERMINATED));
1733 /* Note 1: The sp_start_isp function contains a wait till
1734 * the input network is configured by the SP.
1735 * Note 2: Not all SP binaries supports host2sp_commands.
1736 * In case a binary does support it, the host2sp_command
1737 * will have status cmd_ready after return of the function
1738 * sh_css_hrt_sp_start_isp. There is no race-condition here
1739 * because only after the process_frame command has been
1740 * received, the SP starts configuring the input network.
1743 /* we need to set sp_running before we call ia_css_mmu_invalidate_cache
1744 * as ia_css_mmu_invalidate_cache checks on sp_running to
1745 * avoid that it accesses dmem while the SP is not powered
1748 ia_css_mmu_invalidate_cache();
1749 /* Invalidate all MMU caches */
1750 mmu_invalidate_cache_all();
1752 ia_css_spctrl_start(SP0_ID);
1756 ia_css_isp_has_started(void)
1758 const struct ia_css_fw_info *fw = &sh_css_sp_fw;
1759 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
1760 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
1762 return (bool)load_sp_uint(ia_css_ispctrl_sp_isp_started);
1766 * @brief Initialize the DMA software-mask in the debug mode.
1767 * Refer to "sh_css_sp.h" for more details.
1770 sh_css_sp_init_dma_sw_reg(int dma_id)
1774 /* enable all the DMA channels */
1775 for (i = 0; i < N_DMA_CHANNEL_ID; i++) {
1776 /* enable the writing request */
1777 sh_css_sp_set_dma_sw_reg(dma_id,
1781 /* enable the reading request */
1782 sh_css_sp_set_dma_sw_reg(dma_id,
1792 * @brief Set the DMA software-mask in the debug mode.
1793 * Refer to "sh_css_sp.h" for more details.
1796 sh_css_sp_set_dma_sw_reg(int dma_id,
1808 assert(channel_id >= 0 && channel_id < N_DMA_CHANNEL_ID);
1809 assert(request_type >= 0);
1811 /* get the software-mask */
1813 sh_css_sp_group.debug.dma_sw_reg;
1815 /* get the offest of the target bit */
1816 bit_offset = (8 * request_type) + channel_id;
1818 /* clear the value of the target bit */
1819 bit_mask = ~(1 << bit_offset);
1822 /* set the value of the bit for the DMA channel */
1823 bit_val = enable ? 1 : 0;
1824 bit_val <<= bit_offset;
1827 /* update the software status of DMA channels */
1828 sh_css_sp_group.debug.dma_sw_reg = sw_reg;
1834 sh_css_sp_reset_global_vars(void)
1836 memset(&sh_css_sp_group, 0, sizeof(struct sh_css_sp_group));
1837 memset(&sh_css_sp_stage, 0, sizeof(struct sh_css_sp_stage));
1838 memset(&sh_css_isp_stage, 0, sizeof(struct sh_css_isp_stage));
1839 memset(&sh_css_sp_output, 0, sizeof(struct sh_css_sp_output));
1840 memset(&per_frame_data, 0, sizeof(struct sh_css_sp_per_frame_data));