1 /* 2 * Support for Intel Camera Imaging ISP subsystem. 3 * Copyright (c) 2015, Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 */ 14 15 #include "hmm.h" 16 17 #include "sh_css_sp.h" 18 19 #if !defined(HAS_NO_INPUT_FORMATTER) 20 #include "input_formatter.h" 21 #endif 22 23 #include "dma.h" /* N_DMA_CHANNEL_ID */ 24 25 #include "ia_css_buffer.h" 26 #include "ia_css_binary.h" 27 #include "sh_css_hrt.h" 28 #include "sh_css_defs.h" 29 #include "sh_css_internal.h" 30 #include "ia_css_control.h" 31 #include "ia_css_debug.h" 32 #include "ia_css_debug_pipe.h" 33 #include "ia_css_event_public.h" 34 #include "ia_css_mmu.h" 35 #include "ia_css_stream.h" 36 #include "ia_css_isp_param.h" 37 #include "sh_css_params.h" 38 #include "sh_css_legacy.h" 39 #include "ia_css_frame_comm.h" 40 #if !defined(HAS_NO_INPUT_SYSTEM) 41 #include "ia_css_isys.h" 42 #endif 43 44 #include "gdc_device.h" /* HRT_GDC_N */ 45 46 /*#include "sp.h"*/ /* host2sp_enqueue_frame_data() */ 47 48 49 #include "assert_support.h" 50 #include "platform_support.h" /* hrt_sleep() */ 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 strncpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME - 1); 994 sh_css_isp_stage.binary_name[SH_CSS_MAX_BINARY_NAME - 1] = 0; 995 sh_css_isp_stage.mem_initializers = *isp_mem_if; 996 997 /* 998 * Even when a stage does not need uds and does not params, 999 * ia_css_uds_sp_scale_params() seems to be called (needs 1000 * further investigation). This function can not deal with 1001 * dx, dy = {0, 0} 1002 */ 1003 1004 err = sh_css_sp_write_frame_pointers(args); 1005 /* TODO: move it to a better place */ 1006 if (binary->info->sp.enable.s3a) 1007 { 1008 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_3A_STATISTICS, thread_id, 1009 &queue_id); 1010 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.s3a_buf, queue_id, 1011 mmgr_EXCEPTION, 1012 IA_CSS_BUFFER_TYPE_3A_STATISTICS); 1013 } 1014 if (binary->info->sp.enable.dis) 1015 { 1016 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id, 1017 &queue_id); 1018 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id, 1019 mmgr_EXCEPTION, 1020 IA_CSS_BUFFER_TYPE_DIS_STATISTICS); 1021 } 1022 #if defined SH_CSS_ENABLE_METADATA 1023 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id); 1024 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA); 1025 #endif 1026 if (err) 1027 return err; 1028 1029 #ifdef USE_INPUT_SYSTEM_VERSION_2401 1030 if (stage == 0) { 1031 pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num); 1032 if (!pipe) 1033 return -EINVAL; 1034 1035 if (args->in_frame) 1036 ia_css_get_crop_offsets(pipe, &args->in_frame->info); 1037 else 1038 ia_css_get_crop_offsets(pipe, &binary->in_frame_info); 1039 } 1040 #else 1041 (void)pipe; /*avoid build warning*/ 1042 #endif 1043 1044 err = configure_isp_from_args(&sh_css_sp_group.pipe[thread_id], 1045 binary, args, two_ppc, sh_css_sp_stage.deinterleaved); 1046 if (err) 1047 return err; 1048 1049 initialize_isp_states(binary); 1050 1051 /* we do this only for preview pipe because in fill_binary_info function 1052 * we assign vf_out res to out res, but for ISP internal processing, we need 1053 * the original out res. for video pipe, it has two output pins --- out and 1054 * vf_out, so it can keep these two resolutions already. */ 1055 if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW && 1056 (binary->vf_downscale_log2 > 0)) 1057 { 1058 /* TODO: Remove this after preview output decimation is fixed 1059 * by configuring out&vf info fiels properly */ 1060 sh_css_sp_stage.frames.out[0].info.padded_width 1061 <<= binary->vf_downscale_log2; 1062 sh_css_sp_stage.frames.out[0].info.res.width 1063 <<= binary->vf_downscale_log2; 1064 sh_css_sp_stage.frames.out[0].info.res.height 1065 <<= binary->vf_downscale_log2; 1066 } 1067 err = copy_isp_mem_if_to_ddr(binary); 1068 if (err) 1069 return err; 1070 1071 return 0; 1072 } 1073 1074 static int 1075 sp_init_stage(struct ia_css_pipeline_stage *stage, 1076 unsigned int pipe_num, 1077 bool xnr, 1078 unsigned int if_config_index, 1079 bool two_ppc) { 1080 struct ia_css_binary *binary; 1081 const struct ia_css_fw_info *firmware; 1082 const struct sh_css_binary_args *args; 1083 unsigned int stage_num; 1084 /* 1085 * Initialiser required because of the "else" path below. 1086 * Is this a valid path ? 1087 */ 1088 const char *binary_name = ""; 1089 const struct ia_css_binary_xinfo *info = NULL; 1090 /* note: the var below is made static as it is quite large; 1091 if it is not static it ends up on the stack which could 1092 cause issues for drivers 1093 */ 1094 static struct ia_css_binary tmp_binary; 1095 const struct ia_css_blob_info *blob_info = NULL; 1096 struct ia_css_isp_param_css_segments isp_mem_if; 1097 /* LA: should be ia_css_data, should not contain host pointer. 1098 However, CSS/DDR pointer is not available yet. 1099 Hack is to store it in params->ddr_ptrs and then copy it late in the SP just before vmem init. 1100 TODO: Call this after CSS/DDR allocation and store that pointer. 1101 Best is to allocate it at stage creation time together with host pointer. 1102 Remove vmem from params. 1103 */ 1104 struct ia_css_isp_param_css_segments *mem_if = &isp_mem_if; 1105 1106 int err = 0; 1107 1108 assert(stage); 1109 1110 binary = stage->binary; 1111 firmware = stage->firmware; 1112 args = &stage->args; 1113 stage_num = stage->stage_num; 1114 1115 if (binary) 1116 { 1117 info = binary->info; 1118 binary_name = (const char *)(info->blob->name); 1119 blob_info = &info->blob->header.blob; 1120 ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params); 1121 } else if (firmware) 1122 { 1123 const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL}; 1124 1125 if (args->out_frame[0]) 1126 out_infos[0] = &args->out_frame[0]->info; 1127 info = &firmware->info.isp; 1128 ia_css_binary_fill_info(info, false, false, 1129 ATOMISP_INPUT_FORMAT_RAW_10, 1130 args->in_frame ? &args->in_frame->info : NULL, 1131 NULL, 1132 out_infos, 1133 args->out_vf_frame ? &args->out_vf_frame->info 1134 : NULL, 1135 &tmp_binary, 1136 NULL, 1137 -1, true); 1138 binary = &tmp_binary; 1139 binary->info = info; 1140 binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware); 1141 blob_info = &firmware->blob; 1142 mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers; 1143 } else 1144 { 1145 /* SP stage */ 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 */ 1151 return -EINVAL; 1152 } 1153 1154 err = sh_css_sp_init_stage(binary, 1155 (const char *)binary_name, 1156 blob_info, 1157 args, 1158 pipe_num, 1159 stage_num, 1160 xnr, 1161 mem_if, 1162 if_config_index, 1163 two_ppc); 1164 return err; 1165 } 1166 1167 static void 1168 sp_init_sp_stage(struct ia_css_pipeline_stage *stage, 1169 unsigned int pipe_num, 1170 bool two_ppc, 1171 enum sh_css_pipe_config_override copy_ovrd, 1172 unsigned int if_config_index) 1173 { 1174 const struct sh_css_binary_args *args = &stage->args; 1175 1176 assert(stage); 1177 switch (stage->sp_func) { 1178 case IA_CSS_PIPELINE_RAW_COPY: 1179 sh_css_sp_start_raw_copy(args->out_frame[0], 1180 pipe_num, two_ppc, 1181 stage->max_input_width, 1182 copy_ovrd, if_config_index); 1183 break; 1184 case IA_CSS_PIPELINE_BIN_COPY: 1185 assert(false); /* TBI */ 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 } 1193 } 1194 1195 void 1196 sh_css_sp_init_pipeline(struct ia_css_pipeline *me, 1197 enum ia_css_pipe_id id, 1198 u8 pipe_num, 1199 bool xnr, 1200 bool two_ppc, 1201 bool continuous, 1202 bool offline, 1203 unsigned int required_bds_factor, 1204 enum sh_css_pipe_config_override copy_ovrd, 1205 enum ia_css_input_mode input_mode, 1206 const struct ia_css_metadata_config *md_config, 1207 const struct ia_css_metadata_info *md_info, 1208 #if !defined(HAS_NO_INPUT_SYSTEM) 1209 const enum mipi_port_id port_id, 1210 #endif 1211 const struct ia_css_coordinate 1212 *internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame 1213 positioned on shading table at shading correction in ISP. */ 1214 const struct ia_css_isp_parameters *params 1215 ) { 1216 /* Get first stage */ 1217 struct ia_css_pipeline_stage *stage = NULL; 1218 struct ia_css_binary *first_binary = NULL; 1219 struct ia_css_pipe *pipe = NULL; 1220 unsigned int num; 1221 1222 enum ia_css_pipe_id pipe_id = id; 1223 unsigned int thread_id; 1224 u8 if_config_index, tmp_if_config_index; 1225 1226 assert(me); 1227 1228 #if !defined(HAS_NO_INPUT_SYSTEM) 1229 assert(me->stages); 1230 1231 first_binary = me->stages->binary; 1232 1233 if (input_mode == IA_CSS_INPUT_MODE_SENSOR || 1234 input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) 1235 { 1236 assert(port_id < N_MIPI_PORT_ID); 1237 if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */ 1238 return; /* we should be able to return an error */ 1239 if_config_index = (uint8_t)(port_id - MIPI_PORT0_ID); 1240 } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY) 1241 { 1242 if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; 1243 } else 1244 { 1245 if_config_index = 0x0; 1246 } 1247 #else 1248 (void)input_mode; 1249 if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; 1250 #endif 1251 1252 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 1253 memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline)); 1254 1255 /* Count stages */ 1256 for (stage = me->stages, num = 0; stage; stage = stage->next, num++) 1257 { 1258 stage->stage_num = num; 1259 ia_css_debug_pipe_graph_dump_stage(stage, id); 1260 } 1261 me->num_stages = num; 1262 1263 if (first_binary) 1264 { 1265 /* Init pipeline data */ 1266 sh_css_sp_init_group(two_ppc, first_binary->input_format, 1267 offline, if_config_index); 1268 } /* if (first_binary != NULL) */ 1269 1270 #if defined(USE_INPUT_SYSTEM_VERSION_2401) || defined(USE_INPUT_SYSTEM_VERSION_2) 1271 /* Signal the host immediately after start for SP_ISYS_COPY only */ 1272 if ((me->num_stages == 1) && me->stages && 1273 (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY)) 1274 sh_css_sp_group.config.no_isp_sync = true; 1275 #endif 1276 1277 /* Init stage data */ 1278 sh_css_init_host2sp_frame_data(); 1279 1280 sh_css_sp_group.pipe[thread_id].num_stages = 0; 1281 sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id; 1282 sh_css_sp_group.pipe[thread_id].thread_id = thread_id; 1283 sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num; 1284 sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs; 1285 sh_css_sp_group.pipe[thread_id].pipe_qos_config = me->pipe_qos_config; 1286 sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor; 1287 #if !defined(HAS_NO_INPUT_SYSTEM) 1288 sh_css_sp_group.pipe[thread_id].input_system_mode 1289 = (uint32_t)input_mode; 1290 sh_css_sp_group.pipe[thread_id].port_id = port_id; 1291 #endif 1292 sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay; 1293 1294 /* TODO: next indicates from which queues parameters need to be 1295 sampled, needs checking/improvement */ 1296 if (ia_css_pipeline_uses_params(me)) 1297 { 1298 sh_css_sp_group.pipe[thread_id].pipe_config = 1299 SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id; 1300 } 1301 1302 /* For continuous use-cases, SP copy is responsible for sampling the 1303 * parameters */ 1304 if (continuous) 1305 sh_css_sp_group.pipe[thread_id].pipe_config = 0; 1306 1307 sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config; 1308 1309 pipe = find_pipe_by_num(pipe_num); 1310 assert(pipe); 1311 if (!pipe) 1312 { 1313 return; 1314 } 1315 sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe); 1316 1317 #if defined(SH_CSS_ENABLE_METADATA) 1318 if (md_info && md_info->size > 0) 1319 { 1320 sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width; 1321 sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height; 1322 sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride; 1323 sh_css_sp_group.pipe[thread_id].metadata.size = md_info->size; 1324 ia_css_isys_convert_stream_format_to_mipi_format( 1325 md_config->data_type, MIPI_PREDICTOR_NONE, 1326 &sh_css_sp_group.pipe[thread_id].metadata.format); 1327 } 1328 #else 1329 (void)md_config; 1330 (void)md_info; 1331 #endif 1332 1333 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) 1334 sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID; 1335 if (pipe_id != IA_CSS_PIPE_ID_COPY) 1336 { 1337 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, 1338 (enum sh_css_queue_id *)( 1339 &sh_css_sp_group.pipe[thread_id].output_frame_queue_id)); 1340 } 1341 #endif 1342 1343 if (atomisp_hw_is_isp2401) { 1344 /* For the shading correction type 1 (the legacy shading table conversion in css is not used), 1345 * the parameters are passed to the isp for the shading table centering. 1346 */ 1347 if (internal_frame_origin_bqs_on_sctbl && 1348 params && params->shading_settings.enable_shading_table_conversion == 0) 1349 { 1350 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl 1351 = (uint32_t)internal_frame_origin_bqs_on_sctbl->x; 1352 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl 1353 = (uint32_t)internal_frame_origin_bqs_on_sctbl->y; 1354 } else 1355 { 1356 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl = 1357 0; 1358 sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl = 1359 0; 1360 } 1361 } 1362 1363 IA_CSS_LOG("pipe_id %d port_config %08x", 1364 pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config); 1365 1366 for (stage = me->stages, num = 0; stage; stage = stage->next, num++) 1367 { 1368 sh_css_sp_group.pipe[thread_id].num_stages++; 1369 if (is_sp_stage(stage)) { 1370 sp_init_sp_stage(stage, pipe_num, two_ppc, 1371 copy_ovrd, if_config_index); 1372 } else { 1373 if ((stage->stage_num != 0) || 1374 SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config)) 1375 tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; 1376 else 1377 tmp_if_config_index = if_config_index; 1378 sp_init_stage(stage, pipe_num, 1379 xnr, tmp_if_config_index, two_ppc); 1380 } 1381 1382 store_sp_stage_data(pipe_id, pipe_num, num); 1383 } 1384 sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t) 1385 (me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS); 1386 store_sp_group_data(); 1387 } 1388 1389 void 1390 sh_css_sp_uninit_pipeline(unsigned int pipe_num) 1391 { 1392 unsigned int thread_id; 1393 1394 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 1395 /*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/ 1396 sh_css_sp_group.pipe[thread_id].num_stages = 0; 1397 } 1398 1399 bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command) 1400 { 1401 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1402 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, 1403 host2sp_command) 1404 / sizeof(int); 1405 enum host2sp_commands last_cmd = host2sp_cmd_error; 1406 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1407 1408 /* Previous command must be handled by SP (by design) */ 1409 last_cmd = load_sp_array_uint(host_sp_com, offset); 1410 if (last_cmd != host2sp_cmd_ready) 1411 IA_CSS_ERROR("last host command not handled by SP(%d)", last_cmd); 1412 1413 store_sp_array_uint(host_sp_com, offset, host2sp_command); 1414 1415 return (last_cmd == host2sp_cmd_ready); 1416 } 1417 1418 enum host2sp_commands 1419 sh_css_read_host2sp_command(void) { 1420 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1421 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command) 1422 / sizeof(int); 1423 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1424 return (enum host2sp_commands)load_sp_array_uint(host_sp_com, offset); 1425 } 1426 1427 /* 1428 * Frame data is no longer part of the sp_stage structure but part of a 1429 * separate structure. The aim is to make the sp_data struct static 1430 * (it defines a pipeline) and that the dynamic (per frame) data is stored 1431 * separetly. 1432 * 1433 * This function must be called first every where were you start constructing 1434 * a new pipeline by defining one or more stages with use of variable 1435 * sh_css_sp_stage. Even the special cases like accelerator and copy_frame 1436 * These have a pipeline of just 1 stage. 1437 */ 1438 void 1439 sh_css_init_host2sp_frame_data(void) 1440 { 1441 /* Clean table */ 1442 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1443 1444 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1445 /* 1446 * rvanimme: don't clean it to save static frame info line ref_in 1447 * ref_out, and tnr_frames. Once this static data is in a 1448 * separate data struct, this may be enable (but still, there is 1449 * no need for it) 1450 */ 1451 } 1452 1453 /* 1454 * @brief Update the offline frame information in host_sp_communication. 1455 * Refer to "sh_css_sp.h" for more details. 1456 */ 1457 void 1458 sh_css_update_host2sp_offline_frame( 1459 unsigned int frame_num, 1460 struct ia_css_frame *frame, 1461 struct ia_css_metadata *metadata) 1462 { 1463 unsigned int HIVE_ADDR_host_sp_com; 1464 unsigned int offset; 1465 1466 assert(frame_num < NUM_CONTINUOUS_FRAMES); 1467 1468 /* Write new frame data into SP DMEM */ 1469 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1470 offset = (unsigned int)offsetof(struct host_sp_communication, 1471 host2sp_offline_frames) 1472 / sizeof(int); 1473 offset += frame_num; 1474 store_sp_array_uint(host_sp_com, offset, frame ? frame->data : 0); 1475 1476 /* Write metadata buffer into SP DMEM */ 1477 offset = (unsigned int)offsetof(struct host_sp_communication, 1478 host2sp_offline_metadata) 1479 / sizeof(int); 1480 offset += frame_num; 1481 store_sp_array_uint(host_sp_com, offset, metadata ? metadata->address : 0); 1482 } 1483 1484 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) 1485 /* 1486 * @brief Update the mipi frame information in host_sp_communication. 1487 * Refer to "sh_css_sp.h" for more details. 1488 */ 1489 void 1490 sh_css_update_host2sp_mipi_frame( 1491 unsigned int frame_num, 1492 struct ia_css_frame *frame) 1493 { 1494 unsigned int HIVE_ADDR_host_sp_com; 1495 unsigned int offset; 1496 1497 /* MIPI buffers are dedicated to port, so now there are more of them. */ 1498 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM)); 1499 1500 /* Write new frame data into SP DMEM */ 1501 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1502 offset = (unsigned int)offsetof(struct host_sp_communication, 1503 host2sp_mipi_frames) 1504 / sizeof(int); 1505 offset += frame_num; 1506 1507 store_sp_array_uint(host_sp_com, offset, 1508 frame ? frame->data : 0); 1509 } 1510 1511 /* 1512 * @brief Update the mipi metadata information in host_sp_communication. 1513 * Refer to "sh_css_sp.h" for more details. 1514 */ 1515 void 1516 sh_css_update_host2sp_mipi_metadata( 1517 unsigned int frame_num, 1518 struct ia_css_metadata *metadata) 1519 { 1520 unsigned int HIVE_ADDR_host_sp_com; 1521 unsigned int o; 1522 1523 /* MIPI buffers are dedicated to port, so now there are more of them. */ 1524 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM)); 1525 1526 /* Write new frame data into SP DMEM */ 1527 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1528 o = offsetof(struct host_sp_communication, host2sp_mipi_metadata) 1529 / sizeof(int); 1530 o += frame_num; 1531 store_sp_array_uint(host_sp_com, o, 1532 metadata ? metadata->address : 0); 1533 } 1534 1535 void 1536 sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames) 1537 { 1538 unsigned int HIVE_ADDR_host_sp_com; 1539 unsigned int offset; 1540 1541 /* Write new frame data into SP DMEM */ 1542 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1543 offset = (unsigned int)offsetof(struct host_sp_communication, 1544 host2sp_num_mipi_frames) 1545 / sizeof(int); 1546 1547 store_sp_array_uint(host_sp_com, offset, num_frames); 1548 } 1549 #endif 1550 1551 void 1552 sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames, 1553 bool set_avail) 1554 { 1555 const struct ia_css_fw_info *fw; 1556 unsigned int HIVE_ADDR_host_sp_com; 1557 unsigned int extra_num_frames, avail_num_frames; 1558 unsigned int offset, offset_extra; 1559 1560 /* Write new frame data into SP DMEM */ 1561 fw = &sh_css_sp_fw; 1562 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com; 1563 if (set_avail) { 1564 offset = (unsigned int)offsetof(struct host_sp_communication, 1565 host2sp_cont_avail_num_raw_frames) 1566 / sizeof(int); 1567 avail_num_frames = load_sp_array_uint(host_sp_com, offset); 1568 extra_num_frames = num_frames - avail_num_frames; 1569 offset_extra = (unsigned int)offsetof(struct host_sp_communication, 1570 host2sp_cont_extra_num_raw_frames) 1571 / sizeof(int); 1572 store_sp_array_uint(host_sp_com, offset_extra, extra_num_frames); 1573 } else 1574 offset = (unsigned int)offsetof(struct host_sp_communication, 1575 host2sp_cont_target_num_raw_frames) 1576 / sizeof(int); 1577 1578 store_sp_array_uint(host_sp_com, offset, num_frames); 1579 } 1580 1581 void 1582 sh_css_event_init_irq_mask(void) 1583 { 1584 int i; 1585 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1586 unsigned int offset; 1587 struct sh_css_event_irq_mask event_irq_mask_init; 1588 1589 event_irq_mask_init.or_mask = IA_CSS_EVENT_TYPE_ALL; 1590 event_irq_mask_init.and_mask = IA_CSS_EVENT_TYPE_NONE; 1591 (void)HIVE_ADDR_host_sp_com; /* Suppress warnings in CRUN */ 1592 1593 assert(sizeof(event_irq_mask_init) % HRT_BUS_BYTES == 0); 1594 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { 1595 offset = (unsigned int)offsetof(struct host_sp_communication, 1596 host2sp_event_irq_mask[i]); 1597 assert(offset % HRT_BUS_BYTES == 0); 1598 sp_dmem_store(SP0_ID, 1599 (unsigned int)sp_address_of(host_sp_com) + offset, 1600 &event_irq_mask_init, sizeof(event_irq_mask_init)); 1601 } 1602 } 1603 1604 int 1605 ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe, 1606 unsigned int or_mask, 1607 unsigned int and_mask) { 1608 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1609 unsigned int offset; 1610 struct sh_css_event_irq_mask event_irq_mask; 1611 unsigned int pipe_num; 1612 1613 assert(pipe); 1614 1615 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES); 1616 /* Linux kernel does not have UINT16_MAX 1617 * Therefore decided to comment out these 2 asserts for Linux 1618 * Alternatives that were not chosen: 1619 * - add a conditional #define for UINT16_MAX 1620 * - compare with (uint16_t)~0 or 0xffff 1621 * - different assert for Linux and Windows 1622 */ 1623 1624 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1625 1626 IA_CSS_LOG("or_mask=%x, and_mask=%x", or_mask, and_mask); 1627 event_irq_mask.or_mask = (uint16_t)or_mask; 1628 event_irq_mask.and_mask = (uint16_t)and_mask; 1629 1630 pipe_num = ia_css_pipe_get_pipe_num(pipe); 1631 if (pipe_num >= IA_CSS_PIPE_ID_NUM) 1632 return -EINVAL; 1633 offset = (unsigned int)offsetof(struct host_sp_communication, 1634 host2sp_event_irq_mask[pipe_num]); 1635 assert(offset % HRT_BUS_BYTES == 0); 1636 sp_dmem_store(SP0_ID, 1637 (unsigned int)sp_address_of(host_sp_com) + offset, 1638 &event_irq_mask, sizeof(event_irq_mask)); 1639 1640 return 0; 1641 } 1642 1643 int 1644 ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe, 1645 unsigned int *or_mask, 1646 unsigned int *and_mask) { 1647 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1648 unsigned int offset; 1649 struct sh_css_event_irq_mask event_irq_mask; 1650 unsigned int pipe_num; 1651 1652 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1653 1654 IA_CSS_ENTER_LEAVE(""); 1655 1656 assert(pipe); 1657 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES); 1658 1659 pipe_num = ia_css_pipe_get_pipe_num(pipe); 1660 if (pipe_num >= IA_CSS_PIPE_ID_NUM) 1661 return -EINVAL; 1662 offset = (unsigned int)offsetof(struct host_sp_communication, 1663 host2sp_event_irq_mask[pipe_num]); 1664 assert(offset % HRT_BUS_BYTES == 0); 1665 sp_dmem_load(SP0_ID, 1666 (unsigned int)sp_address_of(host_sp_com) + offset, 1667 &event_irq_mask, sizeof(event_irq_mask)); 1668 1669 if (or_mask) 1670 *or_mask = event_irq_mask.or_mask; 1671 1672 if (and_mask) 1673 *and_mask = event_irq_mask.and_mask; 1674 1675 return 0; 1676 } 1677 1678 void 1679 sh_css_sp_set_sp_running(bool flag) 1680 { 1681 sp_running = flag; 1682 } 1683 1684 bool 1685 sh_css_sp_is_running(void) 1686 { 1687 return sp_running; 1688 } 1689 1690 void 1691 sh_css_sp_start_isp(void) 1692 { 1693 const struct ia_css_fw_info *fw; 1694 unsigned int HIVE_ADDR_sp_sw_state; 1695 1696 fw = &sh_css_sp_fw; 1697 HIVE_ADDR_sp_sw_state = fw->info.sp.sw_state; 1698 1699 if (sp_running) 1700 return; 1701 1702 (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */ 1703 1704 /* no longer here, sp started immediately */ 1705 /*ia_css_debug_pipe_graph_dump_epilogue();*/ 1706 1707 store_sp_group_data(); 1708 store_sp_per_frame_data(fw); 1709 1710 sp_dmem_store_uint32(SP0_ID, 1711 (unsigned int)sp_address_of(sp_sw_state), 1712 (uint32_t)(IA_CSS_SP_SW_TERMINATED)); 1713 1714 /* Note 1: The sp_start_isp function contains a wait till 1715 * the input network is configured by the SP. 1716 * Note 2: Not all SP binaries supports host2sp_commands. 1717 * In case a binary does support it, the host2sp_command 1718 * will have status cmd_ready after return of the function 1719 * sh_css_hrt_sp_start_isp. There is no race-condition here 1720 * because only after the process_frame command has been 1721 * received, the SP starts configuring the input network. 1722 */ 1723 1724 /* we need to set sp_running before we call ia_css_mmu_invalidate_cache 1725 * as ia_css_mmu_invalidate_cache checks on sp_running to 1726 * avoid that it accesses dmem while the SP is not powered 1727 */ 1728 sp_running = true; 1729 ia_css_mmu_invalidate_cache(); 1730 /* Invalidate all MMU caches */ 1731 mmu_invalidate_cache_all(); 1732 1733 ia_css_spctrl_start(SP0_ID); 1734 } 1735 1736 bool 1737 ia_css_isp_has_started(void) 1738 { 1739 const struct ia_css_fw_info *fw = &sh_css_sp_fw; 1740 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started; 1741 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */ 1742 1743 return (bool)load_sp_uint(ia_css_ispctrl_sp_isp_started); 1744 } 1745 1746 /* 1747 * @brief Initialize the DMA software-mask in the debug mode. 1748 * Refer to "sh_css_sp.h" for more details. 1749 */ 1750 bool 1751 sh_css_sp_init_dma_sw_reg(int dma_id) 1752 { 1753 int i; 1754 1755 /* enable all the DMA channels */ 1756 for (i = 0; i < N_DMA_CHANNEL_ID; i++) { 1757 /* enable the writing request */ 1758 sh_css_sp_set_dma_sw_reg(dma_id, 1759 i, 1760 0, 1761 true); 1762 /* enable the reading request */ 1763 sh_css_sp_set_dma_sw_reg(dma_id, 1764 i, 1765 1, 1766 true); 1767 } 1768 1769 return true; 1770 } 1771 1772 /* 1773 * @brief Set the DMA software-mask in the debug mode. 1774 * Refer to "sh_css_sp.h" for more details. 1775 */ 1776 bool 1777 sh_css_sp_set_dma_sw_reg(int dma_id, 1778 int channel_id, 1779 int request_type, 1780 bool enable) 1781 { 1782 u32 sw_reg; 1783 u32 bit_val; 1784 u32 bit_offset; 1785 u32 bit_mask; 1786 1787 (void)dma_id; 1788 1789 assert(channel_id >= 0 && channel_id < N_DMA_CHANNEL_ID); 1790 assert(request_type >= 0); 1791 1792 /* get the software-mask */ 1793 sw_reg = 1794 sh_css_sp_group.debug.dma_sw_reg; 1795 1796 /* get the offest of the target bit */ 1797 bit_offset = (8 * request_type) + channel_id; 1798 1799 /* clear the value of the target bit */ 1800 bit_mask = ~(1 << bit_offset); 1801 sw_reg &= bit_mask; 1802 1803 /* set the value of the bit for the DMA channel */ 1804 bit_val = enable ? 1 : 0; 1805 bit_val <<= bit_offset; 1806 sw_reg |= bit_val; 1807 1808 /* update the software status of DMA channels */ 1809 sh_css_sp_group.debug.dma_sw_reg = sw_reg; 1810 1811 return true; 1812 } 1813 1814 void 1815 sh_css_sp_reset_global_vars(void) 1816 { 1817 memset(&sh_css_sp_group, 0, sizeof(struct sh_css_sp_group)); 1818 memset(&sh_css_sp_stage, 0, sizeof(struct sh_css_sp_stage)); 1819 memset(&sh_css_isp_stage, 0, sizeof(struct sh_css_isp_stage)); 1820 memset(&sh_css_sp_output, 0, sizeof(struct sh_css_sp_output)); 1821 memset(&per_frame_data, 0, sizeof(struct sh_css_sp_per_frame_data)); 1822 } 1823