Merge "msm: camera: Refactor ISP snapshot buffer management"
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 7c7d8b2..ac3ce0a 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
@@ -35,6 +35,8 @@
stream_cfg_cmd->axi_stream_handle =
(++axi_data->stream_handle_cnt) << 8 | i;
+ memset(&axi_data->stream_info[i], 0,
+ sizeof(struct msm_vfe_axi_stream));
axi_data->stream_info[i].session_id = stream_cfg_cmd->session_id;
axi_data->stream_info[i].stream_id = stream_cfg_cmd->stream_id;
axi_data->stream_info[i].buf_divert = stream_cfg_cmd->buf_divert;
@@ -645,40 +647,24 @@
}
}
-int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
- struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
- struct timeval *tv)
+static void msm_isp_cfg_pong_address(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info)
{
- int i, rc = -1;
- struct msm_isp_buffer *buf = NULL;
- struct msm_isp_event_data buf_event;
- uint32_t pingpong_bit = 0;
- uint32_t bufq_handle = stream_info->bufq_handle;
- uint32_t stream_idx = stream_info->stream_handle & 0xFF;
+ int i;
+ struct msm_isp_buffer *buf = stream_info->buf[1];
+ for (i = 0; i < stream_info->num_planes; i++)
+ vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
+ vfe_dev, stream_info->wm[i],
+ VFE_PING_FLAG, buf->mapped_info[i].paddr);
+ stream_info->buf[0] = buf;
+}
+static void msm_isp_get_done_buf(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
+ struct msm_isp_buffer **done_buf)
+{
+ uint32_t pingpong_bit = 0, i;
pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1);
- rc = vfe_dev->buf_mgr->ops->get_buf(
- vfe_dev->buf_mgr, bufq_handle, &buf);
- if (rc < 0) {
- if (stream_info->stream_type == BURST_STREAM &&
- stream_info->num_burst_capture <= 1) {
- rc = 0;
- if (pingpong_bit)
- buf = stream_info->buf[0];
- else
- buf = stream_info->buf[1];
- } else {
- vfe_dev->error_info.
- stream_framedrop_count[stream_idx]++;
- return rc;
- }
- }
-
- if (buf->num_planes != stream_info->num_planes) {
- pr_err("%s: Invalid buffer\n", __func__);
- rc = -EINVAL;
- goto buf_error;
- }
for (i = 0; i < stream_info->num_planes; i++) {
if (pingpong_bit !=
(~(pingpong_status >> stream_info->wm[i]) & 0x1)) {
@@ -686,19 +672,58 @@
__func__, pingpong_status);
}
}
+ *done_buf = stream_info->buf[pingpong_bit];
+}
+
+static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status)
+{
+ int i, rc = -1;
+ struct msm_isp_buffer *buf = NULL;
+ uint32_t pingpong_bit = 0;
+ uint32_t bufq_handle = stream_info->bufq_handle;
+ uint32_t stream_idx = stream_info->stream_handle & 0xFF;
+
+ rc = vfe_dev->buf_mgr->ops->get_buf(
+ vfe_dev->buf_mgr, bufq_handle, &buf);
+ if (rc < 0) {
+ vfe_dev->error_info.
+ stream_framedrop_count[stream_idx]++;
+ return rc;
+ }
+
+ if (buf->num_planes != stream_info->num_planes) {
+ pr_err("%s: Invalid buffer\n", __func__);
+ rc = -EINVAL;
+ goto buf_error;
+ }
+
for (i = 0; i < stream_info->num_planes; i++)
vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
vfe_dev, stream_info->wm[i],
pingpong_status, buf->mapped_info[i].paddr);
- if (stream_info->buf[pingpong_bit] && tv) {
+ pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1);
+ stream_info->buf[pingpong_bit] = buf;
+ return 0;
+buf_error:
+ vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
+ buf->bufq_handle, buf->buf_idx);
+ return rc;
+}
+
+static void msm_isp_process_done_buf(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info, struct msm_isp_buffer *buf,
+ struct timeval *tv)
+{
+ struct msm_isp_event_data buf_event;
+ uint32_t frame_id = vfe_dev->axi_data.
+ src_info[stream_info->stream_src].frame_id;
+ if (buf && tv) {
if (stream_info->buf_divert) {
vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
- stream_info->buf[pingpong_bit]->bufq_handle,
- stream_info->buf[pingpong_bit]->buf_idx,
- tv, stream_info->frame_id);
-
- buf_event.frame_id = stream_info->frame_id;
+ buf->bufq_handle, buf->buf_idx, tv, frame_id);
+ buf_event.frame_id = frame_id;
buf_event.timestamp = *tv;
buf_event.u.buf_done.session_id =
stream_info->session_id;
@@ -706,24 +731,14 @@
stream_info->stream_id;
buf_event.u.buf_done.handle =
stream_info->bufq_handle;
- buf_event.u.buf_done.buf_idx =
- stream_info->buf[pingpong_bit]->buf_idx;
+ buf_event.u.buf_done.buf_idx = buf->buf_idx;
msm_isp_send_event(
vfe_dev, ISP_EVENT_BUF_DIVERT, &buf_event);
} else {
vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
- stream_info->buf[pingpong_bit]->bufq_handle,
- stream_info->buf[pingpong_bit]->buf_idx,
- tv, stream_info->frame_id);
+ buf->bufq_handle, buf->buf_idx, tv, frame_id);
}
}
-
- stream_info->buf[pingpong_bit] = buf;
- return 0;
-buf_error:
- vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
- buf->bufq_handle, buf->buf_idx);
- return rc;
}
enum msm_isp_camif_update_state
@@ -851,7 +866,6 @@
&axi_data->stream_info[
(stream_cfg_cmd->stream_handle[i] & 0xFF)];
-
if (stream_info->stream_src == RDI)
src_state =
axi_data->src_info[
@@ -865,9 +879,23 @@
if (stream_cfg_cmd->cmd == START_STREAM) {
/*Set address for both PING & PONG register */
rc = msm_isp_cfg_ping_pong_address(vfe_dev,
- stream_info, VFE_PING_FLAG, NULL);
- rc = msm_isp_cfg_ping_pong_address(vfe_dev,
- stream_info, VFE_PONG_FLAG, NULL);
+ stream_info, VFE_PONG_FLAG);
+ if (rc < 0) {
+ pr_err("%s: No buffer for start stream\n",
+ __func__);
+ return rc;
+ }
+ /* For burst stream of one capture, only one buffer
+ * is allocated. Duplicate ping buffer address to pong
+ * buffer to ensure hardware write to a valid address
+ */
+ if (stream_info->stream_type == BURST_STREAM &&
+ stream_info->num_burst_capture <= 1) {
+ msm_isp_cfg_pong_address(vfe_dev, stream_info);
+ } else {
+ rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+ stream_info, VFE_PING_FLAG);
+ }
}
if (src_state && camif_update != DISABLE_CAMIF) {
/*On the fly stream start/stop */
@@ -954,7 +982,8 @@
uint32_t irq_status0, uint32_t irq_status1,
struct timeval *tv)
{
- int i;
+ int i, rc = 0;
+ struct msm_isp_buffer *done_buf = NULL;
uint32_t comp_mask = 0, wm_mask = 0;
uint32_t pingpong_status, stream_idx;
struct msm_vfe_axi_stream *stream_info;
@@ -986,8 +1015,18 @@
__func__,
stream_idx, stream_info->frame_id);
stream_info->frame_id++;
- msm_isp_cfg_ping_pong_address(vfe_dev,
- stream_info, pingpong_status, tv);
+ msm_isp_get_done_buf(vfe_dev, stream_info,
+ pingpong_status, &done_buf);
+ if (stream_info->stream_type ==
+ CONTINUOUS_STREAM ||
+ stream_info->num_burst_capture > 1) {
+ rc = msm_isp_cfg_ping_pong_address(
+ vfe_dev, stream_info,
+ pingpong_status);
+ }
+ if (done_buf && !rc)
+ msm_isp_process_done_buf(vfe_dev,
+ stream_info, done_buf, tv);
}
}
wm_mask &= ~(comp_info->stream_composite_mask);
@@ -1003,8 +1042,16 @@
stream_idx = axi_data->free_wm[i] & 0xFF;
stream_info = &axi_data->stream_info[stream_idx];
stream_info->frame_id++;
- msm_isp_cfg_ping_pong_address(vfe_dev,
- stream_info, pingpong_status, tv);
+ msm_isp_get_done_buf(vfe_dev, stream_info,
+ pingpong_status, &done_buf);
+ if (stream_info->stream_type == CONTINUOUS_STREAM ||
+ stream_info->num_burst_capture > 1) {
+ rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+ stream_info, pingpong_status);
+ }
+ if (done_buf && !rc)
+ msm_isp_process_done_buf(vfe_dev,
+ stream_info, done_buf, tv);
}
}
return;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index 0c64c19..9765ae2 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -52,10 +52,6 @@
void msm_isp_axi_stream_update(struct vfe_device *vfe_dev);
-int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
- struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
- struct timeval *tv);
-
void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev);
void msm_isp_update_framedrop_count(struct vfe_device *vfe_dev);
void msm_isp_sof_notify(struct vfe_device *vfe_dev,