Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54b508de authored by Harsh Shah's avatar Harsh Shah Committed by Gerrit - the friendly Code Review server
Browse files

msm: isp: Make HALT independent from disable_camif



AXI should be halted whenever all HW streams are stopping. This will
improve KPI even for RDI streams. Currently halt is determined using
Disable_Camif which is only valid for PIX streams. Decouple the two to
improve KPI on RDI and avoid wait.
Also, cleanup after timeout in start_axi. Remove handling of SD_SHUTDOWN
to avoid multiple release.

Change-Id: I09db8adb766d2e7889443f779a716aaa2f6c09d1
Signed-off-by: default avatarHarsh Shah <harshs@codeaurora.org>
parent 184e2ced
Loading
Loading
Loading
Loading
+73 −30
Original line number Original line Diff line number Diff line
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -76,7 +76,7 @@ int msm_isp_axi_create_stream(struct vfe_device *vfe_dev,
	stream_cfg_cmd->axi_stream_handle =
	stream_cfg_cmd->axi_stream_handle =
		(++axi_data->stream_handle_cnt) << 8 | i;
		(++axi_data->stream_handle_cnt) << 8 | i;


	ISP_DBG(" vfe %d handle %x\n", vfe_dev->pdev->id,
	ISP_DBG("%s: vfe %d handle %x\n", __func__, vfe_dev->pdev->id,
		stream_cfg_cmd->axi_stream_handle);
		stream_cfg_cmd->axi_stream_handle);


	memset(&axi_data->stream_info[i], 0,
	memset(&axi_data->stream_info[i], 0,
@@ -716,8 +716,8 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev,
			master_sof_info;
			master_sof_info;
		master_time = master_sof_info->mono_timestamp_ms;
		master_time = master_sof_info->mono_timestamp_ms;
		delta = vfe_dev->common_data->ms_resource.sof_delta_threshold;
		delta = vfe_dev->common_data->ms_resource.sof_delta_threshold;
		ISP_DBG("%s: vfe %d frame %d Slave time %d Master time %d delta %d\n",
		ISP_DBG("%s: vfe %d frame_src %d frame %d Slave time %d Master time %d delta %d\n",
			__func__, vfe_dev->pdev->id,
			__func__, vfe_dev->pdev->id, frame_src,
			vfe_dev->axi_data.src_info[frame_src].frame_id,
			vfe_dev->axi_data.src_info[frame_src].frame_id,
			time, master_time, time - master_time);
			time, master_time, time - master_time);


@@ -736,6 +736,10 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev,
			vfe_dev->axi_data.src_info[frame_src].frame_id +=
			vfe_dev->axi_data.src_info[frame_src].frame_id +=
				vfe_dev->axi_data.src_info[frame_src].
				vfe_dev->axi_data.src_info[frame_src].
				sof_counter_step;
				sof_counter_step;
			ISP_DBG("%s: vfe %d sof_step %d\n", __func__,
			vfe_dev->pdev->id,
			vfe_dev->axi_data.src_info[frame_src].
				sof_counter_step);
			src_info = &vfe_dev->axi_data.src_info[frame_src];
			src_info = &vfe_dev->axi_data.src_info[frame_src];


			if (!src_info->frame_id &&
			if (!src_info->frame_id &&
@@ -1881,9 +1885,11 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev,
	return 0;
	return 0;
}
}


static enum msm_isp_camif_update_state
static void msm_isp_get_camif_update_state_and_halt(
	msm_isp_get_camif_update_state(struct vfe_device *vfe_dev,
	struct vfe_device *vfe_dev,
	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd)
	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
	enum msm_isp_camif_update_state *camif_update,
	int *halt)
{
{
	int i;
	int i;
	struct msm_vfe_axi_stream *stream_info;
	struct msm_vfe_axi_stream *stream_info;
@@ -1902,21 +1908,29 @@ static enum msm_isp_camif_update_state


	if ((pix_stream_cnt) &&
	if ((pix_stream_cnt) &&
		(axi_data->src_info[VFE_PIX_0].input_mux != EXTERNAL_READ)) {
		(axi_data->src_info[VFE_PIX_0].input_mux != EXTERNAL_READ)) {

		if (cur_pix_stream_cnt == 0 && pix_stream_cnt &&
		if (cur_pix_stream_cnt == 0 && pix_stream_cnt &&
			stream_cfg_cmd->cmd == START_STREAM)
			stream_cfg_cmd->cmd == START_STREAM)
			return ENABLE_CAMIF;
			*camif_update = ENABLE_CAMIF;
		else if (cur_pix_stream_cnt &&
		else if (cur_pix_stream_cnt &&
			(cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
			(cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
			stream_cfg_cmd->cmd == STOP_STREAM)
			stream_cfg_cmd->cmd == STOP_STREAM)
			return DISABLE_CAMIF;
			*camif_update = DISABLE_CAMIF;
		else if (cur_pix_stream_cnt &&
		else if (cur_pix_stream_cnt &&
			(cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
			(cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
			stream_cfg_cmd->cmd == STOP_IMMEDIATELY)
			stream_cfg_cmd->cmd == STOP_IMMEDIATELY)
			return DISABLE_CAMIF_IMMEDIATELY;
			*camif_update = DISABLE_CAMIF_IMMEDIATELY;
	}
		else
			*camif_update = NO_UPDATE;
	} else
		*camif_update = NO_UPDATE;

	if (vfe_dev->axi_data.num_active_stream == stream_cfg_cmd->num_streams
		&& (stream_cfg_cmd->cmd == STOP_STREAM ||
		stream_cfg_cmd->cmd == STOP_IMMEDIATELY))
		*halt = 1;
	else
		*halt = 0;


	return NO_UPDATE;
}
}


static void msm_isp_update_camif_output_count(
static void msm_isp_update_camif_output_count(
@@ -2418,6 +2432,8 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
		return -EINVAL;
		return -EINVAL;


	if (camif_update == ENABLE_CAMIF) {
	if (camif_update == ENABLE_CAMIF) {
		ISP_DBG("%s: vfe %d camif enable\n", __func__,
			vfe_dev->pdev->id);
		vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id = 0;
		vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id = 0;
	}
	}


@@ -2451,8 +2467,12 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
		spin_unlock_irqrestore(&stream_info->lock, flags);
		spin_unlock_irqrestore(&stream_info->lock, flags);


		stream_info->state = START_PENDING;
		stream_info->state = START_PENDING;
		ISP_DBG("%s, Stream 0x%x src_state %d on vfe %d\n", __func__,

			stream_info->stream_id, src_state, vfe_dev->pdev->id);
		ISP_DBG("%s, Stream 0x%x src %d src_state %d on vfe %d\n",
			__func__, stream_info->stream_id,
			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]),
			src_state, vfe_dev->pdev->id);

		if (src_state) {
		if (src_state) {
			src_mask |= (1 << SRC_TO_INTF(stream_info->stream_src));
			src_mask |= (1 << SRC_TO_INTF(stream_info->stream_src));
			wait_for_complete = 1;
			wait_for_complete = 1;
@@ -2506,8 +2526,20 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
	if (wait_for_complete) {
	if (wait_for_complete) {
		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update,
		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update,
			src_mask, 2);
			src_mask, 2);
		if (rc < 0)
		if (rc < 0) {
			pr_err("%s: wait for config done failed\n", __func__);
			pr_err("%s: wait for config done failed\n", __func__);
			for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
				stream_info = &axi_data->stream_info[
					HANDLE_TO_IDX(
					stream_cfg_cmd->stream_handle[i])];
				stream_info->state = STOPPING;
				msm_isp_axi_stream_enable_cfg(
					vfe_dev, stream_info, 0);
				stream_cfg_cmd->cmd = STOP_IMMEDIATELY;
				msm_isp_update_camif_output_count(vfe_dev,
					stream_cfg_cmd);
			}
		}
	}
	}


	return rc;
	return rc;
@@ -2515,7 +2547,8 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,


static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
			struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
			struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
			enum msm_isp_camif_update_state camif_update)
			enum msm_isp_camif_update_state camif_update,
			int halt)
{
{
	int i, rc = 0;
	int i, rc = 0;
	uint8_t wait_for_complete_for_this_stream = 0;
	uint8_t wait_for_complete_for_this_stream = 0;
@@ -2571,12 +2604,11 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
				wait_for_complete_for_this_stream = 1;
				wait_for_complete_for_this_stream = 1;
		} else {
		} else {
			if  ((camif_update != DISABLE_CAMIF_IMMEDIATELY) &&
			if  ((camif_update != DISABLE_CAMIF_IMMEDIATELY) &&
				(!ext_read))
				!halt && (!ext_read))
				wait_for_complete_for_this_stream = 1;
				wait_for_complete_for_this_stream = 1;
		}
		}
		ISP_DBG("%s: vfe_dev %d camif_update %d wait %d\n", __func__,
		ISP_DBG("%s: vfe_dev %d camif_update %d halt %d wait %d\n",
			vfe_dev->pdev->id,
			__func__, vfe_dev->pdev->id, camif_update, halt,
			camif_update,
			wait_for_complete_for_this_stream);
			wait_for_complete_for_this_stream);
		intf = SRC_TO_INTF(stream_info->stream_src);
		intf = SRC_TO_INTF(stream_info->stream_src);
		if (!wait_for_complete_for_this_stream ||
		if (!wait_for_complete_for_this_stream ||
@@ -2620,12 +2652,14 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
					SRC_TO_INTF(stream_info->stream_src));
					SRC_TO_INTF(stream_info->stream_src));
				rc = msm_isp_axi_wait_for_cfg_done(vfe_dev,
				rc = msm_isp_axi_wait_for_cfg_done(vfe_dev,
					camif_update, src_mask, 1);
					camif_update, src_mask, 1);
				if (rc < 0)
				if (rc < 0) {
					pr_err("%s: vfe%d cfg done failed\n",
					pr_err("%s: vfe%d cfg done failed\n",
						__func__, vfe_dev->pdev->id);
						__func__, vfe_dev->pdev->id);
				else
					stream_info->state = INACTIVE;
				} else
					pr_err("%s: vfe%d retry success! report err!\n",
					pr_err("%s: vfe%d retry success! report err!\n",
						__func__, vfe_dev->pdev->id);
						__func__, vfe_dev->pdev->id);

				rc = -EBUSY;
				rc = -EBUSY;
			}
			}
		}
		}
