diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2011-09-09 12:39:20 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-03 16:29:03 -0400 |
commit | 2f0babb7e43278247df512263581c4738afa4cbc (patch) | |
tree | b09a18f6f7756c9f793e36c26db17f4cfc9a558e /drivers/media | |
parent | 1a99b972a86ba9c3984c042f7f641458ad4812d0 (diff) |
[media] V4L: soc-camera: make (almost) all client drivers re-usable outside of the framework
The most important change in this patch is direct linking to struct
soc_camera_link via the client->dev.platform_data pointer. This makes most
of the soc-camera client drivers also usable outside of the soc-camera
framework. After this change all what is needed for these drivers to
function are inclusions of soc-camera headers for some convenience macros,
suitably configured platform data, which is anyway always required, and
loaded soc-camera core module for library functions. If desired, these
library functions can be made generic in the future and moved to a more
neutral location.
The only two client drivers, that still depend on soc-camera are:
mt9t031: it uses struct video_device for its PM. Since no hardware is
available, alternative methods cannot be tested.
ov6650: it uses struct soc_camera_device to pass its sense data back to
the bridge driver. A generic v4l2-subdevice approach should be developed
to perform this.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/mt9t031.c | 29 | ||||
-rw-r--r-- | drivers/media/video/ov6650.c | 2 | ||||
-rw-r--r-- | drivers/media/video/soc_camera.c | 11 | ||||
-rw-r--r-- | drivers/media/video/tw9910.c | 50 |
4 files changed, 65 insertions, 27 deletions
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 95cd602ae4ec..0226486d59be 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c | |||
@@ -22,6 +22,13 @@ | |||
22 | #include <media/v4l2-ctrls.h> | 22 | #include <media/v4l2-ctrls.h> |
23 | 23 | ||
24 | /* | 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 | */ | ||
30 | |||
31 | /* | ||
25 | * mt9t031 i2c address 0x5d | 32 | * mt9t031 i2c address 0x5d |
26 | * The platform has to define i2c_board_info and link to it from | 33 | * The platform has to define i2c_board_info and link to it from |
27 | * struct soc_camera_link | 34 | * struct soc_camera_link |
@@ -606,6 +613,19 @@ static struct device_type mt9t031_dev_type = { | |||
606 | .pm = &mt9t031_dev_pm_ops, | 613 | .pm = &mt9t031_dev_pm_ops, |
607 | }; | 614 | }; |
608 | 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 | |||
609 | /* | 629 | /* |
610 | * 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 |
611 | * 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 |
@@ -613,7 +633,6 @@ static struct device_type mt9t031_dev_type = { | |||
613 | static int mt9t031_video_probe(struct i2c_client *client) | 633 | static int mt9t031_video_probe(struct i2c_client *client) |
614 | { | 634 | { |
615 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 635 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
616 | struct video_device *vdev = soc_camera_i2c_to_vdev(client); | ||
617 | s32 data; | 636 | s32 data; |
618 | int ret; | 637 | int ret; |
619 | 638 | ||
@@ -637,12 +656,11 @@ static int mt9t031_video_probe(struct i2c_client *client) | |||
637 | dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data); | 656 | dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data); |
638 | 657 | ||
639 | ret = mt9t031_idle(client); | 658 | ret = mt9t031_idle(client); |
640 | if (ret < 0) { | 659 | if (ret < 0) |
641 | dev_err(&client->dev, "Failed to initialise the camera\n"); | 660 | dev_err(&client->dev, "Failed to initialise the camera\n"); |
642 | } else { | 661 | else |
643 | vdev->dev.type = &mt9t031_dev_type; | ||
644 | v4l2_ctrl_handler_setup(&mt9t031->hdl); | 662 | v4l2_ctrl_handler_setup(&mt9t031->hdl); |
645 | } | 663 | |
646 | return ret; | 664 | return ret; |
647 | } | 665 | } |
648 | 666 | ||
@@ -663,6 +681,7 @@ static const struct v4l2_ctrl_ops mt9t031_ctrl_ops = { | |||
663 | 681 | ||
664 | static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { | 682 | static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { |
665 | .g_chip_ident = mt9t031_g_chip_ident, | 683 | .g_chip_ident = mt9t031_g_chip_ident, |
684 | .s_power = mt9t031_s_power, | ||
666 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 685 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
667 | .g_register = mt9t031_g_register, | 686 | .g_register = mt9t031_g_register, |
668 | .s_register = mt9t031_s_register, | 687 | .s_register = mt9t031_s_register, |
diff --git a/drivers/media/video/ov6650.c b/drivers/media/video/ov6650.c index f060eaaf916f..eb296f9e69f4 100644 --- a/drivers/media/video/ov6650.c +++ b/drivers/media/video/ov6650.c | |||
@@ -541,7 +541,7 @@ static u8 to_clkrc(struct v4l2_fract *timeperframe, | |||
541 | static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) | 541 | static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) |
542 | { | 542 | { |
543 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 543 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
544 | struct soc_camera_device *icd = client->dev.platform_data; | 544 | struct soc_camera_device *icd = (struct soc_camera_device *)sd->grp_id; |
545 | struct soc_camera_sense *sense = icd->sense; | 545 | struct soc_camera_sense *sense = icd->sense; |
546 | struct ov6650 *priv = to_ov6650(client); | 546 | struct ov6650 *priv = to_ov6650(client); |
547 | bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect); | 547 | bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect); |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 9a62ed08d86a..b72580c38957 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -249,6 +249,14 @@ static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) | |||
249 | return v4l2_subdev_call(sd, core, s_std, *a); | 249 | return v4l2_subdev_call(sd, core, s_std, *a); |
250 | } | 250 | } |
251 | 251 | ||
252 | static int soc_camera_g_std(struct file *file, void *priv, v4l2_std_id *a) | ||
253 | { | ||
254 | struct soc_camera_device *icd = file->private_data; | ||
255 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
256 | |||
257 | return v4l2_subdev_call(sd, core, g_std, a); | ||
258 | } | ||
259 | |||
252 | static int soc_camera_enum_fsizes(struct file *file, void *fh, | 260 | static int soc_camera_enum_fsizes(struct file *file, void *fh, |
253 | struct v4l2_frmsizeenum *fsize) | 261 | struct v4l2_frmsizeenum *fsize) |
254 | { | 262 | { |
@@ -977,7 +985,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
977 | goto ei2cga; | 985 | goto ei2cga; |
978 | } | 986 | } |
979 | 987 | ||
980 | icl->board_info->platform_data = icd; | 988 | icl->board_info->platform_data = icl; |
981 | 989 | ||
982 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, | 990 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, |
983 | icl->board_info, NULL); | 991 | icl->board_info, NULL); |
@@ -1376,6 +1384,7 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { | |||
1376 | .vidioc_g_input = soc_camera_g_input, | 1384 | .vidioc_g_input = soc_camera_g_input, |
1377 | .vidioc_s_input = soc_camera_s_input, | 1385 | .vidioc_s_input = soc_camera_s_input, |
1378 | .vidioc_s_std = soc_camera_s_std, | 1386 | .vidioc_s_std = soc_camera_s_std, |
1387 | .vidioc_g_std = soc_camera_g_std, | ||
1379 | .vidioc_enum_framesizes = soc_camera_enum_fsizes, | 1388 | .vidioc_enum_framesizes = soc_camera_enum_fsizes, |
1380 | .vidioc_reqbufs = soc_camera_reqbufs, | 1389 | .vidioc_reqbufs = soc_camera_reqbufs, |
1381 | .vidioc_querybuf = soc_camera_querybuf, | 1390 | .vidioc_querybuf = soc_camera_querybuf, |
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 5a3722b756c7..efce5371915e 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c | |||
@@ -230,6 +230,7 @@ struct tw9910_priv { | |||
230 | struct v4l2_subdev subdev; | 230 | struct v4l2_subdev subdev; |
231 | struct tw9910_video_info *info; | 231 | struct tw9910_video_info *info; |
232 | const struct tw9910_scale_ctrl *scale; | 232 | const struct tw9910_scale_ctrl *scale; |
233 | v4l2_std_id norm; | ||
233 | u32 revision; | 234 | u32 revision; |
234 | }; | 235 | }; |
235 | 236 | ||
@@ -421,12 +422,11 @@ static int tw9910_power(struct i2c_client *client, int enable) | |||
421 | return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2); | 422 | return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2); |
422 | } | 423 | } |
423 | 424 | ||
424 | static const struct tw9910_scale_ctrl *tw9910_select_norm(struct soc_camera_device *icd, | 425 | static const struct tw9910_scale_ctrl *tw9910_select_norm(v4l2_std_id norm, |
425 | u32 width, u32 height) | 426 | u32 width, u32 height) |
426 | { | 427 | { |
427 | const struct tw9910_scale_ctrl *scale; | 428 | const struct tw9910_scale_ctrl *scale; |
428 | const struct tw9910_scale_ctrl *ret = NULL; | 429 | const struct tw9910_scale_ctrl *ret = NULL; |
429 | v4l2_std_id norm = icd->vdev->current_norm; | ||
430 | __u32 diff = 0xffffffff, tmp; | 430 | __u32 diff = 0xffffffff, tmp; |
431 | int size, i; | 431 | int size, i; |
432 | 432 | ||
@@ -495,14 +495,27 @@ static int tw9910_s_stream(struct v4l2_subdev *sd, int enable) | |||
495 | return tw9910_power(client, enable); | 495 | return tw9910_power(client, enable); |
496 | } | 496 | } |
497 | 497 | ||
498 | static int tw9910_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm) | ||
499 | { | ||
500 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
501 | struct tw9910_priv *priv = to_tw9910(client); | ||
502 | |||
503 | *norm = priv->norm; | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
498 | static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) | 508 | static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) |
499 | { | 509 | { |
500 | int ret = -EINVAL; | 510 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
511 | struct tw9910_priv *priv = to_tw9910(client); | ||
501 | 512 | ||
502 | if (norm & (V4L2_STD_NTSC | V4L2_STD_PAL)) | 513 | if (!(norm & (V4L2_STD_NTSC | V4L2_STD_PAL))) |
503 | ret = 0; | 514 | return -EINVAL; |
504 | 515 | ||
505 | return ret; | 516 | priv->norm = norm; |
517 | |||
518 | return 0; | ||
506 | } | 519 | } |
507 | 520 | ||
508 | static int tw9910_g_chip_ident(struct v4l2_subdev *sd, | 521 | static int tw9910_g_chip_ident(struct v4l2_subdev *sd, |
@@ -557,14 +570,13 @@ static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height) | |||
557 | { | 570 | { |
558 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 571 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
559 | struct tw9910_priv *priv = to_tw9910(client); | 572 | struct tw9910_priv *priv = to_tw9910(client); |
560 | struct soc_camera_device *icd = client->dev.platform_data; | ||
561 | int ret = -EINVAL; | 573 | int ret = -EINVAL; |
562 | u8 val; | 574 | u8 val; |
563 | 575 | ||
564 | /* | 576 | /* |
565 | * select suitable norm | 577 | * select suitable norm |
566 | */ | 578 | */ |
567 | priv->scale = tw9910_select_norm(icd, *width, *height); | 579 | priv->scale = tw9910_select_norm(priv->norm, *width, *height); |
568 | if (!priv->scale) | 580 | if (!priv->scale) |
569 | goto tw9910_set_fmt_error; | 581 | goto tw9910_set_fmt_error; |
570 | 582 | ||
@@ -642,11 +654,11 @@ tw9910_set_fmt_error: | |||
642 | static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 654 | static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
643 | { | 655 | { |
644 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 656 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
645 | struct soc_camera_device *icd = client->dev.platform_data; | 657 | struct tw9910_priv *priv = to_tw9910(client); |
646 | 658 | ||
647 | a->c.left = 0; | 659 | a->c.left = 0; |
648 | a->c.top = 0; | 660 | a->c.top = 0; |
649 | if (icd->vdev->current_norm & V4L2_STD_NTSC) { | 661 | if (priv->norm & V4L2_STD_NTSC) { |
650 | a->c.width = 640; | 662 | a->c.width = 640; |
651 | a->c.height = 480; | 663 | a->c.height = 480; |
652 | } else { | 664 | } else { |
@@ -661,11 +673,11 @@ static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
661 | static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | 673 | static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) |
662 | { | 674 | { |
663 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 675 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
664 | struct soc_camera_device *icd = client->dev.platform_data; | 676 | struct tw9910_priv *priv = to_tw9910(client); |
665 | 677 | ||
666 | a->bounds.left = 0; | 678 | a->bounds.left = 0; |
667 | a->bounds.top = 0; | 679 | a->bounds.top = 0; |
668 | if (icd->vdev->current_norm & V4L2_STD_NTSC) { | 680 | if (priv->norm & V4L2_STD_NTSC) { |
669 | a->bounds.width = 640; | 681 | a->bounds.width = 640; |
670 | a->bounds.height = 480; | 682 | a->bounds.height = 480; |
671 | } else { | 683 | } else { |
@@ -732,7 +744,7 @@ static int tw9910_try_fmt(struct v4l2_subdev *sd, | |||
732 | struct v4l2_mbus_framefmt *mf) | 744 | struct v4l2_mbus_framefmt *mf) |
733 | { | 745 | { |
734 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 746 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
735 | struct soc_camera_device *icd = client->dev.platform_data; | 747 | struct tw9910_priv *priv = to_tw9910(client); |
736 | const struct tw9910_scale_ctrl *scale; | 748 | const struct tw9910_scale_ctrl *scale; |
737 | 749 | ||
738 | if (V4L2_FIELD_ANY == mf->field) { | 750 | if (V4L2_FIELD_ANY == mf->field) { |
@@ -748,7 +760,7 @@ static int tw9910_try_fmt(struct v4l2_subdev *sd, | |||
748 | /* | 760 | /* |
749 | * select suitable norm | 761 | * select suitable norm |
750 | */ | 762 | */ |
751 | scale = tw9910_select_norm(icd, mf->width, mf->height); | 763 | scale = tw9910_select_norm(priv->norm, mf->width, mf->height); |
752 | if (!scale) | 764 | if (!scale) |
753 | return -EINVAL; | 765 | return -EINVAL; |
754 | 766 | ||
@@ -758,8 +770,7 @@ static int tw9910_try_fmt(struct v4l2_subdev *sd, | |||
758 | return 0; | 770 | return 0; |
759 | } | 771 | } |
760 | 772 | ||
761 | static int tw9910_video_probe(struct soc_camera_device *icd, | 773 | static int tw9910_video_probe(struct i2c_client *client) |
762 | struct i2c_client *client) | ||
763 | { | 774 | { |
764 | struct tw9910_priv *priv = to_tw9910(client); | 775 | struct tw9910_priv *priv = to_tw9910(client); |
765 | s32 id; | 776 | s32 id; |
@@ -792,8 +803,7 @@ static int tw9910_video_probe(struct soc_camera_device *icd, | |||
792 | dev_info(&client->dev, | 803 | dev_info(&client->dev, |
793 | "tw9910 Product ID %0x:%0x\n", id, priv->revision); | 804 | "tw9910 Product ID %0x:%0x\n", id, priv->revision); |
794 | 805 | ||
795 | icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; | 806 | priv->norm = V4L2_STD_NTSC; |
796 | icd->vdev->current_norm = V4L2_STD_NTSC; | ||
797 | 807 | ||
798 | return 0; | 808 | return 0; |
799 | } | 809 | } |
@@ -801,6 +811,7 @@ static int tw9910_video_probe(struct soc_camera_device *icd, | |||
801 | static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { | 811 | static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { |
802 | .g_chip_ident = tw9910_g_chip_ident, | 812 | .g_chip_ident = tw9910_g_chip_ident, |
803 | .s_std = tw9910_s_std, | 813 | .s_std = tw9910_s_std, |
814 | .g_std = tw9910_g_std, | ||
804 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 815 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
805 | .g_register = tw9910_g_register, | 816 | .g_register = tw9910_g_register, |
806 | .s_register = tw9910_s_register, | 817 | .s_register = tw9910_s_register, |
@@ -883,7 +894,6 @@ static int tw9910_probe(struct i2c_client *client, | |||
883 | { | 894 | { |
884 | struct tw9910_priv *priv; | 895 | struct tw9910_priv *priv; |
885 | struct tw9910_video_info *info; | 896 | struct tw9910_video_info *info; |
886 | struct soc_camera_device *icd = client->dev.platform_data; | ||
887 | struct i2c_adapter *adapter = | 897 | struct i2c_adapter *adapter = |
888 | to_i2c_adapter(client->dev.parent); | 898 | to_i2c_adapter(client->dev.parent); |
889 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); | 899 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); |
@@ -911,7 +921,7 @@ static int tw9910_probe(struct i2c_client *client, | |||
911 | 921 | ||
912 | v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); | 922 | v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); |
913 | 923 | ||
914 | ret = tw9910_video_probe(icd, client); | 924 | ret = tw9910_video_probe(client); |
915 | if (ret) | 925 | if (ret) |
916 | kfree(priv); | 926 | kfree(priv); |
917 | 927 | ||