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(ISP2401) 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 #include "ia_css_isys.h" 42 43 #include "gdc_device.h" /* HRT_GDC_N */ 44 45 /*#include "sp.h"*/ /* host2sp_enqueue_frame_data() */ 46 47 48 #include "assert_support.h" 49 50 #include "sw_event_global.h" /* Event IDs.*/ 51 #include "ia_css_event.h" 52 #include "mmu_device.h" 53 #include "ia_css_spctrl.h" 54 55 #ifndef offsetof 56 #define offsetof(T, x) ((unsigned int)&(((T *)0)->x)) 57 #endif 58 59 #define IA_CSS_INCLUDE_CONFIGURATIONS 60 #include "ia_css_isp_configs.h" 61 #define IA_CSS_INCLUDE_STATES 62 #include "ia_css_isp_states.h" 63 64 #include "isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.h" 65 66 struct sh_css_sp_group sh_css_sp_group; 67 struct sh_css_sp_stage sh_css_sp_stage; 68 struct sh_css_isp_stage sh_css_isp_stage; 69 static struct sh_css_sp_output sh_css_sp_output; 70 static struct sh_css_sp_per_frame_data per_frame_data; 71 72 /* true if SP supports frame loop and host2sp_commands */ 73 /* For the moment there is only code that sets this bool to true */ 74 /* TODO: add code that sets this bool to false */ 75 static bool sp_running; 76 77 static int 78 set_output_frame_buffer(const struct ia_css_frame *frame, 79 unsigned int idx); 80 81 static void 82 sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf, 83 const enum sh_css_queue_id queue_id, 84 const ia_css_ptr xmem_addr, 85 const enum ia_css_buffer_type buf_type); 86 87 static void 88 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr); 89 90 static void 91 initialize_stage_frames(struct ia_css_frames_sp *frames); 92 93 /* This data is stored every frame */ 94 void 95 store_sp_group_data(void) 96 { 97 per_frame_data.sp_group_addr = sh_css_store_sp_group_to_ddr(); 98 } 99 100 static void 101 copy_isp_stage_to_sp_stage(void) 102 { 103 /* [WW07.5]type casting will cause potential issues */ 104 sh_css_sp_stage.num_stripes = (uint8_t) 105 sh_css_isp_stage.binary_info.iterator.num_stripes; 106 sh_css_sp_stage.row_stripes_height = (uint16_t) 107 sh_css_isp_stage.binary_info.iterator.row_stripes_height; 108 sh_css_sp_stage.row_stripes_overlap_lines = (uint16_t) 109 sh_css_isp_stage.binary_info.iterator.row_stripes_overlap_lines; 110 sh_css_sp_stage.top_cropping = (uint16_t) 111 sh_css_isp_stage.binary_info.pipeline.top_cropping; 112 /* moved to sh_css_sp_init_stage 113 sh_css_sp_stage.enable.vf_output = 114 sh_css_isp_stage.binary_info.enable.vf_veceven || 115 sh_css_isp_stage.binary_info.num_output_pins > 1; 116 */ 117 sh_css_sp_stage.enable.sdis = sh_css_isp_stage.binary_info.enable.dis; 118 sh_css_sp_stage.enable.s3a = sh_css_isp_stage.binary_info.enable.s3a; 119 } 120 121 void 122 store_sp_stage_data(enum ia_css_pipe_id id, unsigned int pipe_num, 123 unsigned int stage) 124 { 125 unsigned int thread_id; 126 127 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 128 copy_isp_stage_to_sp_stage(); 129 if (id != IA_CSS_PIPE_ID_COPY) 130 sh_css_sp_stage.isp_stage_addr = 131 sh_css_store_isp_stage_to_ddr(pipe_num, stage); 132 sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = 133 sh_css_store_sp_stage_to_ddr(pipe_num, stage); 134 135 /* Clear for next frame */ 136 sh_css_sp_stage.program_input_circuit = false; 137 } 138 139 static void 140 store_sp_per_frame_data(const struct ia_css_fw_info *fw) 141 { 142 unsigned int HIVE_ADDR_sp_per_frame_data = 0; 143 144 assert(fw); 145 146 switch (fw->type) { 147 case ia_css_sp_firmware: 148 HIVE_ADDR_sp_per_frame_data = fw->info.sp.per_frame_data; 149 break; 150 case ia_css_acc_firmware: 151 HIVE_ADDR_sp_per_frame_data = fw->info.acc.per_frame_data; 152 break; 153 case ia_css_isp_firmware: 154 return; 155 } 156 157 sp_dmem_store(SP0_ID, 158 (unsigned int)sp_address_of(sp_per_frame_data), 159 &per_frame_data, 160 sizeof(per_frame_data)); 161 } 162 163 static void 164 sh_css_store_sp_per_frame_data(enum ia_css_pipe_id pipe_id, 165 unsigned int pipe_num, 166 const struct ia_css_fw_info *sp_fw) 167 { 168 if (!sp_fw) 169 sp_fw = &sh_css_sp_fw; 170 171 store_sp_stage_data(pipe_id, pipe_num, 0); 172 store_sp_group_data(); 173 store_sp_per_frame_data(sp_fw); 174 } 175 176 #if SP_DEBUG != SP_DEBUG_NONE 177 178 void 179 sh_css_sp_get_debug_state(struct sh_css_sp_debug_state *state) 180 { 181 const struct ia_css_fw_info *fw = &sh_css_sp_fw; 182 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output; 183 unsigned int i; 184 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output, 185 debug) / sizeof(int); 186 187 assert(state); 188 189 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */ 190 for (i = 0; i < sizeof(*state) / sizeof(int); i++) 191 ((unsigned *)state)[i] = load_sp_array_uint(sp_output, i + offset); 192 } 193 194 #endif 195 196 void 197 sh_css_sp_start_binary_copy(unsigned int pipe_num, 198 struct ia_css_frame *out_frame, 199 unsigned int two_ppc) 200 { 201 enum ia_css_pipe_id pipe_id; 202 unsigned int thread_id; 203 struct sh_css_sp_pipeline *pipe; 204 u8 stage_num = 0; 205 206 assert(out_frame); 207 pipe_id = IA_CSS_PIPE_ID_CAPTURE; 208 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 209 pipe = &sh_css_sp_group.pipe[thread_id]; 210 211 pipe->copy.bin.bytes_available = out_frame->data_bytes; 212 pipe->num_stages = 1; 213 pipe->pipe_id = pipe_id; 214 pipe->pipe_num = pipe_num; 215 pipe->thread_id = thread_id; 216 pipe->pipe_config = 0x0; /* No parameters */ 217 pipe->pipe_qos_config = QOS_INVALID; 218 219 if (pipe->inout_port_config == 0) { 220 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config, 221 (uint8_t)SH_CSS_PORT_INPUT, 222 (uint8_t)SH_CSS_HOST_TYPE, 1); 223 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config, 224 (uint8_t)SH_CSS_PORT_OUTPUT, 225 (uint8_t)SH_CSS_HOST_TYPE, 1); 226 } 227 IA_CSS_LOG("pipe_id %d port_config %08x", 228 pipe->pipe_id, pipe->inout_port_config); 229 230 #if !defined(ISP2401) 231 sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc; 232 #else 233 (void)two_ppc; 234 #endif 235 236 sh_css_sp_stage.num = stage_num; 237 sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE; 238 sh_css_sp_stage.func = 239 (unsigned int)IA_CSS_PIPELINE_BIN_COPY; 240 241 set_output_frame_buffer(out_frame, 0); 242 243 /* sp_bin_copy_init on the SP does not deal with dynamica/static yet */ 244 /* For now always update the dynamic data from out frames. */ 245 sh_css_store_sp_per_frame_data(pipe_id, pipe_num, &sh_css_sp_fw); 246 } 247 248 static void 249 sh_css_sp_start_raw_copy(struct ia_css_frame *out_frame, 250 unsigned int pipe_num, 251 unsigned int two_ppc, 252 unsigned int max_input_width, 253 enum sh_css_pipe_config_override pipe_conf_override, 254 unsigned int if_config_index) 255 { 256 enum ia_css_pipe_id pipe_id; 257 unsigned int thread_id; 258 u8 stage_num = 0; 259 struct sh_css_sp_pipeline *pipe; 260 261 assert(out_frame); 262 263 { 264 /* 265 * Clear sh_css_sp_stage for easy debugging. 266 * program_input_circuit must be saved as it is set outside 267 * this function. 268 */ 269 u8 program_input_circuit; 270 271 program_input_circuit = sh_css_sp_stage.program_input_circuit; 272 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage)); 273 sh_css_sp_stage.program_input_circuit = program_input_circuit; 274 } 275 276 pipe_id = IA_CSS_PIPE_ID_COPY; 277 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 278 pipe = &sh_css_sp_group.pipe[thread_id]; 279 280 pipe->copy.raw.height = out_frame->info.res.height; 281 pipe->copy.raw.width = out_frame->info.res.width; 282 pipe->copy.raw.padded_width = out_frame->info.padded_width; 283 pipe->copy.raw.raw_bit_depth = out_frame->info.raw_bit_depth; 284 pipe->copy.raw.max_input_width = max_input_width; 285 pipe->num_stages = 1; 286 pipe->pipe_id = pipe_id; 287 /* TODO: next indicates from which queues parameters need to be 288 sampled, needs checking/improvement */ 289 if (pipe_conf_override == SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD) 290 pipe->pipe_config = 291 (SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id); 292 else 293 pipe->pipe_config = pipe_conf_override; 294 295 pipe->pipe_qos_config = QOS_INVALID; 296 297 if (pipe->inout_port_config == 0) { 298 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config, 299 (uint8_t)SH_CSS_PORT_INPUT, 300 (uint8_t)SH_CSS_HOST_TYPE, 1); 301 SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config, 302 (uint8_t)SH_CSS_PORT_OUTPUT, 303 (uint8_t)SH_CSS_HOST_TYPE, 1); 304 } 305 IA_CSS_LOG("pipe_id %d port_config %08x", 306 pipe->pipe_id, pipe->inout_port_config); 307 308 #if !defined(ISP2401) 309 sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc; 310 #else 311 (void)two_ppc; 312 #endif 313 314 sh_css_sp_stage.num = stage_num; 315 sh_css_sp_stage.xmem_bin_addr = 0x0; 316 sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE; 317 sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_RAW_COPY; 318 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index; 319 set_output_frame_buffer(out_frame, 0); 320 321 ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame); 322 } 323 324 static void 325 sh_css_sp_start_isys_copy(struct ia_css_frame *out_frame, 326 unsigned int pipe_num, unsigned int max_input_width, 327 unsigned int if_config_index) 328 { 329 enum ia_css_pipe_id pipe_id; 330 unsigned int thread_id; 331 u8 stage_num = 0; 332 struct sh_css_sp_pipeline *pipe; 333 #if defined SH_CSS_ENABLE_METADATA 334 enum sh_css_queue_id queue_id; 335 #endif 336 337 assert(out_frame); 338 339 { 340 /* 341 * Clear sh_css_sp_stage for easy debugging. 342 * program_input_circuit must be saved as it is set outside 343 * this function. 344 */ 345 u8 program_input_circuit; 346 347 program_input_circuit = sh_css_sp_stage.program_input_circuit; 348 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage)); 349 sh_css_sp_stage.program_input_circuit = program_input_circuit; 350 } 351 352 pipe_id = IA_CSS_PIPE_ID_COPY; 353 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 354 pipe = &sh_css_sp_group.pipe[thread_id]; 355 356 pipe->copy.raw.height = out_frame->info.res.height; 357 pipe->copy.raw.width = out_frame->info.res.width; 358 pipe->copy.raw.padded_width = out_frame->info.padded_width; 359 pipe->copy.raw.raw_bit_depth = out_frame->info.raw_bit_depth; 360 pipe->copy.raw.max_input_width = max_input_width; 361 pipe->num_stages = 1; 362 pipe->pipe_id = pipe_id; 363 pipe->pipe_config = 0x0; /* No parameters */ 364 pipe->pipe_qos_config = QOS_INVALID; 365 366 initialize_stage_frames(&sh_css_sp_stage.frames); 367 sh_css_sp_stage.num = stage_num; 368 sh_css_sp_stage.xmem_bin_addr = 0x0; 369 sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE; 370 sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_ISYS_COPY; 371 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index; 372 373 set_output_frame_buffer(out_frame, 0); 374 375 #if defined SH_CSS_ENABLE_METADATA 376 if (pipe->metadata.height > 0) { 377 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, 378 &queue_id); 379 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, 380 queue_id, mmgr_EXCEPTION, 381 IA_CSS_BUFFER_TYPE_METADATA); 382 } 383 #endif 384 385 ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame); 386 } 387 388 unsigned int 389 sh_css_sp_get_binary_copy_size(void) 390 { 391 const struct ia_css_fw_info *fw = &sh_css_sp_fw; 392 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output; 393 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output, 394 bin_copy_bytes_copied) / sizeof(int); 395 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */ 396 return load_sp_array_uint(sp_output, offset); 397 } 398 399 unsigned int 400 sh_css_sp_get_sw_interrupt_value(unsigned int irq) 401 { 402 const struct ia_css_fw_info *fw = &sh_css_sp_fw; 403 unsigned int HIVE_ADDR_sp_output = fw->info.sp.output; 404 unsigned int offset = (unsigned int)offsetof(struct sh_css_sp_output, 405 sw_interrupt_value) 406 / sizeof(int); 407 (void)HIVE_ADDR_sp_output; /* To get rid of warning in CRUN */ 408 return load_sp_array_uint(sp_output, offset + irq); 409 } 410 411 static void 412 sh_css_copy_buffer_attr_to_spbuffer(struct ia_css_buffer_sp *dest_buf, 413 const enum sh_css_queue_id queue_id, 414 const ia_css_ptr xmem_addr, 415 const enum ia_css_buffer_type buf_type) 416 { 417 assert(buf_type < IA_CSS_NUM_BUFFER_TYPE); 418 if (queue_id > SH_CSS_INVALID_QUEUE_ID) { 419 /* 420 * value >=0 indicates that function init_frame_pointers() 421 * should use the dynamic data address 422 */ 423 assert(queue_id < SH_CSS_MAX_NUM_QUEUES); 424 425 /* Klocwork assumes assert can be disabled; 426 Since we can get there with any type, and it does not 427 know that frame_in->dynamic_data_index can only be set 428 for one of the types in the assert) it has to assume we 429 can get here for any type. however this could lead to an 430 out of bounds reference when indexing buf_type about 10 431 lines below. In order to satisfy KW an additional if 432 has been added. This one will always yield true. 433 */ 434 if ((queue_id < SH_CSS_MAX_NUM_QUEUES)) { 435 dest_buf->buf_src.queue_id = queue_id; 436 } 437 } else { 438 assert(xmem_addr != mmgr_EXCEPTION); 439 dest_buf->buf_src.xmem_addr = xmem_addr; 440 } 441 dest_buf->buf_type = buf_type; 442 } 443 444 static void 445 sh_css_copy_frame_to_spframe(struct ia_css_frame_sp *sp_frame_out, 446 const struct ia_css_frame *frame_in) 447 { 448 assert(frame_in); 449 450 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, 451 "sh_css_copy_frame_to_spframe():\n"); 452 453 sh_css_copy_buffer_attr_to_spbuffer(&sp_frame_out->buf_attr, 454 frame_in->dynamic_queue_id, 455 frame_in->data, 456 frame_in->buf_type); 457 458 ia_css_frame_info_to_frame_sp_info(&sp_frame_out->info, &frame_in->info); 459 460 switch (frame_in->info.format) { 461 case IA_CSS_FRAME_FORMAT_RAW_PACKED: 462 case IA_CSS_FRAME_FORMAT_RAW: 463 sp_frame_out->planes.raw.offset = frame_in->planes.raw.offset; 464 break; 465 case IA_CSS_FRAME_FORMAT_RGB565: 466 case IA_CSS_FRAME_FORMAT_RGBA888: 467 sp_frame_out->planes.rgb.offset = frame_in->planes.rgb.offset; 468 break; 469 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888: 470 sp_frame_out->planes.planar_rgb.r.offset = 471 frame_in->planes.planar_rgb.r.offset; 472 sp_frame_out->planes.planar_rgb.g.offset = 473 frame_in->planes.planar_rgb.g.offset; 474 sp_frame_out->planes.planar_rgb.b.offset = 475 frame_in->planes.planar_rgb.b.offset; 476 break; 477 case IA_CSS_FRAME_FORMAT_YUYV: 478 case IA_CSS_FRAME_FORMAT_UYVY: 479 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8: 480 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8: 481 case IA_CSS_FRAME_FORMAT_YUV_LINE: 482 sp_frame_out->planes.yuyv.offset = frame_in->planes.yuyv.offset; 483 break; 484 case IA_CSS_FRAME_FORMAT_NV11: 485 case IA_CSS_FRAME_FORMAT_NV12: 486 case IA_CSS_FRAME_FORMAT_NV12_16: 487 case IA_CSS_FRAME_FORMAT_NV12_TILEY: 488 case IA_CSS_FRAME_FORMAT_NV21: 489 case IA_CSS_FRAME_FORMAT_NV16: 490 case IA_CSS_FRAME_FORMAT_NV61: 491 sp_frame_out->planes.nv.y.offset = 492 frame_in->planes.nv.y.offset; 493 sp_frame_out->planes.nv.uv.offset = 494 frame_in->planes.nv.uv.offset; 495 break; 496 case IA_CSS_FRAME_FORMAT_YUV420: 497 case IA_CSS_FRAME_FORMAT_YUV422: 498 case IA_CSS_FRAME_FORMAT_YUV444: 499 case IA_CSS_FRAME_FORMAT_YUV420_16: 500 case IA_CSS_FRAME_FORMAT_YUV422_16: 501 case IA_CSS_FRAME_FORMAT_YV12: 502 case IA_CSS_FRAME_FORMAT_YV16: 503 sp_frame_out->planes.yuv.y.offset = 504 frame_in->planes.yuv.y.offset; 505 sp_frame_out->planes.yuv.u.offset = 506 frame_in->planes.yuv.u.offset; 507 sp_frame_out->planes.yuv.v.offset = 508 frame_in->planes.yuv.v.offset; 509 break; 510 case IA_CSS_FRAME_FORMAT_QPLANE6: 511 sp_frame_out->planes.plane6.r.offset = 512 frame_in->planes.plane6.r.offset; 513 sp_frame_out->planes.plane6.r_at_b.offset = 514 frame_in->planes.plane6.r_at_b.offset; 515 sp_frame_out->planes.plane6.gr.offset = 516 frame_in->planes.plane6.gr.offset; 517 sp_frame_out->planes.plane6.gb.offset = 518 frame_in->planes.plane6.gb.offset; 519 sp_frame_out->planes.plane6.b.offset = 520 frame_in->planes.plane6.b.offset; 521 sp_frame_out->planes.plane6.b_at_r.offset = 522 frame_in->planes.plane6.b_at_r.offset; 523 break; 524 case IA_CSS_FRAME_FORMAT_BINARY_8: 525 sp_frame_out->planes.binary.data.offset = 526 frame_in->planes.binary.data.offset; 527 break; 528 default: 529 /* This should not happen, but in case it does, 530 * nullify the planes 531 */ 532 memset(&sp_frame_out->planes, 0, sizeof(sp_frame_out->planes)); 533 break; 534 } 535 } 536 537 static int 538 set_input_frame_buffer(const struct ia_css_frame *frame) 539 { 540 if (!frame) 541 return -EINVAL; 542 543 switch (frame->info.format) { 544 case IA_CSS_FRAME_FORMAT_QPLANE6: 545 case IA_CSS_FRAME_FORMAT_YUV420_16: 546 case IA_CSS_FRAME_FORMAT_RAW_PACKED: 547 case IA_CSS_FRAME_FORMAT_RAW: 548 case IA_CSS_FRAME_FORMAT_YUV420: 549 case IA_CSS_FRAME_FORMAT_YUYV: 550 case IA_CSS_FRAME_FORMAT_YUV_LINE: 551 case IA_CSS_FRAME_FORMAT_NV12: 552 case IA_CSS_FRAME_FORMAT_NV12_16: 553 case IA_CSS_FRAME_FORMAT_NV12_TILEY: 554 case IA_CSS_FRAME_FORMAT_NV21: 555 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8: 556 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8: 557 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_10: 558 break; 559 default: 560 return -EINVAL; 561 } 562 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.in, frame); 563 564 return 0; 565 } 566 567 static int 568 set_output_frame_buffer(const struct ia_css_frame *frame, 569 unsigned int idx) 570 { 571 if (!frame) 572 return -EINVAL; 573 574 switch (frame->info.format) { 575 case IA_CSS_FRAME_FORMAT_YUV420: 576 case IA_CSS_FRAME_FORMAT_YUV422: 577 case IA_CSS_FRAME_FORMAT_YUV444: 578 case IA_CSS_FRAME_FORMAT_YV12: 579 case IA_CSS_FRAME_FORMAT_YV16: 580 case IA_CSS_FRAME_FORMAT_YUV420_16: 581 case IA_CSS_FRAME_FORMAT_YUV422_16: 582 case IA_CSS_FRAME_FORMAT_NV11: 583 case IA_CSS_FRAME_FORMAT_NV12: 584 case IA_CSS_FRAME_FORMAT_NV12_16: 585 case IA_CSS_FRAME_FORMAT_NV12_TILEY: 586 case IA_CSS_FRAME_FORMAT_NV16: 587 case IA_CSS_FRAME_FORMAT_NV21: 588 case IA_CSS_FRAME_FORMAT_NV61: 589 case IA_CSS_FRAME_FORMAT_YUYV: 590 case IA_CSS_FRAME_FORMAT_UYVY: 591 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8: 592 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8: 593 case IA_CSS_FRAME_FORMAT_YUV_LINE: 594 case IA_CSS_FRAME_FORMAT_RGB565: 595 case IA_CSS_FRAME_FORMAT_RGBA888: 596 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888: 597 case IA_CSS_FRAME_FORMAT_RAW: 598 case IA_CSS_FRAME_FORMAT_RAW_PACKED: 599 case IA_CSS_FRAME_FORMAT_QPLANE6: 600 case IA_CSS_FRAME_FORMAT_BINARY_8: 601 break; 602 default: 603 return -EINVAL; 604 } 605 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out[idx], frame); 606 return 0; 607 } 608 609 static int 610 set_view_finder_buffer(const struct ia_css_frame *frame) 611 { 612 if (!frame) 613 return -EINVAL; 614 615 switch (frame->info.format) { 616 /* the dual output pin */ 617 case IA_CSS_FRAME_FORMAT_NV12: 618 case IA_CSS_FRAME_FORMAT_NV12_16: 619 case IA_CSS_FRAME_FORMAT_NV21: 620 case IA_CSS_FRAME_FORMAT_YUYV: 621 case IA_CSS_FRAME_FORMAT_UYVY: 622 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8: 623 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8: 624 case IA_CSS_FRAME_FORMAT_YUV420: 625 case IA_CSS_FRAME_FORMAT_YV12: 626 case IA_CSS_FRAME_FORMAT_NV12_TILEY: 627 628 /* for vf_veceven */ 629 case IA_CSS_FRAME_FORMAT_YUV_LINE: 630 break; 631 default: 632 return -EINVAL; 633 } 634 635 sh_css_copy_frame_to_spframe(&sh_css_sp_stage.frames.out_vf, frame); 636 return 0; 637 } 638 639 #if !defined(ISP2401) 640 void sh_css_sp_set_if_configs( 641 const input_formatter_cfg_t *config_a, 642 const input_formatter_cfg_t *config_b, 643 const uint8_t if_config_index 644 ) 645 { 646 assert(if_config_index < SH_CSS_MAX_IF_CONFIGS); 647 assert(config_a); 648 649 sh_css_sp_group.config.input_formatter.set[if_config_index].config_a = 650 *config_a; 651 sh_css_sp_group.config.input_formatter.a_changed = true; 652 653 if (config_b) { 654 sh_css_sp_group.config.input_formatter.set[if_config_index].config_b = 655 *config_b; 656 sh_css_sp_group.config.input_formatter.b_changed = true; 657 } 658 659 return; 660 } 661 #endif 662 663 #if !defined(ISP2401) 664 void 665 sh_css_sp_program_input_circuit(int fmt_type, 666 int ch_id, 667 enum ia_css_input_mode input_mode) 668 { 669 sh_css_sp_group.config.input_circuit.no_side_band = false; 670 sh_css_sp_group.config.input_circuit.fmt_type = fmt_type; 671 sh_css_sp_group.config.input_circuit.ch_id = ch_id; 672 sh_css_sp_group.config.input_circuit.input_mode = input_mode; 673 /* 674 * The SP group is only loaded at SP boot time and is read once 675 * change flags as "input_circuit_cfg_changed" must be reset on the SP 676 */ 677 sh_css_sp_group.config.input_circuit_cfg_changed = true; 678 sh_css_sp_stage.program_input_circuit = true; 679 } 680 #endif 681 682 #if !defined(ISP2401) 683 void 684 sh_css_sp_configure_sync_gen(int width, int height, 685 int hblank_cycles, 686 int vblank_cycles) 687 { 688 sh_css_sp_group.config.sync_gen.width = width; 689 sh_css_sp_group.config.sync_gen.height = height; 690 sh_css_sp_group.config.sync_gen.hblank_cycles = hblank_cycles; 691 sh_css_sp_group.config.sync_gen.vblank_cycles = vblank_cycles; 692 } 693 694 void 695 sh_css_sp_configure_tpg(int x_mask, 696 int y_mask, 697 int x_delta, 698 int y_delta, 699 int xy_mask) 700 { 701 sh_css_sp_group.config.tpg.x_mask = x_mask; 702 sh_css_sp_group.config.tpg.y_mask = y_mask; 703 sh_css_sp_group.config.tpg.x_delta = x_delta; 704 sh_css_sp_group.config.tpg.y_delta = y_delta; 705 sh_css_sp_group.config.tpg.xy_mask = xy_mask; 706 } 707 708 void 709 sh_css_sp_configure_prbs(int seed) 710 { 711 sh_css_sp_group.config.prbs.seed = seed; 712 } 713 #endif 714 715 void 716 sh_css_sp_configure_enable_raw_pool_locking(bool lock_all) 717 { 718 sh_css_sp_group.config.enable_raw_pool_locking = true; 719 sh_css_sp_group.config.lock_all = lock_all; 720 } 721 722 void 723 sh_css_sp_enable_isys_event_queue(bool enable) 724 { 725 sh_css_sp_group.config.enable_isys_event_queue = enable; 726 } 727 728 void 729 sh_css_sp_set_disable_continuous_viewfinder(bool flag) 730 { 731 sh_css_sp_group.config.disable_cont_vf = flag; 732 } 733 734 static int 735 sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args) 736 { 737 int err = 0; 738 int i; 739 740 assert(args); 741 742 if (args->in_frame) 743 err = set_input_frame_buffer(args->in_frame); 744 if (!err && args->out_vf_frame) 745 err = set_view_finder_buffer(args->out_vf_frame); 746 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { 747 if (!err && args->out_frame[i]) 748 err = set_output_frame_buffer(args->out_frame[i], i); 749 } 750 751 /* we don't pass this error back to the upper layer, so we add a assert here 752 because we actually hit the error here but it still works by accident... */ 753 if (err) assert(false); 754 return err; 755 } 756 757 static void 758 sh_css_sp_init_group(bool two_ppc, 759 enum atomisp_input_format input_format, 760 bool no_isp_sync, 761 uint8_t if_config_index) 762 { 763 #if !defined(ISP2401) 764 sh_css_sp_group.config.input_formatter.isp_2ppc = two_ppc; 765 #else 766 (void)two_ppc; 767 #endif 768 769 sh_css_sp_group.config.no_isp_sync = (uint8_t)no_isp_sync; 770 /* decide whether the frame is processed online or offline */ 771 if (if_config_index == SH_CSS_IF_CONFIG_NOT_NEEDED) return; 772 #if !defined(ISP2401) 773 assert(if_config_index < SH_CSS_MAX_IF_CONFIGS); 774 sh_css_sp_group.config.input_formatter.set[if_config_index].stream_format = 775 input_format; 776 #else 777 (void)input_format; 778 #endif 779 } 780 781 void 782 sh_css_stage_write_binary_info(struct ia_css_binary_info *info) 783 { 784 assert(info); 785 sh_css_isp_stage.binary_info = *info; 786 } 787 788 static int 789 copy_isp_mem_if_to_ddr(struct ia_css_binary *binary) 790 { 791 int err; 792 793 err = ia_css_isp_param_copy_isp_mem_if_to_ddr( 794 &binary->css_params, 795 &binary->mem_params, 796 IA_CSS_PARAM_CLASS_CONFIG); 797 if (err) 798 return err; 799 err = ia_css_isp_param_copy_isp_mem_if_to_ddr( 800 &binary->css_params, 801 &binary->mem_params, 802 IA_CSS_PARAM_CLASS_STATE); 803 if (err) 804 return err; 805 return 0; 806 } 807 808 static bool 809 is_sp_stage(struct ia_css_pipeline_stage *stage) 810 { 811 assert(stage); 812 return stage->sp_func != IA_CSS_PIPELINE_NO_FUNC; 813 } 814 815 static int configure_isp_from_args(const struct sh_css_sp_pipeline *pipeline, 816 const struct ia_css_binary *binary, 817 const struct sh_css_binary_args *args, 818 bool two_ppc, 819 bool deinterleaved) 820 { 821 int ret; 822 823 ret = ia_css_fpn_configure(binary, &binary->in_frame_info); 824 if (ret) 825 return ret; 826 ret = ia_css_crop_configure(binary, &args->delay_frames[0]->info); 827 if (ret) 828 return ret; 829 ret = ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info); 830 if (ret) 831 return ret; 832 ret = ia_css_output0_configure(binary, &args->out_frame[0]->info); 833 if (ret) 834 return ret; 835 ret = ia_css_output1_configure(binary, &args->out_vf_frame->info); 836 if (ret) 837 return ret; 838 ret = ia_css_copy_output_configure(binary, args->copy_output); 839 if (ret) 840 return ret; 841 ret = ia_css_output0_configure(binary, &args->out_frame[0]->info); 842 if (ret) 843 return ret; 844 ret = ia_css_iterator_configure(binary, &args->in_frame->info); 845 if (ret) 846 return ret; 847 ret = ia_css_dvs_configure(binary, &args->out_frame[0]->info); 848 if (ret) 849 return ret; 850 ret = ia_css_output_configure(binary, &args->out_frame[0]->info); 851 if (ret) 852 return ret; 853 ret = ia_css_raw_configure(pipeline, binary, &args->in_frame->info, &binary->in_frame_info, two_ppc, deinterleaved); 854 if (ret) 855 return ret; 856 857 /* 858 * FIXME: args->delay_frames can be NULL here 859 * 860 * Somehow, the driver at the Intel Atom Yocto tree doesn't seem to 861 * suffer from the same issue. 862 * 863 * Anyway, the function below should now handle a NULL delay_frames 864 * without crashing, but the pipeline should likely be built without 865 * adding it at the first place (or there are a hidden bug somewhere) 866 */ 867 ret = ia_css_ref_configure(binary, args->delay_frames, pipeline->dvs_frame_delay); 868 if (ret) 869 return ret; 870 ret = ia_css_tnr_configure(binary, args->tnr_frames); 871 if (ret) 872 return ret; 873 return ia_css_bayer_io_config(binary, args); 874 } 875 876 static void 877 initialize_isp_states(const struct ia_css_binary *binary) 878 { 879 unsigned int i; 880 881 if (!binary->info->mem_offsets.offsets.state) 882 return; 883 for (i = 0; i < IA_CSS_NUM_STATE_IDS; i++) { 884 ia_css_kernel_init_state[i](binary); 885 } 886 } 887 888 static void 889 initialize_frame_buffer_attribute(struct ia_css_buffer_sp *buf_attr) 890 { 891 buf_attr->buf_src.queue_id = SH_CSS_INVALID_QUEUE_ID; 892 buf_attr->buf_type = IA_CSS_BUFFER_TYPE_INVALID; 893 } 894 895 static void 896 initialize_stage_frames(struct ia_css_frames_sp *frames) 897 { 898 unsigned int i; 899 900 initialize_frame_buffer_attribute(&frames->in.buf_attr); 901 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { 902 initialize_frame_buffer_attribute(&frames->out[i].buf_attr); 903 } 904 initialize_frame_buffer_attribute(&frames->out_vf.buf_attr); 905 initialize_frame_buffer_attribute(&frames->s3a_buf); 906 initialize_frame_buffer_attribute(&frames->dvs_buf); 907 #if defined SH_CSS_ENABLE_METADATA 908 initialize_frame_buffer_attribute(&frames->metadata_buf); 909 #endif 910 } 911 912 static int 913 sh_css_sp_init_stage(struct ia_css_binary *binary, 914 const char *binary_name, 915 const struct ia_css_blob_info *blob_info, 916 const struct sh_css_binary_args *args, 917 unsigned int pipe_num, 918 unsigned int stage, 919 bool xnr, 920 const struct ia_css_isp_param_css_segments *isp_mem_if, 921 unsigned int if_config_index, 922 bool two_ppc) 923 { 924 const struct ia_css_binary_xinfo *xinfo; 925 const struct ia_css_binary_info *info; 926 int err = 0; 927 int i; 928 struct ia_css_pipe *pipe = NULL; 929 unsigned int thread_id; 930 enum sh_css_queue_id queue_id; 931 bool continuous = sh_css_continuous_is_enabled((uint8_t)pipe_num); 932 933 assert(binary); 934 assert(blob_info); 935 assert(args); 936 assert(isp_mem_if); 937 938 xinfo = binary->info; 939 info = &xinfo->sp; 940 { 941 /* 942 * Clear sh_css_sp_stage for easy debugging. 943 * program_input_circuit must be saved as it is set outside 944 * this function. 945 */ 946 u8 program_input_circuit; 947 948 program_input_circuit = sh_css_sp_stage.program_input_circuit; 949 memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage)); 950 sh_css_sp_stage.program_input_circuit = (uint8_t)program_input_circuit; 951 } 952 953 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 954 955 if (!info) { 956 sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL; 957 return 0; 958 } 959 960 #if defined(ISP2401) 961 (void)continuous; 962 sh_css_sp_stage.deinterleaved = 0; 963 #else 964 sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous); 965 #endif 966 967 initialize_stage_frames(&sh_css_sp_stage.frames); 968 /* 969 * TODO: Make the Host dynamically determine 970 * the stage type. 971 */ 972 sh_css_sp_stage.stage_type = SH_CSS_ISP_STAGE_TYPE; 973 sh_css_sp_stage.num = (uint8_t)stage; 974 sh_css_sp_stage.isp_online = (uint8_t)binary->online; 975 sh_css_sp_stage.isp_copy_vf = (uint8_t)args->copy_vf; 976 sh_css_sp_stage.isp_copy_output = (uint8_t)args->copy_output; 977 sh_css_sp_stage.enable.vf_output = (args->out_vf_frame != NULL); 978 979 /* Copy the frame infos first, to be overwritten by the frames, 980 if these are present. 981 */ 982 sh_css_sp_stage.frames.effective_in_res.width = binary->effective_in_frame_res.width; 983 sh_css_sp_stage.frames.effective_in_res.height = binary->effective_in_frame_res.height; 984 985 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.in.info, 986 &binary->in_frame_info); 987 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { 988 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.out[i].info, 989 &binary->out_frame_info[i]); 990 } 991 ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.internal_frame_info, 992 &binary->internal_frame_info); 993 sh_css_sp_stage.dvs_envelope.width = binary->dvs_envelope.width; 994 sh_css_sp_stage.dvs_envelope.height = binary->dvs_envelope.height; 995 sh_css_sp_stage.isp_pipe_version = (uint8_t)info->pipeline.isp_pipe_version; 996 sh_css_sp_stage.isp_deci_log_factor = (uint8_t)binary->deci_factor_log2; 997 sh_css_sp_stage.isp_vf_downscale_bits = (uint8_t)binary->vf_downscale_log2; 998 999 sh_css_sp_stage.if_config_index = (uint8_t)if_config_index; 1000 1001 sh_css_sp_stage.sp_enable_xnr = (uint8_t)xnr; 1002 sh_css_sp_stage.xmem_bin_addr = xinfo->xmem_addr; 1003 sh_css_sp_stage.xmem_map_addr = sh_css_params_ddr_address_map(); 1004 sh_css_isp_stage.blob_info = *blob_info; 1005 sh_css_stage_write_binary_info((struct ia_css_binary_info *)info); 1006 1007 /* Make sure binary name is smaller than allowed string size */ 1008 assert(strlen(binary_name) < SH_CSS_MAX_BINARY_NAME - 1); 1009 strscpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME); 1010 sh_css_isp_stage.mem_initializers = *isp_mem_if; 1011 1012 /* 1013 * Even when a stage does not need uds and does not params, 1014 * ia_css_uds_sp_scale_params() seems to be called (needs 1015 * further investigation). This function can not deal with 1016 * dx, dy = {0, 0} 1017 */ 1018 1019 err = sh_css_sp_write_frame_pointers(args); 1020 /* TODO: move it to a better place */ 1021 if (binary->info->sp.enable.s3a) { 1022 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_3A_STATISTICS, thread_id, 1023 &queue_id); 1024 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.s3a_buf, queue_id, 1025 mmgr_EXCEPTION, 1026 IA_CSS_BUFFER_TYPE_3A_STATISTICS); 1027 } 1028 if (binary->info->sp.enable.dis) { 1029 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id, 1030 &queue_id); 1031 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id, 1032 mmgr_EXCEPTION, 1033 IA_CSS_BUFFER_TYPE_DIS_STATISTICS); 1034 } 1035 #if defined SH_CSS_ENABLE_METADATA 1036 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_METADATA, thread_id, &queue_id); 1037 sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.metadata_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_METADATA); 1038 #endif 1039 if (err) 1040 return err; 1041 1042 #ifdef ISP2401 1043 if (stage == 0) { 1044 pipe = find_pipe_by_num(sh_css_sp_group.pipe[thread_id].pipe_num); 1045 if (!pipe) 1046 return -EINVAL; 1047 1048 if (args->in_frame) 1049 ia_css_get_crop_offsets(pipe, &args->in_frame->info); 1050 else 1051 ia_css_get_crop_offsets(pipe, &binary->in_frame_info); 1052 } 1053 #else 1054 (void)pipe; /*avoid build warning*/ 1055 #endif 1056 1057 err = configure_isp_from_args(&sh_css_sp_group.pipe[thread_id], 1058 binary, args, two_ppc, sh_css_sp_stage.deinterleaved); 1059 if (err) 1060 return err; 1061 1062 initialize_isp_states(binary); 1063 1064 /* we do this only for preview pipe because in fill_binary_info function 1065 * we assign vf_out res to out res, but for ISP internal processing, we need 1066 * the original out res. for video pipe, it has two output pins --- out and 1067 * vf_out, so it can keep these two resolutions already. */ 1068 if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW && 1069 (binary->vf_downscale_log2 > 0)) { 1070 /* TODO: Remove this after preview output decimation is fixed 1071 * by configuring out&vf info fiels properly */ 1072 sh_css_sp_stage.frames.out[0].info.padded_width 1073 <<= binary->vf_downscale_log2; 1074 sh_css_sp_stage.frames.out[0].info.res.width 1075 <<= binary->vf_downscale_log2; 1076 sh_css_sp_stage.frames.out[0].info.res.height 1077 <<= binary->vf_downscale_log2; 1078 } 1079 err = copy_isp_mem_if_to_ddr(binary); 1080 if (err) 1081 return err; 1082 1083 return 0; 1084 } 1085 1086 static int 1087 sp_init_stage(struct ia_css_pipeline_stage *stage, 1088 unsigned int pipe_num, 1089 bool xnr, 1090 unsigned int if_config_index, 1091 bool two_ppc) 1092 { 1093 struct ia_css_binary *binary; 1094 const struct ia_css_fw_info *firmware; 1095 const struct sh_css_binary_args *args; 1096 unsigned int stage_num; 1097 /* 1098 * Initialiser required because of the "else" path below. 1099 * Is this a valid path ? 1100 */ 1101 const char *binary_name = ""; 1102 const struct ia_css_binary_xinfo *info = NULL; 1103 /* note: the var below is made static as it is quite large; 1104 if it is not static it ends up on the stack which could 1105 cause issues for drivers 1106 */ 1107 static struct ia_css_binary tmp_binary; 1108 const struct ia_css_blob_info *blob_info = NULL; 1109 struct ia_css_isp_param_css_segments isp_mem_if; 1110 /* LA: should be ia_css_data, should not contain host pointer. 1111 However, CSS/DDR pointer is not available yet. 1112 Hack is to store it in params->ddr_ptrs and then copy it late in the SP just before vmem init. 1113 TODO: Call this after CSS/DDR allocation and store that pointer. 1114 Best is to allocate it at stage creation time together with host pointer. 1115 Remove vmem from params. 1116 */ 1117 struct ia_css_isp_param_css_segments *mem_if = &isp_mem_if; 1118 1119 int err = 0; 1120 1121 assert(stage); 1122 1123 binary = stage->binary; 1124 firmware = stage->firmware; 1125 args = &stage->args; 1126 stage_num = stage->stage_num; 1127 1128 if (binary) { 1129 info = binary->info; 1130 binary_name = (const char *)(info->blob->name); 1131 blob_info = &info->blob->header.blob; 1132 ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params); 1133 } else if (firmware) { 1134 const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL}; 1135 1136 if (args->out_frame[0]) 1137 out_infos[0] = &args->out_frame[0]->info; 1138 info = &firmware->info.isp; 1139 ia_css_binary_fill_info(info, false, false, 1140 ATOMISP_INPUT_FORMAT_RAW_10, 1141 args->in_frame ? &args->in_frame->info : NULL, 1142 NULL, 1143 out_infos, 1144 args->out_vf_frame ? &args->out_vf_frame->info 1145 : NULL, 1146 &tmp_binary, 1147 NULL, 1148 -1, true); 1149 binary = &tmp_binary; 1150 binary->info = info; 1151 binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware); 1152 blob_info = &firmware->blob; 1153 mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers; 1154 } else { 1155 /* SP stage */ 1156 assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC); 1157 /* binary and blob_info are now NULL. 1158 These will be passed to sh_css_sp_init_stage 1159 and dereferenced there, so passing a NULL 1160 pointer is no good. return an error */ 1161 return -EINVAL; 1162 } 1163 1164 err = sh_css_sp_init_stage(binary, 1165 (const char *)binary_name, 1166 blob_info, 1167 args, 1168 pipe_num, 1169 stage_num, 1170 xnr, 1171 mem_if, 1172 if_config_index, 1173 two_ppc); 1174 return err; 1175 } 1176 1177 static void 1178 sp_init_sp_stage(struct ia_css_pipeline_stage *stage, 1179 unsigned int pipe_num, 1180 bool two_ppc, 1181 enum sh_css_pipe_config_override copy_ovrd, 1182 unsigned int if_config_index) 1183 { 1184 const struct sh_css_binary_args *args = &stage->args; 1185 1186 assert(stage); 1187 switch (stage->sp_func) { 1188 case IA_CSS_PIPELINE_RAW_COPY: 1189 sh_css_sp_start_raw_copy(args->out_frame[0], 1190 pipe_num, two_ppc, 1191 stage->max_input_width, 1192 copy_ovrd, if_config_index); 1193 break; 1194 case IA_CSS_PIPELINE_BIN_COPY: 1195 assert(false); /* TBI */ 1196 break; 1197 case IA_CSS_PIPELINE_ISYS_COPY: 1198 sh_css_sp_start_isys_copy(args->out_frame[0], 1199 pipe_num, stage->max_input_width, if_config_index); 1200 break; 1201 case IA_CSS_PIPELINE_NO_FUNC: 1202 assert(false); 1203 break; 1204 } 1205 } 1206 1207 void 1208 sh_css_sp_init_pipeline(struct ia_css_pipeline *me, 1209 enum ia_css_pipe_id id, 1210 u8 pipe_num, 1211 bool xnr, 1212 bool two_ppc, 1213 bool continuous, 1214 bool offline, 1215 unsigned int required_bds_factor, 1216 enum sh_css_pipe_config_override copy_ovrd, 1217 enum ia_css_input_mode input_mode, 1218 const struct ia_css_metadata_config *md_config, 1219 const struct ia_css_metadata_info *md_info, 1220 const enum mipi_port_id port_id) 1221 { 1222 /* Get first stage */ 1223 struct ia_css_pipeline_stage *stage = NULL; 1224 struct ia_css_binary *first_binary = NULL; 1225 struct ia_css_pipe *pipe = NULL; 1226 unsigned int num; 1227 1228 enum ia_css_pipe_id pipe_id = id; 1229 unsigned int thread_id; 1230 u8 if_config_index, tmp_if_config_index; 1231 1232 assert(me); 1233 1234 assert(me->stages); 1235 1236 first_binary = me->stages->binary; 1237 1238 if (input_mode == IA_CSS_INPUT_MODE_SENSOR || 1239 input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { 1240 assert(port_id < N_MIPI_PORT_ID); 1241 if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */ 1242 return; /* we should be able to return an error */ 1243 if_config_index = (uint8_t)(port_id - MIPI_PORT0_ID); 1244 } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY) { 1245 if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; 1246 } else { 1247 if_config_index = 0x0; 1248 } 1249 1250 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 1251 memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline)); 1252 1253 /* Count stages */ 1254 for (stage = me->stages, num = 0; stage; stage = stage->next, num++) { 1255 stage->stage_num = num; 1256 ia_css_debug_pipe_graph_dump_stage(stage, id); 1257 } 1258 me->num_stages = num; 1259 1260 if (first_binary) { 1261 /* Init pipeline data */ 1262 sh_css_sp_init_group(two_ppc, first_binary->input_format, 1263 offline, if_config_index); 1264 } /* if (first_binary != NULL) */ 1265 1266 /* Signal the host immediately after start for SP_ISYS_COPY only */ 1267 if ((me->num_stages == 1) && me->stages && 1268 (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY)) 1269 sh_css_sp_group.config.no_isp_sync = true; 1270 1271 /* Init stage data */ 1272 sh_css_init_host2sp_frame_data(); 1273 1274 sh_css_sp_group.pipe[thread_id].num_stages = 0; 1275 sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id; 1276 sh_css_sp_group.pipe[thread_id].thread_id = thread_id; 1277 sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num; 1278 sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs; 1279 sh_css_sp_group.pipe[thread_id].pipe_qos_config = me->pipe_qos_config; 1280 sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor; 1281 sh_css_sp_group.pipe[thread_id].input_system_mode 1282 = (uint32_t)input_mode; 1283 sh_css_sp_group.pipe[thread_id].port_id = port_id; 1284 sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay; 1285 1286 /* TODO: next indicates from which queues parameters need to be 1287 sampled, needs checking/improvement */ 1288 if (ia_css_pipeline_uses_params(me)) { 1289 sh_css_sp_group.pipe[thread_id].pipe_config = 1290 SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id; 1291 } 1292 1293 /* For continuous use-cases, SP copy is responsible for sampling the 1294 * parameters */ 1295 if (continuous) 1296 sh_css_sp_group.pipe[thread_id].pipe_config = 0; 1297 1298 sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config; 1299 1300 pipe = find_pipe_by_num(pipe_num); 1301 assert(pipe); 1302 if (!pipe) { 1303 return; 1304 } 1305 sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe); 1306 1307 #if defined(SH_CSS_ENABLE_METADATA) 1308 if (md_info && md_info->size > 0) { 1309 sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width; 1310 sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height; 1311 sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride; 1312 sh_css_sp_group.pipe[thread_id].metadata.size = md_info->size; 1313 ia_css_isys_convert_stream_format_to_mipi_format( 1314 md_config->data_type, MIPI_PREDICTOR_NONE, 1315 &sh_css_sp_group.pipe[thread_id].metadata.format); 1316 } 1317 #else 1318 (void)md_config; 1319 (void)md_info; 1320 #endif 1321 1322 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) 1323 sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID; 1324 if (pipe_id != IA_CSS_PIPE_ID_COPY) { 1325 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, 1326 (enum sh_css_queue_id *)( 1327 &sh_css_sp_group.pipe[thread_id].output_frame_queue_id)); 1328 } 1329 #endif 1330 1331 IA_CSS_LOG("pipe_id %d port_config %08x", 1332 pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config); 1333 1334 for (stage = me->stages, num = 0; stage; stage = stage->next, num++) { 1335 sh_css_sp_group.pipe[thread_id].num_stages++; 1336 if (is_sp_stage(stage)) { 1337 sp_init_sp_stage(stage, pipe_num, two_ppc, 1338 copy_ovrd, if_config_index); 1339 } else { 1340 if ((stage->stage_num != 0) || 1341 SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config)) 1342 tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; 1343 else 1344 tmp_if_config_index = if_config_index; 1345 sp_init_stage(stage, pipe_num, 1346 xnr, tmp_if_config_index, two_ppc); 1347 } 1348 1349 store_sp_stage_data(pipe_id, pipe_num, num); 1350 } 1351 sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t) 1352 (me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS); 1353 store_sp_group_data(); 1354 } 1355 1356 void 1357 sh_css_sp_uninit_pipeline(unsigned int pipe_num) 1358 { 1359 unsigned int thread_id; 1360 1361 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); 1362 /*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/ 1363 sh_css_sp_group.pipe[thread_id].num_stages = 0; 1364 } 1365 1366 bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command) 1367 { 1368 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1369 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, 1370 host2sp_command) 1371 / sizeof(int); 1372 enum host2sp_commands last_cmd = host2sp_cmd_error; 1373 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1374 1375 /* Previous command must be handled by SP (by design) */ 1376 last_cmd = load_sp_array_uint(host_sp_com, offset); 1377 if (last_cmd != host2sp_cmd_ready) 1378 IA_CSS_ERROR("last host command not handled by SP(%d)", last_cmd); 1379 1380 store_sp_array_uint(host_sp_com, offset, host2sp_command); 1381 1382 return (last_cmd == host2sp_cmd_ready); 1383 } 1384 1385 enum host2sp_commands 1386 sh_css_read_host2sp_command(void) 1387 { 1388 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1389 unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command) 1390 / sizeof(int); 1391 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1392 return (enum host2sp_commands)load_sp_array_uint(host_sp_com, offset); 1393 } 1394 1395 /* 1396 * Frame data is no longer part of the sp_stage structure but part of a 1397 * separate structure. The aim is to make the sp_data struct static 1398 * (it defines a pipeline) and that the dynamic (per frame) data is stored 1399 * separetly. 1400 * 1401 * This function must be called first every where were you start constructing 1402 * a new pipeline by defining one or more stages with use of variable 1403 * sh_css_sp_stage. Even the special cases like accelerator and copy_frame 1404 * These have a pipeline of just 1 stage. 1405 */ 1406 void 1407 sh_css_init_host2sp_frame_data(void) 1408 { 1409 /* Clean table */ 1410 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1411 1412 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1413 /* 1414 * rvanimme: don't clean it to save static frame info line ref_in 1415 * ref_out, and tnr_frames. Once this static data is in a 1416 * separate data struct, this may be enable (but still, there is 1417 * no need for it) 1418 */ 1419 } 1420 1421 /* 1422 * @brief Update the offline frame information in host_sp_communication. 1423 * Refer to "sh_css_sp.h" for more details. 1424 */ 1425 void 1426 sh_css_update_host2sp_offline_frame( 1427 unsigned int frame_num, 1428 struct ia_css_frame *frame, 1429 struct ia_css_metadata *metadata) 1430 { 1431 unsigned int HIVE_ADDR_host_sp_com; 1432 unsigned int offset; 1433 1434 assert(frame_num < NUM_CONTINUOUS_FRAMES); 1435 1436 /* Write new frame data into SP DMEM */ 1437 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1438 offset = (unsigned int)offsetof(struct host_sp_communication, 1439 host2sp_offline_frames) 1440 / sizeof(int); 1441 offset += frame_num; 1442 store_sp_array_uint(host_sp_com, offset, frame ? frame->data : 0); 1443 1444 /* Write metadata buffer into SP DMEM */ 1445 offset = (unsigned int)offsetof(struct host_sp_communication, 1446 host2sp_offline_metadata) 1447 / sizeof(int); 1448 offset += frame_num; 1449 store_sp_array_uint(host_sp_com, offset, metadata ? metadata->address : 0); 1450 } 1451 1452 /* 1453 * @brief Update the mipi frame information in host_sp_communication. 1454 * Refer to "sh_css_sp.h" for more details. 1455 */ 1456 void 1457 sh_css_update_host2sp_mipi_frame( 1458 unsigned int frame_num, 1459 struct ia_css_frame *frame) 1460 { 1461 unsigned int HIVE_ADDR_host_sp_com; 1462 unsigned int offset; 1463 1464 /* MIPI buffers are dedicated to port, so now there are more of them. */ 1465 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM)); 1466 1467 /* Write new frame data into SP DMEM */ 1468 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1469 offset = (unsigned int)offsetof(struct host_sp_communication, 1470 host2sp_mipi_frames) 1471 / sizeof(int); 1472 offset += frame_num; 1473 1474 store_sp_array_uint(host_sp_com, offset, 1475 frame ? frame->data : 0); 1476 } 1477 1478 /* 1479 * @brief Update the mipi metadata information in host_sp_communication. 1480 * Refer to "sh_css_sp.h" for more details. 1481 */ 1482 void 1483 sh_css_update_host2sp_mipi_metadata( 1484 unsigned int frame_num, 1485 struct ia_css_metadata *metadata) 1486 { 1487 unsigned int HIVE_ADDR_host_sp_com; 1488 unsigned int o; 1489 1490 /* MIPI buffers are dedicated to port, so now there are more of them. */ 1491 assert(frame_num < (N_CSI_PORTS * NUM_MIPI_FRAMES_PER_STREAM)); 1492 1493 /* Write new frame data into SP DMEM */ 1494 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1495 o = offsetof(struct host_sp_communication, host2sp_mipi_metadata) 1496 / sizeof(int); 1497 o += frame_num; 1498 store_sp_array_uint(host_sp_com, o, 1499 metadata ? metadata->address : 0); 1500 } 1501 1502 void 1503 sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames) 1504 { 1505 unsigned int HIVE_ADDR_host_sp_com; 1506 unsigned int offset; 1507 1508 /* Write new frame data into SP DMEM */ 1509 HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1510 offset = (unsigned int)offsetof(struct host_sp_communication, 1511 host2sp_num_mipi_frames) 1512 / sizeof(int); 1513 1514 store_sp_array_uint(host_sp_com, offset, num_frames); 1515 } 1516 1517 void 1518 sh_css_update_host2sp_cont_num_raw_frames(unsigned int num_frames, 1519 bool set_avail) 1520 { 1521 const struct ia_css_fw_info *fw; 1522 unsigned int HIVE_ADDR_host_sp_com; 1523 unsigned int extra_num_frames, avail_num_frames; 1524 unsigned int offset, offset_extra; 1525 1526 /* Write new frame data into SP DMEM */ 1527 fw = &sh_css_sp_fw; 1528 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com; 1529 if (set_avail) { 1530 offset = (unsigned int)offsetof(struct host_sp_communication, 1531 host2sp_cont_avail_num_raw_frames) 1532 / sizeof(int); 1533 avail_num_frames = load_sp_array_uint(host_sp_com, offset); 1534 extra_num_frames = num_frames - avail_num_frames; 1535 offset_extra = (unsigned int)offsetof(struct host_sp_communication, 1536 host2sp_cont_extra_num_raw_frames) 1537 / sizeof(int); 1538 store_sp_array_uint(host_sp_com, offset_extra, extra_num_frames); 1539 } else 1540 offset = (unsigned int)offsetof(struct host_sp_communication, 1541 host2sp_cont_target_num_raw_frames) 1542 / sizeof(int); 1543 1544 store_sp_array_uint(host_sp_com, offset, num_frames); 1545 } 1546 1547 void 1548 sh_css_event_init_irq_mask(void) 1549 { 1550 int i; 1551 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1552 unsigned int offset; 1553 struct sh_css_event_irq_mask event_irq_mask_init; 1554 1555 event_irq_mask_init.or_mask = IA_CSS_EVENT_TYPE_ALL; 1556 event_irq_mask_init.and_mask = IA_CSS_EVENT_TYPE_NONE; 1557 (void)HIVE_ADDR_host_sp_com; /* Suppress warnings in CRUN */ 1558 1559 assert(sizeof(event_irq_mask_init) % HRT_BUS_BYTES == 0); 1560 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { 1561 offset = (unsigned int)offsetof(struct host_sp_communication, 1562 host2sp_event_irq_mask[i]); 1563 assert(offset % HRT_BUS_BYTES == 0); 1564 sp_dmem_store(SP0_ID, 1565 (unsigned int)sp_address_of(host_sp_com) + offset, 1566 &event_irq_mask_init, sizeof(event_irq_mask_init)); 1567 } 1568 } 1569 1570 int 1571 ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe, 1572 unsigned int or_mask, 1573 unsigned int and_mask) 1574 { 1575 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1576 unsigned int offset; 1577 struct sh_css_event_irq_mask event_irq_mask; 1578 unsigned int pipe_num; 1579 1580 assert(pipe); 1581 1582 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES); 1583 /* Linux kernel does not have UINT16_MAX 1584 * Therefore decided to comment out these 2 asserts for Linux 1585 * Alternatives that were not chosen: 1586 * - add a conditional #define for UINT16_MAX 1587 * - compare with (uint16_t)~0 or 0xffff 1588 * - different assert for Linux and Windows 1589 */ 1590 1591 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1592 1593 IA_CSS_LOG("or_mask=%x, and_mask=%x", or_mask, and_mask); 1594 event_irq_mask.or_mask = (uint16_t)or_mask; 1595 event_irq_mask.and_mask = (uint16_t)and_mask; 1596 1597 pipe_num = ia_css_pipe_get_pipe_num(pipe); 1598 if (pipe_num >= IA_CSS_PIPE_ID_NUM) 1599 return -EINVAL; 1600 offset = (unsigned int)offsetof(struct host_sp_communication, 1601 host2sp_event_irq_mask[pipe_num]); 1602 assert(offset % HRT_BUS_BYTES == 0); 1603 sp_dmem_store(SP0_ID, 1604 (unsigned int)sp_address_of(host_sp_com) + offset, 1605 &event_irq_mask, sizeof(event_irq_mask)); 1606 1607 return 0; 1608 } 1609 1610 int 1611 ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe, 1612 unsigned int *or_mask, 1613 unsigned int *and_mask) 1614 { 1615 unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; 1616 unsigned int offset; 1617 struct sh_css_event_irq_mask event_irq_mask; 1618 unsigned int pipe_num; 1619 1620 (void)HIVE_ADDR_host_sp_com; /* Suppres warnings in CRUN */ 1621 1622 IA_CSS_ENTER_LEAVE(""); 1623 1624 assert(pipe); 1625 assert(IA_CSS_PIPE_ID_NUM == NR_OF_PIPELINES); 1626 1627 pipe_num = ia_css_pipe_get_pipe_num(pipe); 1628 if (pipe_num >= IA_CSS_PIPE_ID_NUM) 1629 return -EINVAL; 1630 offset = (unsigned int)offsetof(struct host_sp_communication, 1631 host2sp_event_irq_mask[pipe_num]); 1632 assert(offset % HRT_BUS_BYTES == 0); 1633 sp_dmem_load(SP0_ID, 1634 (unsigned int)sp_address_of(host_sp_com) + offset, 1635 &event_irq_mask, sizeof(event_irq_mask)); 1636 1637 if (or_mask) 1638 *or_mask = event_irq_mask.or_mask; 1639 1640 if (and_mask) 1641 *and_mask = event_irq_mask.and_mask; 1642 1643 return 0; 1644 } 1645 1646 void 1647 sh_css_sp_set_sp_running(bool flag) 1648 { 1649 sp_running = flag; 1650 } 1651 1652 bool 1653 sh_css_sp_is_running(void) 1654 { 1655 return sp_running; 1656 } 1657 1658 void 1659 sh_css_sp_start_isp(void) 1660 { 1661 const struct ia_css_fw_info *fw; 1662 unsigned int HIVE_ADDR_sp_sw_state; 1663 1664 fw = &sh_css_sp_fw; 1665 HIVE_ADDR_sp_sw_state = fw->info.sp.sw_state; 1666 1667 if (sp_running) 1668 return; 1669 1670 (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */ 1671 1672 /* no longer here, sp started immediately */ 1673 /*ia_css_debug_pipe_graph_dump_epilogue();*/ 1674 1675 store_sp_group_data(); 1676 store_sp_per_frame_data(fw); 1677 1678 sp_dmem_store_uint32(SP0_ID, 1679 (unsigned int)sp_address_of(sp_sw_state), 1680 (uint32_t)(IA_CSS_SP_SW_TERMINATED)); 1681 1682 /* Note 1: The sp_start_isp function contains a wait till 1683 * the input network is configured by the SP. 1684 * Note 2: Not all SP binaries supports host2sp_commands. 1685 * In case a binary does support it, the host2sp_command 1686 * will have status cmd_ready after return of the function 1687 * sh_css_hrt_sp_start_isp. There is no race-condition here 1688 * because only after the process_frame command has been 1689 * received, the SP starts configuring the input network. 1690 */ 1691 1692 /* we need to set sp_running before we call ia_css_mmu_invalidate_cache 1693 * as ia_css_mmu_invalidate_cache checks on sp_running to 1694 * avoid that it accesses dmem while the SP is not powered 1695 */ 1696 sp_running = true; 1697 ia_css_mmu_invalidate_cache(); 1698 /* Invalidate all MMU caches */ 1699 mmu_invalidate_cache_all(); 1700 1701 ia_css_spctrl_start(SP0_ID); 1702 } 1703 1704 bool 1705 ia_css_isp_has_started(void) 1706 { 1707 const struct ia_css_fw_info *fw = &sh_css_sp_fw; 1708 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started; 1709 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */ 1710 1711 return (bool)load_sp_uint(ia_css_ispctrl_sp_isp_started); 1712 } 1713 1714 /* 1715 * @brief Initialize the DMA software-mask in the debug mode. 1716 * Refer to "sh_css_sp.h" for more details. 1717 */ 1718 bool 1719 sh_css_sp_init_dma_sw_reg(int dma_id) 1720 { 1721 int i; 1722 1723 /* enable all the DMA channels */ 1724 for (i = 0; i < N_DMA_CHANNEL_ID; i++) { 1725 /* enable the writing request */ 1726 sh_css_sp_set_dma_sw_reg(dma_id, 1727 i, 1728 0, 1729 true); 1730 /* enable the reading request */ 1731 sh_css_sp_set_dma_sw_reg(dma_id, 1732 i, 1733 1, 1734 true); 1735 } 1736 1737 return true; 1738 } 1739 1740 /* 1741 * @brief Set the DMA software-mask in the debug mode. 1742 * Refer to "sh_css_sp.h" for more details. 1743 */ 1744 bool 1745 sh_css_sp_set_dma_sw_reg(int dma_id, 1746 int channel_id, 1747 int request_type, 1748 bool enable) 1749 { 1750 u32 sw_reg; 1751 u32 bit_val; 1752 u32 bit_offset; 1753 u32 bit_mask; 1754 1755 (void)dma_id; 1756 1757 assert(channel_id >= 0 && channel_id < N_DMA_CHANNEL_ID); 1758 assert(request_type >= 0); 1759 1760 /* get the software-mask */ 1761 sw_reg = 1762 sh_css_sp_group.debug.dma_sw_reg; 1763 1764 /* get the offest of the target bit */ 1765 bit_offset = (8 * request_type) + channel_id; 1766 1767 /* clear the value of the target bit */ 1768 bit_mask = ~(1 << bit_offset); 1769 sw_reg &= bit_mask; 1770 1771 /* set the value of the bit for the DMA channel */ 1772 bit_val = enable ? 1 : 0; 1773 bit_val <<= bit_offset; 1774 sw_reg |= bit_val; 1775 1776 /* update the software status of DMA channels */ 1777 sh_css_sp_group.debug.dma_sw_reg = sw_reg; 1778 1779 return true; 1780 } 1781 1782 void 1783 sh_css_sp_reset_global_vars(void) 1784 { 1785 memset(&sh_css_sp_group, 0, sizeof(struct sh_css_sp_group)); 1786 memset(&sh_css_sp_stage, 0, sizeof(struct sh_css_sp_stage)); 1787 memset(&sh_css_isp_stage, 0, sizeof(struct sh_css_isp_stage)); 1788 memset(&sh_css_sp_output, 0, sizeof(struct sh_css_sp_output)); 1789 memset(&per_frame_data, 0, sizeof(struct sh_css_sp_per_frame_data)); 1790 } 1791