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