static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd, unsigned int subdev_cmd, void *arg) { struct msm_mctl_pp_params *vpe_params; struct msm_mctl_pp_cmd *cmd; int rc = 0; if (subdev_cmd == 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) { 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 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; } case VPE_CMD_DISABLE: rc = vpe_disable(); break; case VPE_CMD_INPUT_PLANE_UPDATE: case VPE_CMD_FLUSH: default: break; } CDBG("%s: end, id = %d, rc = %d", __func__, cmd->id, rc); } return rc; }
static int vpe_proc_general(struct msm_vpe_cmd *cmd) { int rc = 0; uint32_t *cmdp = NULL; struct msm_queue_cmd *qcmd = NULL; struct msm_vpe_buf_info *vpe_buf; int turbo_mode = 0; struct msm_sync *sync = (struct msm_sync *)vpe_ctrl->syncdata; CDBG("vpe_proc_general: cmdID = %s, length = %d\n", vpe_general_cmd[cmd->id], cmd->length); switch (cmd->id) { case VPE_ENABLE: cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; goto vpe_proc_general_done; } if (copy_from_user(cmdp, (void __user *)(cmd->value), cmd->length)) { rc = -EFAULT; goto vpe_proc_general_done; } turbo_mode = *((int *)(cmd->value)); rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) : vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE); break; case VPE_DISABLE: rc = vpe_disable(); break; case VPE_RESET: case VPE_ABORT: rc = vpe_reset(); break; case VPE_START: rc = vpe_start(); break; case VPE_INPUT_PLANE_CFG: cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; goto vpe_proc_general_done; } if (copy_from_user(cmdp, (void __user *)(cmd->value), cmd->length)) { rc = -EFAULT; goto vpe_proc_general_done; } vpe_input_plane_config(cmdp); break; case VPE_OPERATION_MODE_CFG: CDBG("cmd->length = %d\n", cmd->length); if (cmd->length != VPE_OPERATION_MODE_CFG_LEN_ZSL) { rc = -EINVAL; goto vpe_proc_general_done; } cmdp = kmalloc(VPE_OPERATION_MODE_CFG_LEN_ZSL, GFP_ATOMIC); if (copy_from_user(cmdp, (void __user *)(cmd->value), VPE_OPERATION_MODE_CFG_LEN_ZSL)) { rc = -EFAULT; goto vpe_proc_general_done; } rc = vpe_operation_config(cmdp); CDBG("rc = %d \n", rc); break; case VPE_OUTPUT_PLANE_CFG: cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; goto vpe_proc_general_done; } if (copy_from_user(cmdp, (void __user *)(cmd->value), cmd->length)) { rc = -EFAULT; goto vpe_proc_general_done; } vpe_output_plane_config(cmdp); break; case VPE_SCALE_CFG_TYPE: cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; goto vpe_proc_general_done; } if (copy_from_user(cmdp, (void __user *)(cmd->value), cmd->length)) { rc = -EFAULT; goto vpe_proc_general_done; } vpe_update_scale_coef(cmdp); break; case VPE_CMD_DIS_OFFSET_CFG: { struct msm_vfe_resp *vdata; /* first get the dis offset and frame id. */ cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; goto vpe_proc_general_done; } if (copy_from_user(cmdp, (void __user *)(cmd->value), cmd->length)) { rc = -EFAULT; goto vpe_proc_general_done; } /* get the offset. */ vpe_ctrl->dis_offset = *(struct dis_offset_type *)cmdp; qcmd = msm_dequeue_vpe(&sync->vpe_q, list_vpe_frame); if (!qcmd) { pr_err("%s: no video frame.\n", __func__); kfree(cmdp); return -EAGAIN; } vdata = (struct msm_vfe_resp *)(qcmd->command); vpe_buf = &vdata->vpe_bf; vpe_update_scaler_with_dis(&(vpe_buf->vpe_crop), &(vpe_ctrl->dis_offset)); msm_send_frame_to_vpe(vpe_buf->y_phy, vpe_buf->cbcr_phy, &(vpe_buf->ts), OUTPUT_TYPE_V); if (!qcmd || !atomic_read(&qcmd->on_heap)) { kfree(cmdp); return -EAGAIN; } if (!atomic_sub_return(1, &qcmd->on_heap)) kfree(qcmd); break; } default: break; } vpe_proc_general_done: kfree(cmdp); return rc; }
static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd, struct msm_cam_media_controller *mctl) { int rc = 0; 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: cookie=0x%x,action=0x%x,path=0x%x", __func__, zoom->pp_frame_cmd.cookie, zoom->pp_frame_cmd.vpe_output_action, zoom->pp_frame_cmd.path); D("%s Mapping Source frame ", __func__); zoom->src_frame.frame = zoom->pp_frame_cmd.src_frame; rc = msm_mctl_map_user_frame(&zoom->src_frame, zoom->p_mctl->client, mctl->domain_num); if (rc < 0) { pr_err("%s Error mapping source buffer rc = %d", __func__, rc); kfree(zoom); break; } D("%s Mapping Destination frame ", __func__); zoom->dest_frame.frame = zoom->pp_frame_cmd.dest_frame; rc = msm_mctl_map_user_frame(&zoom->dest_frame, zoom->p_mctl->client, mctl->domain_num); if (rc < 0) { pr_err("%s Error mapping dest buffer rc = %d", __func__, rc); msm_mctl_unmap_user_frame(&zoom->src_frame, zoom->p_mctl->client, mctl->domain_num); 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, mctl) : vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE, mctl); break; } case VPE_CMD_DISABLE: #ifdef CONFIG_PANTECH_CAMERA if (vpe_ctrl->pp_frame_info) { pr_err("%s : vpe_ctrl->pp_frame_info = %p ", __func__, vpe_ctrl->pp_frame_info); msm_mctl_unmap_user_frame(&vpe_ctrl->pp_frame_info->src_frame, vpe_ctrl->pp_frame_info->p_mctl->client, mctl->domain_num); msm_mctl_unmap_user_frame(&vpe_ctrl->pp_frame_info->dest_frame, vpe_ctrl->pp_frame_info->p_mctl->client, mctl->domain_num); kfree(vpe_ctrl->pp_frame_info); vpe_ctrl->pp_frame_info = NULL; } #endif rc = vpe_disable(mctl); break; default: break; } return rc; }
static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd) { int rc = 0; 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); kfree(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; }