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: Harsh Shah <harshs@codeaurora.org>
This commit is contained in:
parent
e29112a1f7
commit
a2b1739e1e
3 changed files with 84 additions and 48 deletions
|
@ -1,4 +1,4 @@
|
|||
/* 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
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -80,7 +80,7 @@ int msm_isp_axi_create_stream(struct vfe_device *vfe_dev,
|
|||
stream_cfg_cmd->axi_stream_handle =
|
||||
(++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);
|
||||
|
||||
memset(&axi_data->stream_info[i], 0,
|
||||
|
@ -720,8 +720,8 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev,
|
|||
master_sof_info;
|
||||
master_time = master_sof_info->mono_timestamp_ms;
|
||||
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",
|
||||
__func__, vfe_dev->pdev->id,
|
||||
ISP_DBG("%s: vfe %d frame_src %d frame %d Slave time %d Master time %d delta %d\n",
|
||||
__func__, vfe_dev->pdev->id, frame_src,
|
||||
vfe_dev->axi_data.src_info[frame_src].frame_id,
|
||||
time, master_time, time - master_time);
|
||||
|
||||
|
@ -740,6 +740,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].
|
||||
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];
|
||||
|
||||
if (!src_info->frame_id &&
|
||||
|
@ -1895,9 +1899,11 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static enum msm_isp_camif_update_state
|
||||
msm_isp_get_camif_update_state(struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd)
|
||||
static void msm_isp_get_camif_update_state_and_halt(
|
||||
struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
|
||||
enum msm_isp_camif_update_state *camif_update,
|
||||
int *halt)
|
||||
{
|
||||
int i;
|
||||
struct msm_vfe_axi_stream *stream_info;
|
||||
|
@ -1915,22 +1921,30 @@ static enum msm_isp_camif_update_state
|
|||
}
|
||||
|
||||
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 &&
|
||||
stream_cfg_cmd->cmd == START_STREAM)
|
||||
return ENABLE_CAMIF;
|
||||
*camif_update = ENABLE_CAMIF;
|
||||
else if (cur_pix_stream_cnt &&
|
||||
(cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
|
||||
stream_cfg_cmd->cmd == STOP_STREAM)
|
||||
return DISABLE_CAMIF;
|
||||
*camif_update = DISABLE_CAMIF;
|
||||
else if (cur_pix_stream_cnt &&
|
||||
(cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
|
||||
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(
|
||||
|
@ -2472,6 +2486,8 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
|
|||
return -EINVAL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2505,8 +2521,12 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
|
|||
spin_unlock_irqrestore(&stream_info->lock, flags);
|
||||
|
||||
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) {
|
||||
src_mask |= (1 << SRC_TO_INTF(stream_info->stream_src));
|
||||
wait_for_complete = 1;
|
||||
|
@ -2560,8 +2580,20 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
|
|||
if (wait_for_complete) {
|
||||
rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update,
|
||||
src_mask, 2);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
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;
|
||||
|
@ -2569,7 +2601,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,
|
||||
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;
|
||||
uint8_t wait_for_complete_for_this_stream = 0;
|
||||
|
@ -2625,12 +2658,11 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
|
|||
wait_for_complete_for_this_stream = 1;
|
||||
} else {
|
||||
if ((camif_update != DISABLE_CAMIF_IMMEDIATELY) &&
|
||||
(!ext_read))
|
||||
!halt && (!ext_read))
|
||||
wait_for_complete_for_this_stream = 1;
|
||||
}
|
||||
ISP_DBG("%s: vfe_dev %d camif_update %d wait %d\n", __func__,
|
||||
vfe_dev->pdev->id,
|
||||
camif_update,
|
||||
ISP_DBG("%s: vfe_dev %d camif_update %d halt %d wait %d\n",
|
||||
__func__, vfe_dev->pdev->id, camif_update, halt,
|
||||
wait_for_complete_for_this_stream);
|
||||
intf = SRC_TO_INTF(stream_info->stream_src);
|
||||
if (!wait_for_complete_for_this_stream ||
|
||||
|
@ -2674,12 +2706,14 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
|
|||
SRC_TO_INTF(stream_info->stream_src));
|
||||
rc = msm_isp_axi_wait_for_cfg_done(vfe_dev,
|
||||
camif_update, src_mask, 1);
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
pr_err("%s: vfe%d cfg done failed\n",
|
||||
__func__, vfe_dev->pdev->id);
|
||||
else
|
||||
stream_info->state = INACTIVE;
|
||||
} else
|
||||
pr_err("%s: vfe%d retry success! report err!\n",
|
||||
__func__, vfe_dev->pdev->id);
|
||||
|
||||
rc = -EBUSY;
|
||||
}
|
||||
}
|
||||
|
@ -2702,20 +2736,26 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
|
|||
vfe_dev->axi_data.camif_state = CAMIF_DISABLE;
|
||||
} else if ((camif_update == DISABLE_CAMIF_IMMEDIATELY) ||
|
||||
(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->ignore_error = 1;
|
||||
vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 1);
|
||||
if (!ext_read)
|
||||
vfe_dev->hw_info->vfe_ops.core_ops.
|
||||
update_camif_state(vfe_dev,
|
||||
DISABLE_CAMIF_IMMEDIATELY);
|
||||
vfe_dev->axi_data.camif_state = CAMIF_STOPPED;
|
||||
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.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.init_hw_reg(vfe_dev);
|
||||
vfe_dev->ignore_error = 0;
|
||||
}
|
||||
|
||||
msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
|
||||
msm_isp_update_stream_bandwidth(vfe_dev);
|
||||
|
||||
|
@ -2751,6 +2791,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_shared_data *axi_data = &vfe_dev->axi_data;
|
||||
enum msm_isp_camif_update_state camif_update;
|
||||
int halt = 0;
|
||||
|
||||
rc = msm_isp_axi_check_stream_state(vfe_dev, stream_cfg_cmd);
|
||||
if (rc < 0) {
|
||||
|
@ -2765,7 +2806,8 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
|
|||
atomic_set(&vfe_dev->error_info.overflow_state,
|
||||
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)
|
||||
vfe_dev->axi_data.camif_state = CAMIF_STOPPING;
|
||||
if (stream_cfg_cmd->cmd == START_STREAM) {
|
||||
|
@ -2775,7 +2817,7 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
|
|||
vfe_dev, stream_cfg_cmd, camif_update);
|
||||
} else {
|
||||
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);
|
||||
if (axi_data->num_active_stream == 0) {
|
||||
|
@ -2795,7 +2837,8 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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->vfe_ub_policy = MSM_WM_UB_EQUAL_SLICING;
|
||||
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[dual_hw_ms_cmd->primary_intf];
|
||||
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 &&
|
||||
dual_hw_ms_cmd->dual_hw_ms_type == MS_TYPE_MASTER) {
|
||||
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 =
|
||||
&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,
|
||||
flags);
|
||||
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++) {
|
||||
if (vfe_dev->common_data->ms_resource.
|
||||
|
@ -787,7 +789,8 @@ static int msm_isp_set_dual_HW_master_slave_mode(
|
|||
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
|
||||
* in order for frame id sync. But their timestamp is not saved.
|
||||
* 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]);
|
||||
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[dual_hw_ms_cmd->input_src[i]];
|
||||
src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE;
|
||||
|
|
|
@ -1490,20 +1490,8 @@ static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd,
|
|||
ispif->ispif_rdi2_debug = 0;
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
}
|
||||
case MSM_SD_SHUTDOWN:
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
pr_err_ratelimited("%s: invalid cmd 0x%x received\n",
|
||||
__func__, cmd);
|
||||
|
|
Loading…
Add table
Reference in a new issue