msm: camera: isp: fix a cts test failure due to framedrop pattern

The ITS HAL3 test failed due to broken frames and green frames. The
root cause of the issue is due to the framedrop pattern setting in the
isp driver. This change fixes the following issues:

a) Keep tracking the hw framedrop pattern even after the reg update ack
miss.

b) Remove a race condition between the framedrop pattern setting and
request frame ioctl handling.

c) Correctly set the framedrop pattern after the request frame.

Change-Id: I862046c718d6e3a28d5f372eb2eb5e371471eb58
Signed-off-by: Jing Zhou <jzhou70@codeaurora.org>
This commit is contained in:
Jing Zhou 2016-01-08 21:48:25 -08:00 committed by David Keitel
parent 39385c4921
commit ffa7e518d5
4 changed files with 24 additions and 33 deletions

View file

@ -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
@ -366,8 +366,9 @@ struct msm_vfe_axi_stream {
enum msm_vfe_axi_stream_type stream_type;
uint32_t frame_based;
enum msm_vfe_frame_skip_pattern frame_skip_pattern;
uint32_t current_framedrop_period;
uint32_t prev_framedrop_period;
uint32_t current_framedrop_period; /* user requested period*/
uint32_t requested_framedrop_period; /* requested period*/
uint32_t activated_framedrop_period; /* active hw period */
uint32_t num_burst_capture;/*number of frame to capture*/
uint32_t init_frame_drop;
spinlock_t lock;

View file

@ -663,11 +663,11 @@ static void msm_vfe47_process_epoch_irq(struct vfe_device *vfe_dev,
return;
if (irq_status0 & BIT(2)) {
msm_isp_notify(vfe_dev, ISP_EVENT_SOF, VFE_PIX_0, ts);
ISP_DBG("%s: EPOCH0 IRQ\n", __func__);
msm_isp_update_framedrop_reg(vfe_dev, VFE_PIX_0);
msm_isp_update_stats_framedrop_reg(vfe_dev);
msm_isp_update_error_frame_count(vfe_dev);
msm_isp_notify(vfe_dev, ISP_EVENT_SOF, VFE_PIX_0, ts);
if (vfe_dev->axi_data.src_info[VFE_PIX_0].raw_stream_count > 0
&& vfe_dev->axi_data.src_info[VFE_PIX_0].
pix_stream_count == 0) {

View file

@ -94,7 +94,8 @@ int msm_isp_axi_create_stream(struct vfe_device *vfe_dev,
stream_cfg_cmd->axi_stream_handle;
axi_data->stream_info[i].controllable_output =
stream_cfg_cmd->controllable_output;
axi_data->stream_info[i].prev_framedrop_period = 0x7FFFFFFF;
axi_data->stream_info[i].activated_framedrop_period =
MSM_VFE_STREAM_STOP_PERIOD;
if (stream_cfg_cmd->controllable_output)
stream_cfg_cmd->frame_skip_pattern = SKIP_ALL;
INIT_LIST_HEAD(&axi_data->stream_info[i].request_q);
@ -508,16 +509,16 @@ static void msm_isp_cfg_framedrop_reg(struct vfe_device *vfe_dev,
framedrop_pattern,
framedrop_period);
stream_info->prev_framedrop_period =
(framedrop_period | 0x80000000);
vfe0_stream_info->prev_framedrop_period =
(framedrop_period | 0x80000000);
stream_info->requested_framedrop_period =
framedrop_period;
vfe0_stream_info->requested_framedrop_period =
framedrop_period;
} else if (RDI_OR_NOT_DUAL_VFE(vfe_dev, stream_info)) {
vfe_dev->hw_info->vfe_ops.axi_ops.cfg_framedrop(
vfe_dev->vfe_base, stream_info, framedrop_pattern,
framedrop_period);
stream_info->prev_framedrop_period =
(framedrop_period | 0x80000000);
stream_info->requested_framedrop_period = framedrop_period;
}
}
@ -554,30 +555,19 @@ void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev,
if (BURST_STREAM == stream_info->stream_type) {
if (0 == stream_info->runtime_num_burst_capture)
stream_info->current_framedrop_period =
MSM_VFE_STREAM_STOP_PERIOD;
MSM_VFE_STREAM_STOP_PERIOD;
}
if (stream_info->undelivered_request_cnt > 0)
stream_info->current_framedrop_period =
MSM_VFE_STREAM_STOP_PERIOD;
/*
* re-configure the period pattern, only if it's not already
* set to what we want
*/
if (stream_info->current_framedrop_period !=
stream_info->prev_framedrop_period) {
/*
* If we previously tried to set a valid period which
* did not take effect then we may have missed a reg
* update, print error to indicate this condition
*/
if ((stream_info->prev_framedrop_period & 0x80000000) &&
(stream_info->current_framedrop_period ==
(stream_info->prev_framedrop_period &
~0x80000000)))
ISP_DBG("Framedop setting for %p not taken effect %x/%x, frame_src %x\n",
stream_info,
stream_info->prev_framedrop_period,
stream_info->current_framedrop_period,
frame_src);
stream_info->activated_framedrop_period) {
msm_isp_cfg_framedrop_reg(vfe_dev, stream_info);
}
spin_unlock_irqrestore(&stream_info->lock, flags);
@ -2979,10 +2969,10 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
}
if ((frame_src == VFE_PIX_0) && !stream_info->undelivered_request_cnt &&
MSM_VFE_STREAM_STOP_PERIOD !=
stream_info->current_framedrop_period) {
stream_info->activated_framedrop_period) {
pr_debug("%s:%d vfe %d frame_id %d prev_pattern %x stream_id %x\n",
__func__, __LINE__, vfe_dev->pdev->id, frame_id,
stream_info->prev_framedrop_period,
stream_info->activated_framedrop_period,
stream_info->stream_id);
rc = msm_isp_return_empty_buffer(vfe_dev, stream_info,
@ -2990,10 +2980,9 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
if (rc < 0)
pr_err("%s:%d failed: return_empty_buffer src %d\n",
__func__, __LINE__, frame_src);
vfe_dev->hw_info->vfe_ops.axi_ops.cfg_framedrop(
vfe_dev->vfe_base, stream_info, 0, 0);
stream_info->current_framedrop_period =
MSM_VFE_STREAM_STOP_PERIOD;
msm_isp_cfg_framedrop_reg(vfe_dev, stream_info);
return 0;
}

View file

@ -2303,7 +2303,8 @@ void msm_isp_save_framedrop_values(struct vfe_device *vfe_dev,
stream_info =
&vfe_dev->axi_data.stream_info[j];
spin_lock_irqsave(&stream_info->lock, flags);
stream_info->prev_framedrop_period &= ~0x80000000;
stream_info->activated_framedrop_period =
stream_info->requested_framedrop_period;
spin_unlock_irqrestore(&stream_info->lock, flags);
}
}