aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c/soc_camera
diff options
context:
space:
mode:
authorAnatolij Gustschin <agust@denx.de>2012-09-27 18:03:45 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-11-22 08:35:45 -0500
commit6cc1eb70232a98731fdd385c98f2b694dc621726 (patch)
tree51de96235630cb54d58e77f6c6b0ae8fd68020ec /drivers/media/i2c/soc_camera
parentd1a49eacd944308401ae0417692357dd181b665e (diff)
[media] mt9v022: add v4l2 controls for blanking
Add controls for horizontal and vertical blanking. Also add an error message for case that the control handler init failed. Since setting the blanking registers is done by controls now, we shouldn't change these registers outside of the control function. Use v4l2_ctrl_s_ctrl() to set them. Signed-off-by: Anatolij Gustschin <agust@denx.de> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/i2c/soc_camera')
-rw-r--r--drivers/media/i2c/soc_camera/mt9v022.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index 13057b966ee9..a5210e4d67af 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -71,6 +71,13 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
71#define MT9V022_COLUMN_SKIP 1 71#define MT9V022_COLUMN_SKIP 1
72#define MT9V022_ROW_SKIP 4 72#define MT9V022_ROW_SKIP 4
73 73
74#define MT9V022_HORIZONTAL_BLANKING_MIN 43
75#define MT9V022_HORIZONTAL_BLANKING_MAX 1023
76#define MT9V022_HORIZONTAL_BLANKING_DEF 94
77#define MT9V022_VERTICAL_BLANKING_MIN 2
78#define MT9V022_VERTICAL_BLANKING_MAX 3000
79#define MT9V022_VERTICAL_BLANKING_DEF 45
80
74#define is_mt9v024(id) (id == 0x1324) 81#define is_mt9v024(id) (id == 0x1324)
75 82
76/* MT9V022 has only one fixed colorspace per pixelcode */ 83/* MT9V022 has only one fixed colorspace per pixelcode */
@@ -136,6 +143,8 @@ struct mt9v022 {
136 struct v4l2_ctrl *autogain; 143 struct v4l2_ctrl *autogain;
137 struct v4l2_ctrl *gain; 144 struct v4l2_ctrl *gain;
138 }; 145 };
146 struct v4l2_ctrl *hblank;
147 struct v4l2_ctrl *vblank;
139 struct v4l2_rect rect; /* Sensor window */ 148 struct v4l2_rect rect; /* Sensor window */
140 const struct mt9v022_datafmt *fmt; 149 const struct mt9v022_datafmt *fmt;
141 const struct mt9v022_datafmt *fmts; 150 const struct mt9v022_datafmt *fmts;
@@ -277,11 +286,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
277 * Default 94, Phytec driver says: 286 * Default 94, Phytec driver says:
278 * "width + horizontal blank >= 660" 287 * "width + horizontal blank >= 660"
279 */ 288 */
280 ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, 289 ret = v4l2_ctrl_s_ctrl(mt9v022->hblank,
281 rect.width > 660 - 43 ? 43 : 290 rect.width > 660 - 43 ? 43 : 660 - rect.width);
282 660 - rect.width);
283 if (!ret) 291 if (!ret)
284 ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45); 292 ret = v4l2_ctrl_s_ctrl(mt9v022->vblank, 45);
285 if (!ret) 293 if (!ret)
286 ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width); 294 ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width);
287 if (!ret) 295 if (!ret)
@@ -504,6 +512,18 @@ static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
504 range = exp->maximum - exp->minimum; 512 range = exp->maximum - exp->minimum;
505 exp->val = ((data - 1) * range + 239) / 479 + exp->minimum; 513 exp->val = ((data - 1) * range + 239) / 479 + exp->minimum;
506 return 0; 514 return 0;
515 case V4L2_CID_HBLANK:
516 data = reg_read(client, MT9V022_HORIZONTAL_BLANKING);
517 if (data < 0)
518 return -EIO;
519 ctrl->val = data;
520 return 0;
521 case V4L2_CID_VBLANK:
522 data = reg_read(client, MT9V022_VERTICAL_BLANKING);
523 if (data < 0)
524 return -EIO;
525 ctrl->val = data;
526 return 0;
507 } 527 }
508 return -EINVAL; 528 return -EINVAL;
509} 529}
@@ -585,6 +605,16 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
585 return -EIO; 605 return -EIO;
586 } 606 }
587 return 0; 607 return 0;
608 case V4L2_CID_HBLANK:
609 if (reg_write(client, MT9V022_HORIZONTAL_BLANKING,
610 ctrl->val) < 0)
611 return -EIO;
612 return 0;
613 case V4L2_CID_VBLANK:
614 if (reg_write(client, MT9V022_VERTICAL_BLANKING,
615 ctrl->val) < 0)
616 return -EIO;
617 return 0;
588 } 618 }
589 return -EINVAL; 619 return -EINVAL;
590} 620}
@@ -852,10 +882,21 @@ static int mt9v022_probe(struct i2c_client *client,
852 mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops, 882 mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
853 V4L2_CID_EXPOSURE, 1, 255, 1, 255); 883 V4L2_CID_EXPOSURE, 1, 255, 1, 255);
854 884
885 mt9v022->hblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
886 V4L2_CID_HBLANK, MT9V022_HORIZONTAL_BLANKING_MIN,
887 MT9V022_HORIZONTAL_BLANKING_MAX, 1,
888 MT9V022_HORIZONTAL_BLANKING_DEF);
889
890 mt9v022->vblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
891 V4L2_CID_VBLANK, MT9V022_VERTICAL_BLANKING_MIN,
892 MT9V022_VERTICAL_BLANKING_MAX, 1,
893 MT9V022_VERTICAL_BLANKING_DEF);
894
855 mt9v022->subdev.ctrl_handler = &mt9v022->hdl; 895 mt9v022->subdev.ctrl_handler = &mt9v022->hdl;
856 if (mt9v022->hdl.error) { 896 if (mt9v022->hdl.error) {
857 int err = mt9v022->hdl.error; 897 int err = mt9v022->hdl.error;
858 898
899 dev_err(&client->dev, "control initialisation err %d\n", err);
859 kfree(mt9v022); 900 kfree(mt9v022);
860 return err; 901 return err;
861 } 902 }