summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h7
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c67
2 files changed, 72 insertions, 2 deletions
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 cef2cd9ffcf1..a6fbb4102c2c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -416,6 +416,12 @@ enum msm_isp_comp_irq_types {
#define MSM_VFE_REQUESTQ_SIZE 8
+struct msm_isp_pending_buf_info {
+ uint32_t is_buf_done_pending;
+ struct msm_isp_buffer *buf;
+ uint32_t frame_id;
+};
+
struct msm_vfe_axi_stream {
uint32_t frame_id;
enum msm_vfe_axi_state state;
@@ -472,6 +478,7 @@ struct msm_vfe_axi_stream {
uint32_t vfe_mask;
uint32_t composite_irq[MSM_ISP_COMP_IRQ_MAX];
int lpm_mode;
+ struct msm_isp_pending_buf_info pending_buf_info;
};
struct msm_vfe_axi_composite_info {
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 011a1d4019eb..d498ef0ae7a6 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
@@ -27,6 +27,13 @@ static void __msm_isp_axi_stream_update(
struct msm_vfe_axi_stream *stream_info,
struct msm_isp_timestamp *ts);
+static int msm_isp_process_done_buf(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info, struct msm_isp_buffer *buf,
+ struct timeval *time_stamp, uint32_t frame_id);
+static void msm_isp_free_pending_buffer(
+ struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info,
+ struct msm_isp_timestamp *ts);
static int msm_isp_update_stream_bandwidth(
struct msm_vfe_axi_stream *stream_info, int enable);
@@ -659,6 +666,10 @@ void msm_isp_process_reg_upd_epoch_irq(struct vfe_device *vfe_dev,
case MSM_ISP_COMP_IRQ_REG_UPD:
stream_info->activated_framedrop_period =
stream_info->requested_framedrop_period;
+ /* Free Pending Buffers which are backed-up due to
+ * delay in RUP from userspace to Avoid pageFault
+ */
+ msm_isp_free_pending_buffer(vfe_dev, stream_info, ts);
__msm_isp_axi_stream_update(stream_info, ts);
break;
case MSM_ISP_COMP_IRQ_EPOCH:
@@ -1523,6 +1534,40 @@ static void msm_isp_axi_stream_enable_cfg(
}
}
+static void msm_isp_free_pending_buffer(
+ struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info,
+ struct msm_isp_timestamp *ts)
+{
+ struct timeval *time_stamp;
+ struct msm_isp_buffer *done_buf = NULL;
+ uint32_t frame_id;
+ int rc;
+
+ if (!stream_info->controllable_output ||
+ !stream_info->pending_buf_info.is_buf_done_pending) {
+ return;
+ }
+
+ if (vfe_dev->vt_enable) {
+ msm_isp_get_avtimer_ts(ts);
+ time_stamp = &ts->vt_time;
+ } else {
+ time_stamp = &ts->buf_time;
+ }
+
+ done_buf = stream_info->pending_buf_info.buf;
+ frame_id = stream_info->pending_buf_info.frame_id;
+ if (done_buf) {
+ rc = msm_isp_process_done_buf(vfe_dev, stream_info,
+ done_buf, time_stamp, frame_id);
+ if (rc == 0) {
+ stream_info->pending_buf_info.buf = NULL;
+ stream_info->pending_buf_info.is_buf_done_pending = 0;
+ }
+ }
+}
+
static void __msm_isp_axi_stream_update(
struct msm_vfe_axi_stream *stream_info,
struct msm_isp_timestamp *ts)
@@ -3015,6 +3060,12 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
msm_isp_cfg_stream_scratch(stream_info, VFE_PONG_FLAG);
stream_info->undelivered_request_cnt = 0;
vfe_dev->irq_sof_id = 0;
+ if (stream_info->controllable_output &&
+ stream_info->pending_buf_info.is_buf_done_pending) {
+ msm_isp_free_pending_buffer(vfe_dev, stream_info,
+ &timestamp);
+ stream_info->pending_buf_info.is_buf_done_pending = 0;
+ }
for (k = 0; k < stream_info->num_isp; k++) {
vfe_dev = stream_info->vfe_dev[k];
if (stream_info->num_planes > 1)
@@ -4349,9 +4400,21 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev,
}
spin_unlock_irqrestore(&stream_info->lock, flags);
} else {
+ /* If there is no regupdate from userspace then dont
+ * free buffer immediately, delegate it to RegUpdateAck
+ */
+ if (stream_info->controllable_output &&
+ !(vfe_dev->reg_update_requested &
+ BIT((uint32_t)VFE_PIX_0))) {
+ stream_info->pending_buf_info.is_buf_done_pending = 1;
+ stream_info->pending_buf_info.buf = done_buf;
+ stream_info->pending_buf_info.frame_id = frame_id;
+ }
spin_unlock_irqrestore(&stream_info->lock, flags);
- msm_isp_process_done_buf(vfe_dev, stream_info,
- done_buf, time_stamp, frame_id);
+ if (stream_info->pending_buf_info.is_buf_done_pending != 1) {
+ msm_isp_process_done_buf(vfe_dev, stream_info,
+ done_buf, time_stamp, frame_id);
+ }
}
}