From 6cf8a749e2354cf09e564dfa8104f706dca9b437 Mon Sep 17 00:00:00 2001 From: Jignesh Mehta Date: Sat, 4 Feb 2012 23:40:50 -0800 Subject: [PATCH] camera: vfe32: Enable VFE configuration for inline JPEG encoding. During inline JPEG encoding, one VFE output is routed into internal memory (IMEM) instead of external memory. The JPEG encoding hardware (GEMINI) will read from IMEM and generates JPEG bitstream. Change-Id: I12d3600524538ab85021dd8882af0404bddc488f Signed-off-by: Shuzhen Wang Signed-off-by: Kevin Chan Signed-off-by: Jignesh Mehta --- arch/arm/mach-msm/include/mach/camera.h | 2 ++ drivers/media/video/msm/msm_isp.c | 13 +++++++ drivers/media/video/msm/msm_vfe32.c | 48 ++++++++++++++++++++----- include/media/msm_camera.h | 3 ++ include/media/msm_isp.h | 5 +++ 5 files changed, 62 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h index 530d2c14856..700e28c4907 100644 --- a/arch/arm/mach-msm/include/mach/camera.h +++ b/arch/arm/mach-msm/include/mach/camera.h @@ -52,6 +52,7 @@ enum vfe_mode_of_operation{ VFE_MODE_OF_OPERATION_VIDEO, VFE_MODE_OF_OPERATION_RAW_SNAPSHOT, VFE_MODE_OF_OPERATION_ZSL, + VFE_MODE_OF_OPERATION_JPEG_SNAPSHOT, VFE_LAST_MODE_OF_OPERATION_ENUM }; @@ -87,6 +88,7 @@ enum vfe_resp_msg { VFE_MSG_V32_START, VFE_MSG_V32_START_RECORDING, /* 20 */ VFE_MSG_V32_CAPTURE, + VFE_MSG_V32_JPEG_CAPTURE, VFE_MSG_OUTPUT_IRQ, VFE_MSG_V2X_PREVIEW, VFE_MSG_V2X_CAPTURE, diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c index c9a9f1bd3b2..16964b20382 100644 --- a/drivers/media/video/msm/msm_isp.c +++ b/drivers/media/video/msm/msm_isp.c @@ -199,6 +199,19 @@ static int msm_isp_notify_VFE_BUF_EVT(struct v4l2_subdev *sd, void *arg) vfe_params.data = (void *)&free_buf; rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params); break; + case VFE_MSG_V32_JPEG_CAPTURE: + free_buf.num_planes = 1; + free_buf.ch_paddr[0] = IMEM_Y_OFFSET; + free_buf.ch_paddr[1] = IMEM_CBCR_OFFSET; + cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR; + cfgcmd.value = &vfe_id; + 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 */ + cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR; + rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params); + break; case VFE_MSG_OUTPUT_IRQ: D("%s Got OUTPUT_IRQ: Getting free buf id = %d", __func__, vfe_id); diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c index 99d9911c6d0..89bdf0ffa7b 100644 --- a/drivers/media/video/msm/msm_vfe32.c +++ b/drivers/media/video/msm/msm_vfe32.c @@ -702,8 +702,6 @@ static void vfe32_start_common(void) msm_io_w(VFE_IMASK_WHILE_STOPPING_1, vfe32_ctrl->vfebase + VFE_IRQ_MASK_1); - msm_io_dump(vfe32_ctrl->vfebase, vfe32_ctrl->register_total * 4); - /* Ensure the write order while writing to the command register using the barrier */ msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD); @@ -851,7 +849,9 @@ static int vfe32_capture(uint32_t num_frames_capture) /* capture command is valid for both idle and active state. */ vfe32_ctrl->outpath.out1.capture_cnt = num_frames_capture; if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB || - vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) { + vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN || + vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB || + vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) { vfe32_ctrl->outpath.out0.capture_cnt = num_frames_capture; } @@ -887,6 +887,9 @@ static int vfe32_capture(uint32_t num_frames_capture) vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]); } } + + vfe32_ctrl->vfe_capture_count = num_frames_capture; + msm_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK); msm_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK); msm_camio_bus_scale_cfg( @@ -1286,16 +1289,31 @@ static int vfe32_proc_general(struct msm_isp_cmd *cmd) rc = vfe32_capture_raw(snapshot_cnt); break; case VFE_CMD_CAPTURE: - pr_info("vfe32_proc_general: cmdID = %s\n", - vfe32_general_cmd[cmd->id]); + CDBG("vfe32_proc_general: cmdID = %s op mode = %d\n", + vfe32_general_cmd[cmd->id], vfe32_ctrl->operation_mode); if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value), sizeof(uint32_t))) { rc = -EFAULT; goto proc_general_done; } - /* Configure primary channel */ - rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE, - VFE_MSG_OUTPUT_PRIMARY); + + if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB || + vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) { + if (snapshot_cnt != 1) { + pr_err("only support 1 inline snapshot\n"); + rc = -EINVAL; + goto proc_general_done; + } + /* Configure primary channel for JPEG */ + rc = vfe32_configure_pingpong_buffers( + VFE_MSG_V32_JPEG_CAPTURE, + VFE_MSG_OUTPUT_PRIMARY); + } else { + /* Configure primary channel */ + rc = vfe32_configure_pingpong_buffers( + VFE_MSG_V32_CAPTURE, + VFE_MSG_OUTPUT_PRIMARY); + } if (rc < 0) { pr_err("%s error configuring pingpong buffers" " for primary output", __func__); @@ -2610,7 +2628,9 @@ static void vfe32_process_reg_update_irq(void) } if ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) || - (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB)) { + (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB) || + (vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) || + (vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB)) { /* in snapshot mode */ /* later we need to add check for live snapshot mode. */ if (vfe32_ctrl->frame_skip_pattern & (0x1 << @@ -2858,6 +2878,8 @@ static void vfe32_process_output_path_irq_0(void) */ out_bool = ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN || vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB || + vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG || + vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB || vfe32_ctrl->operation_mode == VFE_OUTPUTS_RAW || vfe32_ctrl->liveshot_state == VFE_STATE_STARTED || vfe32_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED || @@ -2898,6 +2920,10 @@ static void vfe32_process_output_path_irq_0(void) VFE_OUTPUTS_THUMB_AND_MAIN || vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB || + vfe32_ctrl->operation_mode == + VFE_OUTPUTS_THUMB_AND_JPEG || + vfe32_ctrl->operation_mode == + VFE_OUTPUTS_JPEG_AND_THUMB || vfe32_ctrl->operation_mode == VFE_OUTPUTS_RAW || vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED) @@ -3391,6 +3417,10 @@ static void vfe32_do_tasklet(unsigned long data) VFE_OUTPUTS_THUMB_AND_MAIN || vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB || + vfe32_ctrl->operation_mode == + VFE_OUTPUTS_THUMB_AND_JPEG || + vfe32_ctrl->operation_mode == + VFE_OUTPUTS_JPEG_AND_THUMB || vfe32_ctrl->operation_mode == VFE_OUTPUTS_RAW) { if ((vfe32_ctrl->outpath.out0.capture_cnt == 0) diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h index 87fbbd216f9..1a6f68f7827 100644 --- a/include/media/msm_camera.h +++ b/include/media/msm_camera.h @@ -693,6 +693,9 @@ struct msm_stats_buf { #define MSM_V4L2_CAM_OP_ZSL (MSM_V4L2_CAM_OP_DEFAULT+4) /* camera operation mode for raw snapshot - one frame output queue */ #define MSM_V4L2_CAM_OP_RAW (MSM_V4L2_CAM_OP_DEFAULT+5) +/* camera operation mode for jpeg snapshot - one frame output queue */ +#define MSM_V4L2_CAM_OP_JPEG_CAPTURE (MSM_V4L2_CAM_OP_DEFAULT+6) + #define MSM_V4L2_VID_CAP_TYPE 0 #define MSM_V4L2_STREAM_ON 1 diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h index 5dd1445c42a..07784e20df3 100644 --- a/include/media/msm_isp.h +++ b/include/media/msm_isp.h @@ -241,6 +241,9 @@ struct msm_isp_cmd { #define VPE_SCALER_CONFIG_LEN 260 #define VPE_DIS_OFFSET_CFG_LEN 12 +#define IMEM_Y_OFFSET 0x2E000000 +#define IMEM_CBCR_OFFSET 0x2E00FA00 + struct msm_vpe_op_mode_cfg { uint8_t op_mode_cfg[VPE_OPERATION_MODE_CFG_LEN]; }; @@ -311,6 +314,8 @@ struct msm_mctl_pp_frame_cmd { #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) #endif /*__MSM_ISP_H__*/