static void sh_css_sp_start_isys_copy(struct ia_css_frame *out_frame, unsigned pipe_num, unsigned max_input_width) { enum ia_css_pipe_id pipe_id; unsigned int thread_id; uint8_t stage_num = 0; struct sh_css_sp_pipeline *pipe; int i; assert(out_frame != NULL); { /** * Clear sh_css_sp_stage for easy debugging. * program_input_circuit must be saved as it is set outside * this function. */ uint8_t program_input_circuit; program_input_circuit = sh_css_sp_stage.program_input_circuit; memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage)); sh_css_sp_stage.program_input_circuit = program_input_circuit; } pipe_id = IA_CSS_PIPE_ID_COPY; ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); pipe = &sh_css_sp_group.pipe[thread_id]; pipe->copy.raw.height = out_frame->info.res.height; pipe->copy.raw.width = out_frame->info.res.width; pipe->copy.raw.padded_width = out_frame->info.padded_width; pipe->copy.raw.raw_bit_depth = out_frame->info.raw_bit_depth; pipe->copy.raw.max_input_width = max_input_width; pipe->num_stages = 1; pipe->pipe_id = pipe_id; pipe->pipe_config = 0x0; /* No parameters */ /* Clean static frame info before we update it */ /* * TODO: Initialize the static frame data with * "sh_css_frame_null". */ for (i = 0; i < SH_CSS_NUM_FRAME_IDS; i++) /* Here, we do not initialize it to zero for now * to be able to recognize non-updated elements * This is what it should become: * sh_css_sp_stage.frames.static_frame_data[i] = mmgr_NULL; */ sh_css_sp_stage.frames.static_frame_data[i] = mmgr_EXCEPTION; sh_css_sp_stage.num = stage_num; sh_css_sp_stage.xmem_bin_addr = 0x0; sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE; sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_ISYS_COPY; set_output_frame_buffer(out_frame, (unsigned)pipe_id, stage_num); ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame); }
void sh_css_sp_uninit_pipeline(unsigned int pipe_num) { unsigned int thread_id; ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); /*memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline));*/ sh_css_sp_group.pipe[thread_id].num_stages = 0; }
void sh_css_sp_start_binary_copy(unsigned int pipe_num, struct ia_css_frame *out_frame, unsigned two_ppc) { enum ia_css_pipe_id pipe_id; unsigned int thread_id; struct sh_css_sp_pipeline *pipe; uint8_t stage_num = 0; assert(out_frame != NULL); pipe_id = IA_CSS_PIPE_ID_CAPTURE; ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); pipe = &sh_css_sp_group.pipe[thread_id]; pipe->copy.bin.bytes_available = out_frame->data_bytes; pipe->num_stages = 1; pipe->pipe_id = pipe_id; pipe->pipe_num = pipe_num; pipe->thread_id = thread_id; pipe->pipe_config = 0x0; /* No parameters */ if(pipe->inout_port_config == 0) { SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config, (uint8_t)SH_CSS_PORT_INPUT, (uint8_t)SH_CSS_HOST_TYPE,1); SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config, (uint8_t)SH_CSS_PORT_OUTPUT, (uint8_t)SH_CSS_HOST_TYPE,1); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_sp_start_binary_copy pipe_id %d port_config %08x\n",pipe->pipe_id,pipe->inout_port_config); } ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_sp_start_binary_copy pipe_id %d port_config %08x\n",pipe->pipe_id,pipe->inout_port_config); #if !defined(HAS_NO_INPUT_FORMATTER) sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc; #else (void)two_ppc; #endif sh_css_sp_stage.num = stage_num; sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE; sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_BIN_COPY; set_output_frame_buffer(out_frame,pipe_num, stage_num); /* sp_bin_copy_init on the SP does not deal with dynamica/static yet */ /* For now always update the dynamic data from out frames. */ sh_css_store_sp_per_frame_data(pipe_id, pipe_num, &sh_css_sp_fw); }
void store_sp_stage_data(enum ia_css_pipe_id id, unsigned int pipe_num, unsigned stage) { unsigned int thread_id; ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); copy_isp_stage_to_sp_stage(); if (id != IA_CSS_PIPE_ID_COPY) sh_css_sp_stage.isp_stage_addr = sh_css_store_isp_stage_to_ddr(pipe_num, stage); sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = sh_css_store_sp_stage_to_ddr(pipe_num, stage); /* Clear for next frame */ sh_css_sp_stage.program_input_circuit = false; }
/* Run a pipeline and wait till it completes. */ void ia_css_pipeline_start(enum ia_css_pipe_id pipe_id, struct ia_css_pipeline *pipeline) { uint8_t pipe_num = 0; unsigned int thread_id; assert(pipeline != NULL); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipeline_start() enter: pipe_id=%d, pipeline=%p\n", pipe_id, pipeline); pipeline->pipe_id = pipe_id; sh_css_sp_init_pipeline(pipeline, pipe_id, pipe_num, false, false, false, true, SH_CSS_BDS_FACTOR_1_00, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD, #ifndef ISP2401 IA_CSS_INPUT_MODE_MEMORY, NULL, NULL #else IA_CSS_INPUT_MODE_MEMORY, NULL, NULL, #endif #if !defined(HAS_NO_INPUT_SYSTEM) #ifndef ISP2401 , (mipi_port_ID_t) 0 #else (mipi_port_ID_t) 0, #endif #endif #ifndef ISP2401 ); #else NULL, NULL); #endif ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); if (!sh_css_sp_is_running()) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipeline_start() error,leaving\n"); /* queues are invalid*/ return; } ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM, (uint8_t)thread_id, 0, 0); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipeline_start() leave: return_void\n"); }
bool ia_css_pipeline_has_stopped(struct ia_css_pipeline *pipeline) { /* Android compilation files if made an local variable stack size on android is limited to 2k and this structure is around 2.5K, in place of static malloc can be done but if this call is made too often it will lead to fragment memory versus a fixed allocation */ static struct sh_css_sp_group sp_group; unsigned int thread_id; const struct ia_css_fw_info *fw; unsigned int HIVE_ADDR_sp_group; fw = &sh_css_sp_fw; HIVE_ADDR_sp_group = fw->info.sp.group; ia_css_pipeline_get_sp_thread_id(pipeline->pipe_num, &thread_id); sp_dmem_load(SP0_ID, (unsigned int)sp_address_of(sp_group), &sp_group, sizeof(struct sh_css_sp_group)); return sp_group.pipe[thread_id].num_stages == 0; }
enum ia_css_err ia_css_pipeline_request_stop(struct ia_css_pipeline *pipeline) { enum ia_css_err err = IA_CSS_SUCCESS; unsigned int thread_id; assert(pipeline != NULL); if (pipeline == NULL) return IA_CSS_ERR_INVALID_ARGUMENTS; ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipeline_request_stop() enter: pipeline=%p\n", pipeline); pipeline->stop_requested = true; /* Send stop event to the sp*/ /* This needs improvement, stop on all the pipes available * in the stream*/ ia_css_pipeline_get_sp_thread_id(pipeline->pipe_num, &thread_id); if (!sh_css_sp_is_running()) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipeline_request_stop() leaving\n"); /* queues are invalid */ return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE; } ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_STOP_STREAM, (uint8_t)thread_id, 0, 0); sh_css_sp_uninit_pipeline(pipeline->pipe_num); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipeline_request_stop() leave: return_err=%d\n", err); return err; }
static enum ia_css_err sh_css_sp_init_stage(struct ia_css_binary *binary, const char *binary_name, const struct ia_css_blob_info *blob_info, const struct sh_css_binary_args *args, unsigned int pipe_num, unsigned stage, bool xnr, const struct ia_css_isp_param_css_segments *isp_mem_if, unsigned int if_config_index) { const struct ia_css_binary_xinfo *xinfo; const struct ia_css_binary_info *info; enum ia_css_err err = IA_CSS_SUCCESS; int i; unsigned int thread_id; bool continuous = sh_css_continuous_is_enabled((uint8_t)pipe_num); assert(binary != NULL); assert(blob_info != NULL); assert(args != NULL); assert(isp_mem_if != NULL); xinfo = binary->info; info = &xinfo->sp; { /** * Clear sh_css_sp_stage for easy debugging. * program_input_circuit must be saved as it is set outside * this function. */ uint8_t program_input_circuit; program_input_circuit = sh_css_sp_stage.program_input_circuit; memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage)); sh_css_sp_stage.program_input_circuit = (uint8_t)program_input_circuit; } ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); if (info == NULL) { sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL; return IA_CSS_SUCCESS; } #if defined(USE_INPUT_SYSTEM_VERSION_2401) (void)continuous; sh_css_sp_stage.deinterleaved = 0; #else sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous); #endif /* * TODO: Make the Host dynamically determine * the stage type. */ sh_css_sp_stage.stage_type = SH_CSS_ISP_STAGE_TYPE; sh_css_sp_stage.num = (uint8_t)stage; sh_css_sp_stage.isp_online = (uint8_t)binary->online; sh_css_sp_stage.isp_copy_vf = (uint8_t)args->copy_vf; sh_css_sp_stage.isp_copy_output = (uint8_t)args->copy_output; sh_css_sp_stage.enable.vf_output = (args->out_vf_frame != NULL); /* Copy the frame infos first, to be overwritten by the frames, if these are present. */ sh_css_sp_stage.frames.effective_in_res.width = binary->effective_in_frame_res.width; sh_css_sp_stage.frames.effective_in_res.height = binary->effective_in_frame_res.height; sh_css_frame_info_to_sp(&sh_css_sp_stage.frames.in.info, &binary->in_frame_info); sh_css_frame_info_to_sp(&sh_css_sp_stage.frames.out.info, &binary->out_frame_info); sh_css_frame_info_to_sp(&sh_css_sp_stage.frames.internal_frame_info, &binary->internal_frame_info); sh_css_sp_stage.dvs_envelope.width = binary->dvs_envelope.width; sh_css_sp_stage.dvs_envelope.height = binary->dvs_envelope.height; sh_css_sp_stage.isp_pipe_version = (uint8_t)info->isp_pipe_version; sh_css_sp_stage.isp_deci_log_factor = (uint8_t)binary->deci_factor_log2; sh_css_sp_stage.isp_vf_downscale_bits = (uint8_t)binary->vf_downscale_log2; sh_css_sp_stage.if_config_index = (uint8_t) if_config_index; sh_css_sp_stage.sp_enable_xnr = (uint8_t)xnr; sh_css_sp_stage.xmem_bin_addr = xinfo->xmem_addr; sh_css_sp_stage.xmem_map_addr = sh_css_params_ddr_address_map(); sh_css_isp_stage.blob_info = *blob_info; sh_css_stage_write_binary_info((struct ia_css_binary_info *)info); strncpy(sh_css_isp_stage.binary_name, binary_name, SH_CSS_MAX_BINARY_NAME); sh_css_isp_stage.binary_name[SH_CSS_MAX_BINARY_NAME - 1] = 0; sh_css_isp_stage.mem_initializers = *isp_mem_if; /** * Even when a stage does not need uds and does not params, * ia_css_uds_sp_scale_params() seems to be called (needs * further investigation). This function can not deal with * dx, dy = {0, 0} */ /* Clean static frame info before we update it */ /* * TODO: Initialize the static frame data with * "sh_css_frame_null". */ for (i = 0; i < SH_CSS_NUM_FRAME_IDS; i++) /* Here, we do not initialize it to zero for now * to be able to recognize non-updated elements * This is what it should become: * sh_css_sp_stage.frames.static_frame_data[i] = mmgr_NULL; */ sh_css_sp_stage.frames.static_frame_data[i] = mmgr_EXCEPTION; err = sh_css_sp_write_frame_pointers(args, pipe_num, stage); if (err != IA_CSS_SUCCESS) return err; configure_isp_from_args(&sh_css_sp_group.pipe[thread_id], binary, args); /* we do this only for preview pipe because in fill_binary_info function * we assign vf_out res to out res, but for ISP internal processing, we need * the original out res. for video pipe, it has two output pins --- out and * vf_out, so it can keep these two resolutions already. */ if (binary->info->sp.mode == IA_CSS_BINARY_MODE_PREVIEW && (binary->vf_downscale_log2 > 0)) { /* TODO: Remove this after preview output decimation is fixed * by configuring out&vf info fiels properly */ sh_css_sp_stage.frames.out.info.padded_width <<= binary->vf_downscale_log2; sh_css_sp_stage.frames.out.info.width <<= binary->vf_downscale_log2; sh_css_sp_stage.frames.out.info.height <<= binary->vf_downscale_log2; } err = copy_isp_mem_if_to_ddr(binary); if (err != IA_CSS_SUCCESS) return err; return IA_CSS_SUCCESS; }
static void sh_css_sp_start_raw_copy(struct ia_css_frame *out_frame, unsigned pipe_num, unsigned two_ppc, unsigned max_input_width, enum sh_css_pipe_config_override pipe_conf_override, unsigned int if_config_index) { enum ia_css_pipe_id pipe_id; unsigned int thread_id; uint8_t stage_num = 0; struct sh_css_sp_pipeline *pipe; assert(out_frame != NULL); { /** * Clear sh_css_sp_stage for easy debugging. * program_input_circuit must be saved as it is set outside * this function. */ uint8_t program_input_circuit; program_input_circuit = sh_css_sp_stage.program_input_circuit; memset(&sh_css_sp_stage, 0, sizeof(sh_css_sp_stage)); sh_css_sp_stage.program_input_circuit = program_input_circuit; } pipe_id = IA_CSS_PIPE_ID_COPY; ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); pipe = &sh_css_sp_group.pipe[thread_id]; pipe->copy.raw.height = out_frame->info.res.height; pipe->copy.raw.width = out_frame->info.res.width; pipe->copy.raw.padded_width = out_frame->info.padded_width; pipe->copy.raw.raw_bit_depth = out_frame->info.raw_bit_depth; pipe->copy.raw.max_input_width = max_input_width; pipe->num_stages = 1; pipe->pipe_id = pipe_id; /* TODO: next indicates from which queues parameters need to be sampled, needs checking/improvement */ if (pipe_conf_override == SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD) pipe->pipe_config = (SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id); else pipe->pipe_config = pipe_conf_override; if(pipe->inout_port_config == 0) { SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config, (uint8_t)SH_CSS_PORT_INPUT, (uint8_t)SH_CSS_HOST_TYPE,1); SH_CSS_PIPE_PORT_CONFIG_SET(pipe->inout_port_config, (uint8_t)SH_CSS_PORT_OUTPUT, (uint8_t)SH_CSS_HOST_TYPE,1); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_sp_start_raw_copy pipe_id %d port_config %08x\n",pipe->pipe_id,pipe->inout_port_config); } #if !defined(HAS_NO_INPUT_FORMATTER) sh_css_sp_group.config.input_formatter.isp_2ppc = (uint8_t)two_ppc; #else (void)two_ppc; #endif sh_css_sp_stage.num = stage_num; #if 0 sh_css_sp_stage.xmem_bin_addr = binary->info->xmem_addr; #else sh_css_sp_stage.xmem_bin_addr = 0x0; #endif sh_css_sp_stage.stage_type = SH_CSS_SP_STAGE_TYPE; sh_css_sp_stage.func = (unsigned int)IA_CSS_PIPELINE_RAW_COPY; sh_css_sp_stage.if_config_index = (uint8_t) if_config_index; set_output_frame_buffer(out_frame, (unsigned)pipe_id, stage_num); #if 0 /* sp_raw_copy_init on the SP does not deal with dynamica/static yet */ /* For now always update the dynamic data from out frames. */ sh_css_store_sp_per_frame_data(pipe_id, 0, &sh_css_sp_fw); #endif ia_css_debug_pipe_graph_dump_sp_raw_copy(out_frame); }
void sh_css_sp_init_pipeline(struct ia_css_pipeline *me, enum ia_css_pipe_id id, uint8_t pipe_num, bool xnr, bool two_ppc, bool continuous, bool offline, unsigned int required_bds_factor, enum sh_css_pipe_config_override copy_ovrd, enum ia_css_input_mode input_mode, const struct ia_css_metadata_config *md_config, const struct ia_css_metadata_info *md_info #if !defined(IS_ISP_2500_SYSTEM) , const mipi_port_ID_t port_id #endif ) { /* Get first stage */ struct ia_css_pipeline_stage *stage = NULL; struct ia_css_binary *first_binary = NULL; unsigned num; enum ia_css_pipe_id pipe_id = id; unsigned int thread_id; uint8_t if_config_index, tmp_if_config_index; assert(me != NULL); #if !defined(HAS_NO_INPUT_SYSTEM) assert(me->stages != NULL); first_binary = me->stages->binary; if (input_mode == IA_CSS_INPUT_MODE_SENSOR || input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { assert (port_id < N_MIPI_PORT_ID); if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */ return; /* we should be able to return an error */ if_config_index = (uint8_t) (port_id - MIPI_PORT0_ID); } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY){ if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; } else if_config_index = 0x0; #else (void)input_mode; if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; #endif ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline)); /* Count stages */ for (stage = me->stages, num = 0; stage; stage = stage->next, num++) { stage->stage_num = num; ia_css_debug_pipe_graph_dump_stage(stage, id); } me->num_stages = num; if (first_binary != NULL) { /* Init pipeline data */ sh_css_sp_init_group(two_ppc, first_binary->input_format, offline, if_config_index); } /* if (first_binary != NULL) */ #if defined(USE_INPUT_SYSTEM_VERSION_2401) /* Signal the host immediately after start for SP_ISYS_COPY only */ if ((me->num_stages == 1) && me->stages && (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY)) sh_css_sp_group.config.no_isp_sync = true; #endif /* Init stage data */ sh_css_init_host2sp_frame_data(); sh_css_sp_group.pipe[thread_id].num_stages = 0; sh_css_sp_group.pipe[thread_id].pipe_id = pipe_id; sh_css_sp_group.pipe[thread_id].thread_id = thread_id; sh_css_sp_group.pipe[thread_id].pipe_num = pipe_num; sh_css_sp_group.pipe[thread_id].num_execs = me->num_execs; sh_css_sp_group.pipe[thread_id].required_bds_factor = required_bds_factor; #if !defined(HAS_NO_INPUT_SYSTEM) sh_css_sp_group.pipe[thread_id].input_system_mode = (uint32_t)input_mode; sh_css_sp_group.pipe[thread_id].port_id = port_id; #endif sh_css_sp_group.pipe[thread_id].dvs_frame_delay = (uint32_t)me->dvs_frame_delay; /* TODO: next indicates from which queues parameters need to be sampled, needs checking/improvement */ if (ia_css_pipeline_uses_params(me)) { sh_css_sp_group.pipe[thread_id].pipe_config = SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id; } /* For continuous use-cases, SP copy is responsible for sampling the * parameters */ if (continuous) sh_css_sp_group.pipe[thread_id].pipe_config = 0; sh_css_sp_group.pipe[thread_id].inout_port_config = me->inout_port_config; #if defined (SH_CSS_ENABLE_METADATA) if (md_info != NULL && md_info->size > 0) { sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width; sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height; sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride; sh_css_sp_group.pipe[thread_id].metadata.size = md_info->size; ia_css_isys_convert_stream_format_to_mipi_format( md_config->data_type, MIPI_PREDICTOR_NONE, &sh_css_sp_group.pipe[thread_id].metadata.format); } #else (void)md_config; (void)md_info; #endif ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_sp_init_pipeline pipe_id %d port_config %08x\n",pipe_id,sh_css_sp_group.pipe[thread_id].inout_port_config); for (stage = me->stages, num = 0; stage; stage = stage->next, num++) { sh_css_sp_group.pipe[thread_id].num_stages++; if (is_sp_stage(stage)) { sp_init_sp_stage(stage, pipe_num, two_ppc, copy_ovrd, if_config_index); } else { if ((stage->stage_num != 0) || SH_CSS_PIPE_PORT_CONFIG_IS_CONTINUOUS(me->inout_port_config)) tmp_if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; else tmp_if_config_index = if_config_index; sp_init_stage(stage, pipe_num, xnr, tmp_if_config_index); } store_sp_stage_data(pipe_id, pipe_num, num); } sh_css_sp_group.pipe[thread_id].pipe_config |= (uint32_t) (me->acquire_isp_each_stage << IA_CSS_ACQUIRE_ISP_POS); store_sp_group_data(); }