diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h index caa2d32a205..42330b4234b 100644 --- a/drivers/media/video/msm/msm.h +++ b/drivers/media/video/msm/msm.h @@ -39,11 +39,16 @@ #define MSM_V4L2_DIMENSION_SIZE 96 #define MAX_DEV_NAME_LEN 50 -#define ERR_USER_COPY(to) pr_debug("%s(%d): copy %s user\n", \ +#define ERR_USER_COPY(to) pr_err("%s(%d): copy %s user\n", \ __func__, __LINE__, ((to) ? "to" : "from")) #define ERR_COPY_FROM_USER() ERR_USER_COPY(0) #define ERR_COPY_TO_USER() ERR_USER_COPY(1) +#define COPY_FROM_USER(error, dest, src, size) \ + (error = (copy_from_user(dest, src, size) ? -EFAULT : 0)) +#define COPY_TO_USER(error, dest, src, size) \ + (error = (copy_to_user(dest, src, size) ? -EFAULT : 0)) + #define MSM_CSIPHY_DRV_NAME "msm_csiphy" #define MSM_CSID_DRV_NAME "msm_csid" #define MSM_CSIC_DRV_NAME "msm_csic" @@ -102,6 +107,7 @@ enum msm_cam_subdev_type { qcmd = list_first_entry(&__q->list, \ struct msm_queue_cmd, member); \ list_del_init(&qcmd->member); \ + kfree(qcmd->command); \ free_qcmd(qcmd); \ }; \ spin_unlock_irqrestore(&__q->lock, flags); \ @@ -147,7 +153,6 @@ enum msm_camera_v4l2_subdev_notify { NOTIFY_VFE_MSG_COMP_STATS, /* arg = struct msm_stats_buf */ NOTIFY_VFE_BUF_EVT, /* arg = struct msm_vfe_resp */ NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */ - NOTIFY_VPE_MSG_EVT, NOTIFY_PCLK_CHANGE, /* arg = pclk */ NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */ NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */ @@ -206,6 +211,7 @@ struct msm_mctl_pp_frame_info { struct msm_pp_frame src_frame; struct msm_pp_frame dest_frame; struct msm_mctl_pp_frame_cmd pp_frame_cmd; + struct msm_cam_media_controller *p_mctl; }; struct msm_mctl_pp_ctrl { @@ -587,6 +593,10 @@ int msm_cam_server_open_mctl_session(struct msm_cam_v4l2_device *pcam, int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam); long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl, unsigned int cmd, unsigned long evt); +int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom); +void msm_queue_init(struct msm_device_queue *queue, const char *name); +void msm_enqueue(struct msm_device_queue *queue, struct list_head *entry); +void msm_drain_eventq(struct msm_device_queue *queue); #endif /* __KERNEL__ */ #endif /* _MSM_H */ diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c index 848bedad0d8..c266b85a627 100644 --- a/drivers/media/video/msm/msm_isp.c +++ b/drivers/media/video/msm/msm_isp.c @@ -742,13 +742,6 @@ static int msm_isp_config(struct msm_cam_media_controller *pmctl, D("%s: cmd %d\n", __func__, _IOC_NR(cmd)); switch (cmd) { - case MSM_CAM_IOCTL_PICT_PP_DONE: - /* Release the preview of snapshot frame - * that was grabbed. - */ - /*rc = msm_pp_release(pmsm->sync, arg);*/ - break; - case MSM_CAM_IOCTL_CONFIG_VFE: /* Coming from config thread for update */ rc = msm_config_vfe(sd, pmctl, argp); diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c index 1088a5444b9..eade6f1675d 100644 --- a/drivers/media/video/msm/msm_mctl_buf.c +++ b/drivers/media/video/msm/msm_mctl_buf.c @@ -454,7 +454,7 @@ int msm_mctl_buf_done(struct msm_cam_media_controller *p_mctl, image_mode, fbuf, &frame_id, 1); D("%s mctl node buf done %d\n", __func__, 0); - return -EINVAL; + return rc; } else { pr_err("%s Invalid instance, dropping buffer\n", __func__); diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c index f4c04bb9f89..844a3ff6064 100644 --- a/drivers/media/video/msm/msm_mctl_pp.c +++ b/drivers/media/video/msm/msm_mctl_pp.c @@ -36,18 +36,6 @@ #define D(fmt, args...) do {} while (0) #endif - -static int msm_mctl_pp_vpe_ioctl(struct v4l2_subdev *vpe_sd, - struct msm_mctl_pp_cmd *cmd, void *data) -{ - int rc = 0; - struct msm_mctl_pp_params parm; - parm.cmd = cmd; - parm.data = data; - rc = v4l2_subdev_call(vpe_sd, core, ioctl, VIDIOC_MSM_VPE_CFG, &parm); - return rc; -} - static int msm_mctl_pp_buf_divert( struct msm_cam_media_controller *pmctl, struct msm_cam_v4l2_dev_inst *pcam_inst, @@ -384,244 +372,6 @@ static int msm_mctl_pp_path_to_inst_index(struct msm_cam_v4l2_device *pcam, return -EINVAL; } -int msm_mctl_pp_proc_vpe_cmd( - struct msm_cam_media_controller *p_mctl, - struct msm_mctl_pp_cmd *pp_cmd) -{ - int rc = 0, idx; - void __user *argp = (void __user *)pp_cmd->value; - struct msm_cam_v4l2_dev_inst *pcam_inst; - - switch (pp_cmd->id) { - case VPE_CMD_INIT: - case VPE_CMD_DEINIT: - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, NULL); - break; - case VPE_CMD_DISABLE: - case VPE_CMD_RESET: - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, NULL); - break; - case VPE_CMD_ENABLE: { - struct msm_vpe_clock_rate clk_rate; - if (sizeof(struct msm_vpe_clock_rate) != - pp_cmd->length) { - pr_err("%s: vpe cmd size mismatch " - "(id=%d, length = %d, expect size = %d", - __func__, pp_cmd->id, pp_cmd->length, - sizeof(struct msm_vpe_clock_rate)); - rc = -EINVAL; - break; - } - if (copy_from_user(&clk_rate, pp_cmd->value, - sizeof(struct msm_vpe_clock_rate))) { - pr_err("%s:clk_rate copy failed", __func__); - return -EFAULT; - } - pp_cmd->value = (void *)&clk_rate; - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, NULL); - pp_cmd->value = argp; - break; - } - case VPE_CMD_FLUSH: { - struct msm_vpe_flush_frame_buffer flush_buf; - if (sizeof(struct msm_vpe_flush_frame_buffer) != - pp_cmd->length) { - D("%s: size mismatch(id=%d, len = %d, expected = %d", - __func__, pp_cmd->id, pp_cmd->length, - sizeof(struct msm_vpe_flush_frame_buffer)); - rc = -EINVAL; - break; - } - if (copy_from_user( - &flush_buf, pp_cmd->value, sizeof(flush_buf))) - return -EFAULT; - pp_cmd->value = (void *)&flush_buf; - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, NULL); - if (rc == 0) { - if (copy_to_user((void *)argp, - &flush_buf, - sizeof(flush_buf))) { - ERR_COPY_TO_USER(); - rc = -EFAULT; - } - pp_cmd->value = argp; - } - } - break; - case VPE_CMD_OPERATION_MODE_CFG: { - struct msm_vpe_op_mode_cfg op_mode_cfg; - if (sizeof(struct msm_vpe_op_mode_cfg) != - pp_cmd->length) { - D("%s: size mismatch(id=%d, len = %d, expected = %d", - __func__, pp_cmd->id, pp_cmd->length, - sizeof(struct msm_vpe_op_mode_cfg)); - rc = -EINVAL; - break; - } - if (copy_from_user(&op_mode_cfg, - pp_cmd->value, - sizeof(op_mode_cfg))) - return -EFAULT; - pp_cmd->value = (void *)&op_mode_cfg; - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, NULL); - break; - } - case VPE_CMD_INPUT_PLANE_CFG: { - struct msm_vpe_input_plane_cfg input_cfg; - if (sizeof(struct msm_vpe_input_plane_cfg) != - pp_cmd->length) { - D("%s: mismatch(id=%d, len = %d, expected = %d", - __func__, pp_cmd->id, pp_cmd->length, - sizeof(struct msm_vpe_input_plane_cfg)); - rc = -EINVAL; - break; - } - if (copy_from_user( - &input_cfg, pp_cmd->value, sizeof(input_cfg))) - return -EFAULT; - pp_cmd->value = (void *)&input_cfg; - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, NULL); - break; - } - case VPE_CMD_OUTPUT_PLANE_CFG: { - struct msm_vpe_output_plane_cfg output_cfg; - if (sizeof(struct msm_vpe_output_plane_cfg) != - pp_cmd->length) { - D("%s: size mismatch(id=%d, len = %d, expected = %d", - __func__, pp_cmd->id, pp_cmd->length, - sizeof(struct msm_vpe_output_plane_cfg)); - rc = -EINVAL; - break; - } - if (copy_from_user(&output_cfg, pp_cmd->value, - sizeof(output_cfg))) { - D("%s: cannot copy pp_cmd->value, size=%d", - __func__, pp_cmd->length); - return -EFAULT; - } - pp_cmd->value = (void *)&output_cfg; - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, NULL); - break; - } - case VPE_CMD_INPUT_PLANE_UPDATE: { - struct msm_vpe_input_plane_update_cfg input_update_cfg; - if (sizeof(struct msm_vpe_input_plane_update_cfg) != - pp_cmd->length) { - D("%s: size mismatch(id=%d, len = %d, expected = %d", - __func__, pp_cmd->id, pp_cmd->length, - sizeof(struct msm_vpe_input_plane_update_cfg)); - rc = -EINVAL; - break; - } - if (copy_from_user(&input_update_cfg, pp_cmd->value, - sizeof(input_update_cfg))) - return -EFAULT; - pp_cmd->value = (void *)&input_update_cfg; - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, NULL); - break; - } - case VPE_CMD_SCALE_CFG_TYPE: { - struct msm_vpe_scaler_cfg scaler_cfg; - if (sizeof(struct msm_vpe_scaler_cfg) != - pp_cmd->length) { - D("%s: size mismatch(id=%d, len = %d, expected = %d", - __func__, pp_cmd->id, pp_cmd->length, - sizeof(struct msm_vpe_scaler_cfg)); - rc = -EINVAL; - break; - } - if (copy_from_user(&scaler_cfg, pp_cmd->value, - sizeof(scaler_cfg))) - return -EFAULT; - pp_cmd->value = (void *)&scaler_cfg; - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, NULL); - break; - } - case VPE_CMD_ZOOM: { - struct msm_mctl_pp_frame_info *zoom; - zoom = kmalloc(sizeof(struct msm_mctl_pp_frame_info), - GFP_ATOMIC); - if (!zoom) { - rc = -ENOMEM; - break; - } - if (sizeof(zoom->pp_frame_cmd) != pp_cmd->length) { - D("%s: size mismatch(id=%d, len = %d, expected = %d", - __func__, pp_cmd->id, pp_cmd->length, - sizeof(zoom->pp_frame_cmd)); - rc = -EINVAL; - kfree(zoom); - break; - } - if (copy_from_user(&zoom->pp_frame_cmd, pp_cmd->value, - sizeof(zoom->pp_frame_cmd))) { - kfree(zoom); - return -EFAULT; - } - D("%s: src=0x%x, dest=0x%x,cookie=0x%x,action=0x%x,path=0x%x", - __func__, zoom->pp_frame_cmd.src_buf_handle, - zoom->pp_frame_cmd.dest_buf_handle, - zoom->pp_frame_cmd.cookie, - zoom->pp_frame_cmd.vpe_output_action, - zoom->pp_frame_cmd.path); - idx = msm_mctl_pp_path_to_inst_index(p_mctl->pcam_ptr, - zoom->pp_frame_cmd.path); - if (idx < 0) { - pr_err("%s Invalid path, returning\n", __func__); - kfree(zoom); - return idx; - } - pcam_inst = p_mctl->pcam_ptr->dev_inst[idx]; - if (!pcam_inst) { - pr_err("%s Invalid instance, returning\n", __func__); - kfree(zoom); - return -EINVAL; - } - zoom->user_cmd = pp_cmd->id; - rc = msm_mctl_pp_get_phy_addr(pcam_inst, - zoom->pp_frame_cmd.src_buf_handle, &zoom->src_frame); - if (rc) { - kfree(zoom); - break; - } - rc = msm_mctl_pp_get_phy_addr(pcam_inst, - zoom->pp_frame_cmd.dest_buf_handle, &zoom->dest_frame); - if (rc) { - kfree(zoom); - break; - } - rc = msm_mctl_pp_copy_timestamp_and_frame_id( - zoom->pp_frame_cmd.src_buf_handle, - - zoom->pp_frame_cmd.dest_buf_handle); - if (rc) { - kfree(zoom); - break; - } - rc = msm_mctl_pp_vpe_ioctl( - p_mctl->vpe_sdev, pp_cmd, (void *)zoom); - if (rc) { - kfree(zoom); - break; - } - break; - } - default: - rc = -1; - break; - } - return rc; -} - static int msm_mctl_pp_path_to_img_mode(int path) { switch (path) { @@ -717,9 +467,6 @@ int msm_mctl_pp_ioctl(struct msm_cam_media_controller *p_mctl, return -EFAULT; switch (pp_cmd.type) { - case MSM_PP_CMD_TYPE_VPE: - rc = msm_mctl_pp_proc_vpe_cmd(p_mctl, &pp_cmd.cmd); - break; case MSM_PP_CMD_TYPE_MCTL: rc = msm_mctl_pp_proc_cmd(p_mctl, &pp_cmd.cmd); break; @@ -739,71 +486,6 @@ int msm_mctl_pp_ioctl(struct msm_cam_media_controller *p_mctl, return rc; } -int msm_mctl_pp_notify(struct msm_cam_media_controller *p_mctl, - struct msm_mctl_pp_frame_info *pp_frame_info) -{ - struct msm_mctl_pp_frame_cmd *pp_frame_cmd; - pp_frame_cmd = &pp_frame_info->pp_frame_cmd; - - D("%s: msm_cam_evt_divert_frame=%d", - __func__, sizeof(struct msm_mctl_pp_event_info)); - if ((MSM_MCTL_PP_VPE_FRAME_TO_APP & - pp_frame_cmd->vpe_output_action)) { - struct msm_free_buf done_frame; - int img_mode = - msm_mctl_pp_path_to_img_mode( - pp_frame_cmd->path); - if (img_mode < 0) { - pr_err("%s Invalid image mode\n", __func__); - return img_mode; - } - done_frame.ch_paddr[0] = - pp_frame_info->dest_frame.sp.phy_addr; - done_frame.vb = - pp_frame_info->dest_frame.handle; - msm_mctl_buf_done_pp( - 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]); - } - if ((MSM_MCTL_PP_VPE_FRAME_ACK & - pp_frame_cmd->vpe_output_action)) { - struct v4l2_event v4l2_evt; - struct msm_mctl_pp_event_info *pp_event_info; - struct msm_isp_event_ctrl *isp_event; - isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), - GFP_ATOMIC); - if (!isp_event) { - pr_err("%s Insufficient memory.", __func__); - return -ENOMEM; - } - memset(&v4l2_evt, 0, sizeof(v4l2_evt)); - *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event; - - /* Get hold of pp event info struct inside event ctrl.*/ - pp_event_info = &(isp_event->isp_data.pp_event_info); - - pp_event_info->event = MCTL_PP_EVENT_CMD_ACK; - pp_event_info->ack.cmd = pp_frame_info->user_cmd; - pp_event_info->ack.status = 0; - pp_event_info->ack.cookie = pp_frame_cmd->cookie; - v4l2_evt.id = 0; - v4l2_evt.type = V4L2_EVENT_PRIVATE_START + - MSM_CAM_RESP_MCTL_PP_EVENT; - - v4l2_event_queue( - p_mctl->config_device-> - config_stat_event_queue.pvdev, - &v4l2_evt); - D("%s: ack to daemon, cookie=0x%x, event = 0x%x", - __func__, pp_frame_info->pp_frame_cmd.cookie, - v4l2_evt.type); - } - kfree(pp_frame_info); /* free mem */ - return 0; -} - int msm_mctl_pp_reserve_free_frame( struct msm_cam_media_controller *p_mctl, void __user *arg) @@ -1027,3 +709,54 @@ int msm_mctl_pp_mctl_divert_done( return rc; } + +int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom) +{ + struct msm_cam_media_controller *p_mctl; + struct msm_cam_v4l2_dev_inst *pcam_inst; + int rc = 0, idx; + + if (!zoom || !zoom->p_mctl) { + pr_err("%s Invalid input, not sending buffer to VPE ", + __func__); + return -EINVAL; + } + p_mctl = zoom->p_mctl; + idx = msm_mctl_pp_path_to_inst_index(p_mctl->pcam_ptr, + zoom->pp_frame_cmd.path); + if (idx < 0) { + pr_err("%s Invalid path, returning\n", __func__); + return idx; + } + pcam_inst = p_mctl->pcam_ptr->dev_inst[idx]; + if (!pcam_inst) { + pr_err("%s Invalid instance, returning\n", __func__); + return -EINVAL; + } + + rc = msm_mctl_pp_get_phy_addr(pcam_inst, + zoom->pp_frame_cmd.src_buf_handle, &zoom->src_frame); + if (rc) { + pr_err("%s Error getting buffer address for src frame\n", + __func__); + return rc; + } + + rc = msm_mctl_pp_get_phy_addr(pcam_inst, + zoom->pp_frame_cmd.dest_buf_handle, &zoom->dest_frame); + if (rc) { + pr_err("%s Error getting buffer address for dest frame\n", + __func__); + return rc; + } + + rc = msm_mctl_pp_copy_timestamp_and_frame_id( + zoom->pp_frame_cmd.src_buf_handle, + zoom->pp_frame_cmd.dest_buf_handle); + if (rc < 0) { + pr_err("%s Error copying timestamp info\n", + __func__); + return rc; + } + return rc; +} diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c index f9ce74b3db5..54e9582c337 100644 --- a/drivers/media/video/msm/msm_vpe.c +++ b/drivers/media/video/msm/msm_vpe.c @@ -30,14 +30,19 @@ #include "msm.h" #include "msm_vpe.h" +#ifdef CONFIG_MSM_CAMERA_DEBUG +#define D(fmt, args...) pr_debug("msm_vpe: " fmt, ##args) +#else +#define D(fmt, args...) do {} while (0) +#endif + static int vpe_enable(uint32_t); static int vpe_disable(void); static int vpe_update_scaler(struct msm_pp_crop *pcrop); struct vpe_ctrl_type *vpe_ctrl; static atomic_t vpe_init_done = ATOMIC_INIT(0); -static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd, - struct msm_mctl_pp_frame_info *pp_frame_info); +static int msm_vpe_do_pp(struct msm_mctl_pp_frame_info *pp_frame_info); static long long vpe_do_div(long long num, long long den) { @@ -57,8 +62,7 @@ static int vpe_start(void) msm_camera_io_dump(vpe_ctrl->vpebase + 0x50400, 0x10); /* this triggers the operation. */ - msm_camera_io_w(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET); - wmb(); + msm_camera_io_w_mb(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET); return 0; } @@ -72,7 +76,7 @@ void vpe_reset_state_variables(void) static void vpe_config_axi_default(void) { msm_camera_io_w(0x25, vpe_ctrl->vpebase + VPE_AXI_ARB_2_OFFSET); - CDBG("%s: yaddr %ld cbcraddr %ld", __func__, + D("%s: yaddr %ld cbcraddr %ld", __func__, vpe_ctrl->out_y_addr, vpe_ctrl->out_cbcr_addr); if (!vpe_ctrl->out_y_addr || !vpe_ctrl->out_cbcr_addr) return; @@ -81,7 +85,6 @@ static void vpe_config_axi_default(void) /* for video CbCr address */ msm_camera_io_w(vpe_ctrl->out_cbcr_addr, vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET); - } static int vpe_reset(void) @@ -92,7 +95,7 @@ static int vpe_reset(void) spin_lock_irqsave(&vpe_ctrl->lock, flags); if (vpe_ctrl->state == VPE_STATE_IDLE) { - CDBG("%s: VPE already disabled.", __func__); + D("%s: VPE already disabled.", __func__); spin_unlock_irqrestore(&vpe_ctrl->lock, flags); return rc; } @@ -101,7 +104,7 @@ static int vpe_reset(void) vpe_reset_state_variables(); vpe_version = msm_camera_io_r( vpe_ctrl->vpebase + VPE_HW_VERSION_OFFSET); - CDBG("vpe_version = 0x%x\n", vpe_version); + D("vpe_version = 0x%x\n", vpe_version); /* disable all interrupts.*/ msm_camera_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET); /* clear all pending interrupts*/ @@ -139,13 +142,13 @@ static int msm_vpe_cfg_update(void *pinfo) rot_flag = msm_camera_io_r(vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET) & 0xE00; if (pinfo != NULL) { - CDBG("%s: Crop info in2_w = %d, in2_h = %d " + D("%s: Crop info in2_w = %d, in2_h = %d " "out2_w = %d out2_h = %d\n", __func__, pcrop->src_w, pcrop->src_h, pcrop->dst_w, pcrop->dst_h); rc = vpe_update_scaler(pcrop); } - CDBG("return rc = %d rot_flag = %d\n", rc, rot_flag); + D("return rc = %d rot_flag = %d\n", rc, rot_flag); rc |= rot_flag; return rc; @@ -200,7 +203,7 @@ static int vpe_operation_config(uint32_t *p) vpe_ctrl->out_w = w; vpe_ctrl->out_h = h; } - CDBG("%s: out_w=%d, out_h=%d", __func__, vpe_ctrl->out_w, + D("%s: out_w=%d, out_h=%d", __func__, vpe_ctrl->out_w, vpe_ctrl->out_h); return 0; } @@ -239,7 +242,7 @@ static int vpe_update_scaler(struct msm_pp_crop *pcrop) out_ROI_width = pcrop->dst_w; out_ROI_height = pcrop->dst_h; - CDBG("src w = 0x%x, h=0x%x, dst w = 0x%x, h =0x%x.\n", + D("src w = 0x%x, h=0x%x, dst w = 0x%x, h =0x%x.\n", src_ROI_width, src_ROI_height, out_ROI_width, out_ROI_height); src_roi = (src_ROI_height << 16) + src_ROI_width; @@ -249,12 +252,12 @@ static int vpe_update_scaler(struct msm_pp_crop *pcrop) src_x = pcrop->src_x; src_y = pcrop->src_y; - CDBG("src_x = %d, src_y=%d.\n", src_x, src_y); + D("src_x = %d, src_y=%d.\n", src_x, src_y); src_xy = src_y*(1<<16) + src_x; msm_camera_io_w(src_xy, vpe_ctrl->vpebase + VPE_SRC_XY_OFFSET); - CDBG("src_xy = %d, src_roi=%d.\n", src_xy, src_roi); + D("src_xy = %d, src_roi=%d.\n", src_xy, src_roi); /* decide whether to use FIR or M/N for scaling */ if ((out_ROI_width == 1 && src_ROI_width < 4) || @@ -387,9 +390,9 @@ static int vpe_update_scaler(struct msm_pp_crop *pcrop) } else if (scale_unit_sel_y == 1) /* M over N scalar */ phase_init_y = 0; - CDBG("phase step x = %d, step y = %d.\n", + D("phase step x = %d, step y = %d.\n", phase_step_x, phase_step_y); - CDBG("phase init x = %d, init y = %d.\n", + D("phase init x = %d, init y = %d.\n", phase_init_x, phase_init_y); msm_camera_io_w(phase_step_x, vpe_ctrl->vpebase + @@ -416,24 +419,40 @@ int msm_vpe_is_busy(void) spin_unlock_irqrestore(&vpe_ctrl->lock, flags); return busy; } + static int msm_send_frame_to_vpe(void) { int rc = 0; unsigned long flags; + unsigned long srcP0, srcP1, outP0, outP1; + struct msm_mctl_pp_frame_info *frame = vpe_ctrl->pp_frame_info; spin_lock_irqsave(&vpe_ctrl->lock, flags); - msm_camera_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr + - vpe_ctrl->pp_frame_info->src_frame.sp.y_off), - vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET); - msm_camera_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr + - vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off), - vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET); - msm_camera_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr + - vpe_ctrl->pp_frame_info->dest_frame.sp.y_off), - vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET); - msm_camera_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr + - vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off), - vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET); + if (frame->src_frame.num_planes > 1) { + srcP0 = vpe_ctrl->pp_frame_info->src_frame.mp[0].phy_addr + + vpe_ctrl->pp_frame_info->src_frame.mp[0].data_offset; + srcP1 = vpe_ctrl->pp_frame_info->src_frame.mp[1].phy_addr + + vpe_ctrl->pp_frame_info->src_frame.mp[1].data_offset; + outP0 = vpe_ctrl->pp_frame_info->dest_frame.mp[0].phy_addr + + vpe_ctrl->pp_frame_info->dest_frame.mp[0].data_offset; + outP1 = vpe_ctrl->pp_frame_info->dest_frame.mp[1].phy_addr + + vpe_ctrl->pp_frame_info->dest_frame.mp[1].data_offset; + } else { + srcP0 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr + + vpe_ctrl->pp_frame_info->src_frame.sp.y_off; + srcP1 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr + + vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off; + outP0 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr + + vpe_ctrl->pp_frame_info->dest_frame.sp.y_off; + outP1 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr + + vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off; + } + + msm_camera_io_w(srcP0, vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET); + msm_camera_io_w(srcP1, vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET); + msm_camera_io_w(outP0, vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET); + msm_camera_io_w(outP1, vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET); + vpe_ctrl->state = VPE_STATE_ACTIVE; spin_unlock_irqrestore(&vpe_ctrl->lock, flags); vpe_start(); @@ -443,27 +462,33 @@ static int msm_send_frame_to_vpe(void) static void vpe_send_outmsg(void) { unsigned long flags; - struct msm_vpe_resp rp; - memset(&rp, 0, sizeof(rp)); + struct v4l2_event v4l2_evt; + struct msm_queue_cmd *event_qcmd; spin_lock_irqsave(&vpe_ctrl->lock, flags); if (vpe_ctrl->state == VPE_STATE_IDLE) { pr_err("%s VPE is in IDLE state. Ignore the ack msg", __func__); spin_unlock_irqrestore(&vpe_ctrl->lock, flags); return; } - rp.type = vpe_ctrl->pp_frame_info->pp_frame_cmd.path; - rp.extdata = (void *)vpe_ctrl->pp_frame_info; - rp.extlen = sizeof(*vpe_ctrl->pp_frame_info); - vpe_ctrl->state = VPE_STATE_INIT; /* put it back to idle. */ + event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC); + atomic_set(&event_qcmd->on_heap, 1); + event_qcmd->command = (void *)vpe_ctrl->pp_frame_info; vpe_ctrl->pp_frame_info = NULL; + vpe_ctrl->state = VPE_STATE_INIT; /* put it back to idle. */ + + /* Enqueue the event payload. */ + msm_enqueue(&vpe_ctrl->eventData_q, &event_qcmd->list_eventdata); + /* Now queue the event. */ + v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_MCTL_PP_EVENT; + v4l2_evt.id = 0; + v4l2_event_queue(vpe_ctrl->subdev.devnode, &v4l2_evt); + spin_unlock_irqrestore(&vpe_ctrl->lock, flags); - v4l2_subdev_notify(&vpe_ctrl->subdev, - NOTIFY_VPE_MSG_EVT, (void *)&rp); } static void vpe_do_tasklet(unsigned long data) { - CDBG("%s: irq_status = 0x%x", + D("%s: irq_status = 0x%x", __func__, vpe_ctrl->irq_status); if (vpe_ctrl->irq_status & 0x1) vpe_send_outmsg(); @@ -478,7 +503,7 @@ static irqreturn_t vpe_parse_irq(int irq_num, void *data) msm_camera_io_w_mb(vpe_ctrl->irq_status, vpe_ctrl->vpebase + VPE_INTR_CLEAR_OFFSET); msm_camera_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET); - CDBG("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status); + D("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status); tasklet_schedule(&vpe_tasklet); return IRQ_HANDLED; } @@ -492,7 +517,7 @@ int vpe_enable(uint32_t clk_rate) { int rc = 0; unsigned long flags = 0; - CDBG("%s", __func__); + D("%s", __func__); /* don't change the order of clock and irq.*/ spin_lock_irqsave(&vpe_ctrl->lock, flags); if (vpe_ctrl->state != VPE_STATE_IDLE) { @@ -536,10 +561,10 @@ int vpe_disable(void) { int rc = 0; unsigned long flags = 0; - CDBG("%s", __func__); + D("%s", __func__); spin_lock_irqsave(&vpe_ctrl->lock, flags); if (vpe_ctrl->state == VPE_STATE_IDLE) { - CDBG("%s: VPE already disabled", __func__); + D("%s: VPE already disabled", __func__); spin_unlock_irqrestore(&vpe_ctrl->lock, flags); return rc; } @@ -559,8 +584,7 @@ int vpe_disable(void) return rc; } -static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd, - struct msm_mctl_pp_frame_info *pp_frame_info) +static int msm_vpe_do_pp(struct msm_mctl_pp_frame_info *pp_frame_info) { int rc = 0; unsigned long flags; @@ -577,7 +601,7 @@ static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd, vpe_ctrl->pp_frame_info = pp_frame_info; msm_vpe_cfg_update( &vpe_ctrl->pp_frame_info->pp_frame_cmd.crop); - CDBG("%s Sending frame idx %d id %d to VPE ", __func__, + D("%s Sending frame idx %d id %d to VPE ", __func__, pp_frame_info->src_frame.buf_idx, pp_frame_info->src_frame.frame_id); rc = msm_send_frame_to_vpe(); @@ -590,7 +614,7 @@ int msm_vpe_subdev_init(struct v4l2_subdev *sd, struct msm_cam_media_controller *mctl) { int rc = 0; - CDBG("%s:begin", __func__); + D("%s:begin", __func__); if (atomic_read(&vpe_init_done)) { pr_err("%s: VPE has been initialized", __func__); return -EBUSY; @@ -604,7 +628,7 @@ int msm_vpe_subdev_init(struct v4l2_subdev *sd, } v4l2_set_subdev_hostdata(sd, mctl); spin_lock_init(&vpe_ctrl->lock); - CDBG("%s:end", __func__); + D("%s:end", __func__); return rc; } EXPORT_SYMBOL(msm_vpe_subdev_init); @@ -646,84 +670,310 @@ void msm_vpe_subdev_release(void) } EXPORT_SYMBOL(msm_vpe_subdev_release); -static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd, - unsigned int subdev_cmd, void *arg) +static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd) { - struct msm_mctl_pp_params *vpe_params; - struct msm_mctl_pp_cmd *cmd; int rc = 0; - if (subdev_cmd == VIDIOC_MSM_VPE_INIT) { + switch (vpe_cmd->cmd_type) { + case VPE_CMD_RESET: + rc = vpe_reset(); + break; + + case VPE_CMD_OPERATION_MODE_CFG: { + struct msm_vpe_op_mode_cfg op_mode_cfg; + if (sizeof(struct msm_vpe_op_mode_cfg) != vpe_cmd->length) { + pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d", + __func__, vpe_cmd->cmd_type, vpe_cmd->length, + sizeof(struct msm_vpe_op_mode_cfg)); + rc = -EINVAL; + break; + } + COPY_FROM_USER(rc, &op_mode_cfg, (void __user *)vpe_cmd->value, + sizeof(op_mode_cfg)); + if (rc) { + ERR_COPY_FROM_USER(); + break; + } + + vpe_cmd->value = (void *)&op_mode_cfg; + rc = vpe_operation_config(vpe_cmd->value); + break; + } + + case VPE_CMD_INPUT_PLANE_CFG: { + struct msm_vpe_input_plane_cfg input_cfg; + if (sizeof(struct msm_vpe_input_plane_cfg) != vpe_cmd->length) { + pr_err("%s: mismatch cmd = %d, len = %d, expected = %d", + __func__, vpe_cmd->cmd_type, vpe_cmd->length, + sizeof(struct msm_vpe_input_plane_cfg)); + rc = -EINVAL; + break; + } + COPY_FROM_USER(rc, &input_cfg, (void __user *)vpe_cmd->value, + sizeof(input_cfg)); + if (rc) { + ERR_COPY_FROM_USER(); + break; + } + + vpe_cmd->value = (void *)&input_cfg; + vpe_input_plane_config(vpe_cmd->value); + break; + } + + case VPE_CMD_OUTPUT_PLANE_CFG: { + struct msm_vpe_output_plane_cfg output_cfg; + if (sizeof(struct msm_vpe_output_plane_cfg) != + vpe_cmd->length) { + pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d", + __func__, vpe_cmd->cmd_type, vpe_cmd->length, + sizeof(struct msm_vpe_output_plane_cfg)); + rc = -EINVAL; + break; + } + COPY_FROM_USER(rc, &output_cfg, (void __user *)vpe_cmd->value, + sizeof(output_cfg)); + if (rc) { + ERR_COPY_FROM_USER(); + break; + } + + vpe_cmd->value = (void *)&output_cfg; + vpe_output_plane_config(vpe_cmd->value); + break; + } + + case VPE_CMD_SCALE_CFG_TYPE:{ + struct msm_vpe_scaler_cfg scaler_cfg; + if (sizeof(struct msm_vpe_scaler_cfg) != vpe_cmd->length) { + pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d", + __func__, vpe_cmd->cmd_type, vpe_cmd->length, + sizeof(struct msm_vpe_scaler_cfg)); + rc = -EINVAL; + break; + } + COPY_FROM_USER(rc, &scaler_cfg, (void __user *)vpe_cmd->value, + sizeof(scaler_cfg)); + if (rc) { + ERR_COPY_FROM_USER(); + break; + } + + vpe_cmd->value = (void *)&scaler_cfg; + vpe_update_scale_coef(vpe_cmd->value); + break; + } + + case VPE_CMD_ZOOM: { + struct msm_mctl_pp_frame_info *zoom; + zoom = kmalloc(sizeof(struct msm_mctl_pp_frame_info), + GFP_ATOMIC); + if (!zoom) { + pr_err("%s Not enough memory ", __func__); + rc = -ENOMEM; + break; + } + + if (sizeof(zoom->pp_frame_cmd) != vpe_cmd->length) { + pr_err("%s: size mismatch id=%d, len=%d, expected=%d", + __func__, vpe_cmd->cmd_type, vpe_cmd->length, + sizeof(zoom->pp_frame_cmd)); + rc = -EINVAL; + kfree(zoom); + break; + } + COPY_FROM_USER(rc, &zoom->pp_frame_cmd, + (void __user *)vpe_cmd->value, + sizeof(zoom->pp_frame_cmd)); + if (rc) { + ERR_COPY_FROM_USER(); + kfree(zoom); + break; + } + + zoom->user_cmd = vpe_cmd->cmd_type; + zoom->p_mctl = v4l2_get_subdev_hostdata(&vpe_ctrl->subdev); + D("%s: src=0x%x, dest=0x%x,cookie=0x%x,action=0x%x,path=0x%x", + __func__, zoom->pp_frame_cmd.src_buf_handle, + zoom->pp_frame_cmd.dest_buf_handle, + zoom->pp_frame_cmd.cookie, + zoom->pp_frame_cmd.vpe_output_action, + zoom->pp_frame_cmd.path); + rc = msm_mctl_pp_get_vpe_buf_info(zoom); + if (rc < 0) { + pr_err("%s Error getting buffer info from mctl rc = %d", + __func__, rc); + kfree(zoom); + break; + } + rc = msm_vpe_do_pp(zoom); + break; + } + + case VPE_CMD_ENABLE: { + struct msm_vpe_clock_rate clk_rate; + int turbo_mode; + if (sizeof(struct msm_vpe_clock_rate) != vpe_cmd->length) { + pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d", + __func__, vpe_cmd->cmd_type, vpe_cmd->length, + sizeof(struct msm_vpe_clock_rate)); + rc = -EINVAL; + break; + } + if (copy_from_user(&clk_rate, (void __user *)vpe_cmd->value, + sizeof(struct msm_vpe_clock_rate))) { + pr_err("%s:clk_rate copy failed", __func__); + return -EFAULT; + } + turbo_mode = (int)clk_rate.rate; + rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) : + vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE); + break; + } + + case VPE_CMD_DISABLE: + rc = vpe_disable(); + break; + + default: + break; + } + + return rc; +} + +static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + struct msm_vpe_cfg_cmd *vpe_cmd; + int rc = 0; + + switch (cmd) { + case VIDIOC_MSM_VPE_INIT: { struct msm_cam_media_controller *mctl = (struct msm_cam_media_controller *)arg; msm_vpe_subdev_init(sd, mctl); - } else if (subdev_cmd == VIDIOC_MSM_VPE_RELEASE) { + break; + } + + case VIDIOC_MSM_VPE_RELEASE: msm_vpe_subdev_release(); - } else if (subdev_cmd == VIDIOC_MSM_VPE_CFG) { - vpe_params = (struct msm_mctl_pp_params *)arg; - cmd = vpe_params->cmd; - switch (cmd->id) { - case VPE_CMD_INIT: - case VPE_CMD_DEINIT: - break; - case VPE_CMD_RESET: - rc = vpe_reset(); - break; - case VPE_CMD_OPERATION_MODE_CFG: - rc = vpe_operation_config(cmd->value); - break; - case VPE_CMD_INPUT_PLANE_CFG: - vpe_input_plane_config(cmd->value); - break; - case VPE_CMD_OUTPUT_PLANE_CFG: - vpe_output_plane_config(cmd->value); - break; - case VPE_CMD_SCALE_CFG_TYPE: - vpe_update_scale_coef(cmd->value); - break; - case VPE_CMD_ZOOM: { - rc = msm_vpe_do_pp(cmd, - (struct msm_mctl_pp_frame_info *)vpe_params->data); + break; + + case MSM_CAM_V4L2_IOCTL_CFG_VPE: { + vpe_cmd = (struct msm_vpe_cfg_cmd *)arg; + rc = msm_vpe_process_vpe_cmd(vpe_cmd); + if (rc < 0) { + pr_err("%s Error processing VPE cmd %d ", + __func__, vpe_cmd->cmd_type); break; } - case VPE_CMD_ENABLE: { - struct msm_vpe_clock_rate *clk_rate = cmd->value; - int turbo_mode = (int)clk_rate->rate; - rc = turbo_mode ? - vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) : - vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE); - break; + break; } - case VPE_CMD_DISABLE: - rc = vpe_disable(); - break; - case VPE_CMD_INPUT_PLANE_UPDATE: - case VPE_CMD_FLUSH: - default: - break; + + case MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD: { + struct msm_device_queue *queue = &vpe_ctrl->eventData_q; + struct msm_queue_cmd *event_qcmd; + struct msm_mctl_pp_event_info pp_event_info; + struct msm_mctl_pp_frame_info *pp_frame_info; + struct msm_camera_v4l2_ioctl_t *v4l2_ioctl = arg; + + event_qcmd = msm_dequeue(queue, list_eventdata); + if (!event_qcmd) { + pr_err("%s No events in the queue", __func__); + return -EFAULT; } - CDBG("%s: end, id = %d, rc = %d", __func__, cmd->id, rc); + pp_frame_info = event_qcmd->command; + pp_event_info.event = MCTL_PP_EVENT_CMD_ACK; + pp_event_info.ack.cmd = pp_frame_info->user_cmd; + pp_event_info.ack.status = 0; + pp_event_info.ack.cookie = pp_frame_info->pp_frame_cmd.cookie; + D("%s Sending payload %d %d %d", __func__, + pp_event_info.ack.cmd, pp_event_info.ack.status, + pp_event_info.ack.cookie); + if (copy_to_user((void __user *)v4l2_ioctl->ioctl_ptr, + &pp_event_info, + sizeof(struct msm_mctl_pp_event_info))) + pr_err("%s EVENTPAYLOAD Copy to user failed ", + __func__); + kfree(pp_frame_info); + kfree(event_qcmd); + break; + } + + default: + break; } return rc; } +int msm_vpe_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + D("%s E\n", __func__); + return v4l2_event_subscribe(fh, sub, VPE_SUBDEV_MAX_EVENTS); +} + +int msm_vpe_subdev_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + D("%s E\n", __func__); + return v4l2_event_unsubscribe(fh, sub); +} + static const struct v4l2_subdev_core_ops msm_vpe_subdev_core_ops = { .ioctl = msm_vpe_subdev_ioctl, + .subscribe_event = msm_vpe_subdev_subscribe_event, + .unsubscribe_event = msm_vpe_subdev_unsubscribe_event, }; static const struct v4l2_subdev_ops msm_vpe_subdev_ops = { .core = &msm_vpe_subdev_core_ops, }; -static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops; +static int msm_vpe_subdev_open(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd); + /* Only one client of VPE allowed. */ + if (atomic_read(&vpe_ctrl->active) != 0) { + pr_err("%s already opened\n", __func__); + return -EINVAL; + } -static int __devinit vpe_probe(struct platform_device *pdev) + D("%s E ", __func__); + atomic_inc(&vpe_ctrl->active); + return 0; +} + +static int msm_vpe_subdev_close(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd); + if (atomic_read(&vpe_ctrl->active) == 0) { + pr_err("%s already closed\n", __func__); + return -EINVAL; + } + + D("%s E ", __func__); + /* Drain the payload queue. */ + msm_queue_drain(&vpe_ctrl->eventData_q, list_eventdata); + atomic_dec(&vpe_ctrl->active); + return 0; +} + +static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops = { + .open = msm_vpe_subdev_open, + .close = msm_vpe_subdev_close, +}; + +static int __devinit msm_vpe_probe(struct platform_device *pdev) { int rc = 0; - CDBG("%s: device id = %d\n", __func__, pdev->id); + D("%s: device id = %d\n", __func__, pdev->id); vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL); if (!vpe_ctrl) { - pr_err("%s: no enough memory\n", __func__); + pr_err("%s: not enough memory\n", __func__); return -ENOMEM; } @@ -734,6 +984,13 @@ static int __devinit vpe_probe(struct platform_device *pdev) snprintf(vpe_ctrl->subdev.name, sizeof(vpe_ctrl->subdev.name), "vpe"); platform_set_drvdata(pdev, &vpe_ctrl->subdev); + media_entity_init(&vpe_ctrl->subdev.entity, 0, NULL, 0); + vpe_ctrl->subdev.entity.type = MEDIA_ENT_T_DEVNODE_V4L; + vpe_ctrl->subdev.entity.group_id = VPE_DEV; + vpe_ctrl->subdev.entity.name = vpe_ctrl->subdev.name; + + vpe_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_EVENTS; + vpe_ctrl->vpemem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpe"); if (!vpe_ctrl->vpemem) { @@ -769,17 +1026,22 @@ static int __devinit vpe_probe(struct platform_device *pdev) disable_irq(vpe_ctrl->vpeirq->start); + atomic_set(&vpe_ctrl->active, 0); vpe_ctrl->pdev = pdev; msm_cam_register_subdev_node(&vpe_ctrl->subdev, VPE_DEV, pdev->id); + vpe_ctrl->subdev.entity.revision = vpe_ctrl->subdev.devnode->num; + msm_queue_init(&vpe_ctrl->eventData_q, "ackevents"); + return 0; vpe_no_resource: + pr_err("%s: VPE Probe failed.\n", __func__); kfree(vpe_ctrl); return 0; } -struct platform_driver vpe_driver = { - .probe = vpe_probe, +struct platform_driver msm_vpe_driver = { + .probe = msm_vpe_probe, .driver = { .name = MSM_VPE_DRV_NAME, .owner = THIS_MODULE, @@ -788,9 +1050,15 @@ struct platform_driver vpe_driver = { static int __init msm_vpe_init_module(void) { - return platform_driver_register(&vpe_driver); + return platform_driver_register(&msm_vpe_driver); +} + +static void __exit msm_vpe_exit_module(void) +{ + platform_driver_unregister(&msm_vpe_driver); } module_init(msm_vpe_init_module); +module_exit(msm_vpe_exit_module); MODULE_DESCRIPTION("VPE driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h index 0d14626e552..5cf03095f9d 100644 --- a/drivers/media/video/msm/msm_vpe.h +++ b/drivers/media/video/msm/msm_vpe.h @@ -79,8 +79,8 @@ #define VPE_DEFAULT_SCALE_CONFIG 0x3c #define VPE_NORMAL_MODE_CLOCK_RATE 150000000 -#define VPE_TURBO_MODE_CLOCK_RATE 200000000 - +#define VPE_TURBO_MODE_CLOCK_RATE 200000000 +#define VPE_SUBDEV_MAX_EVENTS 30 /**************************************************/ /*********** End of command id ********************/ @@ -119,6 +119,8 @@ struct vpe_ctrl_type { struct regulator *fs_vpe; struct clk *vpe_clk[2]; struct msm_mctl_pp_frame_info *pp_frame_info; + atomic_t active; + struct msm_device_queue eventData_q; /*V4L2 Event Payload Queue*/ }; /* diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c index 8d004f670c5..1f20c8a1d8f 100644 --- a/drivers/media/video/msm/server/msm_cam_server.c +++ b/drivers/media/video/msm/server/msm_cam_server.c @@ -34,7 +34,7 @@ static long msm_server_send_v4l2_evt(void *evt); static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd, unsigned int notification, void *arg); -static void msm_queue_init(struct msm_device_queue *queue, const char *name) +void msm_queue_init(struct msm_device_queue *queue, const char *name) { D("%s\n", __func__); spin_lock_init(&queue->lock); @@ -45,7 +45,7 @@ static void msm_queue_init(struct msm_device_queue *queue, const char *name) init_waitqueue_head(&queue->wait); } -static void msm_enqueue(struct msm_device_queue *queue, +void msm_enqueue(struct msm_device_queue *queue, struct list_head *entry) { unsigned long flags; @@ -62,7 +62,7 @@ static void msm_enqueue(struct msm_device_queue *queue, spin_unlock_irqrestore(&queue->lock, flags); } -static void msm_drain_eventq(struct msm_device_queue *queue) +void msm_drain_eventq(struct msm_device_queue *queue) { unsigned long flags; struct msm_queue_cmd *qcmd; @@ -1421,16 +1421,6 @@ static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd, g_server_dev.vfe_device[0], notification, arg); } break; - case NOTIFY_VPE_MSG_EVT: { - struct msm_cam_media_controller *pmctl = - (struct msm_cam_media_controller *) - v4l2_get_subdev_hostdata(sd); - struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg; - msm_mctl_pp_notify(pmctl, - (struct msm_mctl_pp_frame_info *) - vdata->extdata); - break; - } case NOTIFY_VFE_IRQ:{ struct msm_vfe_cfg_cmd cfg_cmd; struct msm_camvfe_params vfe_params; diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h index 6d72470a7ab..7b5e841a837 100644 --- a/include/media/msm_camera.h +++ b/include/media/msm_camera.h @@ -1467,6 +1467,9 @@ struct img_plane_info { #define MSM_CAM_IOCTL_SEND_EVENT \ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_event) +#define MSM_CAM_V4L2_IOCTL_CFG_VPE \ + _IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct msm_vpe_cfg_cmd) + struct msm_camera_v4l2_ioctl_t { void __user *ioctl_ptr; };