diff options
author | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-04-21 05:12:35 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-04-21 05:12:35 -0400 |
commit | 676ee36be04985062522804c2de04f0764212be6 (patch) | |
tree | 781df135c5a91a04decad1b7d53b5a925dc11522 /drivers/media/i2c/mt9v032.c | |
parent | b18042a673e88c9457a6d1716219c2367ca447b0 (diff) | |
parent | e183201b9e917daf2530b637b2f34f1d5afb934d (diff) |
Merge branch 'patchwork' into v4l_for_linus
* patchwork: (404 commits)
[media] uvcvideo: add support for VIDIOC_QUERY_EXT_CTRL
[media] uvcvideo: fix cropcap v4l2-compliance failure
[media] media: omap3isp: remove unused clkdev
[media] coda: Add tracing support
[media] coda: drop dma_sync_single_for_device in coda_bitstream_queue
[media] coda: fix fill bitstream errors in nonstreaming case
[media] coda: call SEQ_END when the first queue is stopped
[media] coda: fail to start streaming if userspace set invalid formats
[media] coda: remove duplicate error messages for buffer allocations
[media] coda: move parameter buffer in together with context buffer allocation
[media] coda: allocate bitstream buffer from REQBUFS, size depends on the format
[media] coda: allocate per-context buffers from REQBUFS
[media] coda: use strlcpy instead of snprintf
[media] coda: bitstream payload is unsigned
[media] coda: fix double call to debugfs_remove
[media] coda: check kasprintf return value in coda_open
[media] coda: bitrate can only be set in kbps steps
[media] v4l2-mem2mem: no need to initialize b in v4l2_m2m_next_buf and v4l2_m2m_buf_remove
[media] s5p-mfc: set allow_zero_bytesused flag for vb2_queue_init
[media] coda: set allow_zero_bytesused flag for vb2_queue_init
...
Diffstat (limited to 'drivers/media/i2c/mt9v032.c')
-rw-r--r-- | drivers/media/i2c/mt9v032.c | 115 |
1 files changed, 92 insertions, 23 deletions
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index bd3f979a4d49..977f4006edbd 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/log2.h> | 18 | #include <linux/log2.h> |
19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
20 | #include <linux/of.h> | ||
21 | #include <linux/of_gpio.h> | ||
20 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
21 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
22 | #include <linux/videodev2.h> | 24 | #include <linux/videodev2.h> |
@@ -26,6 +28,7 @@ | |||
26 | #include <media/mt9v032.h> | 28 | #include <media/mt9v032.h> |
27 | #include <media/v4l2-ctrls.h> | 29 | #include <media/v4l2-ctrls.h> |
28 | #include <media/v4l2-device.h> | 30 | #include <media/v4l2-device.h> |
31 | #include <media/v4l2-of.h> | ||
29 | #include <media/v4l2-subdev.h> | 32 | #include <media/v4l2-subdev.h> |
30 | 33 | ||
31 | /* The first four rows are black rows. The active area spans 753x481 pixels. */ | 34 | /* The first four rows are black rows. The active area spans 753x481 pixels. */ |
@@ -371,12 +374,12 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on) | |||
371 | */ | 374 | */ |
372 | 375 | ||
373 | static struct v4l2_mbus_framefmt * | 376 | static struct v4l2_mbus_framefmt * |
374 | __mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh, | 377 | __mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_pad_config *cfg, |
375 | unsigned int pad, enum v4l2_subdev_format_whence which) | 378 | unsigned int pad, enum v4l2_subdev_format_whence which) |
376 | { | 379 | { |
377 | switch (which) { | 380 | switch (which) { |
378 | case V4L2_SUBDEV_FORMAT_TRY: | 381 | case V4L2_SUBDEV_FORMAT_TRY: |
379 | return v4l2_subdev_get_try_format(fh, pad); | 382 | return v4l2_subdev_get_try_format(&mt9v032->subdev, cfg, pad); |
380 | case V4L2_SUBDEV_FORMAT_ACTIVE: | 383 | case V4L2_SUBDEV_FORMAT_ACTIVE: |
381 | return &mt9v032->format; | 384 | return &mt9v032->format; |
382 | default: | 385 | default: |
@@ -385,12 +388,12 @@ __mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh, | |||
385 | } | 388 | } |
386 | 389 | ||
387 | static struct v4l2_rect * | 390 | static struct v4l2_rect * |
388 | __mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh, | 391 | __mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_pad_config *cfg, |
389 | unsigned int pad, enum v4l2_subdev_format_whence which) | 392 | unsigned int pad, enum v4l2_subdev_format_whence which) |
390 | { | 393 | { |
391 | switch (which) { | 394 | switch (which) { |
392 | case V4L2_SUBDEV_FORMAT_TRY: | 395 | case V4L2_SUBDEV_FORMAT_TRY: |
393 | return v4l2_subdev_get_try_crop(fh, pad); | 396 | return v4l2_subdev_get_try_crop(&mt9v032->subdev, cfg, pad); |
394 | case V4L2_SUBDEV_FORMAT_ACTIVE: | 397 | case V4L2_SUBDEV_FORMAT_ACTIVE: |
395 | return &mt9v032->crop; | 398 | return &mt9v032->crop; |
396 | default: | 399 | default: |
@@ -448,7 +451,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable) | |||
448 | } | 451 | } |
449 | 452 | ||
450 | static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev, | 453 | static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev, |
451 | struct v4l2_subdev_fh *fh, | 454 | struct v4l2_subdev_pad_config *cfg, |
452 | struct v4l2_subdev_mbus_code_enum *code) | 455 | struct v4l2_subdev_mbus_code_enum *code) |
453 | { | 456 | { |
454 | if (code->index > 0) | 457 | if (code->index > 0) |
@@ -459,7 +462,7 @@ static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev, | |||
459 | } | 462 | } |
460 | 463 | ||
461 | static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev, | 464 | static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev, |
462 | struct v4l2_subdev_fh *fh, | 465 | struct v4l2_subdev_pad_config *cfg, |
463 | struct v4l2_subdev_frame_size_enum *fse) | 466 | struct v4l2_subdev_frame_size_enum *fse) |
464 | { | 467 | { |
465 | if (fse->index >= 3 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) | 468 | if (fse->index >= 3 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) |
@@ -474,12 +477,12 @@ static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev, | |||
474 | } | 477 | } |
475 | 478 | ||
476 | static int mt9v032_get_format(struct v4l2_subdev *subdev, | 479 | static int mt9v032_get_format(struct v4l2_subdev *subdev, |
477 | struct v4l2_subdev_fh *fh, | 480 | struct v4l2_subdev_pad_config *cfg, |
478 | struct v4l2_subdev_format *format) | 481 | struct v4l2_subdev_format *format) |
479 | { | 482 | { |
480 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | 483 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); |
481 | 484 | ||
482 | format->format = *__mt9v032_get_pad_format(mt9v032, fh, format->pad, | 485 | format->format = *__mt9v032_get_pad_format(mt9v032, cfg, format->pad, |
483 | format->which); | 486 | format->which); |
484 | return 0; | 487 | return 0; |
485 | } | 488 | } |
@@ -509,7 +512,7 @@ static unsigned int mt9v032_calc_ratio(unsigned int input, unsigned int output) | |||
509 | } | 512 | } |
510 | 513 | ||
511 | static int mt9v032_set_format(struct v4l2_subdev *subdev, | 514 | static int mt9v032_set_format(struct v4l2_subdev *subdev, |
512 | struct v4l2_subdev_fh *fh, | 515 | struct v4l2_subdev_pad_config *cfg, |
513 | struct v4l2_subdev_format *format) | 516 | struct v4l2_subdev_format *format) |
514 | { | 517 | { |
515 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | 518 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); |
@@ -520,7 +523,7 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev, | |||
520 | unsigned int hratio; | 523 | unsigned int hratio; |
521 | unsigned int vratio; | 524 | unsigned int vratio; |
522 | 525 | ||
523 | __crop = __mt9v032_get_pad_crop(mt9v032, fh, format->pad, | 526 | __crop = __mt9v032_get_pad_crop(mt9v032, cfg, format->pad, |
524 | format->which); | 527 | format->which); |
525 | 528 | ||
526 | /* Clamp the width and height to avoid dividing by zero. */ | 529 | /* Clamp the width and height to avoid dividing by zero. */ |
@@ -536,7 +539,7 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev, | |||
536 | hratio = mt9v032_calc_ratio(__crop->width, width); | 539 | hratio = mt9v032_calc_ratio(__crop->width, width); |
537 | vratio = mt9v032_calc_ratio(__crop->height, height); | 540 | vratio = mt9v032_calc_ratio(__crop->height, height); |
538 | 541 | ||
539 | __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad, | 542 | __format = __mt9v032_get_pad_format(mt9v032, cfg, format->pad, |
540 | format->which); | 543 | format->which); |
541 | __format->width = __crop->width / hratio; | 544 | __format->width = __crop->width / hratio; |
542 | __format->height = __crop->height / vratio; | 545 | __format->height = __crop->height / vratio; |
@@ -553,7 +556,7 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev, | |||
553 | } | 556 | } |
554 | 557 | ||
555 | static int mt9v032_get_selection(struct v4l2_subdev *subdev, | 558 | static int mt9v032_get_selection(struct v4l2_subdev *subdev, |
556 | struct v4l2_subdev_fh *fh, | 559 | struct v4l2_subdev_pad_config *cfg, |
557 | struct v4l2_subdev_selection *sel) | 560 | struct v4l2_subdev_selection *sel) |
558 | { | 561 | { |
559 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | 562 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); |
@@ -561,12 +564,12 @@ static int mt9v032_get_selection(struct v4l2_subdev *subdev, | |||
561 | if (sel->target != V4L2_SEL_TGT_CROP) | 564 | if (sel->target != V4L2_SEL_TGT_CROP) |
562 | return -EINVAL; | 565 | return -EINVAL; |
563 | 566 | ||
564 | sel->r = *__mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which); | 567 | sel->r = *__mt9v032_get_pad_crop(mt9v032, cfg, sel->pad, sel->which); |
565 | return 0; | 568 | return 0; |
566 | } | 569 | } |
567 | 570 | ||
568 | static int mt9v032_set_selection(struct v4l2_subdev *subdev, | 571 | static int mt9v032_set_selection(struct v4l2_subdev *subdev, |
569 | struct v4l2_subdev_fh *fh, | 572 | struct v4l2_subdev_pad_config *cfg, |
570 | struct v4l2_subdev_selection *sel) | 573 | struct v4l2_subdev_selection *sel) |
571 | { | 574 | { |
572 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); | 575 | struct mt9v032 *mt9v032 = to_mt9v032(subdev); |
@@ -598,13 +601,13 @@ static int mt9v032_set_selection(struct v4l2_subdev *subdev, | |||
598 | rect.height = min_t(unsigned int, | 601 | rect.height = min_t(unsigned int, |
599 | rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top); | 602 | rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top); |
600 | 603 | ||
601 | __crop = __mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which); | 604 | __crop = __mt9v032_get_pad_crop(mt9v032, cfg, sel->pad, sel->which); |
602 | 605 | ||
603 | if (rect.width != __crop->width || rect.height != __crop->height) { | 606 | if (rect.width != __crop->width || rect.height != __crop->height) { |
604 | /* Reset the output image size if the crop rectangle size has | 607 | /* Reset the output image size if the crop rectangle size has |
605 | * been modified. | 608 | * been modified. |
606 | */ | 609 | */ |
607 | __format = __mt9v032_get_pad_format(mt9v032, fh, sel->pad, | 610 | __format = __mt9v032_get_pad_format(mt9v032, cfg, sel->pad, |
608 | sel->which); | 611 | sel->which); |
609 | __format->width = rect.width; | 612 | __format->width = rect.width; |
610 | __format->height = rect.height; | 613 | __format->height = rect.height; |
@@ -810,13 +813,13 @@ static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) | |||
810 | struct v4l2_mbus_framefmt *format; | 813 | struct v4l2_mbus_framefmt *format; |
811 | struct v4l2_rect *crop; | 814 | struct v4l2_rect *crop; |
812 | 815 | ||
813 | crop = v4l2_subdev_get_try_crop(fh, 0); | 816 | crop = v4l2_subdev_get_try_crop(subdev, fh->pad, 0); |
814 | crop->left = MT9V032_COLUMN_START_DEF; | 817 | crop->left = MT9V032_COLUMN_START_DEF; |
815 | crop->top = MT9V032_ROW_START_DEF; | 818 | crop->top = MT9V032_ROW_START_DEF; |
816 | crop->width = MT9V032_WINDOW_WIDTH_DEF; | 819 | crop->width = MT9V032_WINDOW_WIDTH_DEF; |
817 | crop->height = MT9V032_WINDOW_HEIGHT_DEF; | 820 | crop->height = MT9V032_WINDOW_HEIGHT_DEF; |
818 | 821 | ||
819 | format = v4l2_subdev_get_try_format(fh, 0); | 822 | format = v4l2_subdev_get_try_format(subdev, fh->pad, 0); |
820 | 823 | ||
821 | if (mt9v032->model->color) | 824 | if (mt9v032->model->color) |
822 | format->code = MEDIA_BUS_FMT_SGRBG10_1X10; | 825 | format->code = MEDIA_BUS_FMT_SGRBG10_1X10; |
@@ -876,10 +879,58 @@ static const struct regmap_config mt9v032_regmap_config = { | |||
876 | * Driver initialization and probing | 879 | * Driver initialization and probing |
877 | */ | 880 | */ |
878 | 881 | ||
882 | static struct mt9v032_platform_data * | ||
883 | mt9v032_get_pdata(struct i2c_client *client) | ||
884 | { | ||
885 | struct mt9v032_platform_data *pdata; | ||
886 | struct v4l2_of_endpoint endpoint; | ||
887 | struct device_node *np; | ||
888 | struct property *prop; | ||
889 | |||
890 | if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) | ||
891 | return client->dev.platform_data; | ||
892 | |||
893 | np = of_graph_get_next_endpoint(client->dev.of_node, NULL); | ||
894 | if (!np) | ||
895 | return NULL; | ||
896 | |||
897 | if (v4l2_of_parse_endpoint(np, &endpoint) < 0) | ||
898 | goto done; | ||
899 | |||
900 | pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); | ||
901 | if (!pdata) | ||
902 | goto done; | ||
903 | |||
904 | prop = of_find_property(np, "link-frequencies", NULL); | ||
905 | if (prop) { | ||
906 | u64 *link_freqs; | ||
907 | size_t size = prop->length / sizeof(*link_freqs); | ||
908 | |||
909 | link_freqs = devm_kcalloc(&client->dev, size, | ||
910 | sizeof(*link_freqs), GFP_KERNEL); | ||
911 | if (!link_freqs) | ||
912 | goto done; | ||
913 | |||
914 | if (of_property_read_u64_array(np, "link-frequencies", | ||
915 | link_freqs, size) < 0) | ||
916 | goto done; | ||
917 | |||
918 | pdata->link_freqs = link_freqs; | ||
919 | pdata->link_def_freq = link_freqs[0]; | ||
920 | } | ||
921 | |||
922 | pdata->clk_pol = !!(endpoint.bus.parallel.flags & | ||
923 | V4L2_MBUS_PCLK_SAMPLE_RISING); | ||
924 | |||
925 | done: | ||
926 | of_node_put(np); | ||
927 | return pdata; | ||
928 | } | ||
929 | |||
879 | static int mt9v032_probe(struct i2c_client *client, | 930 | static int mt9v032_probe(struct i2c_client *client, |
880 | const struct i2c_device_id *did) | 931 | const struct i2c_device_id *did) |
881 | { | 932 | { |
882 | struct mt9v032_platform_data *pdata = client->dev.platform_data; | 933 | struct mt9v032_platform_data *pdata = mt9v032_get_pdata(client); |
883 | struct mt9v032 *mt9v032; | 934 | struct mt9v032 *mt9v032; |
884 | unsigned int i; | 935 | unsigned int i; |
885 | int ret; | 936 | int ret; |
@@ -961,9 +1012,12 @@ static int mt9v032_probe(struct i2c_client *client, | |||
961 | 1012 | ||
962 | mt9v032->subdev.ctrl_handler = &mt9v032->ctrls; | 1013 | mt9v032->subdev.ctrl_handler = &mt9v032->ctrls; |
963 | 1014 | ||
964 | if (mt9v032->ctrls.error) | 1015 | if (mt9v032->ctrls.error) { |
965 | printk(KERN_INFO "%s: control initialization error %d\n", | 1016 | dev_err(&client->dev, "control initialization error %d\n", |
966 | __func__, mt9v032->ctrls.error); | 1017 | mt9v032->ctrls.error); |
1018 | ret = mt9v032->ctrls.error; | ||
1019 | goto err; | ||
1020 | } | ||
967 | 1021 | ||
968 | mt9v032->crop.left = MT9V032_COLUMN_START_DEF; | 1022 | mt9v032->crop.left = MT9V032_COLUMN_START_DEF; |
969 | mt9v032->crop.top = MT9V032_ROW_START_DEF; | 1023 | mt9v032->crop.top = MT9V032_ROW_START_DEF; |
@@ -1016,7 +1070,6 @@ static int mt9v032_remove(struct i2c_client *client) | |||
1016 | 1070 | ||
1017 | v4l2_async_unregister_subdev(subdev); | 1071 | v4l2_async_unregister_subdev(subdev); |
1018 | v4l2_ctrl_handler_free(&mt9v032->ctrls); | 1072 | v4l2_ctrl_handler_free(&mt9v032->ctrls); |
1019 | v4l2_device_unregister_subdev(subdev); | ||
1020 | media_entity_cleanup(&subdev->entity); | 1073 | media_entity_cleanup(&subdev->entity); |
1021 | 1074 | ||
1022 | return 0; | 1075 | return 0; |
@@ -1035,9 +1088,25 @@ static const struct i2c_device_id mt9v032_id[] = { | |||
1035 | }; | 1088 | }; |
1036 | MODULE_DEVICE_TABLE(i2c, mt9v032_id); | 1089 | MODULE_DEVICE_TABLE(i2c, mt9v032_id); |
1037 | 1090 | ||
1091 | #if IS_ENABLED(CONFIG_OF) | ||
1092 | static const struct of_device_id mt9v032_of_match[] = { | ||
1093 | { .compatible = "aptina,mt9v022" }, | ||
1094 | { .compatible = "aptina,mt9v022m" }, | ||
1095 | { .compatible = "aptina,mt9v024" }, | ||
1096 | { .compatible = "aptina,mt9v024m" }, | ||
1097 | { .compatible = "aptina,mt9v032" }, | ||
1098 | { .compatible = "aptina,mt9v032m" }, | ||
1099 | { .compatible = "aptina,mt9v034" }, | ||
1100 | { .compatible = "aptina,mt9v034m" }, | ||
1101 | { /* Sentinel */ } | ||
1102 | }; | ||
1103 | MODULE_DEVICE_TABLE(of, mt9v032_of_match); | ||
1104 | #endif | ||
1105 | |||
1038 | static struct i2c_driver mt9v032_driver = { | 1106 | static struct i2c_driver mt9v032_driver = { |
1039 | .driver = { | 1107 | .driver = { |
1040 | .name = "mt9v032", | 1108 | .name = "mt9v032", |
1109 | .of_match_table = of_match_ptr(mt9v032_of_match), | ||
1041 | }, | 1110 | }, |
1042 | .probe = mt9v032_probe, | 1111 | .probe = mt9v032_probe, |
1043 | .remove = mt9v032_remove, | 1112 | .remove = mt9v032_remove, |