forked from rubenslte/android_kernel_samsung_msm8226
msm: camera: Improve ISP configuration APIs
Change command structure to improve readablity Replace write and clear mask function with config mask Add DMI table support Change-Id: I4efb78ddbf88cdbd1a7defcbdac3d591c725e1c1 Signed-off-by: Kevin Chan <ktchan@codeaurora.org> [smuckle@codeaurora.org: backported from msm-3.7] Signed-off-by: Steve Muckle <smuckle@codeaurora.org>
This commit is contained in:
@@ -155,58 +155,132 @@ long msm_isp_ioctl(struct v4l2_subdev *sd,
|
||||
}
|
||||
|
||||
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)
|
||||
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->reg_offset + reg_cfg_cmd->len)) {
|
||||
(reg_cfg_cmd->u.rw_info.reg_offset +
|
||||
reg_cfg_cmd->u.rw_info.len)) {
|
||||
pr_err("%s: Invalid length\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
msm_camera_io_memcpy(vfe_dev->vfe_base +
|
||||
reg_cfg_cmd->reg_offset,
|
||||
cfg_data + reg_cfg_cmd->cmd_data/4, reg_cfg_cmd->len);
|
||||
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->cmd_data/4;
|
||||
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->reg_offset);
|
||||
reg_cfg_cmd->u.rw_info.reg_offset);
|
||||
break;
|
||||
}
|
||||
case VFE_WRITE_MASK: {
|
||||
case VFE_CFG_MASK: {
|
||||
uint32_t temp;
|
||||
temp = msm_camera_io_r(vfe_dev->vfe_base +
|
||||
reg_cfg_cmd->reg_offset);
|
||||
temp |= reg_cfg_cmd->cmd_data;
|
||||
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->reg_offset);
|
||||
reg_cfg_cmd->u.mask_info.reg_offset);
|
||||
break;
|
||||
}
|
||||
case VFE_CLEAR_MASK: {
|
||||
uint32_t temp;
|
||||
temp = msm_camera_io_r(vfe_dev->vfe_base +
|
||||
reg_cfg_cmd->reg_offset);
|
||||
temp &= ~reg_cfg_cmd->cmd_data;
|
||||
msm_camera_io_w(temp, vfe_dev->vfe_base +
|
||||
reg_cfg_cmd->reg_offset);
|
||||
break;
|
||||
}
|
||||
case VFE_WRITE_AUTO_INCREMENT: {
|
||||
case VFE_WRITE_DMI_16BIT:
|
||||
case VFE_WRITE_DMI_32BIT:
|
||||
case VFE_WRITE_DMI_64BIT: {
|
||||
int i;
|
||||
uint32_t *data_ptr = cfg_data + reg_cfg_cmd->cmd_data/4;
|
||||
for (i = 0; i < reg_cfg_cmd->len/4; i++)
|
||||
msm_camera_io_w(*data_ptr++,
|
||||
vfe_dev->vfe_base + reg_cfg_cmd->reg_offset);
|
||||
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;
|
||||
|
||||
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 +
|
||||
0x091C);
|
||||
} else if (reg_cfg_cmd->cmd_type ==
|
||||
VFE_WRITE_DMI_64BIT) {
|
||||
hi_val = *hi_tbl_ptr++;
|
||||
msm_camera_io_w(hi_val, vfe_dev->vfe_base +
|
||||
0x0918);
|
||||
}
|
||||
msm_camera_io_w(lo_val, vfe_dev->vfe_base +
|
||||
0x091C);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VFE_READ_DMI_16BIT:
|
||||
case VFE_READ_DMI_32BIT:
|
||||
case VFE_READ_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_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 +
|
||||
0x0918);
|
||||
*hi_tbl_ptr++ = hi_val;
|
||||
}
|
||||
|
||||
lo_val = msm_camera_io_r(vfe_dev->vfe_base +
|
||||
0x091C);
|
||||
|
||||
if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_16BIT) {
|
||||
lo_val1 = msm_camera_io_r(vfe_dev->vfe_base +
|
||||
0x091C);
|
||||
lo_val |= lo_val1 << 16;
|
||||
}
|
||||
*lo_tbl_ptr++ = lo_val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VFE_READ: {
|
||||
int i;
|
||||
uint32_t *data_ptr = cfg_data + reg_cfg_cmd->cmd_data/4;
|
||||
for (i = 0; i < reg_cfg_cmd->len/4; i++)
|
||||
*data_ptr++ = msm_camera_io_r(
|
||||
vfe_dev->vfe_base + reg_cfg_cmd->reg_offset++);
|
||||
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++)
|
||||
*data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base +
|
||||
reg_cfg_cmd->u.rw_info.reg_offset++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -250,7 +324,8 @@ int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg)
|
||||
}
|
||||
|
||||
for (i = 0; i < proc_cmd->num_cfg; i++)
|
||||
msm_isp_send_hw_cmd(vfe_dev, ®_cfg_cmd[i], cfg_data);
|
||||
msm_isp_send_hw_cmd(vfe_dev, ®_cfg_cmd[i],
|
||||
cfg_data, proc_cmd->cmd_len);
|
||||
|
||||
if (copy_to_user(proc_cmd->cfg_data,
|
||||
cfg_data, proc_cmd->cmd_len)) {
|
||||
|
||||
@@ -204,9 +204,13 @@ enum msm_vfe_reg_cfg_type {
|
||||
VFE_WRITE,
|
||||
VFE_WRITE_MB,
|
||||
VFE_READ,
|
||||
VFE_WRITE_MASK,
|
||||
VFE_CLEAR_MASK,
|
||||
VFE_WRITE_AUTO_INCREMENT,
|
||||
VFE_CFG_MASK,
|
||||
VFE_WRITE_DMI_16BIT,
|
||||
VFE_WRITE_DMI_32BIT,
|
||||
VFE_WRITE_DMI_64BIT,
|
||||
VFE_READ_DMI_16BIT,
|
||||
VFE_READ_DMI_32BIT,
|
||||
VFE_READ_DMI_64BIT,
|
||||
};
|
||||
|
||||
struct msm_vfe_cfg_cmd2 {
|
||||
@@ -216,10 +220,31 @@ struct msm_vfe_cfg_cmd2 {
|
||||
void __user *cfg_cmd;
|
||||
};
|
||||
|
||||
struct msm_vfe_reg_cfg_cmd {
|
||||
struct msm_vfe_reg_rw_info {
|
||||
uint32_t reg_offset;
|
||||
uint32_t cmd_data;
|
||||
uint32_t cmd_data_offset;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
struct msm_vfe_reg_mask_info {
|
||||
uint32_t reg_offset;
|
||||
uint32_t mask;
|
||||
uint32_t val;
|
||||
};
|
||||
|
||||
struct msm_vfe_reg_dmi_info {
|
||||
uint32_t hi_tbl_offset; /*Optional*/
|
||||
uint32_t lo_tbl_offset; /*Required*/
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
struct msm_vfe_reg_cfg_cmd {
|
||||
union {
|
||||
struct msm_vfe_reg_rw_info rw_info;
|
||||
struct msm_vfe_reg_mask_info mask_info;
|
||||
struct msm_vfe_reg_dmi_info dmi_info;
|
||||
} u;
|
||||
|
||||
enum msm_vfe_reg_cfg_type cmd_type;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user