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;
}
Esempio n. 5
0
/* 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");
}
Esempio n. 6
0
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;
}
Esempio n. 7
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();

}