diff options
-rw-r--r-- | drivers/media/video/tegra/ov5650.c | 100 | ||||
-rw-r--r-- | include/media/ov5650.h | 10 |
2 files changed, 79 insertions, 31 deletions
diff --git a/drivers/media/video/tegra/ov5650.c b/drivers/media/video/tegra/ov5650.c index cc50e9141e66..3adb46a3bb80 100644 --- a/drivers/media/video/tegra/ov5650.c +++ b/drivers/media/video/tegra/ov5650.c @@ -1033,51 +1033,37 @@ static int ov5650_set_mode(struct ov5650_info *info, struct ov5650_mode *mode) static int ov5650_set_frame_length(struct ov5650_info *info, u32 frame_length) { - struct ov5650_reg reg_list[2]; - int i = 0; int ret; + struct ov5650_reg reg_list[2]; + u8 *b_ptr = info->i2c_trans_buf; ov5650_get_frame_length_regs(reg_list, frame_length); - for (i = 0; i < 2; i++) { - ret = ov5650_write_reg_helper(info, reg_list[i].addr, - reg_list[i].val); - if (ret) - return ret; - } + *b_ptr++ = reg_list[0].addr >> 8; + *b_ptr++ = reg_list[0].addr & 0xff; + *b_ptr++ = reg_list[0].val & 0xff; + *b_ptr++ = reg_list[1].val & 0xff; + ret = ov5650_write_bulk_reg_helper(info, 4); - return 0; + return ret; } static int ov5650_set_coarse_time(struct ov5650_info *info, u32 coarse_time) { int ret; - struct ov5650_reg reg_list[3]; - int i = 0; + u8 *b_ptr = info->i2c_trans_buf; ov5650_get_coarse_time_regs(reg_list, coarse_time); - ret = ov5650_write_reg_helper(info, 0x3212, 0x01); - if (ret) - return ret; - - for (i = 0; i < 3; i++) { - ret = ov5650_write_reg_helper(info, reg_list[i].addr, - reg_list[i].val); - if (ret) - return ret; - } - - ret = ov5650_write_reg_helper(info, 0x3212, 0x11); - if (ret) - return ret; - - ret = ov5650_write_reg_helper(info, 0x3212, 0xa1); - if (ret) - return ret; + *b_ptr++ = reg_list[0].addr >> 8; + *b_ptr++ = reg_list[0].addr & 0xff; + *b_ptr++ = reg_list[0].val & 0xff; + *b_ptr++ = reg_list[1].val & 0xff; + *b_ptr++ = reg_list[2].val & 0xff; + ret = ov5650_write_bulk_reg_helper(info, 5); - return 0; + return ret; } static int ov5650_set_gain(struct ov5650_info *info, u16 gain) @@ -1086,12 +1072,53 @@ static int ov5650_set_gain(struct ov5650_info *info, u16 gain) struct ov5650_reg reg_list; ov5650_get_gain_reg(®_list, gain); - ret = ov5650_write_reg_helper(info, reg_list.addr, reg_list.val); return ret; } +static int ov5650_set_group_hold(struct ov5650_info *info, struct ov5650_ae *ae) +{ + int ret; + int count = 0; + bool groupHoldEnabled = false; + + if (ae->gain_enable) + count++; + if (ae->coarse_time_enable) + count++; + if (ae->frame_length_enable) + count++; + if (count >= 2) + groupHoldEnabled = true; + + if (groupHoldEnabled) { + ret = ov5650_write_reg_helper(info, 0x3212, 0x01); + if (ret) + return ret; + } + + if (ae->gain_enable) + ov5650_set_gain(info, ae->gain); + if (ae->coarse_time_enable) + ov5650_set_coarse_time(info, ae->coarse_time); + if (ae->frame_length_enable) + ov5650_set_frame_length(info, ae->frame_length); + + if (groupHoldEnabled) { + ret = ov5650_write_reg_helper(info, 0x3212, 0x11); + if (ret) + return ret; + + ret = ov5650_write_reg_helper(info, 0x3212, 0xa1); + if (ret) + return ret; + } + + return 0; +} + + static int ov5650_set_binning(struct ov5650_info *info, u8 enable) { s32 ret; @@ -1306,6 +1333,17 @@ static long ov5650_ioctl(struct file *file, pr_err("%s %d %d\n", __func__, __LINE__, err); return err; } + case OV5650_IOCTL_SET_GROUP_HOLD: + { + struct ov5650_ae ae; + if (copy_from_user(&ae, + (const void __user *)arg, + sizeof(struct ov5650_ae))) { + pr_info("%s %d\n", __func__, __LINE__); + return -EFAULT; + } + return ov5650_set_group_hold(info, &ae); + } default: return -EINVAL; } diff --git a/include/media/ov5650.h b/include/media/ov5650.h index 00efcec61a5f..5c4a87cfbe8d 100644 --- a/include/media/ov5650.h +++ b/include/media/ov5650.h @@ -29,6 +29,7 @@ #define OV5650_IOCTL_GET_STATUS _IOR('o', 5, __u8) #define OV5650_IOCTL_SET_BINNING _IOW('o', 6, __u8) #define OV5650_IOCTL_TEST_PATTERN _IOW('o', 7, enum ov5650_test_pattern) +#define OV5650_IOCTL_SET_GROUP_HOLD _IOW('o', 8, struct ov5650_ae) #define OV5650_IOCTL_SET_CAMERA_MODE _IOW('o', 10, __u32) #define OV5650_IOCTL_SYNC_SENSORS _IOW('o', 11, __u32) @@ -71,6 +72,15 @@ struct ov5650_mode { __u16 gain; }; +struct ov5650_ae { + __u32 frame_length; + __u8 frame_length_enable; + __u32 coarse_time; + __u8 coarse_time_enable; + __s32 gain; + __u8 gain_enable; +}; + #ifdef __KERNEL__ struct ov5650_platform_data { int (*power_on)(void); |