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