static int vfe40_config_axi( struct axi_ctrl_t *axi_ctrl, int mode, uint32_t *ao) { uint32_t *ch_info; uint32_t *axi_cfg = ao; /* Update the corresponding write masters for each output*/ ch_info = axi_cfg + V40_AXI_CFG_LEN; axi_ctrl->share_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info; axi_ctrl->share_ctrl->outpath.out0.ch1 = 0x0000FFFF & (*ch_info++ >> 16); axi_ctrl->share_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info; axi_ctrl->share_ctrl->outpath.out0.image_mode = 0x0000FFFF & (*ch_info++ >> 16); axi_ctrl->share_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info; axi_ctrl->share_ctrl->outpath.out1.ch1 = 0x0000FFFF & (*ch_info++ >> 16); axi_ctrl->share_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info; axi_ctrl->share_ctrl->outpath.out1.image_mode = 0x0000FFFF & (*ch_info++ >> 16); axi_ctrl->share_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info; axi_ctrl->share_ctrl->outpath.out2.ch1 = 0x0000FFFF & (*ch_info++ >> 16); axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++; switch (mode) { case OUTPUT_PRIM: axi_ctrl->share_ctrl->outpath.output_mode = VFE40_OUTPUT_MODE_PRIMARY; break; case OUTPUT_PRIM_ALL_CHNLS: axi_ctrl->share_ctrl->outpath.output_mode = VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS; break; case OUTPUT_PRIM|OUTPUT_SEC: axi_ctrl->share_ctrl->outpath.output_mode = VFE40_OUTPUT_MODE_PRIMARY; axi_ctrl->share_ctrl->outpath.output_mode |= VFE40_OUTPUT_MODE_SECONDARY; break; case OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS: axi_ctrl->share_ctrl->outpath.output_mode = VFE40_OUTPUT_MODE_PRIMARY; axi_ctrl->share_ctrl->outpath.output_mode |= VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS; break; case OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC: axi_ctrl->share_ctrl->outpath.output_mode = VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS; axi_ctrl->share_ctrl->outpath.output_mode |= VFE40_OUTPUT_MODE_SECONDARY; break; default: pr_err("%s Invalid AXI mode %d ", __func__, mode); return -EINVAL; } msm_camera_io_w(*ao, axi_ctrl->share_ctrl->vfebase + VFE_BUS_IO_FORMAT_CFG); msm_camera_io_memcpy(axi_ctrl->share_ctrl->vfebase + vfe40_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg, vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length - V40_AXI_CH_INF_LEN); msm_camera_io_w(*ch_info++, axi_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG); if (msm_camera_io_r(axi_ctrl->share_ctrl->vfebase + V40_GET_HW_VERSION_OFF) == VFE40_HW_NUMBER) { msm_camera_io_w(*ch_info++, axi_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG); msm_camera_io_w(*ch_info++, axi_ctrl->share_ctrl->vfebase + VFE_RDI2_CFG); } return 0; }
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) { switch (reg_cfg_cmd->cmd_type) { case VFE_WRITE: { if (resource_size(vfe_dev->vfe_mem) < (reg_cfg_cmd->u.rw_info.reg_offset + reg_cfg_cmd->u.rw_info.len)) { pr_err("%s: VFE_WRITE: Invalid length\n", __func__); return -EINVAL; } msm_camera_io_memcpy(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_WRITE_MB: { uint32_t *data_ptr = cfg_data + reg_cfg_cmd->u.rw_info.cmd_data_offset/4; if ((UINT_MAX - sizeof(*data_ptr) < reg_cfg_cmd->u.rw_info.reg_offset) || (resource_size(vfe_dev->vfe_mem) < reg_cfg_cmd->u.rw_info.reg_offset + sizeof(*data_ptr))) { pr_err("%s: VFE_WRITE_MB: Invalid length\n", __func__); return -EINVAL; } msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base + reg_cfg_cmd->u.rw_info.reg_offset); break; } case VFE_CFG_MASK: { uint32_t temp; if (resource_size(vfe_dev->vfe_mem) < reg_cfg_cmd->u.mask_info.reg_offset) 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; 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; } msm_camera_io_w(temp, vfe_dev->vfe_base + reg_cfg_cmd->u.mask_info.reg_offset); break; } case VFE_WRITE_DMI_16BIT: case VFE_WRITE_DMI_32BIT: case VFE_WRITE_DMI_64BIT: { int i; 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 ((UINT_MAX - reg_cfg_cmd->u.dmi_info.hi_tbl_offset < reg_cfg_cmd->u.dmi_info.len) || (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; if (reg_cfg_cmd->cmd_type == VFE_WRITE_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 = *lo_tbl_ptr++; if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_16BIT) { lo_val1 = lo_val & 0x0000FFFF; lo_val = (lo_val & 0xFFFF0000)>>16; msm_camera_io_w(lo_val1, vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset + 0x4); } else if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { lo_tbl_ptr++; hi_val = *hi_tbl_ptr; hi_tbl_ptr = hi_tbl_ptr + 2; msm_camera_io_w(hi_val, vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset); } msm_camera_io_w(lo_val, vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset + 0x4); } break; }
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_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 + reg_cfg_cmd->u.rw_info.len) > resource_size(vfe_dev->vfe_mem))) { pr_err("%s:%d reg_offset %d len %d res %d\n", __func__, __LINE__, reg_cfg_cmd->u.rw_info.reg_offset, reg_cfg_cmd->u.rw_info.len, (uint32_t)resource_size(vfe_dev->vfe_mem)); return -EINVAL; } if ((reg_cfg_cmd->u.rw_info.cmd_data_offset > (UINT_MAX - reg_cfg_cmd->u.rw_info.len)) || ((reg_cfg_cmd->u.rw_info.cmd_data_offset + reg_cfg_cmd->u.rw_info.len) > cmd_len)) { pr_err("%s:%d cmd_data_offset %d len %d cmd_len %d\n", __func__, __LINE__, reg_cfg_cmd->u.rw_info.cmd_data_offset, reg_cfg_cmd->u.rw_info.len, cmd_len); return -EINVAL; } 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 || 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.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; } switch (reg_cfg_cmd->cmd_type) { case VFE_WRITE: { msm_camera_io_memcpy(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_WRITE_MB: { 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 + reg_cfg_cmd->u.mask_info.reg_offset); break; } case VFE_WRITE_DMI_16BIT: case VFE_WRITE_DMI_32BIT: case VFE_WRITE_DMI_64BIT: { int i; 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) { hi_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4; } lo_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4; if (reg_cfg_cmd->cmd_type == VFE_WRITE_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 = *lo_tbl_ptr++; if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_16BIT) { lo_val1 = lo_val & 0x0000FFFF; lo_val = (lo_val & 0xFFFF0000)>>16; msm_camera_io_w(lo_val1, vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset + 0x4); } else if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { lo_tbl_ptr++; hi_val = *hi_tbl_ptr; hi_tbl_ptr = hi_tbl_ptr + 2; msm_camera_io_w(hi_val, vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset); } msm_camera_io_w(lo_val, vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset + 0x4); } break; }