1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Support for Intel Camera Imaging ISP subsystem. 4 * Copyright (c) 2015, Intel Corporation. 5 * 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. 9 * 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 13 * more details. 14 */ 15 16 #include "hmm.h" 17 18 #include "sh_css_sp.h" 19 20 #if !defined(HAS_NO_INPUT_FORMATTER) 21 #include "input_formatter.h" 22 #endif 23 24 #include "dma.h" /* N_DMA_CHANNEL_ID */ 25 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 #if !defined(HAS_NO_INPUT_SYSTEM) 42 #include "ia_css_isys.h" 43 #endif 44 45 #include "gdc_device.h" /* HRT_GDC_N */ 46 47 /*#include "sp.h"*/ /* host2sp_enqueue_frame_data() */ 48 49 50 #include "assert_support.h" 51 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" 56 57 #ifndef offsetof 58 #define offsetof(T, x) ((unsigned int)&(((T *)0)->x)) 59 #endif 60 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" 65 66 #include "isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h" 67 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; 73 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; 78 79 static int 80 set_output_frame_buffer(const struct ia_css_frame *frame, 81 unsigned int idx); 82 83 static void 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); 88 89 static void 90 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr); 91 92 static void 93 initialize_stage_frames(struct ia_css_frames_sp *frames); 94 95 /* This data is stored every frame */ 96 void 97 store_sp_group_data(void) 98 { 99 per_frame_data.sp_group_addr = sh_css_store_sp_group_to_ddr(); 100 } 101 102 static void 103 copy_isp_stage_to_sp_stage(void) 104 { 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; 118 */ 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; 121 } 122 123 void 124 store_sp_stage_data(enum ia_css_pipe_id id, unsigned int pipe_num, 125 unsigned int stage) 126 { 127 unsigned int thread_id; 128 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); 136 137 /* Clear for next frame */ 138 sh_css_sp_stage.program_input_circuit = false; 139 } 140 141 static void 142 store_sp_per_frame_data(const struct ia_css_fw_info *fw) 143 { 144 unsigned int HIVE_ADDR_sp_per_frame_data = 0; 145 146 assert(fw); 147 148 switch (fw->type) { 149 case ia_css_sp_firmware: 150 HIVE_ADDR_sp_per_frame_data = fw->info.sp.per_frame_data; 151 break; 152 case ia_css_acc_firmware: 153 HIVE_ADDR_sp_per_frame_data = fw->info.acc.per_frame_data; 154 break; 155 case ia_css_isp_firmware: 156 return; 157 } 158 159 sp_dmem_store(SP0_ID, 160 (unsigned int)sp_address_of(sp_per_frame_data), 161 &per_frame_data, 162 sizeof(per_frame_data)); 163 } 164 165 static void 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) 169 { 170 if (!sp_fw) 171 sp_fw = &sh_css_sp_fw; 172 173 store_sp_stage_data(pipe_id, pipe_num, 0); 174 store_sp_group_data(); 175 store_sp_per_frame_data(sp_fw); 176 } 177 178 #if SP_DEBUG != SP_DEBUG_NONE 179 180 void 181 sh_css_sp_get_debug_state(struct sh_css_sp_debug_state *state) 182 { 183 const struct ia_css_fw_info *fw = &sh_css_sp_fw; 184 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output; 185 unsigned int i; 186 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output, 187 debug) / sizeof(int); 188 189 assert(state); 190 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); 194 } 195 196 #endif 197 198 void 199 sh_css_sp_start_binary_copy(unsigned int pipe_num, 200 struct ia_css_frame *out_frame, 201 unsigned int two_ppc) 202 { 203 enum ia_css_pipe_id pipe_id; 204 unsigned int thread_id; 205 struct sh_css_sp_pipeline *pipe; 206 u8 stage_num = 0; 207 208 assert(out_frame); 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]; 212 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; 220 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); 228 } 229 IA_CSS_LOG("pipe_id %d port_config %08x", 230 pipe->pipe_id, pipe->inout_port_config); 231 232 #if !defined(HAS_NO_INPUT_FORMATTER) 233 sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc; 234 #else 235 (void)two_ppc; 236 #endif 237 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; 242 243 set_output_frame_buffer(out_frame, 0); 244 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); 248 } 249 250 static void 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) 257 { 258 enum ia_css_pipe_id pipe_id; 259 unsigned int thread_id; 260 u8 stage_num = 0; 261 struct sh_css_sp_pipeline *pipe; 262 263 assert(out_frame); 264 265 { 266 /* 267 * Clear sh_css_sp_stage for easy debugging. 268 * program_input_circuit must be saved as it is set outside 269 * this function. 270 */ 271 u8 program_input_circuit; 272 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; 276 } 277 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]; 281 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) 292 pipe->pipe_config = 293 (SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id); 294 else 295 pipe->pipe_config = pipe_conf_override; 296 297 pipe->pipe_qos_config = QOS_INVALID; 298 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); 306 } 307 IA_CSS_LOG("pipe_id %d port_config %08x", 308 pipe->pipe_id, pipe->inout_port_config); 309 310 #if !defined(HAS_NO_INPUT_FORMATTER) 311 sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc; 312 #else 313 (void)two_ppc; 314 #endif 315 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); 322 323 ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame); 324 } 325 326 static void 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) 330 { 331 enum ia_css_pipe_id pipe_id; 332 unsigned int thread_id; 333 u8 stage_num = 0; 334 struct sh_css_sp_pipeline *pipe; 335 #if defined SH_CSS_ENABLE_METADATA 336 enum sh_css_queue_id queue_id; 337 #endif 338 339 assert(out_frame); 340 341 { 342 /* 343 * Clear sh_css_sp_stage for easy debugging. 344 * program_input_circuit must be saved as it is set outside 345 * this function. 346 */ 347 u8 program_input_circuit; 348 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; 352 } 353 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]; 357 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; 367 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; 374 375 set_output_frame_buffer(out_frame, 0); 376 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, 380 &queue_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); 384 } 385 #endif 386 387 ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame); 388 } 389 390 unsigned int 391 sh_css_sp_get_binary_copy_size(void) 392 { 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); 399 } 400 401 unsigned int 402 sh_css_sp_get_sw_interrupt_value(unsigned int irq) 403 { 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, 407 sw_interrupt_value) 408 / sizeof(int); 409 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */ 410 return load_sp_array_uint(sp_output, offset + irq); 411 } 412 413 static void 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) 418 { 419 assert(buf_type < IA_CSS_NUM_BUFFER_TYPE); 420 if (queue_id > SH_CSS_INVALID_QUEUE_ID) { 421 /* 422 * value >=0 indicates that function init_frame_pointers() 423 * should use the dynamic data address 424 */ 425 assert(queue_id < SH_CSS_MAX_NUM_QUEUES); 426 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. 435 */ 436 if ((queue_id < SH_CSS_MAX_NUM_QUEUES)) { 437 dest_buf->buf_src.queue_id = queue_id; 438 } 439 } else { 440 assert(xmem_addr != mmgr_EXCEPTION); 441 dest_buf->buf_src.xmem_addr = xmem_addr; 442 } 443 dest_buf->buf_type = buf_type; 444 } 445 446 static void 447 sh_css_copy_frame_to_spframe(struct ia_css_frame_sp *sp_frame_out, 448 const struct ia_css_frame *frame_in) 449 { 450 assert(frame_in); 451 452 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 453 "sh_css_copy_frame_to_spframe():\n"); 454 455 sh_css_copy_buffer_attr_to_spbuffer(&sp_frame_out->buf_attr, 456 frame_in->dynamic_queue_id, 457 frame_in->data, 458 frame_in->buf_type); 459 460 ia_css_frame_info_to_frame_sp_info(&sp_frame_out->info, &frame_in->info); 461 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; 466 break; 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; 470 break; 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; 478 break; 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; 485 break; 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; 497 break; 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; 511 break; 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; 525 break; 526 case IA_CSS_FRAME_FORMAT_BINARY_8: 527 sp_frame_out->planes.binary.data.offset = 528 frame_in->planes.binary.data.offset; 529 break; 530 default: 531 /* This should not happen, but in case it does, 532 * nullify the planes 533 */ 534 memset(&sp_frame_out->planes, 0, sizeof(sp_frame_out->planes)); 535 break; 536 } 537 } 538 539 static int 540 set_input_frame_buffer(const struct ia_css_frame *frame) { 541 if (!frame) 542 return -EINVAL; 543 544 switch (frame->info.format) 545 { 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: 560 break; 561 default: 562 return -EINVAL; 563 } 564 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.in, frame); 565 566 return 0; 567 } 568 569 static int 570 set_output_frame_buffer(const struct ia_css_frame *frame, 571 unsigned int idx) { 572 if (!frame) 573 return -EINVAL; 574 575 switch (frame->info.format) 576 { 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: 603 break; 604 default: 605 return -EINVAL; 606 } 607 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out[idx], frame); 608 return 0; 609 } 610 611 static int 612 set_view_finder_buffer(const struct ia_css_frame *frame) { 613 if (!frame) 614 return -EINVAL; 615 616 switch (frame->info.format) 617 { 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: 629 630 /* for vf_veceven */ 631 case IA_CSS_FRAME_FORMAT_YUV_LINE: 632 break; 633 default: 634 return -EINVAL; 635 } 636 637 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out_vf, frame); 638 return 0; 639 } 640 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 646 ) 647 { 648 assert(if_config_index < SH_CSS_MAX_IF_CONFIGS); 649 assert(config_a); 650 651 sh_css_sp_group.config.input_formatter.set[if_config_index].config_a = 652 *config_a; 653 sh_css_sp_group.config.input_formatter.a_changed = true; 654 655 if (config_b) { 656 sh_css_sp_group.config.input_formatter.set[if_config_index].config_b = 657 *config_b; 658 sh_css_sp_group.config.input_formatter.b_changed = true; 659 } 660 661 return; 662 } 663 #endif 664 665 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) 666 void 667 sh_css_sp_program_input_circuit(int fmt_type, 668 int ch_id, 669 enum ia_css_input_mode input_mode) 670 { 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; 675 /* 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 678 */ 679 sh_css_sp_group.config.input_circuit_cfg_changed = true; 680 sh_css_sp_stage.program_input_circuit = true; 681 } 682 #endif 683 684 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2) 685 void 686 sh_css_sp_configure_sync_gen(int width, int height, 687 int hblank_cycles, 688 int vblank_cycles) 689 { 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; 694 } 695 696 void 697 sh_css_sp_configure_tpg(int x_mask, 698 int y_mask, 699 int x_delta, 700 int y_delta, 701 int xy_mask) 702 { 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; 708 } 709 710 void 711 sh_css_sp_configure_prbs(int seed) 712 { 713 sh_css_sp_group.config.prbs.seed = seed; 714 } 715 #endif 716 717 void 718 sh_css_sp_configure_enable_raw_pool_locking(bool lock_all) 719 { 720 sh_css_sp_group.config.enable_raw_pool_locking = true; 721 sh_css_sp_group.config.lock_all = lock_all; 722 } 723 724 void 725 sh_css_sp_enable_isys_event_queue(bool enable) 726 { 727 #if !defined(HAS_NO_INPUT_SYSTEM) 728 sh_css_sp_group.config.enable_isys_event_queue = enable; 729 #else 730 (void)enable; 731 #endif 732 } 733 734 void 735 sh_css_sp_set_disable_continuous_viewfinder(bool flag) 736 { 737 sh_css_sp_group.config.disable_cont_vf = flag; 738 } 739 740 static int 741 sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args) { 742 int err = 0; 743 int i; 744 745 assert(args); 746 747 if (args->in_frame) 748 err = set_input_frame_buffer(args->in_frame); 749 if (!err && 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++) 752 { 753 if (!err && args->out_frame[i]) 754 err = set_output_frame_buffer(args->out_frame[i], i); 755 } 756 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) assert(false); 760 return err; 761 } 762 763 static void 764 sh_css_sp_init_group(bool two_ppc, 765 enum atomisp_input_format input_format, 766 bool no_isp_sync, 767 uint8_t if_config_index) 768 { 769 #if !defined(HAS_NO_INPUT_FORMATTER) 770 sh_css_sp_group.config.input_formatter.isp_2ppc = two_ppc; 771 #else 772 (void)two_ppc; 773 #endif 774 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 = 781 input_format; 782 #else 783 (void)input_format; 784 #endif 785 } 786 787 void 788 sh_css_stage_write_binary_info(struct ia_css_binary_info *info) 789 { 790 assert(info); 791 sh_css_isp_stage.binary_info = *info; 792 } 793 794 static int 795 copy_isp_mem_if_to_ddr(struct ia_css_binary *binary) { 796 int err; 797 798 err = ia_css_isp_param_copy_isp_mem_if_to_ddr( 799 &binary->css_params, 800 &binary->mem_params, 801 IA_CSS_PARAM_CLASS_CONFIG); 802 if (err) 803 return err; 804 err = ia_css_isp_param_copy_isp_mem_if_to_ddr( 805 &binary->css_params, 806 &binary->mem_params, 807 IA_CSS_PARAM_CLASS_STATE); 808 if (err) 809 return err; 810 return 0; 811 } 812 813 static bool 814 is_sp_stage(struct ia_css_pipeline_stage *stage) 815 { 816 assert(stage); 817 return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC; 818 } 819 820 static int 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, 825 bool two_ppc, 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); 834 #ifdef ISP2401 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); 837 #endif 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); 842 843 /* 844 * FIXME: args->delay_frames can be NULL here 845 * 846 * Somehow, the driver at the Intel Atom Yocto tree doesn't seem to 847 * suffer from the same issue. 848 * 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) 852 */ 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 0; 857 } 858 859 static void 860 initialize_isp_states(const struct ia_css_binary *binary) 861 { 862 unsigned int i; 863 864 if (!binary->info->mem_offsets.offsets.state) 865 return; 866 for (i = 0; i < IA_CSS_NUM_STATE_IDS; i++) { 867 ia_css_kernel_init_state[i](binary); 868 } 869 } 870 871 static void 872 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr) 873 { 874 buf_attr->buf_src.queue_id = SH_CSS_INVALID_QUEUE_ID; 875 buf_attr->buf_type = IA_CSS_BUFFER_TYPE_INVALID; 876 } 877 878 static void 879 initialize_stage_frames(struct ia_css_frames_sp *frames) 880 { 881 unsigned int i; 882 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); 886 } 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); 892 #endif 893 } 894 895 static int 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, 901 unsigned int stage, 902 bool xnr, 903 const struct ia_css_isp_param_css_segments *isp_mem_if, 904 unsigned int if_config_index, 905 bool two_ppc) { 906 const struct ia_css_binary_xinfo *xinfo; 907 const struct ia_css_binary_info *info; 908 int err = 0; 909 int i; 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); 914 915 assert(binary); 916 assert(blob_info); 917 assert(args); 918 assert(isp_mem_if); 919 920 xinfo = binary->info; 921 info = &xinfo->sp; 922 { 923 /* 924 * Clear sh_css_sp_stage for easy debugging. 925 * program_input_circuit must be saved as it is set outside 926 * this function. 927 */ 928 u8 program_input_circuit; 929 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; 933 } 934 935 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 936 937 if (!info) 938 { 939 sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL; 940 return 0; 941 } 942 943 #if defined(USE_INPUT_SYSTEM_VERSION_2401) 944 (void)continuous; 945 sh_css_sp_stage.deinterleaved = 0; 946 #else 947 sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous); 948 #endif 949 950 initialize_stage_frames(&sh_css_sp_stage.frames); 951 /* 952 * TODO: Make the Host dynamically determine 953 * the stage type. 954 */ 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); 961 962 /* Copy the frame infos first, to be overwritten by the frames, 963 if these are present. 964 */ 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; 967 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++) 971 { 972 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.out[i].info, 973 &binary->out_frame_info[i]); 974 } 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; 982 983 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index; 984 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); 990 991 /* Make sure binary name is smaller than allowed string size */ 992 assert(strlen(binary_name) < SH_CSS_MAX_BINARY_NAME - 1); 993 strscpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME); 994 sh_css_isp_stage.mem_initializers = *isp_mem_if; 995 996 /* 997 * Even when a stage does not need uds and does not params, 998 * ia_css_uds_sp_scale_params() seems to be called (needs 999 * further investigation). This function can not deal with 1000 * dx, dy = {0, 0} 1001 */ 1002 1003 err = sh_css_sp_write_frame_pointers(args); 1004 /* TODO: move it to a better place */ 1005 if (binary->info->sp.enable.s3a) 1006 { 1007 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_3A_STATISTICS, thread_id, 1008 &queue_id); 1009 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.s3a_buf, queue_id, 1010 mmgr_EXCEPTION, 1011 IA_CSS_BUFFER_TYPE_3A_STATISTICS); 1012 } 1013 if (binary->info->sp.enable.dis) 1014 { 1015 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id, 1016 &queue_id); 1017 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id, 1018 mmgr_EXCEPTION, 1019 IA_CSS_BUFFER_TYPE_DIS_STATISTICS); 1020 } 1021 #if defined SH_CSS_ENABLE_METADATA 1022 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id); 1023 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA); 1024 #endif 1025 if (err) 1026 return err; 1027 1028 #ifdef USE_INPUT_SYSTEM_VERSION_2401 1029 if (stage == 0) { 1030 pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num); 1031 if (!pipe) 1032 return -EINVAL; 1033 1034 if (args->in_frame) 1035 ia_css_get_crop_offsets(pipe, &args->in_frame->info); 1036 else 1037 ia_css_get_crop_offsets(pipe, &binary->in_frame_info); 1038 } 1039 #else 1040 (void)pipe; /*avoid build warning*/ 1041 #endif 1042 1043 err = configure_isp_from_args(&sh_css_sp_group.pipe[thread_id], 1044 binary, args, two_ppc, sh_css_sp_stage.deinterleaved); 1045 if (err) 1046 return err; 1047 1048 initialize_isp_states(binary); 1049 1050 /* we do this only for preview pipe because in fill_binary_info function 1051 * we assign vf_out res to out res, but for ISP internal processing, we need 1052 * the original out res. for video pipe, it has two output pins --- out and 1053 * vf_out, so it can keep these two resolutions already. */ 1054 if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW && 1055 (binary->vf_downscale_log2 > 0)) 1056 { 1057 /* TODO: Remove this after preview output decimation is fixed 1058 * by configuring out&vf info fiels properly */ 1059 sh_css_sp_stage.frames.out[0].info.padded_width 1060 <<= binary->vf_downscale_log2; 1061 sh_css_sp_stage.frames.out[0].info.res.width 1062 <<= binary->vf_downscale_log2; 1063 sh_css_sp_stage.frames.out[0].info.res.height 1064 <<= binary->vf_downscale_log2; 1065 } 1066 err = copy_isp_mem_if_to_ddr(binary); 1067 if (err) 1068 return err; 1069 1070 return 0; 1071 } 1072 1073 static int 1074 sp_init_stage(struct ia_css_pipeline_stage *stage, 1075 unsigned int pipe_num, 1076 bool xnr, 1077 unsigned int if_config_index, 1078 bool two_ppc) { 1079 struct ia_css_binary *binary; 1080 const struct ia_css_fw_info *firmware; 1081 const struct sh_css_binary_args *args; 1082 unsigned int stage_num; 1083 /* 1084 * Initialiser required because of the "else" path below. 1085 * Is this a valid path ? 1086 */ 1087 const char *binary_name = ""; 1088 const struct ia_css_binary_xinfo *info = NULL; 1089 /* note: the var below is made static as it is quite large; 1090 if it is not static it ends up on the stack which could 1091 cause issues for drivers 1092 */ 1093 static struct ia_css_binary tmp_binary; 1094 const struct ia_css_blob_info *blob_info = NULL; 1095 struct ia_css_isp_param_css_segments isp_mem_if; 1096 /* LA: should be ia_css_data, should not contain host pointer. 1097 However, CSS/DDR pointer is not available yet. 1098 Hack is to store it in params->ddr_ptrs and then copy it late in the SP just before vmem init. 1099 TODO: Call this after CSS/DDR allocation and store that pointer. 1100 Best is to allocate it at stage creation time together with host pointer. 1101 Remove vmem from params. 1102 */ 1103 struct ia_css_isp_param_css_segments *mem_if = &isp_mem_if; 1104 1105 int err = 0; 1106 1107 assert(stage); 1108 1109 binary = stage->binary; 1110 firmware = stage->firmware; 1111 args = &stage->args; 1112 stage_num = stage->stage_num; 1113 1114 if (binary) 1115 { 1116 info = binary->info; 1117 binary_name = (const char *)(info->blob->name); 1118 blob_info = &info->blob->header.blob; 1119 ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params); 1120 } else if (firmware) 1121 { 1122 const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL}; 1123 1124 if (args->out_frame[0]) 1125 out_infos[0] = &args->out_frame[0]->info; 1126 info = &firmware->info.isp; 1127 ia_css_binary_fill_info(info, false, false, 1128 ATOMISP_INPUT_FORMAT_RAW_10, 1129 args->in_frame ? &args->in_frame->info : NULL, 1130 NULL, 1131 out_infos, 1132 args->out_vf_frame ? &args->out_vf_frame->info 1133 : NULL, 1134 &tmp_binary, 1135 NULL, 1136 -1, true); 1137 binary = &tmp_binary; 1138 binary->info = info; 1139 binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware); 1140 blob_info = &firmware->blob; 1141 mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers; 1142 } else 1143 { 1144 /* SP stage */ 1145 assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC); 1146 /* binary and blob_info are now NULL. 1147 These will be passed to sh_css_sp_init_stage 1148 and dereferenced there, so passing a NULL 1149 pointer is no good. return an error */ 1150 return -EINVAL; 1151 } 1152 1153 err = sh_css_sp_init_stage(binary, 1154 (const char *)binary_name, 1155 blob_info, 1156 args, 1157 pipe_num, 1158 stage_num, 1159 xnr, 1160 mem_if, 1161 if_config_index, 1162 two_ppc); 1163 return err; 1164 } 1165 1166 static void 1167 sp_init_sp_stage(struct ia_css_pipeline_stage *stage, 1168 unsigned int pipe_num, 1169 bool two_ppc, 1170 enum sh_css_pipe_config_override copy_ovrd, 1171 unsigned int if_config_index) 1172 { 1173 const struct sh_css_binary_args *args = &stage->args; 1174 1175 assert(stage); 1176 switch (stage->sp_func) { 1177 case IA_CSS_PIPELINE_RAW_COPY: 1178 sh_css_sp_start_raw_copy(args->out_frame[0], 1179 pipe_num, two_ppc, 1180 stage->max_input_width, 1181 copy_ovrd, if_config_index); 1182 break; 1183 case IA_CSS_PIPELINE_BIN_COPY: 1184 assert(false); /* TBI */ 1185 break; 1186 case IA_CSS_PIPELINE_ISYS_COPY: 1187 sh_css_sp_start_isys_copy(args->out_frame[0], 1188 pipe_num, stage->max_input_width, if_config_index); 1189 break; 1190 case IA_CSS_PIPELINE_NO_FUNC: 1191 assert(false); 1192 break; 1193 } 1194 } 1195 1196 void 1197 sh_css_sp_init_pipeline(struct ia_css_pipeline *me, 1198 enum ia_css_pipe_id id, 1199 u8 pipe_num, 1200 bool xnr, 1201 bool two_ppc, 1202 bool continuous, 1203 bool offline, 1204 unsigned int required_bds_factor, 1205 enum sh_css_pipe_config_override copy_ovrd, 1206 enum ia_css_input_mode input_mode, 1207 const struct ia_css_metadata_config *md_config, 1208 const struct ia_css_metadata_info *md_info, 1209 #if !defined(HAS_NO_INPUT_SYSTEM) 1210 const enum mipi_port_id port_id, 1211 #endif 1212 const struct ia_css_coordinate 1213 *internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame 1214 positioned on shading table at shading correction in ISP. */ 1215 const struct ia_css_isp_parameters *params 1216 ) { 1217 /* Get first stage */ 1218 struct ia_css_pipeline_stage *stage = NULL; 1219 struct ia_css_binary *first_binary = NULL; 1220 struct ia_css_pipe *pipe = NULL; 1221 unsigned int num; 1222 1223 enum ia_css_pipe_id pipe_id = id; 1224 unsigned int thread_id; 1225 u8 if_config_index, tmp_if_config_index; 1226 1227 assert(me); 1228 1229 #if !defined(HAS_NO_INPUT_SYSTEM) 1230 assert(me->stages); 1231 1232 first_binary = me->stages->binary; 1233 1234 if (input_mode == IA_CSS_INPUT_MODE_SENSOR || 1235 input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 1236 { 1237 assert(port_id < N_MIPI_PORT_ID); 1238 if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */ 1239 return; /* we should be able to return an error */ 1240 if_config_index = (uint8_t)(port_id - MIPI_PORT0_ID); 1241 } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY) 1242 { 1243 if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; 1244 } else 1245 { 1246 if_config_index = 0x0; 1247 } 1248 #else 1249 (void)input_mode; 1250 if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; 1251 #endif 1252 1253 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 1254 memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline)); 1255 1256 /* Count stages */ 1257 for (stage = me->stages, num = 0; stage; stage = stage->next, num++) 1258 { 1259 stage->stage_num = num; 1260 ia_css_debug_pipe_graph_dump_stage(stage, id); 1261 } 1262 me->num_stages = num; 1263 1264 if (first_binary) 1265 { 1266 /* Init pipeline data */ 1267 sh_css_sp_init_group(two_ppc, first_binary->input_format, 1268 offline, if_config_index); 1269 } /* if (first_binary != NULL) */ 1270 1271 #if defined(USE_INPUT_SYSTEM_VERSION_2401) || defined(USE_INPUT_SYSTEM_VERSION_2) 1272 /* Signal the host immediately after start for SP_ISYS_COPY only */ 1273 if ((me->num_stages == 1) && me->stages && 1274 (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY)) 1275 sh_css_sp_group.config.no_isp_sync = true; 1276 #endif 1277 1278 /* Init stage data */ 1279 sh_css_init_host2sp_frame_data(); 1280 1281 sh_css_sp_group.pipe[thread_id].num_stages = 0; 1282 sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id; 1283 sh_css_sp_group.pipe[thread_id].thread_id = thread_id; 1284 sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num; 1285 sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs; 1286 sh_css_sp_group.pipe[thread_id].pipe_qos_config = me->pipe_qos_config; 1287 sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor; 1288 #if !defined(HAS_NO_INPUT_SYSTEM) 1289 sh_css_sp_group.pipe[thread_id].input_system_mode 1290 = (uint32_t)input_mode; 1291 sh_css_sp_group.pipe[thread_id].port_id = port_id; 1292 #endif 1293 sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay; 1294 1295 /* TODO: next indicates from which queues parameters need to be 1296 sampled, needs checking/improvement */ 1297 if (ia_css_pipeline_uses_params(me)) 1298 { 1299 sh_css_sp_group.pipe[thread_id].pipe_config = 1300 SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id; 1301 } 1302 1303 /* For continuous use-cases, SP copy is responsible for sampling the 1304 * parameters */ 1305 if (continuous) 1306 sh_css_sp_group.pipe[thread_id].pipe_config = 0; 1307 1308 sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config; 1309 1310 pipe = find_pipe_by_num(pipe_num); 1311 assert(pipe); 1312 if (!pipe) 1313 { 1314 return; 1315 } 1316 sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe); 1317 1318 #if defined(SH_CSS_ENABLE_METADATA) 1319 if (md_info && md_info->size > 0) 1320 { 1321 sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width; 1322 sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height; 1323 sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride; 1324 sh_css_sp_group.pipe[thread_id].metadata.size = md_info->size; 1325 ia_css_isys_convert_stream_format_to_mipi_format( 1326 md_config->data_type, MIPI_PREDICTOR_NONE, 1327 &sh_css_sp_group.pipe[thread_id].metadata.format); 1328 } 1329 #else 1330 (void)md_config; 1331 (void)md_info; 1332 #endif 1333 1334 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) 1335 sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID; 1336 if (pipe_id != IA_CSS_PIPE_ID_COPY) 1337 { 1338 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, 1339 (enum sh_css_queue_id *)( 1340 &sh_css_sp_group.pipe[thread_id].output_frame_queue_id)); 1341 } 1342 #endif 1343 1344 if (IS_ISP2401) { 1345 /* For the shading correction type 1 (the legacy shading table conversion in css is not used), 1346 * the parameters are passed to the isp for the shading table centering. 1347 */ 1348 if (internal_frame_origin_bqs_on_sctbl && 1349 params && params->shading_settings.enable_shading_table_conversion == 0) 1350 { 1351 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl 1352 = (uint32_t)internal_frame_origin_bqs_on_sctbl->x; 1353 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl 1354 = (uint32_t)internal_frame_origin_bqs_on_sctbl->y; 1355 } else 1356 { 1357 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl = 1358 0; 1359 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl = 1360 0; 1361 } 1362 } 1363 1364 IA_CSS_LOG("pipe_id %d port_config %08x", 1365 pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config); 1366 1367 for (stage = me->stages, num = 0; stage; stage = stage->next, num++) 1368 { 1369 sh_css_sp_group.pipe[thread_id].num_stages++; 1370 if (is_sp_stage(stage)) { 1371 sp_init_sp_stage(stage, pipe_num, two_ppc, 1372 copy_ovrd, if_config_index); 1373 } else { 1374 if ((stage->stage_num != 0) || 1375 SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config)) 1376 tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; 1377 else 1378 tmp_if_config_index = if_config_index; 1379 sp_init_stage(stage, pipe_num, 1380 xnr, tmp_if_config_index, two_ppc); 1381 } 1382 1383 store_sp_stage_data(pipe_id, pipe_num, num); 1384 } 1385 sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t) 1386 (me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS); 1387 store_sp_group_data(); 1388 } 1389 1390 void 1391 sh_css_sp_uninit_pipeline(unsigned int pipe_num) 1392 { 1393 unsigned int thread_id; 1394 1395 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 1396 /*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/ 1397 sh_css_sp_group.pipe[thread_id].num_stages = 0; 1398 } 1399 1400 bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command) 1401 { 1402 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1403 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, 1404 host2sp_command) 1405 / sizeof(int); 1406 enum host2sp_commands last_cmd = host2sp_cmd_error; 1407 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1408 1409 /* Previous command must be handled by SP (by design) */ 1410 last_cmd = load_sp_array_uint(host_sp_com, offset); 1411 if (last_cmd != host2sp_cmd_ready) 1412 IA_CSS_ERROR("last host command not handled by SP(%d)", last_cmd); 1413 1414 store_sp_array_uint(host_sp_com, offset, host2sp_command); 1415 1416 return (last_cmd == host2sp_cmd_ready); 1417 } 1418 1419 enum host2sp_commands 1420 sh_css_read_host2sp_command(void) { 1421 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1422 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command) 1423 / sizeof(int); 1424 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1425 return (enum host2sp_commands)load_sp_array_uint(host_sp_com, offset); 1426 } 1427 1428 /* 1429 * Frame data is no longer part of the sp_stage structure but part of a 1430 * separate structure. The aim is to make the sp_data struct static 1431 * (it defines a pipeline) and that the dynamic (per frame) data is stored 1432 * separetly. 1433 * 1434 * This function must be called first every where were you start constructing 1435 * a new pipeline by defining one or more stages with use of variable 1436 * sh_css_sp_stage. Even the special cases like accelerator and copy_frame 1437 * These have a pipeline of just 1 stage. 1438 */ 1439 void 1440 sh_css_init_host2sp_frame_data(void) 1441 { 1442 /* Clean table */ 1443 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1444 1445 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1446 /* 1447 * rvanimme: don't clean it to save static frame info line ref_in 1448 * ref_out, and tnr_frames. Once this static data is in a 1449 * separate data struct, this may be enable (but still, there is 1450 * no need for it) 1451 */ 1452 } 1453 1454 /* 1455 * @brief Update the offline frame information in host_sp_communication. 1456 * Refer to "sh_css_sp.h" for more details. 1457 */ 1458 void 1459 sh_css_update_host2sp_offline_frame( 1460 unsigned int frame_num, 1461 struct ia_css_frame *frame, 1462 struct ia_css_metadata *metadata) 1463 { 1464 unsigned int HIVE_ADDR_host_sp_com; 1465 unsigned int offset; 1466 1467 assert(frame_num < NUM_CONTINUOUS_FRAMES); 1468 1469 /* Write new frame data into SP DMEM */ 1470 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1471 offset = (unsigned int)offsetof(struct host_sp_communication, 1472 host2sp_offline_frames) 1473 / sizeof(int); 1474 offset += frame_num; 1475 store_sp_array_uint(host_sp_com, offset, frame ? frame->data : 0); 1476 1477 /* Write metadata buffer into SP DMEM */ 1478 offset = (unsigned int)offsetof(struct host_sp_communication, 1479 host2sp_offline_metadata) 1480 / sizeof(int); 1481 offset += frame_num; 1482 store_sp_array_uint(host_sp_com, offset, metadata ? metadata->address : 0); 1483 } 1484 1485 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 1486 /* 1487 * @brief Update the mipi frame information in host_sp_communication. 1488 * Refer to "sh_css_sp.h" for more details. 1489 */ 1490 void 1491 sh_css_update_host2sp_mipi_frame( 1492 unsigned int frame_num, 1493 struct ia_css_frame *frame) 1494 { 1495 unsigned int HIVE_ADDR_host_sp_com; 1496 unsigned int offset; 1497 1498 /* MIPI buffers are dedicated to port, so now there are more of them. */ 1499 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM)); 1500 1501 /* Write new frame data into SP DMEM */ 1502 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1503 offset = (unsigned int)offsetof(struct host_sp_communication, 1504 host2sp_mipi_frames) 1505 / sizeof(int); 1506 offset += frame_num; 1507 1508 store_sp_array_uint(host_sp_com, offset, 1509 frame ? frame->data : 0); 1510 } 1511 1512 /* 1513 * @brief Update the mipi metadata information in host_sp_communication. 1514 * Refer to "sh_css_sp.h" for more details. 1515 */ 1516 void 1517 sh_css_update_host2sp_mipi_metadata( 1518 unsigned int frame_num, 1519 struct ia_css_metadata *metadata) 1520 { 1521 unsigned int HIVE_ADDR_host_sp_com; 1522 unsigned int o; 1523 1524 /* MIPI buffers are dedicated to port, so now there are more of them. */ 1525 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM)); 1526 1527 /* Write new frame data into SP DMEM */ 1528 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1529 o = offsetof(struct host_sp_communication, host2sp_mipi_metadata) 1530 / sizeof(int); 1531 o += frame_num; 1532 store_sp_array_uint(host_sp_com, o, 1533 metadata ? metadata->address : 0); 1534 } 1535 1536 void 1537 sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames) 1538 { 1539 unsigned int HIVE_ADDR_host_sp_com; 1540 unsigned int offset; 1541 1542 /* Write new frame data into SP DMEM */ 1543 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1544 offset = (unsigned int)offsetof(struct host_sp_communication, 1545 host2sp_num_mipi_frames) 1546 / sizeof(int); 1547 1548 store_sp_array_uint(host_sp_com, offset, num_frames); 1549 } 1550 #endif 1551 1552 void 1553 sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames, 1554 bool set_avail) 1555 { 1556 const struct ia_css_fw_info *fw; 1557 unsigned int HIVE_ADDR_host_sp_com; 1558 unsigned int extra_num_frames, avail_num_frames; 1559 unsigned int offset, offset_extra; 1560 1561 /* Write new frame data into SP DMEM */ 1562 fw = &sh_css_sp_fw; 1563 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com; 1564 if (set_avail) { 1565 offset = (unsigned int)offsetof(struct host_sp_communication, 1566 host2sp_cont_avail_num_raw_frames) 1567 / sizeof(int); 1568 avail_num_frames = load_sp_array_uint(host_sp_com, offset); 1569 extra_num_frames = num_frames - avail_num_frames; 1570 offset_extra = (unsigned int)offsetof(struct host_sp_communication, 1571 host2sp_cont_extra_num_raw_frames) 1572 / sizeof(int); 1573 store_sp_array_uint(host_sp_com, offset_extra, extra_num_frames); 1574 } else 1575 offset = (unsigned int)offsetof(struct host_sp_communication, 1576 host2sp_cont_target_num_raw_frames) 1577 / sizeof(int); 1578 1579 store_sp_array_uint(host_sp_com, offset, num_frames); 1580 } 1581 1582 void 1583 sh_css_event_init_irq_mask(void) 1584 { 1585 int i; 1586 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1587 unsigned int offset; 1588 struct sh_css_event_irq_mask event_irq_mask_init; 1589 1590 event_irq_mask_init.or_mask = IA_CSS_EVENT_TYPE_ALL; 1591 event_irq_mask_init.and_mask = IA_CSS_EVENT_TYPE_NONE; 1592 (void)HIVE_ADDR_host_sp_com; /* Suppress warnings in CRUN */ 1593 1594 assert(sizeof(event_irq_mask_init) % HRT_BUS_BYTES == 0); 1595 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { 1596 offset = (unsigned int)offsetof(struct host_sp_communication, 1597 host2sp_event_irq_mask[i]); 1598 assert(offset % HRT_BUS_BYTES == 0); 1599 sp_dmem_store(SP0_ID, 1600 (unsigned int)sp_address_of(host_sp_com) + offset, 1601 &event_irq_mask_init, sizeof(event_irq_mask_init)); 1602 } 1603 } 1604 1605 int 1606 ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe, 1607 unsigned int or_mask, 1608 unsigned int and_mask) { 1609 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1610 unsigned int offset; 1611 struct sh_css_event_irq_mask event_irq_mask; 1612 unsigned int pipe_num; 1613 1614 assert(pipe); 1615 1616 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES); 1617 /* Linux kernel does not have UINT16_MAX 1618 * Therefore decided to comment out these 2 asserts for Linux 1619 * Alternatives that were not chosen: 1620 * - add a conditional #define for UINT16_MAX 1621 * - compare with (uint16_t)~0 or 0xffff 1622 * - different assert for Linux and Windows 1623 */ 1624 1625 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1626 1627 IA_CSS_LOG("or_mask=%x, and_mask=%x", or_mask, and_mask); 1628 event_irq_mask.or_mask = (uint16_t)or_mask; 1629 event_irq_mask.and_mask = (uint16_t)and_mask; 1630 1631 pipe_num = ia_css_pipe_get_pipe_num(pipe); 1632 if (pipe_num >= IA_CSS_PIPE_ID_NUM) 1633 return -EINVAL; 1634 offset = (unsigned int)offsetof(struct host_sp_communication, 1635 host2sp_event_irq_mask[pipe_num]); 1636 assert(offset % HRT_BUS_BYTES == 0); 1637 sp_dmem_store(SP0_ID, 1638 (unsigned int)sp_address_of(host_sp_com) + offset, 1639 &event_irq_mask, sizeof(event_irq_mask)); 1640 1641 return 0; 1642 } 1643 1644 int 1645 ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe, 1646 unsigned int *or_mask, 1647 unsigned int *and_mask) { 1648 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1649 unsigned int offset; 1650 struct sh_css_event_irq_mask event_irq_mask; 1651 unsigned int pipe_num; 1652 1653 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1654 1655 IA_CSS_ENTER_LEAVE(""); 1656 1657 assert(pipe); 1658 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES); 1659 1660 pipe_num = ia_css_pipe_get_pipe_num(pipe); 1661 if (pipe_num >= IA_CSS_PIPE_ID_NUM) 1662 return -EINVAL; 1663 offset = (unsigned int)offsetof(struct host_sp_communication, 1664 host2sp_event_irq_mask[pipe_num]); 1665 assert(offset % HRT_BUS_BYTES == 0); 1666 sp_dmem_load(SP0_ID, 1667 (unsigned int)sp_address_of(host_sp_com) + offset, 1668 &event_irq_mask, sizeof(event_irq_mask)); 1669 1670 if (or_mask) 1671 *or_mask = event_irq_mask.or_mask; 1672 1673 if (and_mask) 1674 *and_mask = event_irq_mask.and_mask; 1675 1676 return 0; 1677 } 1678 1679 void 1680 sh_css_sp_set_sp_running(bool flag) 1681 { 1682 sp_running = flag; 1683 } 1684 1685 bool 1686 sh_css_sp_is_running(void) 1687 { 1688 return sp_running; 1689 } 1690 1691 void 1692 sh_css_sp_start_isp(void) 1693 { 1694 const struct ia_css_fw_info *fw; 1695 unsigned int HIVE_ADDR_sp_sw_state; 1696 1697 fw = &sh_css_sp_fw; 1698 HIVE_ADDR_sp_sw_state = fw->info.sp.sw_state; 1699 1700 if (sp_running) 1701 return; 1702 1703 (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */ 1704 1705 /* no longer here, sp started immediately */ 1706 /*ia_css_debug_pipe_graph_dump_epilogue();*/ 1707 1708 store_sp_group_data(); 1709 store_sp_per_frame_data(fw); 1710 1711 sp_dmem_store_uint32(SP0_ID, 1712 (unsigned int)sp_address_of(sp_sw_state), 1713 (uint32_t)(IA_CSS_SP_SW_TERMINATED)); 1714 1715 /* Note 1: The sp_start_isp function contains a wait till 1716 * the input network is configured by the SP. 1717 * Note 2: Not all SP binaries supports host2sp_commands. 1718 * In case a binary does support it, the host2sp_command 1719 * will have status cmd_ready after return of the function 1720 * sh_css_hrt_sp_start_isp. There is no race-condition here 1721 * because only after the process_frame command has been 1722 * received, the SP starts configuring the input network. 1723 */ 1724 1725 /* we need to set sp_running before we call ia_css_mmu_invalidate_cache 1726 * as ia_css_mmu_invalidate_cache checks on sp_running to 1727 * avoid that it accesses dmem while the SP is not powered 1728 */ 1729 sp_running = true; 1730 ia_css_mmu_invalidate_cache(); 1731 /* Invalidate all MMU caches */ 1732 mmu_invalidate_cache_all(); 1733 1734 ia_css_spctrl_start(SP0_ID); 1735 } 1736 1737 bool 1738 ia_css_isp_has_started(void) 1739 { 1740 const struct ia_css_fw_info *fw = &sh_css_sp_fw; 1741 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started; 1742 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */ 1743 1744 return (bool)load_sp_uint(ia_css_ispctrl_sp_isp_started); 1745 } 1746 1747 /* 1748 * @brief Initialize the DMA software-mask in the debug mode. 1749 * Refer to "sh_css_sp.h" for more details. 1750 */ 1751 bool 1752 sh_css_sp_init_dma_sw_reg(int dma_id) 1753 { 1754 int i; 1755 1756 /* enable all the DMA channels */ 1757 for (i = 0; i < N_DMA_CHANNEL_ID; i++) { 1758 /* enable the writing request */ 1759 sh_css_sp_set_dma_sw_reg(dma_id, 1760 i, 1761 0, 1762 true); 1763 /* enable the reading request */ 1764 sh_css_sp_set_dma_sw_reg(dma_id, 1765 i, 1766 1, 1767 true); 1768 } 1769 1770 return true; 1771 } 1772 1773 /* 1774 * @brief Set the DMA software-mask in the debug mode. 1775 * Refer to "sh_css_sp.h" for more details. 1776 */ 1777 bool 1778 sh_css_sp_set_dma_sw_reg(int dma_id, 1779 int channel_id, 1780 int request_type, 1781 bool enable) 1782 { 1783 u32 sw_reg; 1784 u32 bit_val; 1785 u32 bit_offset; 1786 u32 bit_mask; 1787 1788 (void)dma_id; 1789 1790 assert(channel_id >= 0 && channel_id < N_DMA_CHANNEL_ID); 1791 assert(request_type >= 0); 1792 1793 /* get the software-mask */ 1794 sw_reg = 1795 sh_css_sp_group.debug.dma_sw_reg; 1796 1797 /* get the offest of the target bit */ 1798 bit_offset = (8 * request_type) + channel_id; 1799 1800 /* clear the value of the target bit */ 1801 bit_mask = ~(1 << bit_offset); 1802 sw_reg &= bit_mask; 1803 1804 /* set the value of the bit for the DMA channel */ 1805 bit_val = enable ? 1 : 0; 1806 bit_val <<= bit_offset; 1807 sw_reg |= bit_val; 1808 1809 /* update the software status of DMA channels */ 1810 sh_css_sp_group.debug.dma_sw_reg = sw_reg; 1811 1812 return true; 1813 } 1814 1815 void 1816 sh_css_sp_reset_global_vars(void) 1817 { 1818 memset(&sh_css_sp_group, 0, sizeof(struct sh_css_sp_group)); 1819 memset(&sh_css_sp_stage, 0, sizeof(struct sh_css_sp_stage)); 1820 memset(&sh_css_isp_stage, 0, sizeof(struct sh_css_isp_stage)); 1821 memset(&sh_css_sp_output, 0, sizeof(struct sh_css_sp_output)); 1822 memset(&per_frame_data, 0, sizeof(struct sh_css_sp_per_frame_data)); 1823 } 1824