summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Ollonen <marko.ollonen@ixonos.com>2013-01-23 17:00:55 +0200
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>2013-03-04 16:14:15 +0200
commit575e0af030f43a3cd8ebb26059052c5a4bba1b91 (patch)
tree5b9f208d0bdef281d0be63964a9b5f6a3fa6b25b
parent92fa5af276c04b2fa19d47f5fa5593d47adaec38 (diff)
downloadkernel-mfld-blackbay-575e0af030f43a3cd8ebb26059052c5a4bba1b91.tar.gz
kernel-mfld-blackbay-575e0af030f43a3cd8ebb26059052c5a4bba1b91.tar.bz2
kernel-mfld-blackbay-575e0af030f43a3cd8ebb26059052c5a4bba1b91.zip
camera: keep exposure from previous frame in still image mode change.
-rw-r--r--drivers/media/video/mt9e013/mt9e013.c79
-rw-r--r--drivers/media/video/mt9e013/mt9e013_blackbay.h5
2 files changed, 66 insertions, 18 deletions
diff --git a/drivers/media/video/mt9e013/mt9e013.c b/drivers/media/video/mt9e013/mt9e013.c
index 544d4577eb4..90a6276f7fb 100644
--- a/drivers/media/video/mt9e013/mt9e013.c
+++ b/drivers/media/video/mt9e013/mt9e013.c
@@ -1054,7 +1054,7 @@ static int mt9e013_g_chip_ident(struct v4l2_subdev *sd,
static int
mt9e013_get_intg_factor(struct i2c_client *client,
- struct camera_mipi_info *info,
+ struct sensor_mode_data *buf,
const struct mt9e013_reg *reglist)
{
unsigned int vt_pix_clk_div;
@@ -1065,7 +1065,6 @@ mt9e013_get_intg_factor(struct i2c_client *client,
unsigned int op_sys_clk_div;
- struct sensor_mode_data buf;
const struct mt9e013_reg *next = reglist;
int vt_pix_clk_freq_mhz;
u16 data[MT9E013_SHORT_MAX];
@@ -1078,8 +1077,6 @@ mt9e013_get_intg_factor(struct i2c_client *client,
unsigned int line_length_pck;
unsigned int read_mode;
- if (info == NULL)
- return -EINVAL;
memset(data, 0, MT9E013_SHORT_MAX * sizeof(u16));
if (mt9e013_read_reg(client, 12, MT9E013_VT_PIX_CLK_DIV, data))
@@ -1116,7 +1113,7 @@ mt9e013_get_intg_factor(struct i2c_client *client,
for (; next->type != MT9E013_TOK_TERM; next++) {
if (next->type == MT9E013_16BIT) {
if (next->reg.sreg == MT9E013_FINE_INTEGRATION_TIME) {
- buf.fine_integration_time_def = next->val;
+ buf->fine_integration_time_def = next->val;
break;
}
}
@@ -1126,17 +1123,15 @@ mt9e013_get_intg_factor(struct i2c_client *client,
if (next->type == MT9E013_TOK_TERM)
return -EINVAL;
- buf.coarse_integration_time_min = coarse_integration_time_min;
- buf.coarse_integration_time_max_margin =
+ buf->coarse_integration_time_min = coarse_integration_time_min;
+ buf->coarse_integration_time_max_margin =
coarse_integration_time_max_margin;
- buf.fine_integration_time_min = fine_integration_time_min;
- buf.fine_integration_time_max_margin = fine_integration_time_max_margin;
- buf.vt_pix_clk_freq_mhz = vt_pix_clk_freq_mhz;
- buf.line_length_pck = line_length_pck;
- buf.frame_length_lines = frame_length_lines;
- buf.read_mode = read_mode;
-
- memcpy(&info->data, &buf, sizeof(buf));
+ buf->fine_integration_time_min = fine_integration_time_min;
+ buf->fine_integration_time_max_margin = fine_integration_time_max_margin;
+ buf->vt_pix_clk_freq_mhz = vt_pix_clk_freq_mhz;
+ buf->line_length_pck = line_length_pck;
+ buf->frame_length_lines = frame_length_lines;
+ buf->read_mode = read_mode;
return 0;
}
@@ -1637,11 +1632,13 @@ static int mt9e013_s_mbus_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt)
{
struct mt9e013_device *dev = to_mt9e013_sensor(sd);
- const struct mt9e013_reg *mt9e013_def_reg;
+ const struct mt9e013_reg *mt9e013_def_reg, *next;
struct camera_mipi_info *mt9e013_info = NULL;
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct sensor_mode_data buf;
int ret;
-
+ u16 coarse_old, line_length_pck,new_line_length_pck;
+ u16 coarse_new = 0;
mt9e013_info = v4l2_get_subdev_hostdata(sd);
if (mt9e013_info == NULL)
return -EINVAL;
@@ -1664,6 +1661,36 @@ static int mt9e013_s_mbus_fmt(struct v4l2_subdev *sd,
mt9e013_def_reg = mt9e013_res[dev->fmt_idx].regs;
+ /* In case of still capture take exposure from previous frame
+ * as a initial exposure for the still mode.
+ */
+ if (dev->run_mode == CI_MODE_STILL_CAPTURE) {
+ ret = mt9e013_read_reg(client, MT9E013_16BIT,
+ MT9E013_COARSE_INTEGRATION_TIME, &coarse_old);
+ if (ret) {
+ mutex_unlock(&dev->input_lock);
+ return -EINVAL;
+ }
+ ret = mt9e013_read_reg(client, MT9E013_16BIT,
+ MT9E013_LINE_LENGTH_PCK, &line_length_pck);
+ if (ret) {
+ mutex_unlock(&dev->input_lock);
+ return -EINVAL;
+ }
+ new_line_length_pck = line_length_pck;
+ next = mt9e013_res[dev->fmt_idx].regs;
+ for (; next->type != MT9E013_TOK_TERM; next++) {
+ if (next->type == MT9E013_16BIT) {
+ if (next->reg.sreg == MT9E013_LINE_LENGTH_PCK) {
+ new_line_length_pck = next->val;
+ break;
+ }
+ }
+ }
+ coarse_new = (u16)(((int)coarse_old * line_length_pck) /
+ new_line_length_pck);
+ }
+
ret = mt9e013_write_reg_array(client, mt9e013_def_reg);
if (ret) {
mutex_unlock(&dev->input_lock);
@@ -1677,7 +1704,23 @@ static int mt9e013_s_mbus_fmt(struct v4l2_subdev *sd,
dev->fine_itg = 0;
dev->gain = 0;
- ret = mt9e013_get_intg_factor(client, mt9e013_info, mt9e013_def_reg);
+ ret = mt9e013_get_intg_factor(client, &buf, mt9e013_def_reg);
+ memcpy(&mt9e013_info->data, &buf, sizeof(buf));
+
+ if (dev->run_mode == CI_MODE_STILL_CAPTURE) {
+ /* safety check for integration times */
+ coarse_new = min((unsigned int )coarse_new,
+ (buf.frame_length_lines - buf.coarse_integration_time_max_margin));
+ coarse_new = max((unsigned int )coarse_new,
+ buf.coarse_integration_time_min);
+ ret = mt9e013_write_reg(client, MT9E013_16BIT,
+ MT9E013_COARSE_INTEGRATION_TIME, coarse_new);
+ if (ret) {
+ mutex_unlock(&dev->input_lock);
+ return -EINVAL;
+ }
+ }
+
mutex_unlock(&dev->input_lock);
if (ret) {
v4l2_err(sd, "failed to get integration_factor\n");
diff --git a/drivers/media/video/mt9e013/mt9e013_blackbay.h b/drivers/media/video/mt9e013/mt9e013_blackbay.h
index f13a59393ff..c3328b826c6 100644
--- a/drivers/media/video/mt9e013/mt9e013_blackbay.h
+++ b/drivers/media/video/mt9e013/mt9e013_blackbay.h
@@ -31,6 +31,11 @@
/* Recommended Settings 29 Mar 2011*/
static const struct mt9e013_reg mt9e013_recommended_settings[] = {
+ /* Initial integration time */
+ {MT9E013_16BIT, {0x0342},0x1020},
+ {MT9E013_16BIT, {0X3012},0x0573},
+ {MT9E013_16BIT, {0X3014},0x0846},
+
{MT9E013_16BIT, {0x3044}, 0x0590},
{MT9E013_16BIT, {0x306E}, 0xFC80},
{MT9E013_16BIT, {0x30B2}, 0xC000},