diff options
Diffstat (limited to 'drivers/media/i2c/soc_camera/mt9v022.c')
-rw-r--r-- | drivers/media/i2c/soc_camera/mt9v022.c | 88 |
1 files changed, 78 insertions, 10 deletions
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index 333ef178d6fb..d40a8858be01 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/log2.h> | 15 | #include <linux/log2.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | 17 | ||
18 | #include <media/mt9v022.h> | ||
18 | #include <media/soc_camera.h> | 19 | #include <media/soc_camera.h> |
19 | #include <media/soc_mediabus.h> | 20 | #include <media/soc_mediabus.h> |
20 | #include <media/v4l2-subdev.h> | 21 | #include <media/v4l2-subdev.h> |
@@ -50,6 +51,7 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); | |||
50 | #define MT9V022_PIXEL_OPERATION_MODE 0x0f | 51 | #define MT9V022_PIXEL_OPERATION_MODE 0x0f |
51 | #define MT9V022_LED_OUT_CONTROL 0x1b | 52 | #define MT9V022_LED_OUT_CONTROL 0x1b |
52 | #define MT9V022_ADC_MODE_CONTROL 0x1c | 53 | #define MT9V022_ADC_MODE_CONTROL 0x1c |
54 | #define MT9V022_REG32 0x20 | ||
53 | #define MT9V022_ANALOG_GAIN 0x35 | 55 | #define MT9V022_ANALOG_GAIN 0x35 |
54 | #define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 | 56 | #define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 |
55 | #define MT9V022_PIXCLK_FV_LV 0x74 | 57 | #define MT9V022_PIXCLK_FV_LV 0x74 |
@@ -71,7 +73,15 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); | |||
71 | #define MT9V022_COLUMN_SKIP 1 | 73 | #define MT9V022_COLUMN_SKIP 1 |
72 | #define MT9V022_ROW_SKIP 4 | 74 | #define MT9V022_ROW_SKIP 4 |
73 | 75 | ||
74 | #define is_mt9v024(id) (id == 0x1324) | 76 | #define MT9V022_HORIZONTAL_BLANKING_MIN 43 |
77 | #define MT9V022_HORIZONTAL_BLANKING_MAX 1023 | ||
78 | #define MT9V022_HORIZONTAL_BLANKING_DEF 94 | ||
79 | #define MT9V022_VERTICAL_BLANKING_MIN 2 | ||
80 | #define MT9V022_VERTICAL_BLANKING_MAX 3000 | ||
81 | #define MT9V022_VERTICAL_BLANKING_DEF 45 | ||
82 | |||
83 | #define is_mt9v022_rev3(id) (id == 0x1313) | ||
84 | #define is_mt9v024(id) (id == 0x1324) | ||
75 | 85 | ||
76 | /* MT9V022 has only one fixed colorspace per pixelcode */ | 86 | /* MT9V022 has only one fixed colorspace per pixelcode */ |
77 | struct mt9v022_datafmt { | 87 | struct mt9v022_datafmt { |
@@ -136,6 +146,8 @@ struct mt9v022 { | |||
136 | struct v4l2_ctrl *autogain; | 146 | struct v4l2_ctrl *autogain; |
137 | struct v4l2_ctrl *gain; | 147 | struct v4l2_ctrl *gain; |
138 | }; | 148 | }; |
149 | struct v4l2_ctrl *hblank; | ||
150 | struct v4l2_ctrl *vblank; | ||
139 | struct v4l2_rect rect; /* Sensor window */ | 151 | struct v4l2_rect rect; /* Sensor window */ |
140 | const struct mt9v022_datafmt *fmt; | 152 | const struct mt9v022_datafmt *fmt; |
141 | const struct mt9v022_datafmt *fmts; | 153 | const struct mt9v022_datafmt *fmts; |
@@ -143,6 +155,7 @@ struct mt9v022 { | |||
143 | int num_fmts; | 155 | int num_fmts; |
144 | int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ | 156 | int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ |
145 | u16 chip_control; | 157 | u16 chip_control; |
158 | u16 chip_version; | ||
146 | unsigned short y_skip_top; /* Lines to skip at the top */ | 159 | unsigned short y_skip_top; /* Lines to skip at the top */ |
147 | }; | 160 | }; |
148 | 161 | ||
@@ -225,12 +238,32 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable) | |||
225 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 238 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
226 | struct mt9v022 *mt9v022 = to_mt9v022(client); | 239 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
227 | 240 | ||
228 | if (enable) | 241 | if (enable) { |
229 | /* Switch to master "normal" mode */ | 242 | /* Switch to master "normal" mode */ |
230 | mt9v022->chip_control &= ~0x10; | 243 | mt9v022->chip_control &= ~0x10; |
231 | else | 244 | if (is_mt9v022_rev3(mt9v022->chip_version) || |
245 | is_mt9v024(mt9v022->chip_version)) { | ||
246 | /* | ||
247 | * Unset snapshot mode specific settings: clear bit 9 | ||
248 | * and bit 2 in reg. 0x20 when in normal mode. | ||
249 | */ | ||
250 | if (reg_clear(client, MT9V022_REG32, 0x204)) | ||
251 | return -EIO; | ||
252 | } | ||
253 | } else { | ||
232 | /* Switch to snapshot mode */ | 254 | /* Switch to snapshot mode */ |
233 | mt9v022->chip_control |= 0x10; | 255 | mt9v022->chip_control |= 0x10; |
256 | if (is_mt9v022_rev3(mt9v022->chip_version) || | ||
257 | is_mt9v024(mt9v022->chip_version)) { | ||
258 | /* | ||
259 | * Required settings for snapshot mode: set bit 9 | ||
260 | * (RST enable) and bit 2 (CR enable) in reg. 0x20 | ||
261 | * See TechNote TN0960 or TN-09-225. | ||
262 | */ | ||
263 | if (reg_set(client, MT9V022_REG32, 0x204)) | ||
264 | return -EIO; | ||
265 | } | ||
266 | } | ||
234 | 267 | ||
235 | if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) | 268 | if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) |
236 | return -EIO; | 269 | return -EIO; |
@@ -282,11 +315,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) | |||
282 | * Default 94, Phytec driver says: | 315 | * Default 94, Phytec driver says: |
283 | * "width + horizontal blank >= 660" | 316 | * "width + horizontal blank >= 660" |
284 | */ | 317 | */ |
285 | ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, | 318 | ret = v4l2_ctrl_s_ctrl(mt9v022->hblank, |
286 | rect.width > 660 - 43 ? 43 : | 319 | rect.width > 660 - 43 ? 43 : 660 - rect.width); |
287 | 660 - rect.width); | ||
288 | if (!ret) | 320 | if (!ret) |
289 | ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45); | 321 | ret = v4l2_ctrl_s_ctrl(mt9v022->vblank, 45); |
290 | if (!ret) | 322 | if (!ret) |
291 | ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width); | 323 | ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width); |
292 | if (!ret) | 324 | if (!ret) |
@@ -509,6 +541,18 @@ static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |||
509 | range = exp->maximum - exp->minimum; | 541 | range = exp->maximum - exp->minimum; |
510 | exp->val = ((data - 1) * range + 239) / 479 + exp->minimum; | 542 | exp->val = ((data - 1) * range + 239) / 479 + exp->minimum; |
511 | return 0; | 543 | return 0; |
544 | case V4L2_CID_HBLANK: | ||
545 | data = reg_read(client, MT9V022_HORIZONTAL_BLANKING); | ||
546 | if (data < 0) | ||
547 | return -EIO; | ||
548 | ctrl->val = data; | ||
549 | return 0; | ||
550 | case V4L2_CID_VBLANK: | ||
551 | data = reg_read(client, MT9V022_VERTICAL_BLANKING); | ||
552 | if (data < 0) | ||
553 | return -EIO; | ||
554 | ctrl->val = data; | ||
555 | return 0; | ||
512 | } | 556 | } |
513 | return -EINVAL; | 557 | return -EINVAL; |
514 | } | 558 | } |
@@ -590,6 +634,16 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl) | |||
590 | return -EIO; | 634 | return -EIO; |
591 | } | 635 | } |
592 | return 0; | 636 | return 0; |
637 | case V4L2_CID_HBLANK: | ||
638 | if (reg_write(client, MT9V022_HORIZONTAL_BLANKING, | ||
639 | ctrl->val) < 0) | ||
640 | return -EIO; | ||
641 | return 0; | ||
642 | case V4L2_CID_VBLANK: | ||
643 | if (reg_write(client, MT9V022_VERTICAL_BLANKING, | ||
644 | ctrl->val) < 0) | ||
645 | return -EIO; | ||
646 | return 0; | ||
593 | } | 647 | } |
594 | return -EINVAL; | 648 | return -EINVAL; |
595 | } | 649 | } |
@@ -621,6 +675,8 @@ static int mt9v022_video_probe(struct i2c_client *client) | |||
621 | goto ei2c; | 675 | goto ei2c; |
622 | } | 676 | } |
623 | 677 | ||
678 | mt9v022->chip_version = data; | ||
679 | |||
624 | mt9v022->reg = is_mt9v024(data) ? &mt9v024_register : | 680 | mt9v022->reg = is_mt9v024(data) ? &mt9v024_register : |
625 | &mt9v022_register; | 681 | &mt9v022_register; |
626 | 682 | ||
@@ -819,6 +875,7 @@ static int mt9v022_probe(struct i2c_client *client, | |||
819 | struct mt9v022 *mt9v022; | 875 | struct mt9v022 *mt9v022; |
820 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); | 876 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); |
821 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 877 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
878 | struct mt9v022_platform_data *pdata = icl->priv; | ||
822 | int ret; | 879 | int ret; |
823 | 880 | ||
824 | if (!icl) { | 881 | if (!icl) { |
@@ -857,10 +914,21 @@ static int mt9v022_probe(struct i2c_client *client, | |||
857 | mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops, | 914 | mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops, |
858 | V4L2_CID_EXPOSURE, 1, 255, 1, 255); | 915 | V4L2_CID_EXPOSURE, 1, 255, 1, 255); |
859 | 916 | ||
917 | mt9v022->hblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops, | ||
918 | V4L2_CID_HBLANK, MT9V022_HORIZONTAL_BLANKING_MIN, | ||
919 | MT9V022_HORIZONTAL_BLANKING_MAX, 1, | ||
920 | MT9V022_HORIZONTAL_BLANKING_DEF); | ||
921 | |||
922 | mt9v022->vblank = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops, | ||
923 | V4L2_CID_VBLANK, MT9V022_VERTICAL_BLANKING_MIN, | ||
924 | MT9V022_VERTICAL_BLANKING_MAX, 1, | ||
925 | MT9V022_VERTICAL_BLANKING_DEF); | ||
926 | |||
860 | mt9v022->subdev.ctrl_handler = &mt9v022->hdl; | 927 | mt9v022->subdev.ctrl_handler = &mt9v022->hdl; |
861 | if (mt9v022->hdl.error) { | 928 | if (mt9v022->hdl.error) { |
862 | int err = mt9v022->hdl.error; | 929 | int err = mt9v022->hdl.error; |
863 | 930 | ||
931 | dev_err(&client->dev, "control initialisation err %d\n", err); | ||
864 | kfree(mt9v022); | 932 | kfree(mt9v022); |
865 | return err; | 933 | return err; |
866 | } | 934 | } |
@@ -871,10 +939,10 @@ static int mt9v022_probe(struct i2c_client *client, | |||
871 | mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; | 939 | mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; |
872 | 940 | ||
873 | /* | 941 | /* |
874 | * MT9V022 _really_ corrupts the first read out line. | 942 | * On some platforms the first read out line is corrupted. |
875 | * TODO: verify on i.MX31 | 943 | * Workaround it by skipping if indicated by platform data. |
876 | */ | 944 | */ |
877 | mt9v022->y_skip_top = 1; | 945 | mt9v022->y_skip_top = pdata ? pdata->y_skip_top : 0; |
878 | mt9v022->rect.left = MT9V022_COLUMN_SKIP; | 946 | mt9v022->rect.left = MT9V022_COLUMN_SKIP; |
879 | mt9v022->rect.top = MT9V022_ROW_SKIP; | 947 | mt9v022->rect.top = MT9V022_ROW_SKIP; |
880 | mt9v022->rect.width = MT9V022_MAX_WIDTH; | 948 | mt9v022->rect.width = MT9V022_MAX_WIDTH; |