@@ -2648,20 +2682,26 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
		vfe_dev->axi_data.camif_state = CAMIF_DISABLE;
		vfe_dev->axi_data.camif_state = CAMIF_DISABLE;
	} else if ((camif_update == DISABLE_CAMIF_IMMEDIATELY) ||
	} else if ((camif_update == DISABLE_CAMIF_IMMEDIATELY) ||
					(ext_read)) {
					(ext_read)) {
		/*during stop immediately, stop output then stop input*/
		vfe_dev->hw_info->vfe_ops.irq_ops.enable_camif_err(vfe_dev, 0);
		vfe_dev->hw_info->vfe_ops.irq_ops.enable_camif_err(vfe_dev, 0);

		vfe_dev->ignore_error = 1;
		vfe_dev->ignore_error = 1;
		vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 1);
		if (!ext_read)
		if (!ext_read)
			vfe_dev->hw_info->vfe_ops.core_ops.
			vfe_dev->hw_info->vfe_ops.core_ops.
				update_camif_state(vfe_dev,
				update_camif_state(vfe_dev,
						DISABLE_CAMIF_IMMEDIATELY);
						DISABLE_CAMIF_IMMEDIATELY);
		vfe_dev->axi_data.camif_state = CAMIF_STOPPED;
		vfe_dev->axi_data.camif_state = CAMIF_STOPPED;
		vfe_dev->hw_info->vfe_ops.irq_ops.enable_camif_err(vfe_dev, 1);
		vfe_dev->ignore_error = 0;
	}
	if (halt) {
		/*during stop immediately, stop output then stop input*/
		vfe_dev->ignore_error = 1;
		vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 1);
		vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, 0, 1);
		vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, 0, 1);
		vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
		vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
		vfe_dev->hw_info->vfe_ops.irq_ops.enable_camif_err(vfe_dev, 1);
		vfe_dev->ignore_error = 0;
		vfe_dev->ignore_error = 0;
	}
	}

	msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
	msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
	msm_isp_update_stream_bandwidth(vfe_dev);
	msm_isp_update_stream_bandwidth(vfe_dev);


