1 // SPDX-License-Identifier: GPL-2.0
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2015, Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 #include "sh_css_sp.h"
21 #include "input_formatter.h"
24 #include "dma.h" /* N_DMA_CHANNEL_ID */
26 #include "ia_css_buffer.h"
27 #include "ia_css_binary.h"
28 #include "sh_css_hrt.h"
29 #include "sh_css_defs.h"
30 #include "sh_css_internal.h"
31 #include "ia_css_control.h"
32 #include "ia_css_debug.h"
33 #include "ia_css_debug_pipe.h"
34 #include "ia_css_event_public.h"
35 #include "ia_css_mmu.h"
36 #include "ia_css_stream.h"
37 #include "ia_css_isp_param.h"
38 #include "sh_css_params.h"
39 #include "sh_css_legacy.h"
40 #include "ia_css_frame_comm.h"
41 #include "ia_css_isys.h"
43 #include "gdc_device.h" /* HRT_GDC_N */
45 /*#include "sp.h"*/ /* host2sp_enqueue_frame_data() */
48 #include "assert_support.h"
50 #include "sw_event_global.h" /* Event IDs.*/
51 #include "ia_css_event.h"
52 #include "mmu_device.h"
53 #include "ia_css_spctrl.h"
56 #define offsetof(T, x) ((unsigned int)&(((T *)0)->x))
59 #define IA_CSS_INCLUDE_CONFIGURATIONS
60 #include "ia_css_isp_configs.h"
61 #define IA_CSS_INCLUDE_STATES
62 #include "ia_css_isp_states.h"
64 #include "isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h"
66 struct sh_css_sp_group sh_css_sp_group;
67 struct sh_css_sp_stage sh_css_sp_stage;
68 struct sh_css_isp_stage sh_css_isp_stage;
69 static struct sh_css_sp_output sh_css_sp_output;
70 static struct sh_css_sp_per_frame_data per_frame_data;
72 /* true if SP supports frame loop and host2sp_commands */
73 /* For the moment there is only code that sets this bool to true */
74 /* TODO: add code that sets this bool to false */
75 static bool sp_running;
78 set_output_frame_buffer(const struct ia_css_frame *frame,
82 sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf,
83 const enum sh_css_queue_id queue_id,
84 const ia_css_ptr xmem_addr,
85 const enum ia_css_buffer_type buf_type);
88 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr);
91 initialize_stage_frames(struct ia_css_frames_sp *frames);
93 /* This data is stored every frame */
95 store_sp_group_data(void)
97 per_frame_data.sp_group_addr = sh_css_store_sp_group_to_ddr();
101 copy_isp_stage_to_sp_stage(void)
103 /* [WW07.5]type casting will cause potential issues */
104 sh_css_sp_stage.num_stripes = (uint8_t)
105 sh_css_isp_stage.binary_info.iterator.num_stripes;
106 sh_css_sp_stage.row_stripes_height = (uint16_t)
107 sh_css_isp_stage.binary_info.iterator.row_stripes_height;
108 sh_css_sp_stage.row_stripes_overlap_lines = (uint16_t)
109 sh_css_isp_stage.binary_info.iterator.row_stripes_overlap_lines;
110 sh_css_sp_stage.top_cropping = (uint16_t)
111 sh_css_isp_stage.binary_info.pipeline.top_cropping;
112 /* moved to sh_css_sp_init_stage
113 sh_css_sp_stage.enable.vf_output =
114 sh_css_isp_stage.binary_info.enable.vf_veceven ||
115 sh_css_isp_stage.binary_info.num_output_pins > 1;
117 sh_css_sp_stage.enable.sdis = sh_css_isp_stage.binary_info.enable.dis;
118 sh_css_sp_stage.enable.s3a = sh_css_isp_stage.binary_info.enable.s3a;
122 store_sp_stage_data(enum ia_css_pipe_id id, unsigned int pipe_num,
125 unsigned int thread_id;
127 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
128 copy_isp_stage_to_sp_stage();
129 if (id != IA_CSS_PIPE_ID_COPY)
130 sh_css_sp_stage.isp_stage_addr =
131 sh_css_store_isp_stage_to_ddr(pipe_num, stage);
132 sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] =
133 sh_css_store_sp_stage_to_ddr(pipe_num, stage);
135 /* Clear for next frame */
136 sh_css_sp_stage.program_input_circuit = false;
140 store_sp_per_frame_data(const struct ia_css_fw_info *fw)
142 unsigned int HIVE_ADDR_sp_per_frame_data = 0;
147 case ia_css_sp_firmware:
148 HIVE_ADDR_sp_per_frame_data = fw->info.sp.per_frame_data;
150 case ia_css_acc_firmware:
151 HIVE_ADDR_sp_per_frame_data = fw->info.acc.per_frame_data;
153 case ia_css_isp_firmware:
157 sp_dmem_store(SP0_ID,
158 (unsigned int)sp_address_of(sp_per_frame_data),
160 sizeof(per_frame_data));
164 sh_css_store_sp_per_frame_data(enum ia_css_pipe_id pipe_id,
165 unsigned int pipe_num,
166 const struct ia_css_fw_info *sp_fw)
169 sp_fw = &sh_css_sp_fw;
171 store_sp_stage_data(pipe_id, pipe_num, 0);
172 store_sp_group_data();
173 store_sp_per_frame_data(sp_fw);
176 #if SP_DEBUG != SP_DEBUG_NONE
179 sh_css_sp_get_debug_state(struct sh_css_sp_debug_state *state)
181 const struct ia_css_fw_info *fw = &sh_css_sp_fw;
182 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
184 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
185 debug) / sizeof(int);
189 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
190 for (i = 0; i < sizeof(*state) / sizeof(int); i++)
191 ((unsigned *)state)[i] = load_sp_array_uint(sp_output, i + offset);
197 sh_css_sp_start_binary_copy(unsigned int pipe_num,
198 struct ia_css_frame *out_frame,
199 unsigned int two_ppc)
201 enum ia_css_pipe_id pipe_id;
202 unsigned int thread_id;
203 struct sh_css_sp_pipeline *pipe;
207 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
208 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
209 pipe = &sh_css_sp_group.pipe[thread_id];
211 pipe->copy.bin.bytes_available = out_frame->data_bytes;
212 pipe->num_stages = 1;
213 pipe->pipe_id = pipe_id;
214 pipe->pipe_num = pipe_num;
215 pipe->thread_id = thread_id;
216 pipe->pipe_config = 0x0; /* No parameters */
217 pipe->pipe_qos_config = QOS_INVALID;
219 if (pipe->inout_port_config == 0) {
220 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
221 (uint8_t)SH_CSS_PORT_INPUT,
222 (uint8_t)SH_CSS_HOST_TYPE, 1);
223 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
224 (uint8_t)SH_CSS_PORT_OUTPUT,
225 (uint8_t)SH_CSS_HOST_TYPE, 1);
227 IA_CSS_LOG("pipe_id %d port_config %08x",
228 pipe->pipe_id, pipe->inout_port_config);
230 #if !defined(ISP2401)
231 sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc;
236 sh_css_sp_stage.num = stage_num;
237 sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
238 sh_css_sp_stage.func =
239 (unsigned int)IA_CSS_PIPELINE_BIN_COPY;
241 set_output_frame_buffer(out_frame, 0);
243 /* sp_bin_copy_init on the SP does not deal with dynamica/static yet */
244 /* For now always update the dynamic data from out frames. */
245 sh_css_store_sp_per_frame_data(pipe_id, pipe_num, &sh_css_sp_fw);
249 sh_css_sp_start_raw_copy(struct ia_css_frame *out_frame,
250 unsigned int pipe_num,
251 unsigned int two_ppc,
252 unsigned int max_input_width,
253 enum sh_css_pipe_config_override pipe_conf_override,
254 unsigned int if_config_index)
256 enum ia_css_pipe_id pipe_id;
257 unsigned int thread_id;
259 struct sh_css_sp_pipeline *pipe;
265 * Clear sh_css_sp_stage for easy debugging.
266 * program_input_circuit must be saved as it is set outside
269 u8 program_input_circuit;
271 program_input_circuit = sh_css_sp_stage.program_input_circuit;
272 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
273 sh_css_sp_stage.program_input_circuit = program_input_circuit;
276 pipe_id = IA_CSS_PIPE_ID_COPY;
277 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
278 pipe = &sh_css_sp_group.pipe[thread_id];
280 pipe->copy.raw.height = out_frame->info.res.height;
281 pipe->copy.raw.width = out_frame->info.res.width;
282 pipe->copy.raw.padded_width = out_frame->info.padded_width;
283 pipe->copy.raw.raw_bit_depth = out_frame->info.raw_bit_depth;
284 pipe->copy.raw.max_input_width = max_input_width;
285 pipe->num_stages = 1;
286 pipe->pipe_id = pipe_id;
287 /* TODO: next indicates from which queues parameters need to be
288 sampled, needs checking/improvement */
289 if (pipe_conf_override == SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD)
291 (SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id);
293 pipe->pipe_config = pipe_conf_override;
295 pipe->pipe_qos_config = QOS_INVALID;
297 if (pipe->inout_port_config == 0) {
298 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
299 (uint8_t)SH_CSS_PORT_INPUT,
300 (uint8_t)SH_CSS_HOST_TYPE, 1);
301 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config,
302 (uint8_t)SH_CSS_PORT_OUTPUT,
303 (uint8_t)SH_CSS_HOST_TYPE, 1);
305 IA_CSS_LOG("pipe_id %d port_config %08x",
306 pipe->pipe_id, pipe->inout_port_config);
308 #if !defined(ISP2401)
309 sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc;
314 sh_css_sp_stage.num = stage_num;
315 sh_css_sp_stage.xmem_bin_addr = 0x0;
316 sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
317 sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_RAW_COPY;
318 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
319 set_output_frame_buffer(out_frame, 0);
321 ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame);
325 sh_css_sp_start_isys_copy(struct ia_css_frame *out_frame,
326 unsigned int pipe_num, unsigned int max_input_width,
327 unsigned int if_config_index)
329 enum ia_css_pipe_id pipe_id;
330 unsigned int thread_id;
332 struct sh_css_sp_pipeline *pipe;
333 enum sh_css_queue_id queue_id;
339 * Clear sh_css_sp_stage for easy debugging.
340 * program_input_circuit must be saved as it is set outside
343 u8 program_input_circuit;
345 program_input_circuit = sh_css_sp_stage.program_input_circuit;
346 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
347 sh_css_sp_stage.program_input_circuit = program_input_circuit;
350 pipe_id = IA_CSS_PIPE_ID_COPY;
351 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
352 pipe = &sh_css_sp_group.pipe[thread_id];
354 pipe->copy.raw.height = out_frame->info.res.height;
355 pipe->copy.raw.width = out_frame->info.res.width;
356 pipe->copy.raw.padded_width = out_frame->info.padded_width;
357 pipe->copy.raw.raw_bit_depth = out_frame->info.raw_bit_depth;
358 pipe->copy.raw.max_input_width = max_input_width;
359 pipe->num_stages = 1;
360 pipe->pipe_id = pipe_id;
361 pipe->pipe_config = 0x0; /* No parameters */
362 pipe->pipe_qos_config = QOS_INVALID;
364 initialize_stage_frames(&sh_css_sp_stage.frames);
365 sh_css_sp_stage.num = stage_num;
366 sh_css_sp_stage.xmem_bin_addr = 0x0;
367 sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE;
368 sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_ISYS_COPY;
369 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
371 set_output_frame_buffer(out_frame, 0);
373 if (pipe->metadata.height > 0) {
374 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id,
376 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf,
377 queue_id, mmgr_EXCEPTION,
378 IA_CSS_BUFFER_TYPE_METADATA);
381 ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame);
385 sh_css_sp_get_binary_copy_size(void)
387 const struct ia_css_fw_info *fw = &sh_css_sp_fw;
388 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
389 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
390 bin_copy_bytes_copied) / sizeof(int);
391 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
392 return load_sp_array_uint(sp_output, offset);
396 sh_css_sp_get_sw_interrupt_value(unsigned int irq)
398 const struct ia_css_fw_info *fw = &sh_css_sp_fw;
399 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output;
400 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output,
403 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */
404 return load_sp_array_uint(sp_output, offset + irq);
408 sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf,
409 const enum sh_css_queue_id queue_id,
410 const ia_css_ptr xmem_addr,
411 const enum ia_css_buffer_type buf_type)
413 assert(buf_type < IA_CSS_NUM_BUFFER_TYPE);
414 if (queue_id > SH_CSS_INVALID_QUEUE_ID) {
416 * value >=0 indicates that function init_frame_pointers()
417 * should use the dynamic data address
419 assert(queue_id < SH_CSS_MAX_NUM_QUEUES);
421 /* Klocwork assumes assert can be disabled;
422 Since we can get there with any type, and it does not
423 know that frame_in->dynamic_data_index can only be set
424 for one of the types in the assert) it has to assume we
425 can get here for any type. however this could lead to an
426 out of bounds reference when indexing buf_type about 10
427 lines below. In order to satisfy KW an additional if
428 has been added. This one will always yield true.
430 if ((queue_id < SH_CSS_MAX_NUM_QUEUES)) {
431 dest_buf->buf_src.queue_id = queue_id;
434 assert(xmem_addr != mmgr_EXCEPTION);
435 dest_buf->buf_src.xmem_addr = xmem_addr;
437 dest_buf->buf_type = buf_type;
441 sh_css_copy_frame_to_spframe(struct ia_css_frame_sp *sp_frame_out,
442 const struct ia_css_frame *frame_in)
446 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
447 "sh_css_copy_frame_to_spframe():\n");
449 sh_css_copy_buffer_attr_to_spbuffer(&sp_frame_out->buf_attr,
450 frame_in->dynamic_queue_id,
454 ia_css_frame_info_to_frame_sp_info(&sp_frame_out->info, &frame_in->info);
456 switch (frame_in->info.format) {
457 case IA_CSS_FRAME_FORMAT_RAW_PACKED:
458 case IA_CSS_FRAME_FORMAT_RAW:
459 sp_frame_out->planes.raw.offset = frame_in->planes.raw.offset;
461 case IA_CSS_FRAME_FORMAT_RGB565:
462 case IA_CSS_FRAME_FORMAT_RGBA888:
463 sp_frame_out->planes.rgb.offset = frame_in->planes.rgb.offset;
465 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
466 sp_frame_out->planes.planar_rgb.r.offset =
467 frame_in->planes.planar_rgb.r.offset;
468 sp_frame_out->planes.planar_rgb.g.offset =
469 frame_in->planes.planar_rgb.g.offset;
470 sp_frame_out->planes.planar_rgb.b.offset =
471 frame_in->planes.planar_rgb.b.offset;
473 case IA_CSS_FRAME_FORMAT_YUYV:
474 case IA_CSS_FRAME_FORMAT_UYVY:
475 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
476 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
477 case IA_CSS_FRAME_FORMAT_YUV_LINE:
478 sp_frame_out->planes.yuyv.offset = frame_in->planes.yuyv.offset;
480 case IA_CSS_FRAME_FORMAT_NV11:
481 case IA_CSS_FRAME_FORMAT_NV12:
482 case IA_CSS_FRAME_FORMAT_NV12_16:
483 case IA_CSS_FRAME_FORMAT_NV12_TILEY:
484 case IA_CSS_FRAME_FORMAT_NV21:
485 case IA_CSS_FRAME_FORMAT_NV16:
486 case IA_CSS_FRAME_FORMAT_NV61:
487 sp_frame_out->planes.nv.y.offset =
488 frame_in->planes.nv.y.offset;
489 sp_frame_out->planes.nv.uv.offset =
490 frame_in->planes.nv.uv.offset;
492 case IA_CSS_FRAME_FORMAT_YUV420:
493 case IA_CSS_FRAME_FORMAT_YUV422:
494 case IA_CSS_FRAME_FORMAT_YUV444:
495 case IA_CSS_FRAME_FORMAT_YUV420_16:
496 case IA_CSS_FRAME_FORMAT_YUV422_16:
497 case IA_CSS_FRAME_FORMAT_YV12:
498 case IA_CSS_FRAME_FORMAT_YV16:
499 sp_frame_out->planes.yuv.y.offset =
500 frame_in->planes.yuv.y.offset;
501 sp_frame_out->planes.yuv.u.offset =
502 frame_in->planes.yuv.u.offset;
503 sp_frame_out->planes.yuv.v.offset =
504 frame_in->planes.yuv.v.offset;
506 case IA_CSS_FRAME_FORMAT_QPLANE6:
507 sp_frame_out->planes.plane6.r.offset =
508 frame_in->planes.plane6.r.offset;
509 sp_frame_out->planes.plane6.r_at_b.offset =
510 frame_in->planes.plane6.r_at_b.offset;
511 sp_frame_out->planes.plane6.gr.offset =
512 frame_in->planes.plane6.gr.offset;
513 sp_frame_out->planes.plane6.gb.offset =
514 frame_in->planes.plane6.gb.offset;
515 sp_frame_out->planes.plane6.b.offset =
516 frame_in->planes.plane6.b.offset;
517 sp_frame_out->planes.plane6.b_at_r.offset =
518 frame_in->planes.plane6.b_at_r.offset;
520 case IA_CSS_FRAME_FORMAT_BINARY_8:
521 sp_frame_out->planes.binary.data.offset =
522 frame_in->planes.binary.data.offset;
525 /* This should not happen, but in case it does,
528 memset(&sp_frame_out->planes, 0, sizeof(sp_frame_out->planes));
534 set_input_frame_buffer(const struct ia_css_frame *frame)
539 switch (frame->info.format) {
540 case IA_CSS_FRAME_FORMAT_QPLANE6:
541 case IA_CSS_FRAME_FORMAT_YUV420_16:
542 case IA_CSS_FRAME_FORMAT_RAW_PACKED:
543 case IA_CSS_FRAME_FORMAT_RAW:
544 case IA_CSS_FRAME_FORMAT_YUV420:
545 case IA_CSS_FRAME_FORMAT_YUYV:
546 case IA_CSS_FRAME_FORMAT_YUV_LINE:
547 case IA_CSS_FRAME_FORMAT_NV12:
548 case IA_CSS_FRAME_FORMAT_NV12_16:
549 case IA_CSS_FRAME_FORMAT_NV12_TILEY:
550 case IA_CSS_FRAME_FORMAT_NV21:
551 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
552 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
553 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_10:
558 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.in, frame);
564 set_output_frame_buffer(const struct ia_css_frame *frame,
570 switch (frame->info.format) {
571 case IA_CSS_FRAME_FORMAT_YUV420:
572 case IA_CSS_FRAME_FORMAT_YUV422:
573 case IA_CSS_FRAME_FORMAT_YUV444:
574 case IA_CSS_FRAME_FORMAT_YV12:
575 case IA_CSS_FRAME_FORMAT_YV16:
576 case IA_CSS_FRAME_FORMAT_YUV420_16:
577 case IA_CSS_FRAME_FORMAT_YUV422_16:
578 case IA_CSS_FRAME_FORMAT_NV11:
579 case IA_CSS_FRAME_FORMAT_NV12:
580 case IA_CSS_FRAME_FORMAT_NV12_16:
581 case IA_CSS_FRAME_FORMAT_NV12_TILEY:
582 case IA_CSS_FRAME_FORMAT_NV16:
583 case IA_CSS_FRAME_FORMAT_NV21:
584 case IA_CSS_FRAME_FORMAT_NV61:
585 case IA_CSS_FRAME_FORMAT_YUYV:
586 case IA_CSS_FRAME_FORMAT_UYVY:
587 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
588 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
589 case IA_CSS_FRAME_FORMAT_YUV_LINE:
590 case IA_CSS_FRAME_FORMAT_RGB565:
591 case IA_CSS_FRAME_FORMAT_RGBA888:
592 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
593 case IA_CSS_FRAME_FORMAT_RAW:
594 case IA_CSS_FRAME_FORMAT_RAW_PACKED:
595 case IA_CSS_FRAME_FORMAT_QPLANE6:
596 case IA_CSS_FRAME_FORMAT_BINARY_8:
601 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out[idx], frame);
606 set_view_finder_buffer(const struct ia_css_frame *frame)
611 switch (frame->info.format) {
612 /* the dual output pin */
613 case IA_CSS_FRAME_FORMAT_NV12:
614 case IA_CSS_FRAME_FORMAT_NV12_16:
615 case IA_CSS_FRAME_FORMAT_NV21:
616 case IA_CSS_FRAME_FORMAT_YUYV:
617 case IA_CSS_FRAME_FORMAT_UYVY:
618 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
619 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
620 case IA_CSS_FRAME_FORMAT_YUV420:
621 case IA_CSS_FRAME_FORMAT_YV12:
622 case IA_CSS_FRAME_FORMAT_NV12_TILEY:
625 case IA_CSS_FRAME_FORMAT_YUV_LINE:
631 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out_vf, frame);
635 #if !defined(ISP2401)
636 void sh_css_sp_set_if_configs(
637 const input_formatter_cfg_t *config_a,
638 const input_formatter_cfg_t *config_b,
639 const uint8_t if_config_index
642 assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
645 sh_css_sp_group.config.input_formatter.set[if_config_index].config_a =
647 sh_css_sp_group.config.input_formatter.a_changed = true;
650 sh_css_sp_group.config.input_formatter.set[if_config_index].config_b =
652 sh_css_sp_group.config.input_formatter.b_changed = true;
659 #if !defined(ISP2401)
661 sh_css_sp_program_input_circuit(int fmt_type,
663 enum ia_css_input_mode input_mode)
665 sh_css_sp_group.config.input_circuit.no_side_band = false;
666 sh_css_sp_group.config.input_circuit.fmt_type = fmt_type;
667 sh_css_sp_group.config.input_circuit.ch_id = ch_id;
668 sh_css_sp_group.config.input_circuit.input_mode = input_mode;
670 * The SP group is only loaded at SP boot time and is read once
671 * change flags as "input_circuit_cfg_changed" must be reset on the SP
673 sh_css_sp_group.config.input_circuit_cfg_changed = true;
674 sh_css_sp_stage.program_input_circuit = true;
678 #if !defined(ISP2401)
680 sh_css_sp_configure_sync_gen(int width, int height,
684 sh_css_sp_group.config.sync_gen.width = width;
685 sh_css_sp_group.config.sync_gen.height = height;
686 sh_css_sp_group.config.sync_gen.hblank_cycles = hblank_cycles;
687 sh_css_sp_group.config.sync_gen.vblank_cycles = vblank_cycles;
691 sh_css_sp_configure_tpg(int x_mask,
697 sh_css_sp_group.config.tpg.x_mask = x_mask;
698 sh_css_sp_group.config.tpg.y_mask = y_mask;
699 sh_css_sp_group.config.tpg.x_delta = x_delta;
700 sh_css_sp_group.config.tpg.y_delta = y_delta;
701 sh_css_sp_group.config.tpg.xy_mask = xy_mask;
705 sh_css_sp_configure_prbs(int seed)
707 sh_css_sp_group.config.prbs.seed = seed;
712 sh_css_sp_configure_enable_raw_pool_locking(bool lock_all)
714 sh_css_sp_group.config.enable_raw_pool_locking = true;
715 sh_css_sp_group.config.lock_all = lock_all;
719 sh_css_sp_enable_isys_event_queue(bool enable)
721 sh_css_sp_group.config.enable_isys_event_queue = enable;
725 sh_css_sp_set_disable_continuous_viewfinder(bool flag)
727 sh_css_sp_group.config.disable_cont_vf = flag;
731 sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args)
739 err = set_input_frame_buffer(args->in_frame);
740 if (!err && args->out_vf_frame)
741 err = set_view_finder_buffer(args->out_vf_frame);
742 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
743 if (!err && args->out_frame[i])
744 err = set_output_frame_buffer(args->out_frame[i], i);
747 /* we don't pass this error back to the upper layer, so we add a assert here
748 because we actually hit the error here but it still works by accident... */
749 if (err) assert(false);
754 sh_css_sp_init_group(bool two_ppc,
755 enum atomisp_input_format input_format,
757 uint8_t if_config_index)
759 #if !defined(ISP2401)
760 sh_css_sp_group.config.input_formatter.isp_2ppc = two_ppc;
765 sh_css_sp_group.config.no_isp_sync = (uint8_t)no_isp_sync;
766 /* decide whether the frame is processed online or offline */
767 if (if_config_index == SH_CSS_IF_CONFIG_NOT_NEEDED) return;
768 #if !defined(ISP2401)
769 assert(if_config_index < SH_CSS_MAX_IF_CONFIGS);
770 sh_css_sp_group.config.input_formatter.set[if_config_index].stream_format =
778 sh_css_stage_write_binary_info(struct ia_css_binary_info *info)
781 sh_css_isp_stage.binary_info = *info;
785 copy_isp_mem_if_to_ddr(struct ia_css_binary *binary)
789 err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
792 IA_CSS_PARAM_CLASS_CONFIG);
795 err = ia_css_isp_param_copy_isp_mem_if_to_ddr(
798 IA_CSS_PARAM_CLASS_STATE);
805 is_sp_stage(struct ia_css_pipeline_stage *stage)
808 return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC;
811 static int configure_isp_from_args(const struct sh_css_sp_pipeline *pipeline,
812 const struct ia_css_binary *binary,
813 const struct sh_css_binary_args *args,
819 ret = ia_css_fpn_configure(binary, &binary->in_frame_info);
822 ret = ia_css_crop_configure(binary, &args->delay_frames[0]->info);
825 ret = ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info);
828 ret = ia_css_output0_configure(binary, &args->out_frame[0]->info);
831 ret = ia_css_output1_configure(binary, &args->out_vf_frame->info);
834 ret = ia_css_copy_output_configure(binary, args->copy_output);
837 ret = ia_css_output0_configure(binary, &args->out_frame[0]->info);
840 ret = ia_css_iterator_configure(binary, &args->in_frame->info);
843 ret = ia_css_dvs_configure(binary, &args->out_frame[0]->info);
846 ret = ia_css_output_configure(binary, &args->out_frame[0]->info);
849 ret = ia_css_raw_configure(pipeline, binary, &args->in_frame->info, &binary->in_frame_info, two_ppc, deinterleaved);
854 * FIXME: args->delay_frames can be NULL here
856 * Somehow, the driver at the Intel Atom Yocto tree doesn't seem to
857 * suffer from the same issue.
859 * Anyway, the function below should now handle a NULL delay_frames
860 * without crashing, but the pipeline should likely be built without
861 * adding it at the first place (or there are a hidden bug somewhere)
863 ret = ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay);
866 ret = ia_css_tnr_configure(binary, args->tnr_frames);
869 return ia_css_bayer_io_config(binary, args);
873 initialize_isp_states(const struct ia_css_binary *binary)
877 if (!binary->info->mem_offsets.offsets.state)
879 for (i = 0; i < IA_CSS_NUM_STATE_IDS; i++) {
880 ia_css_kernel_init_state[i](binary);
885 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr)
887 buf_attr->buf_src.queue_id = SH_CSS_INVALID_QUEUE_ID;
888 buf_attr->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
892 initialize_stage_frames(struct ia_css_frames_sp *frames)
896 initialize_frame_buffer_attribute(&frames->in.buf_attr);
897 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
898 initialize_frame_buffer_attribute(&frames->out[i].buf_attr);
900 initialize_frame_buffer_attribute(&frames->out_vf.buf_attr);
901 initialize_frame_buffer_attribute(&frames->s3a_buf);
902 initialize_frame_buffer_attribute(&frames->dvs_buf);
903 initialize_frame_buffer_attribute(&frames->metadata_buf);
907 sh_css_sp_init_stage(struct ia_css_binary *binary,
908 const char *binary_name,
909 const struct ia_css_blob_info *blob_info,
910 const struct sh_css_binary_args *args,
911 unsigned int pipe_num,
914 const struct ia_css_isp_param_css_segments *isp_mem_if,
915 unsigned int if_config_index,
918 const struct ia_css_binary_xinfo *xinfo;
919 const struct ia_css_binary_info *info;
922 struct ia_css_pipe *pipe = NULL;
923 unsigned int thread_id;
924 enum sh_css_queue_id queue_id;
925 bool continuous = sh_css_continuous_is_enabled((uint8_t)pipe_num);
932 xinfo = binary->info;
936 * Clear sh_css_sp_stage for easy debugging.
937 * program_input_circuit must be saved as it is set outside
940 u8 program_input_circuit;
942 program_input_circuit = sh_css_sp_stage.program_input_circuit;
943 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage));
944 sh_css_sp_stage.program_input_circuit = (uint8_t)program_input_circuit;
947 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
950 sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL;
956 sh_css_sp_stage.deinterleaved = 0;
958 sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous);
961 initialize_stage_frames(&sh_css_sp_stage.frames);
963 * TODO: Make the Host dynamically determine
966 sh_css_sp_stage.stage_type = SH_CSS_ISP_STAGE_TYPE;
967 sh_css_sp_stage.num = (uint8_t)stage;
968 sh_css_sp_stage.isp_online = (uint8_t)binary->online;
969 sh_css_sp_stage.isp_copy_vf = (uint8_t)args->copy_vf;
970 sh_css_sp_stage.isp_copy_output = (uint8_t)args->copy_output;
971 sh_css_sp_stage.enable.vf_output = (args->out_vf_frame != NULL);
973 /* Copy the frame infos first, to be overwritten by the frames,
974 if these are present.
976 sh_css_sp_stage.frames.effective_in_res.width = binary->effective_in_frame_res.width;
977 sh_css_sp_stage.frames.effective_in_res.height = binary->effective_in_frame_res.height;
979 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.in.info,
980 &binary->in_frame_info);
981 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
982 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.out[i].info,
983 &binary->out_frame_info[i]);
985 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.internal_frame_info,
986 &binary->internal_frame_info);
987 sh_css_sp_stage.dvs_envelope.width = binary->dvs_envelope.width;
988 sh_css_sp_stage.dvs_envelope.height = binary->dvs_envelope.height;
989 sh_css_sp_stage.isp_pipe_version = (uint8_t)info->pipeline.isp_pipe_version;
990 sh_css_sp_stage.isp_deci_log_factor = (uint8_t)binary->deci_factor_log2;
991 sh_css_sp_stage.isp_vf_downscale_bits = (uint8_t)binary->vf_downscale_log2;
993 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index;
995 sh_css_sp_stage.sp_enable_xnr = (uint8_t)xnr;
996 sh_css_sp_stage.xmem_bin_addr = xinfo->xmem_addr;
997 sh_css_sp_stage.xmem_map_addr = sh_css_params_ddr_address_map();
998 sh_css_isp_stage.blob_info = *blob_info;
999 sh_css_stage_write_binary_info((struct ia_css_binary_info *)info);
1001 /* Make sure binary name is smaller than allowed string size */
1002 assert(strlen(binary_name) < SH_CSS_MAX_BINARY_NAME - 1);
1003 strscpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME);
1004 sh_css_isp_stage.mem_initializers = *isp_mem_if;
1007 * Even when a stage does not need uds and does not params,
1008 * ia_css_uds_sp_scale_params() seems to be called (needs
1009 * further investigation). This function can not deal with
1013 err = sh_css_sp_write_frame_pointers(args);
1014 /* TODO: move it to a better place */
1015 if (binary->info->sp.enable.s3a) {
1016 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_3A_STATISTICS, thread_id,
1018 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.s3a_buf, queue_id,
1020 IA_CSS_BUFFER_TYPE_3A_STATISTICS);
1022 if (binary->info->sp.enable.dis) {
1023 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id,
1025 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id,
1027 IA_CSS_BUFFER_TYPE_DIS_STATISTICS);
1029 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id);
1030 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA);
1035 pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num);
1040 ia_css_get_crop_offsets(pipe, &args->in_frame->info);
1042 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1044 (void)pipe; /*avoid build warning*/
1047 err = configure_isp_from_args(&sh_css_sp_group.pipe[thread_id],
1048 binary, args, two_ppc, sh_css_sp_stage.deinterleaved);
1052 initialize_isp_states(binary);
1054 /* we do this only for preview pipe because in fill_binary_info function
1055 * we assign vf_out res to out res, but for ISP internal processing, we need
1056 * the original out res. for video pipe, it has two output pins --- out and
1057 * vf_out, so it can keep these two resolutions already. */
1058 if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW &&
1059 (binary->vf_downscale_log2 > 0)) {
1060 /* TODO: Remove this after preview output decimation is fixed
1061 * by configuring out&vf info fiels properly */
1062 sh_css_sp_stage.frames.out[0].info.padded_width
1063 <<= binary->vf_downscale_log2;
1064 sh_css_sp_stage.frames.out[0].info.res.width
1065 <<= binary->vf_downscale_log2;
1066 sh_css_sp_stage.frames.out[0].info.res.height
1067 <<= binary->vf_downscale_log2;
1069 err = copy_isp_mem_if_to_ddr(binary);
1077 sp_init_stage(struct ia_css_pipeline_stage *stage,
1078 unsigned int pipe_num,
1080 unsigned int if_config_index,
1083 struct ia_css_binary *binary;
1084 const struct ia_css_fw_info *firmware;
1085 const struct sh_css_binary_args *args;
1086 unsigned int stage_num;
1088 * Initialiser required because of the "else" path below.
1089 * Is this a valid path ?
1091 const char *binary_name = "";
1092 const struct ia_css_binary_xinfo *info = NULL;
1093 /* note: the var below is made static as it is quite large;
1094 if it is not static it ends up on the stack which could
1095 cause issues for drivers
1097 static struct ia_css_binary tmp_binary;
1098 const struct ia_css_blob_info *blob_info = NULL;
1099 struct ia_css_isp_param_css_segments isp_mem_if;
1100 /* LA: should be ia_css_data, should not contain host pointer.
1101 However, CSS/DDR pointer is not available yet.
1102 Hack is to store it in params->ddr_ptrs and then copy it late in the SP just before vmem init.
1103 TODO: Call this after CSS/DDR allocation and store that pointer.
1104 Best is to allocate it at stage creation time together with host pointer.
1105 Remove vmem from params.
1107 struct ia_css_isp_param_css_segments *mem_if = &isp_mem_if;
1113 binary = stage->binary;
1114 firmware = stage->firmware;
1115 args = &stage->args;
1116 stage_num = stage->stage_num;
1119 info = binary->info;
1120 binary_name = (const char *)(info->blob->name);
1121 blob_info = &info->blob->header.blob;
1122 ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params);
1123 } else if (firmware) {
1124 const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
1126 if (args->out_frame[0])
1127 out_infos[0] = &args->out_frame[0]->info;
1128 info = &firmware->info.isp;
1129 ia_css_binary_fill_info(info, false, false,
1130 ATOMISP_INPUT_FORMAT_RAW_10,
1131 args->in_frame ? &args->in_frame->info : NULL,
1134 args->out_vf_frame ? &args->out_vf_frame->info
1139 binary = &tmp_binary;
1140 binary->info = info;
1141 binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware);
1142 blob_info = &firmware->blob;
1143 mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers;
1146 assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC);
1147 /* binary and blob_info are now NULL.
1148 These will be passed to sh_css_sp_init_stage
1149 and dereferenced there, so passing a NULL
1150 pointer is no good. return an error */
1154 err = sh_css_sp_init_stage(binary,
1155 (const char *)binary_name,
1168 sp_init_sp_stage(struct ia_css_pipeline_stage *stage,
1169 unsigned int pipe_num,
1171 enum sh_css_pipe_config_override copy_ovrd,
1172 unsigned int if_config_index)
1174 const struct sh_css_binary_args *args = &stage->args;
1177 switch (stage->sp_func) {
1178 case IA_CSS_PIPELINE_RAW_COPY:
1179 sh_css_sp_start_raw_copy(args->out_frame[0],
1181 stage->max_input_width,
1182 copy_ovrd, if_config_index);
1184 case IA_CSS_PIPELINE_BIN_COPY:
1185 assert(false); /* TBI */
1187 case IA_CSS_PIPELINE_ISYS_COPY:
1188 sh_css_sp_start_isys_copy(args->out_frame[0],
1189 pipe_num, stage->max_input_width, if_config_index);
1191 case IA_CSS_PIPELINE_NO_FUNC:
1198 sh_css_sp_init_pipeline(struct ia_css_pipeline *me,
1199 enum ia_css_pipe_id id,
1205 unsigned int required_bds_factor,
1206 enum sh_css_pipe_config_override copy_ovrd,
1207 enum ia_css_input_mode input_mode,
1208 const struct ia_css_metadata_config *md_config,
1209 const struct ia_css_metadata_info *md_info,
1210 const enum mipi_port_id port_id)
1212 /* Get first stage */
1213 struct ia_css_pipeline_stage *stage = NULL;
1214 struct ia_css_binary *first_binary = NULL;
1215 struct ia_css_pipe *pipe = NULL;
1218 enum ia_css_pipe_id pipe_id = id;
1219 unsigned int thread_id;
1220 u8 if_config_index, tmp_if_config_index;
1226 first_binary = me->stages->binary;
1228 if (input_mode == IA_CSS_INPUT_MODE_SENSOR ||
1229 input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
1230 assert(port_id < N_MIPI_PORT_ID);
1231 if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */
1232 return; /* we should be able to return an error */
1233 if_config_index = (uint8_t)(port_id - MIPI_PORT0_ID);
1234 } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY) {
1235 if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1237 if_config_index = 0x0;
1240 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1241 memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));
1244 for (stage = me->stages, num = 0; stage; stage = stage->next, num++) {
1245 stage->stage_num = num;
1246 ia_css_debug_pipe_graph_dump_stage(stage, id);
1248 me->num_stages = num;
1251 /* Init pipeline data */
1252 sh_css_sp_init_group(two_ppc, first_binary->input_format,
1253 offline, if_config_index);
1254 } /* if (first_binary != NULL) */
1256 /* Signal the host immediately after start for SP_ISYS_COPY only */
1257 if ((me->num_stages == 1) && me->stages &&
1258 (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY))
1259 sh_css_sp_group.config.no_isp_sync = true;
1261 /* Init stage data */
1262 sh_css_init_host2sp_frame_data();
1264 sh_css_sp_group.pipe[thread_id].num_stages = 0;
1265 sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id;
1266 sh_css_sp_group.pipe[thread_id].thread_id = thread_id;
1267 sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num;
1268 sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs;
1269 sh_css_sp_group.pipe[thread_id].pipe_qos_config = me->pipe_qos_config;
1270 sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor;
1271 sh_css_sp_group.pipe[thread_id].input_system_mode
1272 = (uint32_t)input_mode;
1273 sh_css_sp_group.pipe[thread_id].port_id = port_id;
1274 sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay;
1276 /* TODO: next indicates from which queues parameters need to be
1277 sampled, needs checking/improvement */
1278 if (ia_css_pipeline_uses_params(me)) {
1279 sh_css_sp_group.pipe[thread_id].pipe_config =
1280 SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id;
1283 /* For continuous use-cases, SP copy is responsible for sampling the
1286 sh_css_sp_group.pipe[thread_id].pipe_config = 0;
1288 sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config;
1290 pipe = find_pipe_by_num(pipe_num);
1295 sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe);
1297 if (md_info && md_info->size > 0) {
1298 sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width;
1299 sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height;
1300 sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride;
1301 sh_css_sp_group.pipe[thread_id].metadata.size = md_info->size;
1302 ia_css_isys_convert_stream_format_to_mipi_format(
1303 md_config->data_type, MIPI_PREDICTOR_NONE,
1304 &sh_css_sp_group.pipe[thread_id].metadata.format);
1307 sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID;
1308 if (pipe_id != IA_CSS_PIPE_ID_COPY) {
1309 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id,
1310 (enum sh_css_queue_id *)(
1311 &sh_css_sp_group.pipe[thread_id].output_frame_queue_id));
1314 IA_CSS_LOG("pipe_id %d port_config %08x",
1315 pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config);
1317 for (stage = me->stages, num = 0; stage; stage = stage->next, num++) {
1318 sh_css_sp_group.pipe[thread_id].num_stages++;
1319 if (is_sp_stage(stage)) {
1320 sp_init_sp_stage(stage, pipe_num, two_ppc,
1321 copy_ovrd, if_config_index);
1323 if ((stage->stage_num != 0) ||
1324 SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config))
1325 tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED;
1327 tmp_if_config_index = if_config_index;
1328 sp_init_stage(stage, pipe_num,
1329 xnr, tmp_if_config_index, two_ppc);
1332 store_sp_stage_data(pipe_id, pipe_num, num);
1334 sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t)
1335 (me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS);
1336 store_sp_group_data();
1340 sh_css_sp_uninit_pipeline(unsigned int pipe_num)
1342 unsigned int thread_id;
1344 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
1345 /*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/
1346 sh_css_sp_group.pipe[thread_id].num_stages = 0;
1349 bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command)
1351 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1352 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication,
1355 enum host2sp_commands last_cmd = host2sp_cmd_error;
1356 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1358 /* Previous command must be handled by SP (by design) */
1359 last_cmd = load_sp_array_uint(host_sp_com, offset);
1360 if (last_cmd != host2sp_cmd_ready)
1361 IA_CSS_ERROR("last host command not handled by SP(%d)", last_cmd);
1363 store_sp_array_uint(host_sp_com, offset, host2sp_command);
1365 return (last_cmd == host2sp_cmd_ready);
1368 enum host2sp_commands
1369 sh_css_read_host2sp_command(void)
1371 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1372 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command)
1374 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1375 return (enum host2sp_commands)load_sp_array_uint(host_sp_com, offset);
1379 * Frame data is no longer part of the sp_stage structure but part of a
1380 * separate structure. The aim is to make the sp_data struct static
1381 * (it defines a pipeline) and that the dynamic (per frame) data is stored
1384 * This function must be called first every where were you start constructing
1385 * a new pipeline by defining one or more stages with use of variable
1386 * sh_css_sp_stage. Even the special cases like accelerator and copy_frame
1387 * These have a pipeline of just 1 stage.
1390 sh_css_init_host2sp_frame_data(void)
1393 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1395 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1397 * rvanimme: don't clean it to save static frame info line ref_in
1398 * ref_out, and tnr_frames. Once this static data is in a
1399 * separate data struct, this may be enable (but still, there is
1405 * @brief Update the offline frame information in host_sp_communication.
1406 * Refer to "sh_css_sp.h" for more details.
1409 sh_css_update_host2sp_offline_frame(
1410 unsigned int frame_num,
1411 struct ia_css_frame *frame,
1412 struct ia_css_metadata *metadata)
1414 unsigned int HIVE_ADDR_host_sp_com;
1415 unsigned int offset;
1417 assert(frame_num < NUM_CONTINUOUS_FRAMES);
1419 /* Write new frame data into SP DMEM */
1420 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1421 offset = (unsigned int)offsetof(struct host_sp_communication,
1422 host2sp_offline_frames)
1424 offset += frame_num;
1425 store_sp_array_uint(host_sp_com, offset, frame ? frame->data : 0);
1427 /* Write metadata buffer into SP DMEM */
1428 offset = (unsigned int)offsetof(struct host_sp_communication,
1429 host2sp_offline_metadata)
1431 offset += frame_num;
1432 store_sp_array_uint(host_sp_com, offset, metadata ? metadata->address : 0);
1436 * @brief Update the mipi frame information in host_sp_communication.
1437 * Refer to "sh_css_sp.h" for more details.
1440 sh_css_update_host2sp_mipi_frame(
1441 unsigned int frame_num,
1442 struct ia_css_frame *frame)
1444 unsigned int HIVE_ADDR_host_sp_com;
1445 unsigned int offset;
1447 /* MIPI buffers are dedicated to port, so now there are more of them. */
1448 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1450 /* Write new frame data into SP DMEM */
1451 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1452 offset = (unsigned int)offsetof(struct host_sp_communication,
1453 host2sp_mipi_frames)
1455 offset += frame_num;
1457 store_sp_array_uint(host_sp_com, offset,
1458 frame ? frame->data : 0);
1462 * @brief Update the mipi metadata information in host_sp_communication.
1463 * Refer to "sh_css_sp.h" for more details.
1466 sh_css_update_host2sp_mipi_metadata(
1467 unsigned int frame_num,
1468 struct ia_css_metadata *metadata)
1470 unsigned int HIVE_ADDR_host_sp_com;
1473 /* MIPI buffers are dedicated to port, so now there are more of them. */
1474 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM));
1476 /* Write new frame data into SP DMEM */
1477 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1478 o = offsetof(struct host_sp_communication, host2sp_mipi_metadata)
1481 store_sp_array_uint(host_sp_com, o,
1482 metadata ? metadata->address : 0);
1486 sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames)
1488 unsigned int HIVE_ADDR_host_sp_com;
1489 unsigned int offset;
1491 /* Write new frame data into SP DMEM */
1492 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1493 offset = (unsigned int)offsetof(struct host_sp_communication,
1494 host2sp_num_mipi_frames)
1497 store_sp_array_uint(host_sp_com, offset, num_frames);
1501 sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames,
1504 const struct ia_css_fw_info *fw;
1505 unsigned int HIVE_ADDR_host_sp_com;
1506 unsigned int extra_num_frames, avail_num_frames;
1507 unsigned int offset, offset_extra;
1509 /* Write new frame data into SP DMEM */
1511 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
1513 offset = (unsigned int)offsetof(struct host_sp_communication,
1514 host2sp_cont_avail_num_raw_frames)
1516 avail_num_frames = load_sp_array_uint(host_sp_com, offset);
1517 extra_num_frames = num_frames - avail_num_frames;
1518 offset_extra = (unsigned int)offsetof(struct host_sp_communication,
1519 host2sp_cont_extra_num_raw_frames)
1521 store_sp_array_uint(host_sp_com, offset_extra, extra_num_frames);
1523 offset = (unsigned int)offsetof(struct host_sp_communication,
1524 host2sp_cont_target_num_raw_frames)
1527 store_sp_array_uint(host_sp_com, offset, num_frames);
1531 sh_css_event_init_irq_mask(void)
1534 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1535 unsigned int offset;
1536 struct sh_css_event_irq_mask event_irq_mask_init;
1538 event_irq_mask_init.or_mask = IA_CSS_EVENT_TYPE_ALL;
1539 event_irq_mask_init.and_mask = IA_CSS_EVENT_TYPE_NONE;
1540 (void)HIVE_ADDR_host_sp_com; /* Suppress warnings in CRUN */
1542 assert(sizeof(event_irq_mask_init) % HRT_BUS_BYTES == 0);
1543 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
1544 offset = (unsigned int)offsetof(struct host_sp_communication,
1545 host2sp_event_irq_mask[i]);
1546 assert(offset % HRT_BUS_BYTES == 0);
1547 sp_dmem_store(SP0_ID,
1548 (unsigned int)sp_address_of(host_sp_com) + offset,
1549 &event_irq_mask_init, sizeof(event_irq_mask_init));
1554 ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe,
1555 unsigned int or_mask,
1556 unsigned int and_mask)
1558 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1559 unsigned int offset;
1560 struct sh_css_event_irq_mask event_irq_mask;
1561 unsigned int pipe_num;
1565 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1566 /* Linux kernel does not have UINT16_MAX
1567 * Therefore decided to comment out these 2 asserts for Linux
1568 * Alternatives that were not chosen:
1569 * - add a conditional #define for UINT16_MAX
1570 * - compare with (uint16_t)~0 or 0xffff
1571 * - different assert for Linux and Windows
1574 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1576 IA_CSS_LOG("or_mask=%x, and_mask=%x", or_mask, and_mask);
1577 event_irq_mask.or_mask = (uint16_t)or_mask;
1578 event_irq_mask.and_mask = (uint16_t)and_mask;
1580 pipe_num = ia_css_pipe_get_pipe_num(pipe);
1581 if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1583 offset = (unsigned int)offsetof(struct host_sp_communication,
1584 host2sp_event_irq_mask[pipe_num]);
1585 assert(offset % HRT_BUS_BYTES == 0);
1586 sp_dmem_store(SP0_ID,
1587 (unsigned int)sp_address_of(host_sp_com) + offset,
1588 &event_irq_mask, sizeof(event_irq_mask));
1594 ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe,
1595 unsigned int *or_mask,
1596 unsigned int *and_mask)
1598 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com;
1599 unsigned int offset;
1600 struct sh_css_event_irq_mask event_irq_mask;
1601 unsigned int pipe_num;
1603 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */
1605 IA_CSS_ENTER_LEAVE("");
1608 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES);
1610 pipe_num = ia_css_pipe_get_pipe_num(pipe);
1611 if (pipe_num >= IA_CSS_PIPE_ID_NUM)
1613 offset = (unsigned int)offsetof(struct host_sp_communication,
1614 host2sp_event_irq_mask[pipe_num]);
1615 assert(offset % HRT_BUS_BYTES == 0);
1616 sp_dmem_load(SP0_ID,
1617 (unsigned int)sp_address_of(host_sp_com) + offset,
1618 &event_irq_mask, sizeof(event_irq_mask));
1621 *or_mask = event_irq_mask.or_mask;
1624 *and_mask = event_irq_mask.and_mask;
1630 sh_css_sp_set_sp_running(bool flag)
1636 sh_css_sp_is_running(void)
1642 sh_css_sp_start_isp(void)
1644 const struct ia_css_fw_info *fw;
1645 unsigned int HIVE_ADDR_sp_sw_state;
1648 HIVE_ADDR_sp_sw_state = fw->info.sp.sw_state;
1653 (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */
1655 /* no longer here, sp started immediately */
1656 /*ia_css_debug_pipe_graph_dump_epilogue();*/
1658 store_sp_group_data();
1659 store_sp_per_frame_data(fw);
1661 sp_dmem_store_uint32(SP0_ID,
1662 (unsigned int)sp_address_of(sp_sw_state),
1663 (uint32_t)(IA_CSS_SP_SW_TERMINATED));
1665 /* Note 1: The sp_start_isp function contains a wait till
1666 * the input network is configured by the SP.
1667 * Note 2: Not all SP binaries supports host2sp_commands.
1668 * In case a binary does support it, the host2sp_command
1669 * will have status cmd_ready after return of the function
1670 * sh_css_hrt_sp_start_isp. There is no race-condition here
1671 * because only after the process_frame command has been
1672 * received, the SP starts configuring the input network.
1675 /* we need to set sp_running before we call ia_css_mmu_invalidate_cache
1676 * as ia_css_mmu_invalidate_cache checks on sp_running to
1677 * avoid that it accesses dmem while the SP is not powered
1680 ia_css_mmu_invalidate_cache();
1681 /* Invalidate all MMU caches */
1682 mmu_invalidate_cache_all();
1684 ia_css_spctrl_start(SP0_ID);
1688 ia_css_isp_has_started(void)
1690 const struct ia_css_fw_info *fw = &sh_css_sp_fw;
1691 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
1692 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
1694 return (bool)load_sp_uint(ia_css_ispctrl_sp_isp_started);
1698 * @brief Initialize the DMA software-mask in the debug mode.
1699 * Refer to "sh_css_sp.h" for more details.
1702 sh_css_sp_init_dma_sw_reg(int dma_id)
1706 /* enable all the DMA channels */
1707 for (i = 0; i < N_DMA_CHANNEL_ID; i++) {
1708 /* enable the writing request */
1709 sh_css_sp_set_dma_sw_reg(dma_id,
1713 /* enable the reading request */
1714 sh_css_sp_set_dma_sw_reg(dma_id,
1724 * @brief Set the DMA software-mask in the debug mode.
1725 * Refer to "sh_css_sp.h" for more details.
1728 sh_css_sp_set_dma_sw_reg(int dma_id,
1740 assert(channel_id >= 0 && channel_id < N_DMA_CHANNEL_ID);
1741 assert(request_type >= 0);
1743 /* get the software-mask */
1745 sh_css_sp_group.debug.dma_sw_reg;
1747 /* get the offest of the target bit */
1748 bit_offset = (8 * request_type) + channel_id;
1750 /* clear the value of the target bit */
1751 bit_mask = ~(1 << bit_offset);
1754 /* set the value of the bit for the DMA channel */
1755 bit_val = enable ? 1 : 0;
1756 bit_val <<= bit_offset;
1759 /* update the software status of DMA channels */
1760 sh_css_sp_group.debug.dma_sw_reg = sw_reg;
1766 sh_css_sp_reset_global_vars(void)
1768 memset(&sh_css_sp_group, 0, sizeof(struct sh_css_sp_group));
1769 memset(&sh_css_sp_stage, 0, sizeof(struct sh_css_sp_stage));
1770 memset(&sh_css_isp_stage, 0, sizeof(struct sh_css_isp_stage));
1771 memset(&sh_css_sp_output, 0, sizeof(struct sh_css_sp_output));
1772 memset(&per_frame_data, 0, sizeof(struct sh_css_sp_per_frame_data));