diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 2de849c9e666d65b881ad4045fab67bb42c7559e..2cbc150eb945084c21fcdcc45d8f2053145110ce 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -402,9 +402,24 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd, uint32_t *cfg_data, uint32_t cmd_len) { + if (!vfe_dev || !reg_cfg_cmd) { + pr_err("%s:%d failed: vfe_dev %p reg_cfg_cmd %p\n", __func__, + __LINE__, vfe_dev, reg_cfg_cmd); + return -EINVAL; + } + if ((reg_cfg_cmd->cmd_type != VFE_CFG_MASK) && + (!cfg_data || !cmd_len)) { + pr_err("%s:%d failed: cmd type %d cfg_data %p cmd_len %d\n", + __func__, __LINE__, reg_cfg_cmd->cmd_type, cfg_data, + cmd_len); + return -EINVAL; + } + + /* Validate input parameters */ switch (reg_cfg_cmd->cmd_type) { case VFE_WRITE: - case VFE_READ: { + case VFE_READ: + case VFE_WRITE_MB: { if ((reg_cfg_cmd->u.rw_info.reg_offset > (UINT_MAX - reg_cfg_cmd->u.rw_info.len)) || ((reg_cfg_cmd->u.rw_info.reg_offset + @@ -430,6 +445,58 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, } break; } + + case VFE_WRITE_DMI_16BIT: + case VFE_WRITE_DMI_32BIT: + case VFE_WRITE_DMI_64BIT: + case VFE_READ_DMI_16BIT: + case VFE_READ_DMI_32BIT: + case VFE_READ_DMI_64BIT: { + if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { + if ((reg_cfg_cmd->u.dmi_info.hi_tbl_offset <= + reg_cfg_cmd->u.dmi_info.lo_tbl_offset) || + (reg_cfg_cmd->u.dmi_info.hi_tbl_offset - + reg_cfg_cmd->u.dmi_info.lo_tbl_offset != + (sizeof(uint32_t)))) { + pr_err("%s:%d hi %d lo %d\n", + __func__, __LINE__, + reg_cfg_cmd->u.dmi_info.hi_tbl_offset, + reg_cfg_cmd->u.dmi_info.hi_tbl_offset); + return -EINVAL; + } + if (reg_cfg_cmd->u.dmi_info.len <= sizeof(uint32_t)) { + pr_err("%s:%d len %d\n", + __func__, __LINE__, + reg_cfg_cmd->u.dmi_info.len); + return -EINVAL; + } + if (((UINT_MAX - + reg_cfg_cmd->u.dmi_info.hi_tbl_offset) < + (reg_cfg_cmd->u.dmi_info.len - + sizeof(uint32_t))) || + ((reg_cfg_cmd->u.dmi_info.hi_tbl_offset + + reg_cfg_cmd->u.dmi_info.len - + sizeof(uint32_t)) > cmd_len)) { + pr_err("%s:%d hi_tbl_offset %d len %d cmd %d\n", + __func__, __LINE__, + reg_cfg_cmd->u.dmi_info.hi_tbl_offset, + reg_cfg_cmd->u.dmi_info.len, cmd_len); + return -EINVAL; + } + } + if ((reg_cfg_cmd->u.dmi_info.lo_tbl_offset > + (UINT_MAX - reg_cfg_cmd->u.dmi_info.len)) || + ((reg_cfg_cmd->u.dmi_info.lo_tbl_offset + + reg_cfg_cmd->u.dmi_info.len) > cmd_len)) { + pr_err("%s:%d lo_tbl_offset %d len %d cmd_len %d\n", + __func__, __LINE__, + reg_cfg_cmd->u.dmi_info.lo_tbl_offset, + reg_cfg_cmd->u.dmi_info.len, cmd_len); + return -EINVAL; + } + break; + } + default: break; } @@ -443,16 +510,25 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, break; } case VFE_WRITE_MB: { - uint32_t *data_ptr = cfg_data + - reg_cfg_cmd->u.rw_info.cmd_data_offset/4; - msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base + - reg_cfg_cmd->u.rw_info.reg_offset); + msm_camera_io_memcpy_mb(vfe_dev->vfe_base + + reg_cfg_cmd->u.rw_info.reg_offset, + cfg_data + reg_cfg_cmd->u.rw_info.cmd_data_offset/4, + reg_cfg_cmd->u.rw_info.len); break; } case VFE_CFG_MASK: { uint32_t temp; + if ((UINT_MAX - sizeof(temp) < + reg_cfg_cmd->u.mask_info.reg_offset) || + (resource_size(vfe_dev->vfe_mem) < + reg_cfg_cmd->u.mask_info.reg_offset + + sizeof(temp))) { + pr_err("%s: VFE_CFG_MASK: Invalid length\n", __func__); + return -EINVAL; + } temp = msm_camera_io_r(vfe_dev->vfe_base + reg_cfg_cmd->u.mask_info.reg_offset); + temp &= ~reg_cfg_cmd->u.mask_info.mask; temp |= reg_cfg_cmd->u.mask_info.val; msm_camera_io_w(temp, vfe_dev->vfe_base + @@ -466,20 +542,9 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL; uint32_t hi_val, lo_val, lo_val1; if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { - if (reg_cfg_cmd->u.dmi_info.hi_tbl_offset + - reg_cfg_cmd->u.dmi_info.len > cmd_len) { - pr_err("Invalid Hi Table out of bounds\n"); - return -EINVAL; - } hi_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4; } - - if (reg_cfg_cmd->u.dmi_info.lo_tbl_offset + - reg_cfg_cmd->u.dmi_info.len > cmd_len) { - pr_err("Invalid Lo Table out of bounds\n"); - return -EINVAL; - } lo_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4; @@ -510,30 +575,18 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL; uint32_t hi_val, lo_val, lo_val1; if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) { - if (reg_cfg_cmd->u.dmi_info.hi_tbl_offset + - reg_cfg_cmd->u.dmi_info.len > cmd_len) { - pr_err("Invalid Hi Table out of bounds\n"); - return -EINVAL; - } hi_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4; } - if (reg_cfg_cmd->u.dmi_info.lo_tbl_offset + - reg_cfg_cmd->u.dmi_info.len > cmd_len) { - pr_err("Invalid Lo Table out of bounds\n"); - return -EINVAL; - } lo_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4; - for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) { - if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) { - hi_val = msm_camera_io_r(vfe_dev->vfe_base + - vfe_dev->hw_info->dmi_reg_offset); - *hi_tbl_ptr++ = hi_val; - } + if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) + reg_cfg_cmd->u.dmi_info.len = + reg_cfg_cmd->u.dmi_info.len / 2; + for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) { lo_val = msm_camera_io_r(vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset + 0x4); @@ -543,6 +596,13 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, lo_val |= lo_val1 << 16; } *lo_tbl_ptr++ = lo_val; + if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) { + hi_val = msm_camera_io_r(vfe_dev->vfe_base + + vfe_dev->hw_info->dmi_reg_offset); + *hi_tbl_ptr = hi_val; + hi_tbl_ptr += 2; + lo_tbl_ptr++; + } } break; } @@ -550,9 +610,16 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, int i; uint32_t *data_ptr = cfg_data + reg_cfg_cmd->u.rw_info.cmd_data_offset/4; - for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++) + for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++) { + if ((data_ptr < cfg_data) || + (UINT_MAX / sizeof(*data_ptr) < + (data_ptr - cfg_data)) || + (sizeof(*data_ptr) * (data_ptr - cfg_data) >= + cmd_len)) + return -EINVAL; *data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base + reg_cfg_cmd->u.rw_info.reg_offset++); + } break; } } diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c index 0f91ed9000df024e5355fd168c83b2b24b05f2f5..ea90ffed7708f5e885b12ba4097f3832b78fa9f8 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c @@ -109,6 +109,45 @@ void msm_camera_io_memcpy(void __iomem *dest_addr, msm_camera_io_dump(dest_addr, len); } +void msm_camera_io_memcpy_mb(void __iomem *dest_addr, + void __iomem *src_addr, u32 len) +{ + int i; + u32 *d = (u32 *) dest_addr; + u32 *s = (u32 *) src_addr; + + for (i = 0; i < (len / 4); i++) + msm_camera_io_w_mb(*s++, d++); +} + +int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info, + struct msm_cam_clk_info *clk_src_info, int num_clk) +{ + int i; + int rc = 0; + struct clk *mux_clk = NULL; + struct clk *src_clk = NULL; + + for (i = 0; i < num_clk; i++) { + if (clk_src_info[i].clk_name) { + mux_clk = clk_get(dev, clk_info[i].clk_name); + if (IS_ERR(mux_clk)) { + pr_err("%s get failed\n", + clk_info[i].clk_name); + continue; + } + src_clk = clk_get(dev, clk_src_info[i].clk_name); + if (IS_ERR(src_clk)) { + pr_err("%s get failed\n", + clk_src_info[i].clk_name); + continue; + } + clk_set_parent(mux_clk, src_clk); + } + } + return rc; +} + int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info, struct clk **clk_ptr, int num_clk, int enable) { diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h index 499a045e7d1bff2e81723c0b5b18faef6899f6b6..40bc7ce34bc579cc4505d6fe6d911628372095a8 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h @@ -25,7 +25,10 @@ u32 msm_camera_io_r_mb(void __iomem *addr); void msm_camera_io_dump(void __iomem *addr, int size); void msm_camera_io_memcpy(void __iomem *dest_addr, void __iomem *src_addr, u32 len); - +void msm_camera_io_memcpy_mb(void __iomem *dest_addr, + void __iomem *src_addr, u32 len); +int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info, + struct msm_cam_clk_info *clk_src_info, int num_clk); int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info, struct clk **clk_ptr, int num_clk, int enable);