diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 025b4649f80b..e60524f55c87 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -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; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index f4ded24762c2..1e7ab380d743 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -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; diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c index 95b6f8d46df9..ae8ef167596d 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c @@ -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);