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 225572c00ff2..fbac6d81ded0 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 @@ -631,6 +631,7 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info; struct msm_vfe_axi_shared_data *axi_data; int i; + uint32_t stream_idx; if (!vfe_dev || !sof_info) { pr_err("%s %d failed: vfe_dev %pK sof_info %pK\n", __func__, @@ -648,17 +649,31 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, if (!vfe_dev->reg_updated) { sof_info->regs_not_updated = vfe_dev->reg_update_requested; - for (i = 0; i < VFE_AXI_SRC_MAX; i++) { - struct msm_vfe_axi_stream *temp_stream_info; - stream_info = &axi_data->stream_info[i]; - if (stream_info->state != ACTIVE || - !stream_info->controllable_output || - (SRC_TO_INTF(stream_info->stream_src) != - VFE_PIX_0)) + } + for (i = 0; i < VFE_AXI_SRC_MAX; i++) { + struct msm_vfe_axi_stream *temp_stream_info; + + stream_info = &axi_data->stream_info[i]; + stream_idx = HANDLE_TO_IDX(stream_info->stream_handle); + + /* + * Process drop only if controllable ACTIVE PIX stream && + * reg_not_updated + * OR stream is in RESUMING state. + * Other cases there is no drop to report, so continue. + */ + if (!((stream_info->state == ACTIVE && + stream_info->controllable_output && + (SRC_TO_INTF(stream_info->stream_src) == + VFE_PIX_0)) || + stream_info->state == RESUMING)) continue; + + if (stream_info->controllable_output && + !vfe_dev->reg_updated) { temp_stream_info = msm_isp_get_controllable_stream(vfe_dev, - stream_info); + stream_info); if (temp_stream_info->undelivered_request_cnt) { if (msm_isp_drop_frame(vfe_dev, stream_info, ts, sof_info)) { @@ -666,7 +681,18 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, } } } + + if (stream_info->state == RESUMING && + !stream_info->controllable_output) { + ISP_DBG("%s: axi_updating_mask stream_id %x frame_id %d\n", + __func__, stream_idx, vfe_dev->axi_data. + src_info[SRC_TO_INTF(stream_info->stream_src)] + .frame_id); + sof_info->axi_updating_mask |= + 1 << stream_idx; + } } + vfe_dev->reg_updated = 0; /* report frame drop per stream */ @@ -1875,8 +1901,8 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, __func__, done_buf->bufq_handle); return -EINVAL; } - sof_info->reg_update_fail_mask |= - 1 << (bufq->bufq_handle & 0xF); + sof_info->reg_update_fail_mask_ext |= + (bufq->bufq_handle & 0xFF); } spin_unlock_irqrestore(&stream_info->lock, flags); diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h index 7f7ebd3ba21f..e658f4b56df9 100644 --- a/include/uapi/media/msmb_isp.h +++ b/include/uapi/media/msmb_isp.h @@ -719,7 +719,7 @@ struct msm_isp_output_info { /* This structure is piggybacked with SOF event */ struct msm_isp_sof_info { uint8_t regs_not_updated; - /* mask with AXI_SRC for regs not updated */ + /* mask with bufq_handle for regs not updated */ uint16_t reg_update_fail_mask; /* mask with bufq_handle for get_buf failed */ uint32_t stream_get_buf_fail_mask; @@ -727,7 +727,17 @@ struct msm_isp_sof_info { uint16_t stats_get_buf_fail_mask; /* delta between master and slave */ struct msm_isp_ms_delta_info ms_delta_info; + /* + * mask with AXI_SRC in paused state. In PAUSED + * state there is no Buffer output. So this mask is used + * to report drop. + */ + uint16_t axi_updating_mask; + /* extended mask with bufq_handle for regs not updated */ + uint32_t reg_update_fail_mask_ext; }; +#define AXI_UPDATING_MASK 1 +#define REG_UPDATE_FAIL_MASK_EXT 1 struct msm_isp_event_data { /*Wall clock except for buffer divert events