Example #1
0
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;
}
Example #2
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;
	}