aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c/mt9v032.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-04-21 05:12:35 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-04-21 05:12:35 -0400
commit676ee36be04985062522804c2de04f0764212be6 (patch)
tree781df135c5a91a04decad1b7d53b5a925dc11522 /drivers/media/i2c/mt9v032.c
parentb18042a673e88c9457a6d1716219c2367ca447b0 (diff)
parente183201b9e917daf2530b637b2f34f1d5afb934d (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.c115
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
373static struct v4l2_mbus_framefmt * 376static 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
387static struct v4l2_rect * 390static 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
450static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev, 453static 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
461static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev, 464static 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
476static int mt9v032_get_format(struct v4l2_subdev *subdev, 479static 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
511static int mt9v032_set_format(struct v4l2_subdev *subdev, 514static 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
555static int mt9v032_get_selection(struct v4l2_subdev *subdev, 558static 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
568static int mt9v032_set_selection(struct v4l2_subdev *subdev, 571static 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
882static struct mt9v032_platform_data *
883mt9v032_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
925done:
926 of_node_put(np);
927 return pdata;
928}
929
879static int mt9v032_probe(struct i2c_client *client, 930static 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};
1036MODULE_DEVICE_TABLE(i2c, mt9v032_id); 1089MODULE_DEVICE_TABLE(i2c, mt9v032_id);
1037 1090
1091#if IS_ENABLED(CONFIG_OF)
1092static 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};
1103MODULE_DEVICE_TABLE(of, mt9v032_of_match);
1104#endif
1105
1038static struct i2c_driver mt9v032_driver = { 1106static 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,