msm: camera: Add support for concurrent Ispif interface streaming
Add support for multiple ispif interfaces streaming concurrently.
PIX abd RDI interface can stream at same time or two RDI interfaces
may stream at one time depending on usecase
Change-Id: Ib3cef418cd2816bc19891c1855e1dcae5a2a55a1
Signed-off-by: Nishant Pandit <npandit@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 6d2c25a..4d66d88 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -95,6 +95,7 @@
VFE_MSG_OUTPUT_PRIMARY,
VFE_MSG_OUTPUT_SECONDARY,
VFE_MSG_OUTPUT_TERTIARY1,
+ VFE_MSG_OUTPUT_TERTIARY2,
};
enum vpe_resp_msg {
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index c6fadc0..b67af4f 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -668,6 +668,10 @@
return OUTPUT_TYPE_S;
case MSM_V4L2_EXT_CAPTURE_MODE_VIDEO:
return OUTPUT_TYPE_V;
+ case MSM_V4L2_EXT_CAPTURE_MODE_RDI:
+ return OUTPUT_TYPE_R;
+ case MSM_V4L2_EXT_CAPTURE_MODE_RDI1:
+ return OUTPUT_TYPE_R1;
case MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT:
case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
default:
@@ -817,10 +821,6 @@
break;
}
- server_q_idx = msm_find_free_queue();
- if (server_q_idx < 0)
- return server_q_idx;
-
/* if no instance is available, return error */
if (i == MSM_DEV_INST_MAX) {
mutex_unlock(&pcam->vid_lock);
@@ -843,6 +843,10 @@
pcam->use_count++;
D("%s use_count %d\n", __func__, pcam->use_count);
if (pcam->use_count == 1) {
+ server_q_idx = msm_find_free_queue();
+ if (server_q_idx < 0)
+ return server_q_idx;
+
rc = msm_server_begin_session(pcam, server_q_idx);
if (rc < 0) {
pr_err("%s error starting server session ", __func__);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 7d07e7b..95e1b0e 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -181,7 +181,7 @@
struct msm_cam_v4l2_device;
struct msm_cam_v4l2_dev_inst;
-#define MSM_MAX_IMG_MODE 8
+#define MSM_MAX_IMG_MODE MSM_V4L2_EXT_CAPTURE_MODE_MAX
enum msm_buffer_state {
MSM_BUFFER_STATE_UNUSED,
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 9b42f9b..5c61cdb 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -85,8 +85,10 @@
int vfe_msg)
{
int image_mode;
+ uint32_t vfe_output_mode = pmctl->vfe_output_mode;
+ vfe_output_mode &= ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
if (vfe_msg == VFE_MSG_OUTPUT_PRIMARY) {
- switch (pmctl->vfe_output_mode) {
+ switch (vfe_output_mode) {
case VFE_OUTPUTS_MAIN_AND_PREVIEW:
case VFE_OUTPUTS_MAIN_AND_VIDEO:
case VFE_OUTPUTS_MAIN_AND_THUMB:
@@ -110,7 +112,7 @@
break;
}
} else if (vfe_msg == VFE_MSG_OUTPUT_SECONDARY) {
- switch (pmctl->vfe_output_mode) {
+ switch (vfe_output_mode) {
case VFE_OUTPUTS_MAIN_AND_PREVIEW:
case VFE_OUTPUTS_VIDEO_AND_PREVIEW:
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
@@ -137,14 +139,15 @@
break;
}
} else if (vfe_msg == VFE_MSG_OUTPUT_TERTIARY1) {
- switch (pmctl->vfe_output_mode) {
- case VFE_OUTPUTS_RDI0:
- image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
- break;
- default:
+ if (pmctl->vfe_output_mode & VFE_OUTPUTS_RDI0)
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_RDI;
+ else
image_mode = -1;
- break;
- }
+ } else if (vfe_msg == VFE_MSG_OUTPUT_TERTIARY2) {
+ if (pmctl->vfe_output_mode & VFE_OUTPUTS_RDI1)
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_RDI1;
+ else
+ image_mode = -1;
} else
image_mode = -1;
@@ -343,6 +346,10 @@
case MSG_ID_OUTPUT_TERTIARY1:
msgid = VFE_MSG_OUTPUT_TERTIARY1;
break;
+ case MSG_ID_OUTPUT_TERTIARY2:
+ msgid = VFE_MSG_OUTPUT_TERTIARY2;
+ break;
+
default:
pr_err("%s: Invalid VFE output id: %d\n",
__func__, isp_output->output_id);
@@ -686,6 +693,7 @@
case CMD_AXI_START:
case CMD_AXI_STOP:
case CMD_AXI_CFG_TERT1:
+ case CMD_AXI_CFG_TERT2:
/* Dont need to pass buffer information.
* subdev will get the buffer from media
* controller free queue.
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 1359792..0da5043 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -1559,6 +1559,10 @@
return OUTPUT_TYPE_S;
case MSM_V4L2_EXT_CAPTURE_MODE_VIDEO:
return OUTPUT_TYPE_V;
+ case MSM_V4L2_EXT_CAPTURE_MODE_RDI:
+ return OUTPUT_TYPE_R;
+ case MSM_V4L2_EXT_CAPTURE_MODE_RDI1:
+ return OUTPUT_TYPE_R1;
case MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT:
case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
default:
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 844a3ff..abcee4b 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -506,7 +506,7 @@
return -EINVAL;
}
/* Always reserve the buffer from user's video node */
- pcam_inst = p_mctl->pcam_ptr->dev_inst[image_mode];
+ pcam_inst = p_mctl->pcam_ptr->dev_inst_map[image_mode];
if (!pcam_inst) {
pr_err("%s Instance already closed ", __func__);
return -EINVAL;
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 75904cc..ffc193a 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -416,6 +416,7 @@
{
uint32_t *ch_info;
uint32_t *axi_cfg = ao+V32_AXI_BUS_FMT_OFF;
+ int vfe_mode = (mode & ~(OUTPUT_TERT1|OUTPUT_TERT2));
/* Update the corresponding write masters for each output*/
ch_info = axi_cfg + V32_AXI_CFG_LEN;
@@ -434,38 +435,50 @@
axi_ctrl->share_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
axi_ctrl->share_ctrl->outpath.out2.ch1 =
0x0000FFFF & (*ch_info++ >> 16);
- axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+ axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info;
axi_ctrl->share_ctrl->outpath.out2.image_mode =
0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out3.ch0 = 0x0000FFFF & *ch_info;
+ axi_ctrl->share_ctrl->outpath.out3.ch1 =
+ 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out3.ch2 = 0x0000FFFF & *ch_info;
+ axi_ctrl->share_ctrl->outpath.out3.image_mode =
+ 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.output_mode = 0;
-
- switch (mode) {
- case OUTPUT_TERT1:
- axi_ctrl->share_ctrl->outpath.output_mode =
+ if (mode & OUTPUT_TERT1)
+ axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_TERTIARY1;
- break;
+ if (mode & OUTPUT_TERT2)
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE32_OUTPUT_MODE_TERTIARY2;
+ if (mode == OUTPUT_TERT1 || mode == OUTPUT_TERT1
+ || mode == (OUTPUT_TERT1|OUTPUT_TERT2))
+ goto bus_cfg;
+
+ switch (vfe_mode) {
case OUTPUT_PRIM:
- axi_ctrl->share_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_PRIMARY;
break;
case OUTPUT_PRIM_ALL_CHNLS:
- axi_ctrl->share_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
break;
case OUTPUT_PRIM|OUTPUT_SEC:
- axi_ctrl->share_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_PRIMARY;
axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_SECONDARY;
break;
case OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS:
- axi_ctrl->share_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_PRIMARY;
axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
break;
case OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC:
- axi_ctrl->share_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_SECONDARY;
@@ -474,6 +487,8 @@
pr_err("%s Invalid AXI mode %d ", __func__, mode);
return -EINVAL;
}
+
+bus_cfg:
msm_camera_io_w(*ao, axi_ctrl->share_ctrl->vfebase +
VFE_BUS_IO_FORMAT_CFG);
msm_camera_io_memcpy(axi_ctrl->share_ctrl->vfebase +
@@ -724,7 +739,10 @@
static void vfe32_start_common(struct vfe32_ctrl_type *vfe32_ctrl)
{
- uint32_t irq_mask = 0x00E00021, irq_mask1;
+ uint32_t irq_mask = 0x00E00021, irq_mask1, reg_update;
+ uint16_t vfe_operation_mode =
+ vfe32_ctrl->share_ctrl->operation_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
vfe32_ctrl->start_ack_pending = TRUE;
CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
vfe32_ctrl->share_ctrl->operation_mode,
@@ -741,18 +759,30 @@
msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
- if (vfe32_ctrl->share_ctrl->operation_mode == VFE_OUTPUTS_RDI0) {
- irq_mask1 =
+ irq_mask1 =
msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
VFE_IRQ_MASK_1);
+ reg_update =
+ msm_camera_io_r_mb(vfe32_ctrl->share_ctrl->vfebase +
+ VFE_REG_UPDATE_CMD);
+
+ if (vfe32_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0) {
irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
msm_camera_io_w(irq_mask1, vfe32_ctrl->share_ctrl->vfebase +
VFE_IRQ_MASK_1);
- msm_camera_io_w_mb(2, vfe32_ctrl->share_ctrl->vfebase +
- VFE_REG_UPDATE_CMD);
- } else {
- msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
- VFE_REG_UPDATE_CMD);
+ msm_camera_io_w_mb(reg_update|0x2, vfe32_ctrl->share_ctrl->
+ vfebase + VFE_REG_UPDATE_CMD);
+ }
+ if (vfe32_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1) {
+ irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
+ msm_camera_io_w(irq_mask1, vfe32_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+ msm_camera_io_w_mb(reg_update|0x4, vfe32_ctrl->share_ctrl->
+ vfebase + VFE_REG_UPDATE_CMD);
+ }
+ if (vfe_operation_mode) {
+ msm_camera_io_w_mb(reg_update|0x1, vfe32_ctrl->share_ctrl->
+ vfebase + VFE_REG_UPDATE_CMD);
msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
VFE_CAMIF_COMMAND);
}
@@ -1059,6 +1089,15 @@
msm_camera_io_w(irq_mask, vfe32_ctrl->share_ctrl->vfebase +
VFE_IRQ_MASK_0);
}
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_TERTIARY2) {
+ irq_mask = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask |= (0x1 << (vfe32_ctrl->share_ctrl->outpath.out3.ch0 +
+ VFE_WM_OFFSET));
+ msm_camera_io_w(irq_mask, vfe32_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ }
msm_camera_io_w(irq_comp_mask,
vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
@@ -1279,6 +1318,8 @@
ch = &share_ctrl->outpath.out1;
else if (path == VFE_MSG_OUTPUT_TERTIARY1)
ch = &share_ctrl->outpath.out2;
+ else if (path == VFE_MSG_OUTPUT_TERTIARY2)
+ ch = &share_ctrl->outpath.out3;
else
pr_err("%s: Invalid path %d\n", __func__,
path);
@@ -1299,6 +1340,8 @@
image_mode = axi_ctrl->share_ctrl->outpath.out1.image_mode;
else if (path == VFE_MSG_OUTPUT_TERTIARY1)
image_mode = axi_ctrl->share_ctrl->outpath.out2.image_mode;
+ else if (path == VFE_MSG_OUTPUT_TERTIARY2)
+ image_mode = axi_ctrl->share_ctrl->outpath.out3.image_mode;
vfe32_subdev_notify(id, path, image_mode,
&axi_ctrl->subdev, axi_ctrl->share_ctrl);
@@ -1319,6 +1362,8 @@
image_mode = vfe32_ctrl->share_ctrl->outpath.out1.image_mode;
else if (path == VFE_MSG_OUTPUT_TERTIARY1)
image_mode = vfe32_ctrl->share_ctrl->outpath.out2.image_mode;
+ else if (path == VFE_MSG_OUTPUT_TERTIARY2)
+ image_mode = vfe32_ctrl->share_ctrl->outpath.out3.image_mode;
vfe32_subdev_notify(id, path, image_mode,
&vfe32_ctrl->subdev, vfe32_ctrl->share_ctrl);
@@ -1335,8 +1380,8 @@
outch->pong.ch_paddr[0]);
if ((vfe32_ctrl->share_ctrl->operation_mode !=
- VFE_OUTPUTS_RAW) &&
- (path != VFE_MSG_OUTPUT_TERTIARY1)) {
+ VFE_OUTPUTS_RAW) && (path != VFE_MSG_OUTPUT_TERTIARY1)
+ && (path != VFE_MSG_OUTPUT_TERTIARY2)) {
vfe32_put_ch_ping_addr(
vfe32_ctrl->share_ctrl->vfebase, outch->ch1,
outch->ping.ch_paddr[1]);
@@ -1406,6 +1451,7 @@
uint32_t *cmdp_local = NULL;
uint32_t snapshot_cnt = 0;
uint32_t temp1 = 0, temp2 = 0;
+ uint16_t vfe_mode = 0;
CDBG("vfe32_proc_general: cmdID = %s, length = %d\n",
vfe32_general_cmd[cmd->id], cmd->length);
@@ -1418,24 +1464,36 @@
case VFE_CMD_START:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- if ((vfe32_ctrl->share_ctrl->operation_mode ==
+ vfe_mode = vfe32_ctrl->share_ctrl->operation_mode
+ & ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
+ if (vfe_mode) {
+ if ((vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_PREVIEW_AND_VIDEO) ||
- (vfe32_ctrl->share_ctrl->operation_mode ==
+ (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_PREVIEW))
- /* Configure primary channel */
- rc = vfe32_configure_pingpong_buffers(
- VFE_MSG_V32_START, VFE_MSG_OUTPUT_PRIMARY,
- vfe32_ctrl);
- else if (vfe32_ctrl->share_ctrl->operation_mode ==
+ /* Configure primary channel */
+ rc = vfe32_configure_pingpong_buffers(
+ VFE_MSG_V32_START,
+ VFE_MSG_OUTPUT_PRIMARY,
+ vfe32_ctrl);
+ else
+ /* Configure secondary channel */
+ rc = vfe32_configure_pingpong_buffers(
+ VFE_MSG_V32_START,
+ VFE_MSG_OUTPUT_SECONDARY,
+ vfe32_ctrl);
+ }
+ if (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_RDI0)
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_V32_START, VFE_MSG_OUTPUT_TERTIARY1,
vfe32_ctrl);
- else
- /* Configure secondary channel */
+ if (vfe32_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_RDI1)
rc = vfe32_configure_pingpong_buffers(
- VFE_MSG_V32_START, VFE_MSG_OUTPUT_SECONDARY,
+ VFE_MSG_V32_START, VFE_MSG_OUTPUT_TERTIARY2,
vfe32_ctrl);
+
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for preview", __func__);
@@ -1514,13 +1572,13 @@
case VFE_CMD_START_RECORDING:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- if (vfe32_ctrl->share_ctrl->operation_mode ==
+ if (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_PREVIEW_AND_VIDEO)
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_V32_START_RECORDING,
VFE_MSG_OUTPUT_SECONDARY,
vfe32_ctrl);
- else if (vfe32_ctrl->share_ctrl->operation_mode ==
+ else if (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_VIDEO_AND_PREVIEW)
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_V32_START_RECORDING,
@@ -2859,7 +2917,7 @@
unsigned long flags;
if (vfe32_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
- if (vfe32_ctrl->share_ctrl->operation_mode ==
+ if (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[vfe32_ctrl->
@@ -2867,7 +2925,7 @@
msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[vfe32_ctrl->
share_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->share_ctrl->operation_mode ==
+ } else if (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[vfe32_ctrl->
@@ -2882,7 +2940,7 @@
CDBG("start video triggered .\n");
} else if (vfe32_ctrl->recording_state ==
VFE_STATE_STOP_REQUESTED) {
- if (vfe32_ctrl->share_ctrl->operation_mode ==
+ if (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[vfe32_ctrl->
@@ -2890,7 +2948,7 @@
msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[vfe32_ctrl->
share_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->share_ctrl->operation_mode ==
+ } else if (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[vfe32_ctrl->
@@ -3069,8 +3127,25 @@
}
}
+static void vfe32_process_rdi1_reg_update_irq(
+ struct vfe32_ctrl_type *vfe32_ctrl)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&vfe32_ctrl->start_ack_lock, flags);
+ if (vfe32_ctrl->start_ack_pending == TRUE) {
+ vfe32_ctrl->start_ack_pending = FALSE;
+ spin_unlock_irqrestore(
+ &vfe32_ctrl->start_ack_lock, flags);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_START_ACK);
+ } else {
+ spin_unlock_irqrestore(
+ &vfe32_ctrl->start_ack_lock, flags);
+ }
+}
+
static void vfe32_set_default_reg_values(
- struct vfe32_ctrl_type *vfe32_ctrl)
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
msm_camera_io_w(0x800080,
vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
@@ -3478,7 +3553,7 @@
/* this must be rdi image output. */
struct msm_free_buf *free_buf = NULL;
/*RDI0*/
- if (axi_ctrl->share_ctrl->operation_mode == VFE_OUTPUTS_RDI0) {
+ if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0) {
free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
VFE_MSG_OUTPUT_TERTIARY1, axi_ctrl);
if (free_buf) {
@@ -3512,6 +3587,46 @@
}
}
+static void vfe32_process_output_path_irq_rdi1(
+ struct axi_ctrl_t *axi_ctrl)
+{
+ uint32_t ping_pong;
+ uint32_t ch0_paddr = 0;
+ /* this must be rdi image output. */
+ struct msm_free_buf *free_buf = NULL;
+ /*RDI1*/
+ if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1) {
+ free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_TERTIARY2, axi_ctrl);
+ if (free_buf) {
+ ping_pong = msm_camera_io_r(axi_ctrl->
+ share_ctrl->vfebase +
+ VFE_BUS_PING_PONG_STATUS);
+
+ /* Y channel */
+ ch0_paddr = vfe32_get_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out3.ch0);
+ pr_debug("%s ch0 = 0x%x\n",
+ __func__, ch0_paddr);
+
+ /* Y channel */
+ vfe32_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out3.ch0,
+ free_buf->ch_paddr[0]);
+
+ vfe_send_outmsg(axi_ctrl,
+ MSG_ID_OUTPUT_TERTIARY2, ch0_paddr,
+ 0, 0,
+ axi_ctrl->share_ctrl->outpath.out3.image_mode);
+ } else {
+ axi_ctrl->share_ctrl->outpath.out3.frame_drop_cnt++;
+ pr_err("path_irq irq - no free buffer for rdi1!\n");
+ }
+ }
+}
+
static uint32_t vfe32_process_stats_irq_common(
struct vfe32_ctrl_type *vfe32_ctrl,
uint32_t statsNum, uint32_t newAddr)
@@ -3891,6 +4006,10 @@
CDBG("irq rdi0 regUpdateIrq\n");
vfe32_process_rdi0_reg_update_irq(vfe32_ctrl);
break;
+ case VFE_IRQ_STATUS1_RDI1_REG_UPDATE:
+ CDBG("irq rdi1 regUpdateIrq\n");
+ vfe32_process_rdi1_reg_update_irq(vfe32_ctrl);
+ break;
case VFE_IMASK_WHILE_STOPPING_1:
CDBG("irq resetAckIrq\n");
vfe32_process_reset_irq(vfe32_ctrl);
@@ -3986,6 +4105,12 @@
(void *)VFE_IRQ_STATUS1_RDI0_REG_UPDATE);
if (qcmd->vfeInterruptStatus1 &
+ VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK)
+ v4l2_subdev_notify(&axi_ctrl->subdev,
+ NOTIFY_VFE_IRQ,
+ (void *)VFE_IRQ_STATUS1_RDI1_REG_UPDATE);
+
+ if (qcmd->vfeInterruptStatus1 &
VFE_IMASK_WHILE_STOPPING_1)
v4l2_subdev_notify(&axi_ctrl->subdev,
NOTIFY_VFE_IRQ,
@@ -4484,7 +4609,11 @@
void axi_start(struct axi_ctrl_t *axi_ctrl)
{
- switch (axi_ctrl->share_ctrl->operation_mode) {
+ uint16_t operation_mode =
+ (axi_ctrl->share_ctrl->operation_mode &
+ ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
+
+ switch (operation_mode) {
case VFE_OUTPUTS_PREVIEW:
case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
if (axi_ctrl->share_ctrl->outpath.output_mode &
@@ -4508,11 +4637,6 @@
share_ctrl->outpath.out0.ch2]);
}
break;
- case VFE_OUTPUTS_RDI0:
- msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out2.ch0]);
- break;
default:
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY) {
@@ -4536,6 +4660,16 @@
}
break;
}
+
+ if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0)
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
+ outpath.out2.ch0]);
+ if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1)
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
+ outpath.out3.ch0]);
+
}
void axi_stop(struct axi_ctrl_t *axi_ctrl)
@@ -4573,8 +4707,8 @@
{
struct msm_vfe_cfg_cmd cfgcmd;
struct msm_isp_cmd vfecmd;
- int rc = 0;
struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ int rc = 0, vfe_cmd_type = 0, rdi_mode = 0;
if (!axi_ctrl->share_ctrl->vfebase) {
pr_err("%s: base address unmapped\n", __func__);
@@ -4596,7 +4730,65 @@
}
}
+ vfe_cmd_type = (cfgcmd.cmd_type & ~(CMD_AXI_CFG_TERT1|
+ CMD_AXI_CFG_TERT2));
switch (cfgcmd.cmd_type) {
+ case CMD_AXI_CFG_TERT1:{
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ return -EFAULT;
+ }
+ vfe32_config_axi(axi_ctrl, OUTPUT_TERT1, axio);
+ kfree(axio);
+ return rc;
+ }
+ case CMD_AXI_CFG_TERT2:{
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio)
+ return -ENOMEM;
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ return -EFAULT;
+ }
+ vfe32_config_axi(axi_ctrl, OUTPUT_TERT2, axio);
+ kfree(axio);
+ return rc;
+ }
+ case CMD_AXI_CFG_TERT1|CMD_AXI_CFG_TERT2:{
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio)
+ return -ENOMEM;
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ return -EFAULT;
+ }
+ vfe32_config_axi(axi_ctrl, OUTPUT_TERT1|OUTPUT_TERT2, axio);
+ kfree(axio);
+ return rc;
+ }
+ default:
+ if (cfgcmd.cmd_type & CMD_AXI_CFG_TERT1)
+ rdi_mode |= OUTPUT_TERT1;
+ if (cfgcmd.cmd_type & CMD_AXI_CFG_TERT2)
+ rdi_mode |= OUTPUT_TERT2;
+ }
+ switch (vfe_cmd_type) {
case CMD_AXI_CFG_PRIM: {
uint32_t *axio = NULL;
axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
@@ -4612,7 +4804,7 @@
rc = -EFAULT;
break;
}
- vfe32_config_axi(axi_ctrl, OUTPUT_PRIM, axio);
+ vfe32_config_axi(axi_ctrl, rdi_mode|OUTPUT_PRIM, axio);
kfree(axio);
break;
}
@@ -4631,7 +4823,8 @@
rc = -EFAULT;
break;
}
- vfe32_config_axi(axi_ctrl, OUTPUT_PRIM_ALL_CHNLS, axio);
+ vfe32_config_axi(axi_ctrl, rdi_mode|OUTPUT_PRIM_ALL_CHNLS,
+ axio);
kfree(axio);
break;
}
@@ -4650,7 +4843,8 @@
rc = -EFAULT;
break;
}
- vfe32_config_axi(axi_ctrl, OUTPUT_PRIM|OUTPUT_SEC, axio);
+ vfe32_config_axi(axi_ctrl,
+ rdi_mode|OUTPUT_PRIM|OUTPUT_SEC, axio);
kfree(axio);
break;
}
@@ -4670,7 +4864,7 @@
break;
}
vfe32_config_axi(axi_ctrl,
- OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
+ rdi_mode|OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
kfree(axio);
break;
}
@@ -4690,30 +4884,11 @@
break;
}
vfe32_config_axi(axi_ctrl,
- OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
+ rdi_mode|OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
kfree(axio);
break;
}
- case CMD_AXI_CFG_TERT1: {
- uint32_t *axio = NULL;
- axio = kmalloc(vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length,
- GFP_ATOMIC);
- if (!axio) {
- rc = -ENOMEM;
- break;
- }
- if (copy_from_user(axio, (void __user *)(vfecmd.value),
- vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
- kfree(axio);
- rc = -EFAULT;
- break;
- }
- vfe32_config_axi(axi_ctrl,
- OUTPUT_TERT1, axio);
- kfree(axio);
- break;
- }
case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC_ALL_CHNLS:
pr_err("%s Invalid/Unsupported AXI configuration %x",
__func__, cfgcmd.cmd_type);
@@ -4758,6 +4933,11 @@
if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0
+ VFE_WM_OFFSET)))
vfe32_process_output_path_irq_rdi0(axi_ctrl);
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_TERTIARY2)
+ if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0
+ + VFE_WM_OFFSET)))
+ vfe32_process_output_path_irq_rdi1(axi_ctrl);
/* in snapshot mode if done then send
snapshot done message */
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 1746f3f..c41df09 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -240,8 +240,8 @@
#define V32_OPERATION_CFG_LEN 44
#define V32_AXI_OUT_OFF 0x00000038
-#define V32_AXI_OUT_LEN 216
-#define V32_AXI_CH_INF_LEN 24
+#define V32_AXI_OUT_LEN 224
+#define V32_AXI_CH_INF_LEN 32
#define V32_AXI_CFG_LEN 47
#define V32_AXI_BUS_FMT_OFF 1
#define V32_AXI_BUS_FMT_LEN 4
@@ -803,6 +803,7 @@
struct vfe32_output_ch out0; /* preview and thumbnail */
struct vfe32_output_ch out1; /* snapshot */
struct vfe32_output_ch out2; /* rdi0 */
+ struct vfe32_output_ch out3; /* rdi01 */
};
struct vfe32_frame_extra {
@@ -908,6 +909,7 @@
#define VFE32_OUTPUT_MODE_SECONDARY BIT(8)
#define VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS BIT(9)
#define VFE32_OUTPUT_MODE_TERTIARY1 BIT(10)
+#define VFE32_OUTPUT_MODE_TERTIARY2 BIT(11)
struct vfe_stats_control {
uint8_t ackPending;
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index da450fc..81b6a40 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -29,6 +29,8 @@
#include <linux/ion.h>
+#define BIT(nr) (1UL << (nr))
+
#define MSM_CAM_IOCTL_MAGIC 'm'
#define MSM_CAM_IOCTL_GET_SENSOR_INFO \
@@ -446,12 +448,12 @@
#define CMD_VFE_BUFFER_RELEASE 51
#define CMD_VFE_PROCESS_IRQ 52
-#define CMD_AXI_CFG_PRIM 0xc1
-#define CMD_AXI_CFG_PRIM_ALL_CHNLS 0xc2
-#define CMD_AXI_CFG_SEC 0xc4
-#define CMD_AXI_CFG_SEC_ALL_CHNLS 0xc8
-#define CMD_AXI_CFG_TERT1 0xd0
-
+#define CMD_AXI_CFG_PRIM BIT(8)
+#define CMD_AXI_CFG_PRIM_ALL_CHNLS BIT(9)
+#define CMD_AXI_CFG_SEC BIT(10)
+#define CMD_AXI_CFG_SEC_ALL_CHNLS BIT(11)
+#define CMD_AXI_CFG_TERT1 BIT(12)
+#define CMD_AXI_CFG_TERT2 BIT(13)
#define CMD_AXI_START 0xE1
#define CMD_AXI_STOP 0xE2
@@ -551,25 +553,31 @@
#define OUTPUT_ZSL_ALL_CHNLS 10
#define LAST_AXI_OUTPUT_MODE_ENUM = OUTPUT_ZSL_ALL_CHNLS
-#define OUTPUT_PRIM 0xC1
-#define OUTPUT_PRIM_ALL_CHNLS 0xC2
-#define OUTPUT_SEC 0xC4
-#define OUTPUT_SEC_ALL_CHNLS 0xC8
-#define OUTPUT_TERT1 0xD0
+#define OUTPUT_PRIM BIT(8)
+#define OUTPUT_PRIM_ALL_CHNLS BIT(9)
+#define OUTPUT_SEC BIT(10)
+#define OUTPUT_SEC_ALL_CHNLS BIT(11)
+#define OUTPUT_TERT1 BIT(12)
+#define OUTPUT_TERT2 BIT(13)
+
#define MSM_FRAME_PREV_1 0
#define MSM_FRAME_PREV_2 1
#define MSM_FRAME_ENC 2
-#define OUTPUT_TYPE_P (1<<0)
-#define OUTPUT_TYPE_T (1<<1)
-#define OUTPUT_TYPE_S (1<<2)
-#define OUTPUT_TYPE_V (1<<3)
-#define OUTPUT_TYPE_L (1<<4)
-#define OUTPUT_TYPE_ST_L (1<<5)
-#define OUTPUT_TYPE_ST_R (1<<6)
-#define OUTPUT_TYPE_ST_D (1<<7)
+#define OUTPUT_TYPE_P BIT(0)
+#define OUTPUT_TYPE_T BIT(1)
+#define OUTPUT_TYPE_S BIT(2)
+#define OUTPUT_TYPE_V BIT(3)
+#define OUTPUT_TYPE_L BIT(4)
+#define OUTPUT_TYPE_ST_L BIT(5)
+#define OUTPUT_TYPE_ST_R BIT(6)
+#define OUTPUT_TYPE_ST_D BIT(7)
+#define OUTPUT_TYPE_R BIT(8)
+#define OUTPUT_TYPE_R1 BIT(9)
+
+
struct fd_roi_info {
void *info;
@@ -685,7 +693,13 @@
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+4)
#define MSM_V4L2_EXT_CAPTURE_MODE_RAW \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+5)
-#define MSM_V4L2_EXT_CAPTURE_MODE_MAX (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+6)
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI \
+ (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+6)
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI1 \
+ (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+7)
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI2 \
+ (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+8)
+#define MSM_V4L2_EXT_CAPTURE_MODE_MAX (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+9)
#define MSM_V4L2_PID_MOTION_ISO V4L2_CID_PRIVATE_BASE
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 0309fd5..6547795 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -61,6 +61,7 @@
#define MSG_ID_STATS_COMPOSITE 42
#define MSG_ID_OUTPUT_TERTIARY1 43
#define MSG_ID_STOP_LS_ACK 44
+#define MSG_ID_OUTPUT_TERTIARY2 45
/* ISP command IDs */
#define VFE_CMD_DUMMY_0 0
@@ -317,20 +318,19 @@
/* TBD: 3D related */
};
-#define VFE_OUTPUTS_MAIN_AND_PREVIEW BIT(0)
-#define VFE_OUTPUTS_MAIN_AND_VIDEO BIT(1)
-#define VFE_OUTPUTS_MAIN_AND_THUMB BIT(2)
-#define VFE_OUTPUTS_THUMB_AND_MAIN BIT(3)
-#define VFE_OUTPUTS_PREVIEW_AND_VIDEO BIT(4)
-#define VFE_OUTPUTS_VIDEO_AND_PREVIEW BIT(5)
-#define VFE_OUTPUTS_PREVIEW BIT(6)
-#define VFE_OUTPUTS_VIDEO BIT(7)
-#define VFE_OUTPUTS_RAW BIT(8)
-#define VFE_OUTPUTS_JPEG_AND_THUMB BIT(9)
-#define VFE_OUTPUTS_THUMB_AND_JPEG BIT(10)
-#define VFE_OUTPUTS_RDI0 BIT(11)
-
-
+#define VFE_OUTPUTS_MAIN_AND_PREVIEW BIT(0)
+#define VFE_OUTPUTS_MAIN_AND_VIDEO BIT(1)
+#define VFE_OUTPUTS_MAIN_AND_THUMB BIT(2)
+#define VFE_OUTPUTS_THUMB_AND_MAIN BIT(3)
+#define VFE_OUTPUTS_PREVIEW_AND_VIDEO BIT(4)
+#define VFE_OUTPUTS_VIDEO_AND_PREVIEW BIT(5)
+#define VFE_OUTPUTS_PREVIEW BIT(6)
+#define VFE_OUTPUTS_VIDEO BIT(7)
+#define VFE_OUTPUTS_RAW BIT(8)
+#define VFE_OUTPUTS_JPEG_AND_THUMB BIT(9)
+#define VFE_OUTPUTS_THUMB_AND_JPEG BIT(10)
+#define VFE_OUTPUTS_RDI0 BIT(11)
+#define VFE_OUTPUTS_RDI1 BIT(12)
struct msm_frame_info {
uint32_t image_mode;