@@ -2697,6 +2737,7 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
	enum msm_isp_camif_update_state camif_update;
	enum msm_isp_camif_update_state camif_update;
	int halt = 0;


	rc = msm_isp_axi_check_stream_state(vfe_dev, stream_cfg_cmd);
	rc = msm_isp_axi_check_stream_state(vfe_dev, stream_cfg_cmd);
	if (rc < 0) {
	if (rc < 0) {
@@ -2711,7 +2752,8 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
		atomic_set(&vfe_dev->error_info.overflow_state,
		atomic_set(&vfe_dev->error_info.overflow_state,
			NO_OVERFLOW);
			NO_OVERFLOW);
	}
	}
	camif_update = msm_isp_get_camif_update_state(vfe_dev, stream_cfg_cmd);
	msm_isp_get_camif_update_state_and_halt(vfe_dev, stream_cfg_cmd,
		&camif_update, &halt);
	if (camif_update == DISABLE_CAMIF)
	if (camif_update == DISABLE_CAMIF)
		vfe_dev->axi_data.camif_state = CAMIF_STOPPING;
		vfe_dev->axi_data.camif_state = CAMIF_STOPPING;
	if (stream_cfg_cmd->cmd == START_STREAM) {
	if (stream_cfg_cmd->cmd == START_STREAM) {
@@ -2721,7 +2763,7 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
			vfe_dev, stream_cfg_cmd, camif_update);
			vfe_dev, stream_cfg_cmd, camif_update);
	} else {
	} else {
		rc = msm_isp_stop_axi_stream(
		rc = msm_isp_stop_axi_stream(
			vfe_dev, stream_cfg_cmd, camif_update);
			vfe_dev, stream_cfg_cmd, camif_update, halt);


		msm_isp_axi_update_cgc_override(vfe_dev, stream_cfg_cmd, 0);
		msm_isp_axi_update_cgc_override(vfe_dev, stream_cfg_cmd, 0);
		if (axi_data->num_active_stream == 0) {
		if (axi_data->num_active_stream == 0) {
@@ -2741,7 +2783,8 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
	}
	}


	if (rc < 0)
	if (rc < 0)
		pr_err("%s: start/stop stream failed\n", __func__);
		pr_err("%s: start/stop %d stream failed\n", __func__,
			stream_cfg_cmd->cmd);
	return rc;
	return rc;
}
}


