static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data) { struct msm_pmem_region *regptr; struct msm_vfe_command_8k vfecmd; uint32_t i; void *cmd_data = NULL; long rc = 0; struct vfe_cmd_axi_output_config *axio = NULL; struct vfe_cmd_stats_setting *scfg = NULL; if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE && cmd->cmd_type != CMD_STATS_BUF_RELEASE) { if (copy_from_user(&vfecmd, (void __user *)(cmd->value), sizeof(struct msm_vfe_command_8k))) return -EFAULT; } CDBG("vfe_config: cmdType = %d\n", cmd->cmd_type); switch (cmd->cmd_type) { case CMD_GENERAL: rc = vfe_proc_general(&vfecmd); break; case CMD_STATS_ENABLE: case CMD_STATS_AXI_CFG: { struct axidata *axid; axid = data; if (!axid) return -EFAULT; scfg = kmalloc(sizeof(struct vfe_cmd_stats_setting), GFP_ATOMIC); if (!scfg) return -ENOMEM; if (copy_from_user(scfg, (void __user *)(vfecmd.value), vfecmd.length)) { kfree(scfg); return -EFAULT; } regptr = axid->region; if (axid->bufnum1 > 0) { for (i = 0; i < axid->bufnum1; i++) { scfg->awbBuffer[i] = (uint32_t)(regptr->paddr); regptr++; } } if (axid->bufnum2 > 0) { for (i = 0; i < axid->bufnum2; i++) { scfg->afBuffer[i] = (uint32_t)(regptr->paddr); regptr++; } } vfe_stats_config(scfg); } break; case CMD_STATS_AF_AXI_CFG: { } break; case CMD_FRAME_BUF_RELEASE: { /* preview buffer release */ struct msm_frame *b; unsigned long p; struct vfe_cmd_output_ack fack; if (!data) return -EFAULT; b = (struct msm_frame *)(cmd->value); p = *(unsigned long *)data; b->path = MSM_FRAME_ENC; fack.ybufaddr[0] = (uint32_t)(p + b->y_off); fack.chromabufaddr[0] = (uint32_t)(p + b->cbcr_off); if (b->path == MSM_FRAME_PREV_1) vfe_output1_ack(&fack); if (b->path == MSM_FRAME_ENC || b->path == MSM_FRAME_PREV_2) vfe_output2_ack(&fack); } break; case CMD_SNAP_BUF_RELEASE: { } break; case CMD_STATS_BUF_RELEASE: { struct vfe_cmd_stats_wb_exp_ack sack; if (!data) return -EFAULT; sack.nextWbExpOutputBufferAddr = *(uint32_t *)data; vfe_stats_wb_exp_ack(&sack); } break; case CMD_AXI_CFG_OUT1: { struct axidata *axid; axid = data; if (!axid) return -EFAULT; axio = memdup_user((void __user *)(vfecmd.value), sizeof(struct vfe_cmd_axi_output_config)); if (IS_ERR(axio)) return PTR_ERR(axio); vfe_config_axi(OUTPUT_1, axid, axio); vfe_axi_output_config(axio); } break; case CMD_AXI_CFG_OUT2: case CMD_RAW_PICT_AXI_CFG: { struct axidata *axid; axid = data; if (!axid) return -EFAULT; axio = memdup_user((void __user *)(vfecmd.value), sizeof(struct vfe_cmd_axi_output_config)); if (IS_ERR(axio)) return PTR_ERR(axio); vfe_config_axi(OUTPUT_2, axid, axio); axio->outputDataSize = 0; vfe_axi_output_config(axio); } break; case CMD_AXI_CFG_SNAP_O1_AND_O2: { struct axidata *axid; axid = data; if (!axid) return -EFAULT; axio = memdup_user((void __user *)(vfecmd.value), sizeof(struct vfe_cmd_axi_output_config)); if (IS_ERR(axio)) return PTR_ERR(axio); vfe_config_axi(OUTPUT_1_AND_2, axid, axio); vfe_axi_output_config(axio); cmd_data = axio; } break; default: break; } /* switch */ kfree(scfg); kfree(axio); /* if (cmd->length > 256 && cmd_data && (cmd->cmd_type == CMD_GENERAL || cmd->cmd_type == CMD_STATS_DISABLE)) { kfree(cmd_data); } */ return rc; }
static int vfe_config(struct msm_vfe_cfg_cmd *cmd, void *data) { struct msm_pmem_region *regptr; struct msm_vfe_command_8k vfecmd; struct vfe_cmd_axi_output_config axio; struct axidata *axid = data; int rc = 0; if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE && cmd->cmd_type != CMD_STATS_BUF_RELEASE && cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE) { if (copy_from_user(&vfecmd, (void __user *)(cmd->value), sizeof(vfecmd))) { ERR_COPY_FROM_USER(); return -EFAULT; } } CDBG("%s: cmdType = %d\n", __func__, cmd->cmd_type); switch (cmd->cmd_type) { case CMD_GENERAL: rc = vfe_proc_general(&vfecmd); break; case CMD_STATS_ENABLE: case CMD_STATS_AXI_CFG: { int i; struct vfe_cmd_stats_setting scfg; BUG_ON(!axid); if (vfecmd.length != sizeof(scfg)) { pr_err ("msm_camera: %s: cmd %d: user-space "\ "data size %d != kernel data size %d\n", __func__, cmd->cmd_type, vfecmd.length, sizeof(scfg)); return -EIO; } if (copy_from_user(&scfg, (void __user *)(vfecmd.value), sizeof(scfg))) { ERR_COPY_FROM_USER(); return -EFAULT; } regptr = axid->region; if (axid->bufnum1 > 0) { for (i = 0; i < axid->bufnum1; i++) { scfg.awbBuffer[i] = (uint32_t) (regptr->paddr); regptr++; } } if (axid->bufnum2 > 0) { for (i = 0; i < axid->bufnum2; i++) { scfg.afBuffer[i] = (uint32_t) (regptr->paddr); regptr++; } } vfe_stats_setting(&scfg); } break; case CMD_STATS_AF_AXI_CFG: break; case CMD_FRAME_BUF_RELEASE: { /* preview buffer release */ struct msm_frame *b; unsigned long p; struct vfe_cmd_output_ack fack; BUG_ON(!data); b = (struct msm_frame *)(cmd->value); p = *(unsigned long *)data; b->path = MSM_FRAME_ENC; fack.ybufaddr[0] = (uint32_t) (p + b->y_off); fack.chromabufaddr[0] = (uint32_t) (p + b->cbcr_off); if (b->path == MSM_FRAME_PREV_1) vfe_output1_ack(&fack); if (b->path == MSM_FRAME_ENC || b->path == MSM_FRAME_PREV_2) vfe_output2_ack(&fack); } break; case CMD_SNAP_BUF_RELEASE: break; case CMD_STATS_BUF_RELEASE: { struct vfe_cmd_stats_wb_exp_ack sack; BUG_ON(!data); sack.nextWbExpOutputBufferAddr = *(uint32_t *) data; vfe_stats_wb_exp_ack(&sack); } break; case CMD_STATS_AF_BUF_RELEASE: { struct vfe_cmd_stats_af_ack ack; BUG_ON(!data); ack.nextAFOutputBufferAddr = *(uint32_t *) data; vfe_stats_af_ack(&ack); } break; case CMD_AXI_CFG_OUT1: { BUG_ON(!axid); if (copy_from_user(&axio, (void __user *)(vfecmd.value), sizeof(axio))) { ERR_COPY_FROM_USER(); return -EFAULT; } vfe_config_axi(OUTPUT_1, axid, &axio); vfe_axi_output_config(&axio); } break; case CMD_AXI_CFG_OUT2: case CMD_RAW_PICT_AXI_CFG: { BUG_ON(!axid); if (copy_from_user(&axio, (void __user *)(vfecmd.value), sizeof(axio))) { ERR_COPY_FROM_USER(); return -EFAULT; } vfe_config_axi(OUTPUT_2, axid, &axio); axio.outputDataSize = 0; vfe_axi_output_config(&axio); } break; case CMD_AXI_CFG_SNAP_O1_AND_O2:{ BUG_ON(!axid); if (copy_from_user(&axio, (void __user *)(vfecmd.value), sizeof(axio))) { ERR_COPY_FROM_USER(); return -EFAULT; } vfe_config_axi(OUTPUT_1_AND_2, axid, &axio); vfe_axi_output_config(&axio); } break; default: break; } /* switch */ return rc; }