From: Tuukka Toivonen Date: Fri, 16 Mar 2012 16:06:19 +0000 (+0200) Subject: ov8830: add exposure and gain control X-Git-Tag: 2.1b_release~1165 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fb9a208f8629322b72466fac947f0d2eb9cc712f;p=kernel%2Fkernel-mfld-blackbay.git ov8830: add exposure and gain control BZ: 27475 Add exposure and gain control. Only the private ioctl ATOMISP_IOC_S_EXPOSURE is supported for now. Change-Id: I1021db882ee0b3bc3c7c88df9e99a0ec4af7d61c Signed-off-by: Tuukka Toivonen Reviewed-on: http://android.intel.com:8080/40163 Reviewed-by: Cohen, David A Reviewed-by: Koski, Anttu Tested-by: Koski, Anttu Reviewed-by: buildbot Tested-by: buildbot --- diff --git a/drivers/media/video/ov8830.c b/drivers/media/video/ov8830.c index 908ea24..f141448 100644 --- a/drivers/media/video/ov8830.c +++ b/drivers/media/video/ov8830.c @@ -1439,23 +1439,48 @@ static int ov8830_vcm_enable(struct v4l2_subdev *sd) OV8830_VCM_ENABLE, 0x1); } */ -static long ov8830_set_exposure(struct v4l2_subdev *sd, u16 coarse_itg, - u16 fine_itg, u16 gain) - +static int ov8830_set_exposure(struct v4l2_subdev *sd, int exposure, int gain) { - return -ENXIO; /* Not supported yet */ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov8830_device *dev = to_ov8830_sensor(sd); + int exp_val, ret; + + /* set exposure time */ + exp_val = exposure << 4; + ret = ov8830_write_reg(client, OV8830_8BIT, + OV8830_LONG_EXPO+2, exp_val & 0xFF); + if (ret) + goto out; + + ret = ov8830_write_reg(client, OV8830_8BIT, + OV8830_LONG_EXPO+1, (exp_val >> 8) & 0xFF); + if (ret) + goto out; + + ret = ov8830_write_reg(client, OV8830_8BIT, + OV8830_LONG_EXPO, (exp_val >> 16) & 0x0F); + if (ret) + goto out; + + /* set global gain */ + ret = ov8830_write_reg(client, OV8830_8BIT, + OV8830_AGC_ADJ, gain); + if (ret) + goto out; + + dev->gain = gain; + dev->exposure = exposure; +out: + return ret; } -static long ov8830_s_exposure(struct v4l2_subdev *sd, - struct atomisp_exposure *exposure) +static int ov8830_s_exposure(struct v4l2_subdev *sd, + struct atomisp_exposure *exposure) { - u16 coarse_itg, fine_itg, gain; - - coarse_itg = exposure->integration_time[0]; - fine_itg = exposure->integration_time[1]; - gain = exposure->gain[0]; + int exp = exposure->integration_time[0]; + int gain = exposure->gain[0]; - return ov8830_set_exposure(sd, coarse_itg, fine_itg, gain); + return ov8830_set_exposure(sd, exp, gain); } static long ov8830_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -1492,10 +1517,9 @@ static void ov8830_uninit(struct v4l2_subdev *sd) { struct ov8830_device *dev = to_ov8830_sensor(sd); - dev->coarse_itg = 0; - dev->fine_itg = 0; - dev->gain = 0; - dev->focus = OV8830_INVALID_CONFIG; + dev->exposure = 0; + dev->gain = 0; + dev->focus = OV8830_INVALID_CONFIG; } static int power_up(struct v4l2_subdev *sd) @@ -1594,16 +1618,9 @@ static int ov8830_g_chip_ident(struct v4l2_subdev *sd, for filling in EXIF data, not for actual image processing. */ static int ov8830_q_exposure(struct v4l2_subdev *sd, s32 *value) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - u16 coarse; - int ret; - - /* the fine integration time is currently not calculated */ - ret = ov8830_read_reg(client, OV8830_16BIT, - OV8830_COARSE_INTEGRATION_TIME, &coarse); - *value = coarse; - - return ret; + struct ov8830_device *dev = to_ov8830_sensor(sd); + *value = dev->exposure; + return 0; } static int ov8830_test_pattern(struct v4l2_subdev *sd, s32 value) @@ -1986,18 +2003,22 @@ static int ov8830_s_mbus_fmt(struct v4l2_subdev *sd, dev->fps = ov8830_res[dev->fmt_idx].fps; dev->pixels_per_line = ov8830_res[dev->fmt_idx].pixels_per_line; dev->lines_per_frame = ov8830_res[dev->fmt_idx].lines_per_frame; + #if 0 - ret = ov8830_get_intg_factor(client, ov8830_info, ov8830_def_reg); + ret = ov8830_get_intg_factor(sd, ov8830_info, ov8830_def_reg); if (ret) { v4l2_err(sd, "failed to get integration_factor\n"); return -EINVAL; } +#endif /* restore exposure, gain settings */ - if (dev->coarse_itg) - ov8830_set_exposure(sd, dev->coarse_itg, dev->fine_itg, - dev->gain); -#endif + if (dev->exposure) { + ret = ov8830_set_exposure(sd, dev->exposure, dev->gain); + if (ret) + v4l2_warn(sd, "failed to set exposure time\n"); + } + return 0; } @@ -2305,17 +2326,17 @@ ov8830_g_frame_interval(struct v4l2_subdev *sd, * lines_per_frame the frame_size will be expanded to * coarse_integration_time+1 */ - if (dev->coarse_itg > dev->lines_per_frame) { - if (dev->coarse_itg == 0xFFFF) { + if (dev->exposure > dev->lines_per_frame) { + if (dev->exposure == 0xFFFF) { /* * we can not add 1 according to ds, as this will * cause over flow */ - v4l2_warn(client, "%s: abnormal coarse_itg:0x%x\n", - __func__, dev->coarse_itg); - lines_per_frame = dev->coarse_itg; + v4l2_warn(client, "%s: abnormal exposure:0x%x\n", + __func__, dev->exposure); + lines_per_frame = dev->exposure; } else - lines_per_frame = dev->coarse_itg + 1; + lines_per_frame = dev->exposure + 1; } else lines_per_frame = dev->lines_per_frame; diff --git a/drivers/media/video/ov8830.h b/drivers/media/video/ov8830.h index b4c4281..6b7ca05 100644 --- a/drivers/media/video/ov8830.h +++ b/drivers/media/video/ov8830.h @@ -86,13 +86,8 @@ #define OV8830_FINE_INTG_MAX_DEF 0x3EE #define OV8830_READ_MODE 0x3040 - - -#define OV8830_COARSE_INTEGRATION_TIME 0x3012 -#define OV8830_FINE_INTEGRATION_TIME 0x3014 -#define OV8830_ROW_SPEED 0x3016 -#define OV8830_GLOBAL_GAIN 0x305e -#define OV8830_GLOBAL_GAIN_WR 0x1000 +#define OV8830_LONG_EXPO 0x3500 +#define OV8830_AGC_ADJ 0x350B #define OV8830_TEST_PATTERN_MODE 0x3070 #define OV8830_VCM_SLEW_STEP 0x30F0 #define OV8830_VCM_SLEW_STEP_MAX 0x7 @@ -369,9 +364,8 @@ struct ov8830_device { u8 type; u16 sensor_id; u8 sensor_revision; - u16 coarse_itg; - u16 fine_itg; - u16 gain; + int exposure; + int gain; u32 focus; u16 pixels_per_line; u16 lines_per_frame;