diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index 95465fb24feb..763b6a575326 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -40,6 +40,7 @@ #define VFE40_8952_VERSION 0x10060000 #define VFE40_8976_VERSION 0x10050000 #define VFE40_8937_VERSION 0x10080000 +#define VFE40_8917_VERSION 0x10080001 #define VFE40_8953_VERSION 0x10090000 #define VFE32_8909_VERSION 0x30600 @@ -652,6 +653,7 @@ struct dual_vfe_resource { struct msm_vfe_stats_shared_data *stats_data[MAX_VFE]; struct msm_vfe_axi_shared_data *axi_data[MAX_VFE]; uint32_t wm_reload_mask[MAX_VFE]; + uint32_t epoch_sync_mask; }; struct master_slave_resource_info { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index d4f0453d72ff..a76ccc06c9e1 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -326,6 +326,7 @@ static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev) break; case VFE40_8937_VERSION: case VFE40_8953_VERSION: + case VFE40_8917_VERSION: default: ISP_DBG("%s: No special QOS\n", __func__); } @@ -1475,6 +1476,7 @@ static void msm_vfe40_axi_cfg_wm_reg( wm_bit_shift = VFE40_WM_BIT_SHIFT; } else if (vfe_dev->vfe_hw_version == VFE40_8976_VERSION || vfe_dev->vfe_hw_version == VFE40_8937_VERSION || + vfe_dev->vfe_hw_version == VFE40_8917_VERSION || vfe_dev->vfe_hw_version == VFE40_8953_VERSION) { burst_len = VFE40_BURST_LEN_8952_VERSION; wm_bit_shift = VFE40_WM_BIT_SHIFT_8976_VERSION; @@ -1986,6 +1988,7 @@ static void msm_vfe40_stats_cfg_ub(struct vfe_device *vfe_dev) if (vfe_dev->vfe_hw_version == VFE40_8916_VERSION || vfe_dev->vfe_hw_version == VFE40_8939_VERSION || vfe_dev->vfe_hw_version == VFE40_8937_VERSION || + vfe_dev->vfe_hw_version == VFE40_8917_VERSION || vfe_dev->vfe_hw_version == VFE40_8953_VERSION) { stats_burst_len = VFE40_STATS_BURST_LEN_8916_VERSION; ub_offset = VFE40_UB_SIZE_8916; 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 fbac6d81ded0..3dd55e02826d 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 @@ -539,6 +539,89 @@ static void msm_isp_cfg_framedrop_reg(struct vfe_device *vfe_dev, } } +/** + * msm_isp_check_epoch_status() - check the epock signal for framedrop + * + * @vfe_dev: The h/w on which the epoch signel is reveived + * @frame_src: The source of the epoch signal for this frame + * + * For dual vfe case and pixel stream, if both vfe's epoch signal is + * received, this function will return success. + * It will also return the vfe1 for further process + * For none dual VFE stream or none pixl source, this + * funciton will just return success. + * + * Returns 1 - epoch received is complete. + * 0 - epoch reveived is not complete. + */ +static int msm_isp_check_epoch_status(struct vfe_device **vfe_dev, + enum msm_vfe_input_src frame_src) +{ + struct vfe_device *vfe_dev_cur = *vfe_dev; + struct vfe_device *vfe_dev_other = NULL; + uint32_t vfe_id_other = 0; + uint32_t vfe_id_cur = 0; + uint32_t epoch_mask = 0; + unsigned long flags; + int completed = 0; + + spin_lock_irqsave( + &vfe_dev_cur->common_data->common_dev_data_lock, flags); + + if (vfe_dev_cur->is_split && + frame_src == VFE_PIX_0) { + if (vfe_dev_cur->pdev->id == ISP_VFE0) { + vfe_id_cur = ISP_VFE0; + vfe_id_other = ISP_VFE1; + } else { + vfe_id_cur = ISP_VFE1; + vfe_id_other = ISP_VFE0; + } + vfe_dev_other = vfe_dev_cur->common_data->dual_vfe_res-> + vfe_dev[vfe_id_other]; + + if (vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask & (1 << vfe_id_cur)) { + /* serious scheduling delay */ + pr_err("Missing epoch: vfe %d, epoch mask 0x%x\n", + vfe_dev_cur->pdev->id, + vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask); + goto fatal; + } + + vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask |= (1 << vfe_id_cur); + + epoch_mask = (1 << vfe_id_cur) | (1 << vfe_id_other); + if ((vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask & epoch_mask) == epoch_mask) { + + if (vfe_id_other == ISP_VFE0) + *vfe_dev = vfe_dev_cur; + else + *vfe_dev = vfe_dev_other; + + vfe_dev_cur->common_data->dual_vfe_res-> + epoch_sync_mask &= ~epoch_mask; + completed = 1; + } + } else + completed = 1; + + spin_unlock_irqrestore( + &vfe_dev_cur->common_data->common_dev_data_lock, flags); + + return completed; +fatal: + spin_unlock_irqrestore( + &vfe_dev_cur->common_data->common_dev_data_lock, flags); + /* new error event code will be added later */ + msm_isp_halt_send_error(vfe_dev_cur, ISP_EVENT_PING_PONG_MISMATCH); + return 0; +} + + /** * msm_isp_update_framedrop_reg() - Update frame period pattern on h/w * @vfe_dev: The h/w on which the perion pattern is updated. @@ -554,10 +637,15 @@ void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev, enum msm_vfe_input_src frame_src) { int i; - struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; + struct msm_vfe_axi_shared_data *axi_data = NULL; struct msm_vfe_axi_stream *stream_info; unsigned long flags; + if (msm_isp_check_epoch_status(&vfe_dev, frame_src) != 1) + return; + + axi_data = &vfe_dev->axi_data; + for (i = 0; i < VFE_AXI_SRC_MAX; i++) { if (SRC_TO_INTF(axi_data->stream_info[i].stream_src) != frame_src) { @@ -1937,24 +2025,6 @@ static void msm_isp_get_camif_update_state_and_halt( pix_stream_cnt++; } - if ((pix_stream_cnt) && - (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) - *camif_update = ENABLE_CAMIF; - else if (cur_pix_stream_cnt && - (cur_pix_stream_cnt - pix_stream_cnt) == 0 && - stream_cfg_cmd->cmd == STOP_STREAM) - *camif_update = DISABLE_CAMIF; - else if (cur_pix_stream_cnt && - (cur_pix_stream_cnt - pix_stream_cnt) == 0 && - stream_cfg_cmd->cmd == STOP_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)) @@ -1962,6 +2032,24 @@ static void msm_isp_get_camif_update_state_and_halt( else *halt = 0; + if ((pix_stream_cnt) && + (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) + *camif_update = ENABLE_CAMIF; + else if (cur_pix_stream_cnt && + (cur_pix_stream_cnt - pix_stream_cnt) == 0 && + (stream_cfg_cmd->cmd == STOP_STREAM || + stream_cfg_cmd->cmd == STOP_IMMEDIATELY)) { + if (*halt) + *camif_update = DISABLE_CAMIF_IMMEDIATELY; + else + *camif_update = DISABLE_CAMIF; + } + else + *camif_update = NO_UPDATE; + } else + *camif_update = NO_UPDATE; } static void msm_isp_update_camif_output_count( @@ -2584,6 +2672,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, vfe_dev->hw_info->vfe_ops.core_ops. update_camif_state(vfe_dev, camif_update); vfe_dev->axi_data.camif_state = CAMIF_ENABLE; + vfe_dev->common_data->dual_vfe_res->epoch_sync_mask = 0; } if (wait_for_complete) { @@ -2645,34 +2734,20 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev, wait_for_complete_for_this_stream = 0; stream_info->state = STOP_PENDING; - ISP_DBG("Stop axi Stream 0x%x\n", stream_info->stream_id); - if (stream_info->stream_src == CAMIF_RAW || - stream_info->stream_src == IDEAL_RAW) { - /* We dont get reg update IRQ for raw snapshot - * so frame skip cant be ocnfigured - */ - if ((camif_update != DISABLE_CAMIF_IMMEDIATELY) && - (!ext_read)) - wait_for_complete_for_this_stream = 1; - } else if (stream_info->stream_type == BURST_STREAM && - stream_info->runtime_num_burst_capture == 0) { - /* Configure AXI writemasters to stop immediately - * since for burst case, write masters already skip - * all frames. - */ - if (stream_info->stream_src == RDI_INTF_0 || - stream_info->stream_src == RDI_INTF_1 || - stream_info->stream_src == RDI_INTF_2) - wait_for_complete_for_this_stream = 1; - } else { - if ((camif_update != DISABLE_CAMIF_IMMEDIATELY) && - !halt && (!ext_read)) - wait_for_complete_for_this_stream = 1; - } - ISP_DBG("%s: vfe_dev %d camif_update %d halt %d wait %d\n", - __func__, vfe_dev->pdev->id, camif_update, halt, + if (!halt && !ext_read && + !(stream_info->stream_type == BURST_STREAM && + stream_info->runtime_num_burst_capture == 0)) + wait_for_complete_for_this_stream = 1; + + ISP_DBG("%s: stream 0x%x, vfe %d camif %d halt %d wait %d\n", + __func__, + stream_info->stream_id, + 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 || stream_info->state == INACTIVE || 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 460746089c53..5b12c1239bf4 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 @@ -1917,11 +1917,16 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) ISP_DBG("%s open_cnt %u\n", __func__, vfe_dev->vfe_open_cnt); - if (vfe_dev->common_data == NULL) { - pr_err("%s: Error in probe. No common_data\n", __func__); + if (vfe_dev->common_data == NULL || + vfe_dev->common_data->dual_vfe_res == NULL) { + pr_err("%s: Error in probe. No common_data or dual vfe res\n", + __func__); return -EINVAL; } + if (vfe_dev->pdev->id == ISP_VFE0) + vfe_dev->common_data->dual_vfe_res->epoch_sync_mask = 0; + mutex_lock(&vfe_dev->realtime_mutex); mutex_lock(&vfe_dev->core_mutex);