diff options
Diffstat (limited to 'drivers/media/video/mt9t031.c')
-rw-r--r-- | drivers/media/video/mt9t031.c | 347 |
1 files changed, 141 insertions, 206 deletions
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 30547cc3f89b..7ee84cc578b9 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c | |||
@@ -13,11 +13,20 @@ | |||
13 | #include <linux/log2.h> | 13 | #include <linux/log2.h> |
14 | #include <linux/pm.h> | 14 | #include <linux/pm.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/v4l2-mediabus.h> | ||
16 | #include <linux/videodev2.h> | 17 | #include <linux/videodev2.h> |
17 | 18 | ||
18 | #include <media/soc_camera.h> | 19 | #include <media/soc_camera.h> |
19 | #include <media/v4l2-chip-ident.h> | 20 | #include <media/v4l2-chip-ident.h> |
20 | #include <media/v4l2-subdev.h> | 21 | #include <media/v4l2-subdev.h> |
22 | #include <media/v4l2-ctrls.h> | ||
23 | |||
24 | /* | ||
25 | * ATTENTION: this driver still cannot be used outside of the soc-camera | ||
26 | * framework because of its PM implementation, using the video_device node. | ||
27 | * If hardware becomes available for testing, alternative PM approaches shall | ||
28 | * be considered and tested. | ||
29 | */ | ||
21 | 30 | ||
22 | /* | 31 | /* |
23 | * mt9t031 i2c address 0x5d | 32 | * mt9t031 i2c address 0x5d |
@@ -57,21 +66,20 @@ | |||
57 | #define MT9T031_COLUMN_SKIP 32 | 66 | #define MT9T031_COLUMN_SKIP 32 |
58 | #define MT9T031_ROW_SKIP 20 | 67 | #define MT9T031_ROW_SKIP 20 |
59 | 68 | ||
60 | #define MT9T031_BUS_PARAM (SOCAM_PCLK_SAMPLE_RISING | \ | ||
61 | SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | \ | ||
62 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | \ | ||
63 | SOCAM_MASTER | SOCAM_DATAWIDTH_10) | ||
64 | |||
65 | struct mt9t031 { | 69 | struct mt9t031 { |
66 | struct v4l2_subdev subdev; | 70 | struct v4l2_subdev subdev; |
71 | struct v4l2_ctrl_handler hdl; | ||
72 | struct { | ||
73 | /* exposure/auto-exposure cluster */ | ||
74 | struct v4l2_ctrl *autoexposure; | ||
75 | struct v4l2_ctrl *exposure; | ||
76 | }; | ||
67 | struct v4l2_rect rect; /* Sensor window */ | 77 | struct v4l2_rect rect; /* Sensor window */ |
68 | int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ | 78 | int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ |
69 | u16 xskip; | 79 | u16 xskip; |
70 | u16 yskip; | 80 | u16 yskip; |
71 | unsigned int gain; | 81 | unsigned int total_h; |
72 | unsigned short y_skip_top; /* Lines to skip at the top */ | 82 | unsigned short y_skip_top; /* Lines to skip at the top */ |
73 | unsigned int exposure; | ||
74 | unsigned char autoexposure; | ||
75 | }; | 83 | }; |
76 | 84 | ||
77 | static struct mt9t031 *to_mt9t031(const struct i2c_client *client) | 85 | static struct mt9t031 *to_mt9t031(const struct i2c_client *client) |
@@ -179,95 +187,6 @@ static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable) | |||
179 | return 0; | 187 | return 0; |
180 | } | 188 | } |
181 | 189 | ||
182 | static int mt9t031_set_bus_param(struct soc_camera_device *icd, | ||
183 | unsigned long flags) | ||
184 | { | ||
185 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
186 | |||
187 | /* The caller should have queried our parameters, check anyway */ | ||
188 | if (flags & ~MT9T031_BUS_PARAM) | ||
189 | return -EINVAL; | ||
190 | |||
191 | if (flags & SOCAM_PCLK_SAMPLE_FALLING) | ||
192 | reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); | ||
193 | else | ||
194 | reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) | ||
200 | { | ||
201 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
202 | |||
203 | return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); | ||
204 | } | ||
205 | |||
206 | enum { | ||
207 | MT9T031_CTRL_VFLIP, | ||
208 | MT9T031_CTRL_HFLIP, | ||
209 | MT9T031_CTRL_GAIN, | ||
210 | MT9T031_CTRL_EXPOSURE, | ||
211 | MT9T031_CTRL_EXPOSURE_AUTO, | ||
212 | }; | ||
213 | |||
214 | static const struct v4l2_queryctrl mt9t031_controls[] = { | ||
215 | [MT9T031_CTRL_VFLIP] = { | ||
216 | .id = V4L2_CID_VFLIP, | ||
217 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
218 | .name = "Flip Vertically", | ||
219 | .minimum = 0, | ||
220 | .maximum = 1, | ||
221 | .step = 1, | ||
222 | .default_value = 0, | ||
223 | }, | ||
224 | [MT9T031_CTRL_HFLIP] = { | ||
225 | .id = V4L2_CID_HFLIP, | ||
226 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
227 | .name = "Flip Horizontally", | ||
228 | .minimum = 0, | ||
229 | .maximum = 1, | ||
230 | .step = 1, | ||
231 | .default_value = 0, | ||
232 | }, | ||
233 | [MT9T031_CTRL_GAIN] = { | ||
234 | .id = V4L2_CID_GAIN, | ||
235 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
236 | .name = "Gain", | ||
237 | .minimum = 0, | ||
238 | .maximum = 127, | ||
239 | .step = 1, | ||
240 | .default_value = 64, | ||
241 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
242 | }, | ||
243 | [MT9T031_CTRL_EXPOSURE] = { | ||
244 | .id = V4L2_CID_EXPOSURE, | ||
245 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
246 | .name = "Exposure", | ||
247 | .minimum = 1, | ||
248 | .maximum = 255, | ||
249 | .step = 1, | ||
250 | .default_value = 255, | ||
251 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
252 | }, | ||
253 | [MT9T031_CTRL_EXPOSURE_AUTO] = { | ||
254 | .id = V4L2_CID_EXPOSURE_AUTO, | ||
255 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
256 | .name = "Automatic Exposure", | ||
257 | .minimum = 0, | ||
258 | .maximum = 1, | ||
259 | .step = 1, | ||
260 | .default_value = 1, | ||
261 | } | ||
262 | }; | ||
263 | |||
264 | static struct soc_camera_ops mt9t031_ops = { | ||
265 | .set_bus_param = mt9t031_set_bus_param, | ||
266 | .query_bus_param = mt9t031_query_bus_param, | ||
267 | .controls = mt9t031_controls, | ||
268 | .num_controls = ARRAY_SIZE(mt9t031_controls), | ||
269 | }; | ||
270 | |||
271 | /* target must be _even_ */ | 190 | /* target must be _even_ */ |
272 | static u16 mt9t031_skip(s32 *source, s32 target, s32 max) | 191 | static u16 mt9t031_skip(s32 *source, s32 target, s32 max) |
273 | { | 192 | { |
@@ -353,7 +272,7 @@ static int mt9t031_set_params(struct i2c_client *client, | |||
353 | 272 | ||
354 | /* | 273 | /* |
355 | * The caller provides a supported format, as guaranteed by | 274 | * The caller provides a supported format, as guaranteed by |
356 | * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() | 275 | * .try_mbus_fmt(), soc_camera_s_crop() and soc_camera_cropcap() |
357 | */ | 276 | */ |
358 | if (ret >= 0) | 277 | if (ret >= 0) |
359 | ret = reg_write(client, MT9T031_COLUMN_START, rect->left); | 278 | ret = reg_write(client, MT9T031_COLUMN_START, rect->left); |
@@ -364,17 +283,10 @@ static int mt9t031_set_params(struct i2c_client *client, | |||
364 | if (ret >= 0) | 283 | if (ret >= 0) |
365 | ret = reg_write(client, MT9T031_WINDOW_HEIGHT, | 284 | ret = reg_write(client, MT9T031_WINDOW_HEIGHT, |
366 | rect->height + mt9t031->y_skip_top - 1); | 285 | rect->height + mt9t031->y_skip_top - 1); |
367 | if (ret >= 0 && mt9t031->autoexposure) { | 286 | if (ret >= 0 && v4l2_ctrl_g_ctrl(mt9t031->autoexposure) == V4L2_EXPOSURE_AUTO) { |
368 | unsigned int total_h = rect->height + mt9t031->y_skip_top + vblank; | 287 | mt9t031->total_h = rect->height + mt9t031->y_skip_top + vblank; |
369 | ret = set_shutter(client, total_h); | 288 | |
370 | if (ret >= 0) { | 289 | ret = set_shutter(client, mt9t031->total_h); |
371 | const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; | ||
372 | const struct v4l2_queryctrl *qctrl = | ||
373 | &mt9t031_controls[MT9T031_CTRL_EXPOSURE]; | ||
374 | mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * | ||
375 | (qctrl->maximum - qctrl->minimum)) / | ||
376 | shutter_max + qctrl->minimum; | ||
377 | } | ||
378 | } | 290 | } |
379 | 291 | ||
380 | /* Re-enable register update, commit all changes */ | 292 | /* Re-enable register update, commit all changes */ |
@@ -543,71 +455,57 @@ static int mt9t031_s_register(struct v4l2_subdev *sd, | |||
543 | } | 455 | } |
544 | #endif | 456 | #endif |
545 | 457 | ||
546 | static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 458 | static int mt9t031_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
547 | { | 459 | { |
548 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 460 | struct mt9t031 *mt9t031 = container_of(ctrl->handler, |
549 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 461 | struct mt9t031, hdl); |
550 | int data; | 462 | const u32 shutter_max = MT9T031_MAX_HEIGHT + MT9T031_VERTICAL_BLANK; |
463 | s32 min, max; | ||
551 | 464 | ||
552 | switch (ctrl->id) { | 465 | switch (ctrl->id) { |
553 | case V4L2_CID_VFLIP: | ||
554 | data = reg_read(client, MT9T031_READ_MODE_2); | ||
555 | if (data < 0) | ||
556 | return -EIO; | ||
557 | ctrl->value = !!(data & 0x8000); | ||
558 | break; | ||
559 | case V4L2_CID_HFLIP: | ||
560 | data = reg_read(client, MT9T031_READ_MODE_2); | ||
561 | if (data < 0) | ||
562 | return -EIO; | ||
563 | ctrl->value = !!(data & 0x4000); | ||
564 | break; | ||
565 | case V4L2_CID_EXPOSURE_AUTO: | 466 | case V4L2_CID_EXPOSURE_AUTO: |
566 | ctrl->value = mt9t031->autoexposure; | 467 | min = mt9t031->exposure->minimum; |
567 | break; | 468 | max = mt9t031->exposure->maximum; |
568 | case V4L2_CID_GAIN: | 469 | mt9t031->exposure->val = |
569 | ctrl->value = mt9t031->gain; | 470 | (shutter_max / 2 + (mt9t031->total_h - 1) * (max - min)) |
570 | break; | 471 | / shutter_max + min; |
571 | case V4L2_CID_EXPOSURE: | ||
572 | ctrl->value = mt9t031->exposure; | ||
573 | break; | 472 | break; |
574 | } | 473 | } |
575 | return 0; | 474 | return 0; |
576 | } | 475 | } |
577 | 476 | ||
578 | static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 477 | static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl) |
579 | { | 478 | { |
479 | struct mt9t031 *mt9t031 = container_of(ctrl->handler, | ||
480 | struct mt9t031, hdl); | ||
481 | struct v4l2_subdev *sd = &mt9t031->subdev; | ||
580 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 482 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
581 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 483 | struct v4l2_ctrl *exp = mt9t031->exposure; |
582 | const struct v4l2_queryctrl *qctrl; | ||
583 | int data; | 484 | int data; |
584 | 485 | ||
585 | switch (ctrl->id) { | 486 | switch (ctrl->id) { |
586 | case V4L2_CID_VFLIP: | 487 | case V4L2_CID_VFLIP: |
587 | if (ctrl->value) | 488 | if (ctrl->val) |
588 | data = reg_set(client, MT9T031_READ_MODE_2, 0x8000); | 489 | data = reg_set(client, MT9T031_READ_MODE_2, 0x8000); |
589 | else | 490 | else |
590 | data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000); | 491 | data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000); |
591 | if (data < 0) | 492 | if (data < 0) |
592 | return -EIO; | 493 | return -EIO; |
593 | break; | 494 | return 0; |
594 | case V4L2_CID_HFLIP: | 495 | case V4L2_CID_HFLIP: |
595 | if (ctrl->value) | 496 | if (ctrl->val) |
596 | data = reg_set(client, MT9T031_READ_MODE_2, 0x4000); | 497 | data = reg_set(client, MT9T031_READ_MODE_2, 0x4000); |
597 | else | 498 | else |
598 | data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000); | 499 | data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000); |
599 | if (data < 0) | 500 | if (data < 0) |
600 | return -EIO; | 501 | return -EIO; |
601 | break; | 502 | return 0; |
602 | case V4L2_CID_GAIN: | 503 | case V4L2_CID_GAIN: |
603 | qctrl = &mt9t031_controls[MT9T031_CTRL_GAIN]; | ||
604 | if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) | ||
605 | return -EINVAL; | ||
606 | /* See Datasheet Table 7, Gain settings. */ | 504 | /* See Datasheet Table 7, Gain settings. */ |
607 | if (ctrl->value <= qctrl->default_value) { | 505 | if (ctrl->val <= ctrl->default_value) { |
608 | /* Pack it into 0..1 step 0.125, register values 0..8 */ | 506 | /* Pack it into 0..1 step 0.125, register values 0..8 */ |
609 | unsigned long range = qctrl->default_value - qctrl->minimum; | 507 | unsigned long range = ctrl->default_value - ctrl->minimum; |
610 | data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; | 508 | data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range; |
611 | 509 | ||
612 | dev_dbg(&client->dev, "Setting gain %d\n", data); | 510 | dev_dbg(&client->dev, "Setting gain %d\n", data); |
613 | data = reg_write(client, MT9T031_GLOBAL_GAIN, data); | 511 | data = reg_write(client, MT9T031_GLOBAL_GAIN, data); |
@@ -616,9 +514,9 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
616 | } else { | 514 | } else { |
617 | /* Pack it into 1.125..128 variable step, register values 9..0x7860 */ | 515 | /* Pack it into 1.125..128 variable step, register values 9..0x7860 */ |
618 | /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ | 516 | /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ |
619 | unsigned long range = qctrl->maximum - qctrl->default_value - 1; | 517 | unsigned long range = ctrl->maximum - ctrl->default_value - 1; |
620 | /* calculated gain: map 65..127 to 9..1024 step 0.125 */ | 518 | /* calculated gain: map 65..127 to 9..1024 step 0.125 */ |
621 | unsigned long gain = ((ctrl->value - qctrl->default_value - 1) * | 519 | unsigned long gain = ((ctrl->val - ctrl->default_value - 1) * |
622 | 1015 + range / 2) / range + 9; | 520 | 1015 + range / 2) / range + 9; |
623 | 521 | ||
624 | if (gain <= 32) /* calculated gain 9..32 -> 9..32 */ | 522 | if (gain <= 32) /* calculated gain 9..32 -> 9..32 */ |
@@ -635,19 +533,13 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
635 | if (data < 0) | 533 | if (data < 0) |
636 | return -EIO; | 534 | return -EIO; |
637 | } | 535 | } |
536 | return 0; | ||
638 | 537 | ||
639 | /* Success */ | 538 | case V4L2_CID_EXPOSURE_AUTO: |
640 | mt9t031->gain = ctrl->value; | 539 | if (ctrl->val == V4L2_EXPOSURE_MANUAL) { |
641 | break; | 540 | unsigned int range = exp->maximum - exp->minimum; |
642 | case V4L2_CID_EXPOSURE: | 541 | unsigned int shutter = ((exp->val - exp->minimum) * 1048 + |
643 | qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE]; | 542 | range / 2) / range + 1; |
644 | /* mt9t031 has maximum == default */ | ||
645 | if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) | ||
646 | return -EINVAL; | ||
647 | else { | ||
648 | const unsigned long range = qctrl->maximum - qctrl->minimum; | ||
649 | const u32 shutter = ((ctrl->value - qctrl->minimum) * 1048 + | ||
650 | range / 2) / range + 1; | ||
651 | u32 old; | 543 | u32 old; |
652 | 544 | ||
653 | get_shutter(client, &old); | 545 | get_shutter(client, &old); |
@@ -655,27 +547,15 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
655 | old, shutter); | 547 | old, shutter); |
656 | if (set_shutter(client, shutter) < 0) | 548 | if (set_shutter(client, shutter) < 0) |
657 | return -EIO; | 549 | return -EIO; |
658 | mt9t031->exposure = ctrl->value; | 550 | } else { |
659 | mt9t031->autoexposure = 0; | ||
660 | } | ||
661 | break; | ||
662 | case V4L2_CID_EXPOSURE_AUTO: | ||
663 | if (ctrl->value) { | ||
664 | const u16 vblank = MT9T031_VERTICAL_BLANK; | 551 | const u16 vblank = MT9T031_VERTICAL_BLANK; |
665 | const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; | 552 | mt9t031->total_h = mt9t031->rect.height + |
666 | unsigned int total_h = mt9t031->rect.height + | ||
667 | mt9t031->y_skip_top + vblank; | 553 | mt9t031->y_skip_top + vblank; |
668 | 554 | ||
669 | if (set_shutter(client, total_h) < 0) | 555 | if (set_shutter(client, mt9t031->total_h) < 0) |
670 | return -EIO; | 556 | return -EIO; |
671 | qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE]; | 557 | } |
672 | mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * | 558 | return 0; |
673 | (qctrl->maximum - qctrl->minimum)) / | ||
674 | shutter_max + qctrl->minimum; | ||
675 | mt9t031->autoexposure = 1; | ||
676 | } else | ||
677 | mt9t031->autoexposure = 0; | ||
678 | break; | ||
679 | default: | 559 | default: |
680 | return -EINVAL; | 560 | return -EINVAL; |
681 | } | 561 | } |
@@ -700,8 +580,7 @@ static int mt9t031_runtime_suspend(struct device *dev) | |||
700 | static int mt9t031_runtime_resume(struct device *dev) | 580 | static int mt9t031_runtime_resume(struct device *dev) |
701 | { | 581 | { |
702 | struct video_device *vdev = to_video_device(dev); | 582 | struct video_device *vdev = to_video_device(dev); |
703 | struct soc_camera_device *icd = dev_get_drvdata(vdev->parent); | 583 | struct v4l2_subdev *sd = soc_camera_vdev_to_subdev(vdev); |
704 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
705 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 584 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
706 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 585 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
707 | 586 | ||
@@ -734,6 +613,19 @@ static struct device_type mt9t031_dev_type = { | |||
734 | .pm = &mt9t031_dev_pm_ops, | 613 | .pm = &mt9t031_dev_pm_ops, |
735 | }; | 614 | }; |
736 | 615 | ||
616 | static int mt9t031_s_power(struct v4l2_subdev *sd, int on) | ||
617 | { | ||
618 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
619 | struct video_device *vdev = soc_camera_i2c_to_vdev(client); | ||
620 | |||
621 | if (on) | ||
622 | vdev->dev.type = &mt9t031_dev_type; | ||
623 | else | ||
624 | vdev->dev.type = NULL; | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | |||
737 | /* | 629 | /* |
738 | * Interface active, can use i2c. If it fails, it can indeed mean, that | 630 | * Interface active, can use i2c. If it fails, it can indeed mean, that |
739 | * this wasn't our capture interface, so, we wait for the right one | 631 | * this wasn't our capture interface, so, we wait for the right one |
@@ -741,7 +633,6 @@ static struct device_type mt9t031_dev_type = { | |||
741 | static int mt9t031_video_probe(struct i2c_client *client) | 633 | static int mt9t031_video_probe(struct i2c_client *client) |
742 | { | 634 | { |
743 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 635 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
744 | struct video_device *vdev = soc_camera_i2c_to_vdev(client); | ||
745 | s32 data; | 636 | s32 data; |
746 | int ret; | 637 | int ret; |
747 | 638 | ||
@@ -768,11 +659,7 @@ static int mt9t031_video_probe(struct i2c_client *client) | |||
768 | if (ret < 0) | 659 | if (ret < 0) |
769 | dev_err(&client->dev, "Failed to initialise the camera\n"); | 660 | dev_err(&client->dev, "Failed to initialise the camera\n"); |
770 | else | 661 | else |
771 | vdev->dev.type = &mt9t031_dev_type; | 662 | v4l2_ctrl_handler_setup(&mt9t031->hdl); |
772 | |||
773 | /* mt9t031_idle() has reset the chip to default. */ | ||
774 | mt9t031->exposure = 255; | ||
775 | mt9t031->gain = 64; | ||
776 | 663 | ||
777 | return ret; | 664 | return ret; |
778 | } | 665 | } |
@@ -787,10 +674,14 @@ static int mt9t031_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) | |||
787 | return 0; | 674 | return 0; |
788 | } | 675 | } |
789 | 676 | ||
677 | static const struct v4l2_ctrl_ops mt9t031_ctrl_ops = { | ||
678 | .g_volatile_ctrl = mt9t031_g_volatile_ctrl, | ||
679 | .s_ctrl = mt9t031_s_ctrl, | ||
680 | }; | ||
681 | |||
790 | static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { | 682 | static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { |
791 | .g_ctrl = mt9t031_g_ctrl, | ||
792 | .s_ctrl = mt9t031_s_ctrl, | ||
793 | .g_chip_ident = mt9t031_g_chip_ident, | 683 | .g_chip_ident = mt9t031_g_chip_ident, |
684 | .s_power = mt9t031_s_power, | ||
794 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 685 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
795 | .g_register = mt9t031_g_register, | 686 | .g_register = mt9t031_g_register, |
796 | .s_register = mt9t031_s_register, | 687 | .s_register = mt9t031_s_register, |
@@ -807,6 +698,34 @@ static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | |||
807 | return 0; | 698 | return 0; |
808 | } | 699 | } |
809 | 700 | ||
701 | static int mt9t031_g_mbus_config(struct v4l2_subdev *sd, | ||
702 | struct v4l2_mbus_config *cfg) | ||
703 | { | ||
704 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
705 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); | ||
706 | |||
707 | cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | | ||
708 | V4L2_MBUS_PCLK_SAMPLE_FALLING | V4L2_MBUS_HSYNC_ACTIVE_HIGH | | ||
709 | V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_HIGH; | ||
710 | cfg->type = V4L2_MBUS_PARALLEL; | ||
711 | cfg->flags = soc_camera_apply_board_flags(icl, cfg); | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | static int mt9t031_s_mbus_config(struct v4l2_subdev *sd, | ||
717 | const struct v4l2_mbus_config *cfg) | ||
718 | { | ||
719 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
720 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); | ||
721 | |||
722 | if (soc_camera_apply_board_flags(icl, cfg) & | ||
723 | V4L2_MBUS_PCLK_SAMPLE_FALLING) | ||
724 | return reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); | ||
725 | else | ||
726 | return reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); | ||
727 | } | ||
728 | |||
810 | static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { | 729 | static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { |
811 | .s_stream = mt9t031_s_stream, | 730 | .s_stream = mt9t031_s_stream, |
812 | .s_mbus_fmt = mt9t031_s_fmt, | 731 | .s_mbus_fmt = mt9t031_s_fmt, |
@@ -816,6 +735,8 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { | |||
816 | .g_crop = mt9t031_g_crop, | 735 | .g_crop = mt9t031_g_crop, |
817 | .cropcap = mt9t031_cropcap, | 736 | .cropcap = mt9t031_cropcap, |
818 | .enum_mbus_fmt = mt9t031_enum_fmt, | 737 | .enum_mbus_fmt = mt9t031_enum_fmt, |
738 | .g_mbus_config = mt9t031_g_mbus_config, | ||
739 | .s_mbus_config = mt9t031_s_mbus_config, | ||
819 | }; | 740 | }; |
820 | 741 | ||
821 | static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { | 742 | static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { |
@@ -832,18 +753,13 @@ static int mt9t031_probe(struct i2c_client *client, | |||
832 | const struct i2c_device_id *did) | 753 | const struct i2c_device_id *did) |
833 | { | 754 | { |
834 | struct mt9t031 *mt9t031; | 755 | struct mt9t031 *mt9t031; |
835 | struct soc_camera_device *icd = client->dev.platform_data; | 756 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); |
836 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 757 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
837 | int ret; | 758 | int ret; |
838 | 759 | ||
839 | if (icd) { | 760 | if (!icl) { |
840 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 761 | dev_err(&client->dev, "MT9T031 driver needs platform data\n"); |
841 | if (!icl) { | 762 | return -EINVAL; |
842 | dev_err(&client->dev, "MT9T031 driver needs platform data\n"); | ||
843 | return -EINVAL; | ||
844 | } | ||
845 | |||
846 | icd->ops = &mt9t031_ops; | ||
847 | } | 763 | } |
848 | 764 | ||
849 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { | 765 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { |
@@ -857,6 +773,33 @@ static int mt9t031_probe(struct i2c_client *client, | |||
857 | return -ENOMEM; | 773 | return -ENOMEM; |
858 | 774 | ||
859 | v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops); | 775 | v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops); |
776 | v4l2_ctrl_handler_init(&mt9t031->hdl, 5); | ||
777 | v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops, | ||
778 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
779 | v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops, | ||
780 | V4L2_CID_HFLIP, 0, 1, 1, 0); | ||
781 | v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops, | ||
782 | V4L2_CID_GAIN, 0, 127, 1, 64); | ||
783 | |||
784 | /* | ||
785 | * Simulated autoexposure. If enabled, we calculate shutter width | ||
786 | * ourselves in the driver based on vertical blanking and frame width | ||
787 | */ | ||
788 | mt9t031->autoexposure = v4l2_ctrl_new_std_menu(&mt9t031->hdl, | ||
789 | &mt9t031_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0, | ||
790 | V4L2_EXPOSURE_AUTO); | ||
791 | mt9t031->exposure = v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops, | ||
792 | V4L2_CID_EXPOSURE, 1, 255, 1, 255); | ||
793 | |||
794 | mt9t031->subdev.ctrl_handler = &mt9t031->hdl; | ||
795 | if (mt9t031->hdl.error) { | ||
796 | int err = mt9t031->hdl.error; | ||
797 | |||
798 | kfree(mt9t031); | ||
799 | return err; | ||
800 | } | ||
801 | v4l2_ctrl_auto_cluster(2, &mt9t031->autoexposure, | ||
802 | V4L2_EXPOSURE_MANUAL, true); | ||
860 | 803 | ||
861 | mt9t031->y_skip_top = 0; | 804 | mt9t031->y_skip_top = 0; |
862 | mt9t031->rect.left = MT9T031_COLUMN_SKIP; | 805 | mt9t031->rect.left = MT9T031_COLUMN_SKIP; |
@@ -864,12 +807,6 @@ static int mt9t031_probe(struct i2c_client *client, | |||
864 | mt9t031->rect.width = MT9T031_MAX_WIDTH; | 807 | mt9t031->rect.width = MT9T031_MAX_WIDTH; |
865 | mt9t031->rect.height = MT9T031_MAX_HEIGHT; | 808 | mt9t031->rect.height = MT9T031_MAX_HEIGHT; |
866 | 809 | ||
867 | /* | ||
868 | * Simulated autoexposure. If enabled, we calculate shutter width | ||
869 | * ourselves in the driver based on vertical blanking and frame width | ||
870 | */ | ||
871 | mt9t031->autoexposure = 1; | ||
872 | |||
873 | mt9t031->xskip = 1; | 810 | mt9t031->xskip = 1; |
874 | mt9t031->yskip = 1; | 811 | mt9t031->yskip = 1; |
875 | 812 | ||
@@ -880,8 +817,7 @@ static int mt9t031_probe(struct i2c_client *client, | |||
880 | mt9t031_disable(client); | 817 | mt9t031_disable(client); |
881 | 818 | ||
882 | if (ret) { | 819 | if (ret) { |
883 | if (icd) | 820 | v4l2_ctrl_handler_free(&mt9t031->hdl); |
884 | icd->ops = NULL; | ||
885 | kfree(mt9t031); | 821 | kfree(mt9t031); |
886 | } | 822 | } |
887 | 823 | ||
@@ -891,10 +827,9 @@ static int mt9t031_probe(struct i2c_client *client, | |||
891 | static int mt9t031_remove(struct i2c_client *client) | 827 | static int mt9t031_remove(struct i2c_client *client) |
892 | { | 828 | { |
893 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 829 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
894 | struct soc_camera_device *icd = client->dev.platform_data; | ||
895 | 830 | ||
896 | if (icd) | 831 | v4l2_device_unregister_subdev(&mt9t031->subdev); |
897 | icd->ops = NULL; | 832 | v4l2_ctrl_handler_free(&mt9t031->hdl); |
898 | kfree(mt9t031); | 833 | kfree(mt9t031); |
899 | 834 | ||
900 | return 0; | 835 | return 0; |