diff options
author | Sudhir Vyas <svyas@nvidia.com> | 2012-07-26 11:12:33 +0530 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-08-02 17:37:42 -0700 |
commit | 6108813876889c49a0373248d6e1cfc34a3831ef (patch) | |
tree | 37e38403f325ed65e54b6200037e52d1f96dfb8c /drivers/media | |
parent | fdd994075a8525d702e67eb76a296f5bf80b8b8d (diff) |
media: video: tegra: Focuser range tuning support
* Add support for focuser range tuning.
* Fix focuser position move programming.
* Optimize focuser read/write.
* Optimize focuser power consumption.
* Fix foucser sound issue while capture.
* Improve overall focuser performance.
Bug 1013062
Bug 1018136
Bug 978541
Change-Id: I57fc0566a3a43468ce9a07319014cf3c038ed1e1
Signed-off-by: Sudhir Vyas <svyas@nvidia.com>
Reviewed-on: http://git-master/r/118543
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Prayas Mohanty <pmohanty@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/tegra/ad5816.c | 135 |
1 files changed, 99 insertions, 36 deletions
diff --git a/drivers/media/video/tegra/ad5816.c b/drivers/media/video/tegra/ad5816.c index 9e31acc33cc3..6fdb9f184614 100644 --- a/drivers/media/video/tegra/ad5816.c +++ b/drivers/media/video/tegra/ad5816.c @@ -96,12 +96,14 @@ #define AD5816_ID 0x04 #define AD5816_FOCAL_LENGTH (4.570f) #define AD5816_FNUMBER (2.8f) -#define AD5816_ACTUATOR_RANGE 680 -#define AD5816_SETTLETIME 110 +#define AD5816_SLEW_RATE 1 +#define AD5816_ACTUATOR_RANGE 1023 +#define AD5816_SETTLETIME 50 #define AD5816_FOCUS_MACRO 810 #define AD5816_FOCUS_INFINITY 50 /* Exact value needs to be decided */ -#define AD5816_POS_LOW_DEFAULT 220 -#define AD5816_POS_HIGH_DEFAULT 900 +#define AD5816_POS_LOW_DEFAULT 0 +#define AD5816_POS_HIGH_DEFAULT 1023 +#define AD5816_POS_CLAMP 0x03ff /* Need to decide exact value of VCM_THRESHOLD and its use */ /* define AD5816_VCM_THRESHOLD 20 */ @@ -140,6 +142,7 @@ struct ad5816_info { struct ad5816_info *s_info; struct nvc_focus_nvc nvc; struct nvc_focus_cap cap; + struct nv_focuser_config nv_config; struct ad5816_pdata_info config; }; @@ -154,10 +157,12 @@ static struct ad5816_pdata_info ad5816_default_info = { static struct nvc_focus_cap ad5816_default_cap = { .version = NVC_FOCUS_CAP_VER2, + .slew_rate = AD5816_SLEW_RATE, .actuator_range = AD5816_ACTUATOR_RANGE, .settle_time = AD5816_SETTLETIME, .focus_macro = AD5816_FOCUS_MACRO, .focus_infinity = AD5816_FOCUS_INFINITY, + .focus_hyper = AD5816_FOCUS_INFINITY, }; static struct nvc_focus_nvc ad5816_default_nvc = { @@ -637,28 +642,76 @@ static int ad5816_position_rd(struct ad5816_info *info, unsigned *position) int err = 0; err = ad5816_i2c_rd8(info, 0, VCM_CODE_MSB, &t1); - pos = t1 & 0x03; + pos = t1; err = ad5816_i2c_rd8(info, 0, VCM_CODE_LSB, &t1); pos = (pos << 8) | t1; - if(pos) - *position = pos - info->config.pos_low; - else - *position = info->config.pos_low; - return 0; + if (pos < info->config.pos_low) + pos = info->config.pos_low; + else if (pos > info->config.pos_high) + pos = info->config.pos_high; + + *position = pos; + + return err; } -static int ad5816_position_wr(struct ad5816_info *info, unsigned position) +static int ad5816_position_wr(struct ad5816_info *info, s32 position) { - u16 data; + s16 data; - position = position + info->config.pos_low; - if(position > info->config.pos_high) - position = info->config.pos_high; + ad5816_set_arc_mode(info); - data = position & 0x03ff; + if (position > info->config.pos_high) + return -EINVAL; + data = position & AD5816_POS_CLAMP; return ad5816_i2c_wr16(info, VCM_CODE_MSB, data); + +} + +static void ad5816_get_focuser_capabilities(struct ad5816_info *info) +{ + memset(&info->nv_config, 0, sizeof(info->nv_config)); + + info->nv_config.focal_length = info->nvc.focal_length; + info->nv_config.fnumber = info->nvc.fnumber; + info->nv_config.max_aperture = info->nvc.fnumber; + info->nv_config.range_ends_reversed = 0; + info->nv_config.settle_time = info->cap.settle_time; + + info->nv_config.pos_working_low = AF_POS_INVALID_VALUE; + info->nv_config.pos_working_high = AF_POS_INVALID_VALUE; + + info->nv_config.pos_actual_low = info->config.pos_low; + info->nv_config.pos_actual_high = info->config.pos_high; + + info->nv_config.slew_rate = info->cap.slew_rate; + info->nv_config.circle_of_confusion = -1; + info->nv_config.num_focuser_sets = 1; + info->nv_config.focuser_set[0].macro = info->cap.focus_macro; + info->nv_config.focuser_set[0].hyper = info->cap.focus_hyper; + info->nv_config.focuser_set[0].inf = info->cap.focus_infinity; + info->nv_config.focuser_set[0].settle_time = info->cap.settle_time; +} + +static int ad5816_set_focuser_capabilities(struct ad5816_info *info, + struct nvc_param *params) +{ + if (copy_from_user(&info->nv_config, (const void __user *)params->p_value, + sizeof(struct nv_focuser_config))) { + dev_err(&info->i2c_client->dev, "%s Error: copy_from_user bytes %d\n", + __func__, sizeof(struct nv_focuser_config)); + return -EFAULT; + } + + /* set pre-set value, as currently ODM sets incorrect value */ + info->cap.settle_time = AD5816_SETTLETIME; + + dev_dbg(&info->i2c_client->dev, "%s: copy_from_user bytes %d info->cap.settle_time %d\n", + __func__, sizeof(struct nv_focuser_config), info->cap.settle_time); + + return 0; } static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg) @@ -706,13 +759,10 @@ static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg) __func__, info->nvc.fnumber); break; case NVC_PARAM_CAPS: - data_ptr = &info->cap; - /* there are different sizes depending on the version */ /* send back just what's requested or our max size */ - if (params.sizeofvalue < sizeof(info->cap)) - data_size = params.sizeofvalue; - else - data_size = sizeof(info->cap); + ad5816_get_focuser_capabilities(info); + data_ptr = &info->nv_config; + data_size = sizeof(info->nv_config); dev_err(&info->i2c_client->dev, "%s CAPS\n", __func__); break; case NVC_PARAM_STS: @@ -745,16 +795,16 @@ static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg) } static int ad5816_param_wr_s(struct ad5816_info *info, - struct nvc_param *params, u32 u32val) + struct nvc_param *params, s32 s32val) { int err = 0; switch (params->param) { case NVC_PARAM_LOCUS: - dev_dbg(&info->i2c_client->dev, "%s LOCUS: %u\n", __func__, u32val); - err = ad5816_position_wr(info, u32val); + dev_dbg(&info->i2c_client->dev, "%s LOCUS: %d\n", __func__, s32val); + err = ad5816_position_wr(info, s32val); return err; case NVC_PARAM_RESET: - err = ad5816_reset(info, u32val); + err = ad5816_reset(info, s32val); dev_dbg(&info->i2c_client->dev, "%s RESET: %d\n", __func__, err); return err; case NVC_PARAM_SELF_TEST: @@ -773,7 +823,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg) { struct nvc_param params; u8 u8val; - u32 u32val; + s32 s32val; int err = 0; if (copy_from_user(¶ms, (const void __user *)arg, sizeof(struct nvc_param))) { @@ -781,11 +831,11 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg) __func__, __LINE__); return -EFAULT; } - if (copy_from_user(&u32val, (const void __user *)params.p_value, sizeof(u32val))) { + if (copy_from_user(&s32val, (const void __user *)params.p_value, sizeof(s32val))) { dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n", __func__, __LINE__); return -EFAULT; } - u8val = (u8)u32val; + u8val = (u8)s32val; /* parameters independent of sync mode */ switch (params.param) { case NVC_PARAM_STEREO: @@ -833,7 +883,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg) /* sync power */ info->s_info->pwr_api = info->pwr_api; /* move slave lens to master position */ - err = ad5816_position_wr(info->s_info, info->pos); + err = ad5816_position_wr(info->s_info, (s32)info->pos); if (!err) { info->s_mode = u8val; info->s_info->s_mode = u8val; @@ -854,20 +904,29 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg) if (info->pdata->cfg & NVC_CFG_NOERR) return 0; return err; + + case NVC_PARAM_CAPS: + if (ad5816_set_focuser_capabilities(info, ¶ms)) { + dev_err(&info->i2c_client->dev, "%s: Error: copy_from_user bytes %d\n", + __func__, params.sizeofvalue); + return -EFAULT; + } + return 0; + default: /* parameters dependent on sync mode */ switch (info->s_mode) { case NVC_SYNC_OFF: case NVC_SYNC_MASTER: - return ad5816_param_wr_s(info, ¶ms, u32val); + return ad5816_param_wr_s(info, ¶ms, s32val); case NVC_SYNC_SLAVE: - return ad5816_param_wr_s(info->s_info, ¶ms, u32val); + return ad5816_param_wr_s(info->s_info, ¶ms, s32val); case NVC_SYNC_STEREO: - err = ad5816_param_wr_s(info, ¶ms, u32val); + err = ad5816_param_wr_s(info, ¶ms, s32val); if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX)) err |= ad5816_param_wr_s(info->s_info, ¶ms, - u32val); + s32val); return err; default: dev_err(&info->i2c_client->dev, "%s %d internal err\n", @@ -886,10 +945,14 @@ static long ad5816_ioctl(struct file *file, int err = 0; switch (cmd) { case NVC_IOCTL_PARAM_WR: + ad5816_pm_dev_wr(info, NVC_PWR_ON); err = ad5816_param_wr(info, arg); + ad5816_pm_dev_wr(info, NVC_PWR_OFF); return err; case NVC_IOCTL_PARAM_RD: + ad5816_pm_dev_wr(info, NVC_PWR_ON); err = ad5816_param_rd(info, arg); + ad5816_pm_dev_wr(info, NVC_PWR_OFF); return err; case NVC_IOCTL_PWR_WR: /* This is a Guaranteed Level of Service (GLOS) call */ @@ -1032,8 +1095,8 @@ static int ad5816_open(struct inode *inode, struct file *file) } file->private_data = info; ad5816_pm_dev_wr(info, NVC_PWR_ON); - /* set ARC Mode to ensure faster focus */ - ad5816_set_arc_mode(info); + ad5816_position_wr(info, info->cap.focus_infinity); + ad5816_pm_dev_wr(info, NVC_PWR_OFF); dev_dbg(&info->i2c_client->dev, "%s\n", __func__); return 0; |