msm: camera: support exposure metering and HDR snapshots
With this change we achieve multiple things related
to correct HDR functionality. First, we do not
always configure ping and pong to be the same buffer in
case of the snapshot mode. This would help support taking
mulitple snapshots. Second, we support for logic to skip
frames in case of snapshot, a necessity for the exposure
metering feature. Third, we support post processing
divert of both snapshot and thumbnail buffers to be
taken from either mctl queue or video queue, to be
determined at runtime.
Change-Id: Ibcf2bbfc171b2686ca44e6366feadf435368fa5f
Signed-off-by: Ankit Premrajka <ankitp@codeaurora.org>
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 7cab16e..7680559 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -427,7 +427,7 @@
int msg_type, struct msm_free_buf *buf,
uint32_t frame_id);
int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
- int msg_type, struct msm_free_buf *frame, int dirty);
+ int msg_type, struct msm_free_buf *frame, int dirty, int node_type);
int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
int path, struct msm_free_buf *free_buf);
@@ -474,7 +474,7 @@
int msm_mctl_pp_notify(struct msm_cam_media_controller *pmctl,
struct msm_mctl_pp_frame_info *pp_frame_info);
int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
- int out_type);
+ int out_type, int node_type);
struct msm_frame_buffer *msm_mctl_buf_find(
struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst, int del_buf,
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 0cffbbf..bb50d77 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -142,7 +142,7 @@
{
int rc = -EINVAL, image_mode;
struct msm_vfe_resp *vdata = (struct msm_vfe_resp *)arg;
- struct msm_free_buf free_buf;
+ struct msm_free_buf free_buf, temp_free_buf;
struct msm_camvfe_params vfe_params;
struct msm_vfe_cfg_cmd cfgcmd;
struct msm_sync *sync =
@@ -190,7 +190,12 @@
vfe_params.vfe_cfg = &cfgcmd;
vfe_params.data = (void *)&free_buf;
rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
- /* Write the same buffer into PONG */
+ temp_free_buf = free_buf;
+ if (msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+ image_mode, &free_buf)) {
+ /* Write the same buffer into PONG */
+ free_buf = temp_free_buf;
+ }
cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
cfgcmd.value = &vfe_id;
vfe_params.vfe_cfg = &cfgcmd;
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 1ab76fe..8148f1f 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -325,9 +325,13 @@
}
int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
- int image_mode)
+ int image_mode, int node_type)
{
- if ((image_mode >= 0) &&
+ if ((image_mode >= 0) && node_type &&
+ pmctl->sync.pcam_sync->mctl_node.dev_inst_map[image_mode])
+ return pmctl->sync.pcam_sync->
+ mctl_node.dev_inst_map[image_mode]->my_index;
+ else if ((image_mode >= 0) &&
pmctl->sync.pcam_sync->dev_inst_map[image_mode])
return pmctl->sync.pcam_sync->
dev_inst_map[image_mode]->my_index;
@@ -424,13 +428,13 @@
msm_mctl_check_pp(p_mctl, image_mode, &pp_divert_type, &pp_type);
D("%s: pp_type=%d, pp_divert_type = %d, frame_id = 0x%x",
- __func__, pp_type, pp_divert_type, frame_id);
+ __func__, pp_type, pp_divert_type, frame_id);
if (pp_type || pp_divert_type)
rc = msm_mctl_do_pp_divert(p_mctl,
image_mode, fbuf, frame_id, pp_type);
else {
idx = msm_mctl_img_mode_to_inst_index(
- p_mctl, image_mode);
+ p_mctl, image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, dropping buffer\n",
__func__);
@@ -450,6 +454,22 @@
return 0;
}
+static int is_buffer_queued(struct msm_cam_v4l2_device *pcam, int image_mode)
+{
+ int idx;
+ int ret = 0;
+ struct msm_frame_buffer *buf = NULL;
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ idx = pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+ if (buf->state != MSM_BUFFER_STATE_QUEUED)
+ continue;
+ ret = 1;
+ }
+ return ret;
+}
+
struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
struct msm_cam_media_controller *pmctl,
int image_mode)
@@ -462,22 +482,39 @@
/* Valid image mode. Search the mctl node first.
* If mctl node doesnt have the instance, then
* search in the user's video node */
- if (pcam->mctl_node.dev_inst_map[image_mode]) {
- idx =
- pcam->mctl_node.dev_inst_map[image_mode]->my_index;
- pcam_inst = pcam->mctl_node.dev_inst[idx];
- D("%s Found instance %p in mctl node device\n",
+ if (pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_THUMB
+ || pmctl->vfe_output_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
+ if (pcam->mctl_node.dev_inst_map[image_mode]
+ && is_buffer_queued(pcam, image_mode)) {
+ idx =
+ pcam->mctl_node.dev_inst_map[image_mode]
+ ->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ D("%s Found instance %p in mctl node device\n",
+ __func__, pcam_inst);
+ } else if (pcam->dev_inst_map[image_mode]) {
+ idx = pcam->dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ D("%s Found instance %p in video device",
__func__, pcam_inst);
- } else if (pcam->dev_inst_map[image_mode]) {
- idx = pcam->dev_inst_map[image_mode]->my_index;
- pcam_inst = pcam->dev_inst[idx];
- D("%s Found instance %p in video device",
+ }
+ } else {
+ if (pcam->mctl_node.dev_inst_map[image_mode]) {
+ idx = pcam->mctl_node.dev_inst_map[image_mode]
+ ->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ D("%s Found instance %p in mctl node device\n",
__func__, pcam_inst);
+ } else if (pcam->dev_inst_map[image_mode]) {
+ idx = pcam->dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ D("%s Found instance %p in video device",
+ __func__, pcam_inst);
+ }
}
} else
pr_err("%s Invalid image mode %d. Return NULL\n",
__func__, image_mode);
-
return pcam_inst;
}
@@ -597,19 +634,21 @@
return rc;
}
-int msm_mctl_buf_done_pp(
- struct msm_cam_media_controller *pmctl,
- int image_mode, struct msm_free_buf *frame, int dirty)
+int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
+ int image_mode, struct msm_free_buf *frame, int dirty, int node_type)
{
struct msm_cam_v4l2_dev_inst *pcam_inst;
int rc = 0, idx;
- idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode);
+ idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode, node_type);
if (idx < 0) {
pr_err("%s Invalid instance, buffer not released\n", __func__);
return idx;
}
- pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+ if (node_type)
+ pcam_inst = pmctl->sync.pcam_sync->mctl_node.dev_inst[idx];
+ else
+ pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
if (!pcam_inst) {
pr_err("%s Invalid instance, cannot send buf to user",
__func__);
@@ -638,7 +677,7 @@
int rc = -EINVAL, idx;
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode);
+ image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, cant get buffer\n", __func__);
return NULL;
@@ -677,7 +716,7 @@
struct msm_frame_buffer *buf = NULL;
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode);
+ image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, cant put buffer\n", __func__);
return idx;
@@ -712,7 +751,7 @@
int idx;
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode);
+ image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, cant delete buffer\n", __func__);
return idx;
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 1593e7e..82c5bf7 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -95,20 +95,95 @@
*pp_type = OUTPUT_TYPE_V;
break;
case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
+ pp_key = PP_THUMB;
+ if (p_mctl->pp_info.pp_key & pp_key)
+ *pp_divert_type = OUTPUT_TYPE_T;
if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_T)
*pp_type = OUTPUT_TYPE_T;
break;
default:
break;
}
- if (p_mctl->pp_info.div_frame[image_mode].ch_paddr[0])
- *pp_divert_type = 0;
+ if (p_mctl->vfe_output_mode != VFE_OUTPUTS_MAIN_AND_THUMB &&
+ p_mctl->vfe_output_mode != VFE_OUTPUTS_THUMB_AND_MAIN) {
+ if (p_mctl->pp_info.div_frame[image_mode].ch_paddr[0])
+ *pp_divert_type = 0;
+ }
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
D("%s: pp_type=%d, pp_divert_type = %d",
__func__, *pp_type, *pp_divert_type);
return rc;
}
+static int is_buf_in_queue(struct msm_cam_v4l2_device *pcam,
+ struct msm_free_buf *fbuf, int image_mode)
+{
+ struct msm_frame_buffer *buf = NULL, *tmp;
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ unsigned long flags = 0;
+ struct videobuf2_contig_pmem *mem;
+ uint32_t buf_idx, offset = 0;
+ uint32_t buf_phyaddr = 0;
+ int idx;
+ idx = pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+ list_for_each_entry_safe(buf, tmp,
+ &pcam_inst->free_vq, list) {
+ buf_idx = buf->vidbuf.v4l2_buf.index;
+ mem = vb2_plane_cookie(&buf->vidbuf, 0);
+ if (mem->buffer_type == VIDEOBUF2_MULTIPLE_PLANES)
+ offset = mem->offset.data_offset +
+ pcam_inst->buf_offset[buf_idx][0].data_offset;
+ else
+ offset = mem->offset.sp_off.y_off;
+ buf_phyaddr = (unsigned long)
+ videobuf2_to_pmem_contig(&buf->vidbuf, 0) +
+ offset;
+ D("%s vb_idx=%d,vb_paddr=0x%x ch0=0x%x\n",
+ __func__, buf->vidbuf.v4l2_buf.index,
+ buf_phyaddr, fbuf->ch_paddr[0]);
+ if (fbuf->ch_paddr[0] == buf_phyaddr) {
+ spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+ return 1;
+ }
+ }
+ spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+ return 0;
+}
+static struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst_for_divert(
+ struct msm_cam_media_controller *pmctl,
+ int image_mode, struct msm_free_buf *fbuf, int *node_type)
+{
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+ int idx;
+
+ if (image_mode >= 0) {
+ /* Valid image mode. Search the mctl node first.
+ * If mctl node doesnt have the instance, then
+ * search in the user's video node */
+ if (pcam->mctl_node.dev_inst_map[image_mode]
+ && is_buf_in_queue(pcam, fbuf, image_mode)) {
+ idx =
+ pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ *node_type = MCTL_NODE;
+ D("%s Found instance %p in mctl node device\n",
+ __func__, pcam_inst);
+ } else if (pcam->dev_inst_map[image_mode]) {
+ idx = pcam->dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ *node_type = VIDEO_NODE;
+ D("%s Found instance %p in video device",
+ __func__, pcam_inst);
+ } else
+ pr_err("%s Invalid image mode %d. Return NULL\n",
+ __func__, image_mode);
+ }
+ return pcam_inst;
+}
+
int msm_mctl_do_pp_divert(
struct msm_cam_media_controller *p_mctl,
int image_mode, struct msm_free_buf *fbuf,
@@ -120,8 +195,10 @@
struct msm_cam_evt_divert_frame div;
struct msm_frame_buffer *vb = NULL;
struct videobuf2_contig_pmem *mem;
+ int node;
- pcam_inst = msm_mctl_get_pcam_inst(p_mctl, image_mode);
+ pcam_inst = msm_mctl_get_pcam_inst_for_divert
+ (p_mctl, image_mode, fbuf, &node);
if (!pcam_inst) {
pr_err("%s Invalid instance. Cannot divert frame.\n",
__func__);
@@ -155,6 +232,7 @@
* this buffer.*/
mem = vb2_plane_cookie(&vb->vidbuf, 0);
div.frame.path = mem->path;
+ div.frame.node_type = node;
if (mem->buffer_type == VIDEOBUF2_SINGLE_PLANE) {
/* This buffer contains only 1 plane. Use the
* single planar structure to store the info.*/
@@ -670,7 +748,7 @@
done_frame.vb =
pp_frame_info->dest_frame.handle;
msm_mctl_buf_done_pp(
- p_mctl, img_mode, &done_frame, 0);
+ p_mctl, img_mode, &done_frame, 0, 0);
D("%s: vpe done to app, vb=0x%x, path=%d, phy=0x%x",
__func__, done_frame.vb,
pp_frame_cmd->path, done_frame.ch_paddr[0]);
@@ -848,7 +926,7 @@
}
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
/* here buf.addr is phy_addr */
- rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
+ rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty, 0);
return rc;
}
@@ -882,6 +960,9 @@
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
break;
case OUTPUT_TYPE_T:
+ msg_type = VFE_MSG_OUTPUT_T;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+ break;
default:
rc = -EFAULT;
goto err;
@@ -895,7 +976,8 @@
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
D("%s Frame done id: %d\n", __func__, frame.frame_id);
- rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
+ rc = msm_mctl_buf_done_pp(p_mctl, image_mode,
+ &buf, dirty, frame.node_type);
return rc;
err:
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index e1a36a8..99d9911 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -547,6 +547,10 @@
memset(&(vfe32_ctrl->csStatsControl), 0,
sizeof(struct vfe_stats_control));
+
+ vfe32_ctrl->frame_skip_cnt = 31;
+ vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+ vfe32_ctrl->snapshot_frame_cnt = 0;
}
static void vfe32_reset(void)
@@ -2370,6 +2374,23 @@
goto proc_general_done;
}
break;
+ case VFE_CMD_FRAME_SKIP_CFG:
+ if (cmd->length != vfe32_cmd[cmd->id].length)
+ return -EINVAL;
+
+ cmdp = kmalloc(vfe32_cmd[cmd->id].length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+
+ CHECKED_COPY_FROM_USER(cmdp);
+ msm_io_memcpy(vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ cmdp, (vfe32_cmd[cmd->id].length));
+ vfe32_ctrl->frame_skip_cnt = ((uint32_t)
+ *cmdp & VFE_FRAME_SKIP_PERIOD_MASK) + 1;
+ vfe32_ctrl->frame_skip_pattern = (uint32_t)(*(cmdp + 2));
+ break;
default:
if (cmd->length != vfe32_cmd[cmd->id].length)
return -EINVAL;
@@ -2592,30 +2613,43 @@
(vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB)) {
/* in snapshot mode */
/* later we need to add check for live snapshot mode. */
- vfe32_ctrl->vfe_capture_count--;
- /* if last frame to be captured: */
- if (vfe32_ctrl->vfe_capture_count == 0) {
- if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- }
- if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
- }
- msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
+ (vfe32_ctrl->snapshot_frame_cnt %
+ vfe32_ctrl->frame_skip_cnt))) {
+ vfe32_ctrl->vfe_capture_count--;
+ /* if last frame to be captured: */
+ if (vfe32_ctrl->vfe_capture_count == 0) {
+ /* stop the bus output:write master enable = 0*/
+ if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out0.ch0]);
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out0.ch1]);
+ }
+ if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out1.ch0]);
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out1.ch1]);
+ }
+ msm_io_w_mb
+ (CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
- /* then do reg_update. */
- msm_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- }
- } /* in snapshot mode. */
+ vfe32_ctrl->snapshot_frame_cnt = -1;
+ vfe32_ctrl->frame_skip_cnt = 31;
+ vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+ } /*if snapshot count is 0*/
+ } /*if frame is not being dropped*/
+ vfe32_ctrl->snapshot_frame_cnt++;
+ /* then do reg_update. */
+ msm_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ } /* if snapshot mode. */
}
static void vfe32_set_default_reg_values(void)
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index c511b69..62c3639 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -169,6 +169,7 @@
#define VFE_AWB_PINGPONG_STATUS_BIT 0x200
#define HFR_MODE_OFF 1
+#define VFE_FRAME_SKIP_PERIOD_MASK 0x0000001F /*bits 0 -4*/
enum VFE32_DMI_RAM_SEL {
NO_MEM_SELECTED = 0,
@@ -968,6 +969,9 @@
struct clk *vfe_clk[3];
spinlock_t sd_notify_lock;
uint32_t hfr_mode;
+ uint32_t frame_skip_cnt;
+ uint32_t frame_skip_pattern;
+ uint32_t snapshot_frame_cnt;
};
#define statsAeNum 0
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 8d2852b..87fbbd2 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -217,7 +217,8 @@
#define PP_SNAP 0x01
#define PP_RAW_SNAP ((0x01)<<1)
#define PP_PREV ((0x01)<<2)
-#define PP_MASK (PP_SNAP|PP_RAW_SNAP|PP_PREV)
+#define PP_THUMB ((0x01)<<3)
+#define PP_MASK (PP_SNAP|PP_RAW_SNAP|PP_PREV|PP_THUMB)
#define MSM_CAM_CTRL_CMD_DONE 0
#define MSM_CAM_SENSOR_VFE_CMD 1
@@ -295,6 +296,7 @@
struct msm_pp_frame_sp sp;
struct msm_pp_frame_mp mp[MAX_PLANES];
};
+ int node_type;
};
struct msm_cam_evt_divert_frame {
@@ -509,6 +511,9 @@
uint32_t window_height_lastline;
};
+#define VIDEO_NODE 0
+#define MCTL_NODE 1
+
#define OUTPUT_1 0
#define OUTPUT_2 1
#define OUTPUT_1_AND_2 2 /* snapshot only */