+9 −4
Original line number Original line Diff line number Diff line
@@ -739,6 +739,8 @@ static int msm_isp_set_dual_HW_master_slave_mode(
	vfe_dev->common_data->ms_resource.dual_hw_type = DUAL_HW_MASTER_SLAVE;
	vfe_dev->common_data->ms_resource.dual_hw_type = DUAL_HW_MASTER_SLAVE;
	vfe_dev->vfe_ub_policy = MSM_WM_UB_EQUAL_SLICING;
	vfe_dev->vfe_ub_policy = MSM_WM_UB_EQUAL_SLICING;
	if (dual_hw_ms_cmd->primary_intf < VFE_SRC_MAX) {
	if (dual_hw_ms_cmd->primary_intf < VFE_SRC_MAX) {
		ISP_DBG("%s: vfe %d primary_intf %d\n", __func__,
			vfe_dev->pdev->id, dual_hw_ms_cmd->primary_intf);
		src_info = &vfe_dev->axi_data.
		src_info = &vfe_dev->axi_data.
			src_info[dual_hw_ms_cmd->primary_intf];
			src_info[dual_hw_ms_cmd->primary_intf];
		src_info->dual_hw_ms_info.dual_hw_ms_type =
		src_info->dual_hw_ms_info.dual_hw_ms_type =
@@ -749,7 +751,7 @@ static int msm_isp_set_dual_HW_master_slave_mode(
	if (src_info != NULL &&
	if (src_info != NULL &&
		dual_hw_ms_cmd->dual_hw_ms_type == MS_TYPE_MASTER) {
		dual_hw_ms_cmd->dual_hw_ms_type == MS_TYPE_MASTER) {
		src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE;
		src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE;
		ISP_DBG("%s: Master\n", __func__);
		ISP_DBG("%s: vfe %d Master\n", __func__, vfe_dev->pdev->id);


		src_info->dual_hw_ms_info.sof_info =
		src_info->dual_hw_ms_info.sof_info =
			&vfe_dev->common_data->ms_resource.master_sof_info;
			&vfe_dev->common_data->ms_resource.master_sof_info;
@@ -760,7 +762,7 @@ static int msm_isp_set_dual_HW_master_slave_mode(
			&vfe_dev->common_data->common_dev_data_lock,
			&vfe_dev->common_data->common_dev_data_lock,
			flags);
			flags);
		src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE;
		src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE;
		ISP_DBG("%s: Slave\n", __func__);
		ISP_DBG("%s: vfe %d Slave\n", __func__, vfe_dev->pdev->id);


		for (j = 0; j < MS_NUM_SLAVE_MAX; j++) {
		for (j = 0; j < MS_NUM_SLAVE_MAX; j++) {
			if (vfe_dev->common_data->ms_resource.
			if (vfe_dev->common_data->ms_resource.
@@ -787,7 +789,8 @@ static int msm_isp_set_dual_HW_master_slave_mode(
			return -EBUSY;
			return -EBUSY;
		}
		}
	}
	}
	ISP_DBG("%s: num_src %d\n", __func__, dual_hw_ms_cmd->num_src);
	ISP_DBG("%s: vfe %d num_src %d\n", __func__, vfe_dev->pdev->id,
		dual_hw_ms_cmd->num_src);
	/* This for loop is for non-primary intf to be marked with Master/Slave
	/* This for loop is for non-primary intf to be marked with Master/Slave
	 * in order for frame id sync. But their timestamp is not saved.
	 * in order for frame id sync. But their timestamp is not saved.
	 * So no sof_info resource is allocated */
	 * So no sof_info resource is allocated */
@@ -797,7 +800,9 @@ static int msm_isp_set_dual_HW_master_slave_mode(
				dual_hw_ms_cmd->input_src[i]);
				dual_hw_ms_cmd->input_src[i]);
			return -EINVAL;
			return -EINVAL;
		}
		}
		ISP_DBG("%s: src %d\n", __func__, dual_hw_ms_cmd->input_src[i]);
		ISP_DBG("%s: vfe %d src %d type %d\n", __func__,
			vfe_dev->pdev->id, dual_hw_ms_cmd->input_src[i],
			dual_hw_ms_cmd->dual_hw_ms_type);
		src_info = &vfe_dev->axi_data.
		src_info = &vfe_dev->axi_data.
			src_info[dual_hw_ms_cmd->input_src[i]];
			src_info[dual_hw_ms_cmd->input_src[i]];
		src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE;
		src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE;
+1 −13
Original line number Original line Diff line number Diff line
@@ -1490,20 +1490,8 @@ static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd,
		ispif->ispif_rdi2_debug = 0;
		ispif->ispif_rdi2_debug = 0;
		return 0;
		return 0;
	}
	}
	case MSM_SD_SHUTDOWN: {
	case MSM_SD_SHUTDOWN:
		struct ispif_device *ispif =
			(struct ispif_device *)v4l2_get_subdevdata(sd);

		if (ispif && ispif->base) {
			while (ispif->open_cnt != 0)
				ispif_close_node(sd, NULL);
		} else {
			pr_debug("%s:SD SHUTDOWN fail, ispif%s %p\n", __func__,
				ispif ? "_base" : "",
				ispif ? ispif->base : NULL);
		}
		return 0;
		return 0;
	}
	default:
	default:
		pr_err_ratelimited("%s: invalid cmd 0x%x received\n",
		pr_err_ratelimited("%s: invalid cmd 0x%x received\n",
			__func__, cmd);
			__func__, cmd);