Merge "msm: camera: isp: Fix RDI stream streamoff issue"

This commit is contained in:
Linux Build Service Account 2016-07-13 15:44:52 -07:00 committed by Gerrit - the friendly Code Review server
commit afc9724015
4 changed files with 132 additions and 47 deletions

View file

@ -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 {

View file

@ -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;

View file

@ -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 ||

View file

@ -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);