diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9v022.c | 49 |
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 | } |