diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2009-08-25 10:43:33 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-18 23:18:35 -0400 |
commit | 979ea1ddf80ac7383acdea03471355ca62702539 (patch) | |
tree | 2ee4c73eb672c1ee8167ed7e0906bac6f3b00e69 /drivers/media/video/ov772x.c | |
parent | 0bab829de1ab60d8c3cbf7e402192bb9446840b7 (diff) |
V4L/DVB (12510): soc-camera: (partially) convert to v4l2-(sub)dev API
Convert the soc-camera framework to use the v4l2-(sub)dev API. Start using
v4l2-subdev operations. Only a part of the interface between the
soc_camera core, soc_camera host drivers on one side and soc_camera device
drivers on the other side is replaced so far. The rest of the interface
will be replaced in incremental steps, and will require extensions and,
possibly, modifications to the v4l2-subdev code.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/ov772x.c')
-rw-r--r-- | drivers/media/video/ov772x.c | 169 |
1 files changed, 68 insertions, 101 deletions
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 3ea650d55b17..119159773a68 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/videodev2.h> | 23 | #include <linux/videodev2.h> |
24 | #include <media/v4l2-chip-ident.h> | 24 | #include <media/v4l2-chip-ident.h> |
25 | #include <media/v4l2-common.h> | 25 | #include <media/v4l2-subdev.h> |
26 | #include <media/soc_camera.h> | 26 | #include <media/soc_camera.h> |
27 | #include <media/ov772x.h> | 27 | #include <media/ov772x.h> |
28 | 28 | ||
@@ -398,6 +398,7 @@ struct ov772x_win_size { | |||
398 | }; | 398 | }; |
399 | 399 | ||
400 | struct ov772x_priv { | 400 | struct ov772x_priv { |
401 | struct v4l2_subdev subdev; | ||
401 | struct ov772x_camera_info *info; | 402 | struct ov772x_camera_info *info; |
402 | const struct ov772x_color_format *fmt; | 403 | const struct ov772x_color_format *fmt; |
403 | const struct ov772x_win_size *win; | 404 | const struct ov772x_win_size *win; |
@@ -575,6 +576,11 @@ static const struct v4l2_queryctrl ov772x_controls[] = { | |||
575 | * general function | 576 | * general function |
576 | */ | 577 | */ |
577 | 578 | ||
579 | static struct ov772x_priv *to_ov772x(const struct i2c_client *client) | ||
580 | { | ||
581 | return container_of(i2c_get_clientdata(client), struct ov772x_priv, subdev); | ||
582 | } | ||
583 | |||
578 | static int ov772x_write_array(struct i2c_client *client, | 584 | static int ov772x_write_array(struct i2c_client *client, |
579 | const struct regval_list *vals) | 585 | const struct regval_list *vals) |
580 | { | 586 | { |
@@ -615,61 +621,29 @@ static int ov772x_reset(struct i2c_client *client) | |||
615 | * soc_camera_ops function | 621 | * soc_camera_ops function |
616 | */ | 622 | */ |
617 | 623 | ||
618 | static int ov772x_init(struct soc_camera_device *icd) | 624 | static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) |
619 | { | 625 | { |
620 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 626 | struct i2c_client *client = sd->priv; |
621 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 627 | struct ov772x_priv *priv = to_ov772x(client); |
622 | int ret = 0; | ||
623 | 628 | ||
624 | if (icl->power) { | 629 | if (!enable) { |
625 | ret = icl->power(&client->dev, 1); | 630 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); |
626 | if (ret < 0) | 631 | return 0; |
627 | return ret; | ||
628 | } | 632 | } |
629 | 633 | ||
630 | if (icl->reset) | ||
631 | ret = icl->reset(&client->dev); | ||
632 | |||
633 | return ret; | ||
634 | } | ||
635 | |||
636 | static int ov772x_release(struct soc_camera_device *icd) | ||
637 | { | ||
638 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
639 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
640 | int ret = 0; | ||
641 | |||
642 | if (icl->power) | ||
643 | ret = icl->power(&client->dev, 0); | ||
644 | |||
645 | return ret; | ||
646 | } | ||
647 | |||
648 | static int ov772x_start_capture(struct soc_camera_device *icd) | ||
649 | { | ||
650 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
651 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
652 | |||
653 | if (!priv->win || !priv->fmt) { | 634 | if (!priv->win || !priv->fmt) { |
654 | dev_err(&icd->dev, "norm or win select error\n"); | 635 | dev_err(&client->dev, "norm or win select error\n"); |
655 | return -EPERM; | 636 | return -EPERM; |
656 | } | 637 | } |
657 | 638 | ||
658 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); | 639 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); |
659 | 640 | ||
660 | dev_dbg(&icd->dev, | 641 | dev_dbg(&client->dev, |
661 | "format %s, win %s\n", priv->fmt->name, priv->win->name); | 642 | "format %s, win %s\n", priv->fmt->name, priv->win->name); |
662 | 643 | ||
663 | return 0; | 644 | return 0; |
664 | } | 645 | } |
665 | 646 | ||
666 | static int ov772x_stop_capture(struct soc_camera_device *icd) | ||
667 | { | ||
668 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
669 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); | ||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | static int ov772x_set_bus_param(struct soc_camera_device *icd, | 647 | static int ov772x_set_bus_param(struct soc_camera_device *icd, |
674 | unsigned long flags) | 648 | unsigned long flags) |
675 | { | 649 | { |
@@ -688,11 +662,10 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) | |||
688 | return soc_camera_apply_sensor_flags(icl, flags); | 662 | return soc_camera_apply_sensor_flags(icl, flags); |
689 | } | 663 | } |
690 | 664 | ||
691 | static int ov772x_get_control(struct soc_camera_device *icd, | 665 | static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
692 | struct v4l2_control *ctrl) | ||
693 | { | 666 | { |
694 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 667 | struct i2c_client *client = sd->priv; |
695 | struct ov772x_priv *priv = i2c_get_clientdata(client); | 668 | struct ov772x_priv *priv = to_ov772x(client); |
696 | 669 | ||
697 | switch (ctrl->id) { | 670 | switch (ctrl->id) { |
698 | case V4L2_CID_VFLIP: | 671 | case V4L2_CID_VFLIP: |
@@ -705,11 +678,10 @@ static int ov772x_get_control(struct soc_camera_device *icd, | |||
705 | return 0; | 678 | return 0; |
706 | } | 679 | } |
707 | 680 | ||
708 | static int ov772x_set_control(struct soc_camera_device *icd, | 681 | static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
709 | struct v4l2_control *ctrl) | ||
710 | { | 682 | { |
711 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 683 | struct i2c_client *client = sd->priv; |
712 | struct ov772x_priv *priv = i2c_get_clientdata(client); | 684 | struct ov772x_priv *priv = to_ov772x(client); |
713 | int ret = 0; | 685 | int ret = 0; |
714 | u8 val; | 686 | u8 val; |
715 | 687 | ||
@@ -733,11 +705,11 @@ static int ov772x_set_control(struct soc_camera_device *icd, | |||
733 | return ret; | 705 | return ret; |
734 | } | 706 | } |
735 | 707 | ||
736 | static int ov772x_get_chip_id(struct soc_camera_device *icd, | 708 | static int ov772x_g_chip_ident(struct v4l2_subdev *sd, |
737 | struct v4l2_dbg_chip_ident *id) | 709 | struct v4l2_dbg_chip_ident *id) |
738 | { | 710 | { |
739 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 711 | struct i2c_client *client = sd->priv; |
740 | struct ov772x_priv *priv = i2c_get_clientdata(client); | 712 | struct ov772x_priv *priv = to_ov772x(client); |
741 | 713 | ||
742 | id->ident = priv->model; | 714 | id->ident = priv->model; |
743 | id->revision = 0; | 715 | id->revision = 0; |
@@ -746,10 +718,10 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, | |||
746 | } | 718 | } |
747 | 719 | ||
748 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 720 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
749 | static int ov772x_get_register(struct soc_camera_device *icd, | 721 | static int ov772x_g_register(struct v4l2_subdev *sd, |
750 | struct v4l2_dbg_register *reg) | 722 | struct v4l2_dbg_register *reg) |
751 | { | 723 | { |
752 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 724 | struct i2c_client *client = sd->priv; |
753 | int ret; | 725 | int ret; |
754 | 726 | ||
755 | reg->size = 1; | 727 | reg->size = 1; |
@@ -765,10 +737,10 @@ static int ov772x_get_register(struct soc_camera_device *icd, | |||
765 | return 0; | 737 | return 0; |
766 | } | 738 | } |
767 | 739 | ||
768 | static int ov772x_set_register(struct soc_camera_device *icd, | 740 | static int ov772x_s_register(struct v4l2_subdev *sd, |
769 | struct v4l2_dbg_register *reg) | 741 | struct v4l2_dbg_register *reg) |
770 | { | 742 | { |
771 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 743 | struct i2c_client *client = sd->priv; |
772 | 744 | ||
773 | if (reg->reg > 0xff || | 745 | if (reg->reg > 0xff || |
774 | reg->val > 0xff) | 746 | reg->val > 0xff) |
@@ -778,8 +750,7 @@ static int ov772x_set_register(struct soc_camera_device *icd, | |||
778 | } | 750 | } |
779 | #endif | 751 | #endif |
780 | 752 | ||
781 | static const struct ov772x_win_size* | 753 | static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) |
782 | ov772x_select_win(u32 width, u32 height) | ||
783 | { | 754 | { |
784 | __u32 diff; | 755 | __u32 diff; |
785 | const struct ov772x_win_size *win; | 756 | const struct ov772x_win_size *win; |
@@ -798,11 +769,10 @@ ov772x_select_win(u32 width, u32 height) | |||
798 | return win; | 769 | return win; |
799 | } | 770 | } |
800 | 771 | ||
801 | static int ov772x_set_params(struct soc_camera_device *icd, | 772 | static int ov772x_set_params(struct i2c_client *client, |
802 | u32 width, u32 height, u32 pixfmt) | 773 | u32 width, u32 height, u32 pixfmt) |
803 | { | 774 | { |
804 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 775 | struct ov772x_priv *priv = to_ov772x(client); |
805 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
806 | int ret = -EINVAL; | 776 | int ret = -EINVAL; |
807 | u8 val; | 777 | u8 val; |
808 | int i; | 778 | int i; |
@@ -817,7 +787,6 @@ static int ov772x_set_params(struct soc_camera_device *icd, | |||
817 | break; | 787 | break; |
818 | } | 788 | } |
819 | } | 789 | } |
820 | dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i); | ||
821 | if (!priv->fmt) | 790 | if (!priv->fmt) |
822 | goto ov772x_set_fmt_error; | 791 | goto ov772x_set_fmt_error; |
823 | 792 | ||
@@ -939,26 +908,26 @@ static int ov772x_set_crop(struct soc_camera_device *icd, | |||
939 | struct v4l2_rect *rect) | 908 | struct v4l2_rect *rect) |
940 | { | 909 | { |
941 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 910 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
942 | struct ov772x_priv *priv = i2c_get_clientdata(client); | 911 | struct ov772x_priv *priv = to_ov772x(client); |
943 | 912 | ||
944 | if (!priv->fmt) | 913 | if (!priv->fmt) |
945 | return -EINVAL; | 914 | return -EINVAL; |
946 | 915 | ||
947 | return ov772x_set_params(icd, rect->width, rect->height, | 916 | return ov772x_set_params(client, rect->width, rect->height, |
948 | priv->fmt->fourcc); | 917 | priv->fmt->fourcc); |
949 | } | 918 | } |
950 | 919 | ||
951 | static int ov772x_set_fmt(struct soc_camera_device *icd, | 920 | static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) |
952 | struct v4l2_format *f) | ||
953 | { | 921 | { |
922 | struct i2c_client *client = sd->priv; | ||
954 | struct v4l2_pix_format *pix = &f->fmt.pix; | 923 | struct v4l2_pix_format *pix = &f->fmt.pix; |
955 | 924 | ||
956 | return ov772x_set_params(icd, pix->width, pix->height, | 925 | return ov772x_set_params(client, pix->width, pix->height, |
957 | pix->pixelformat); | 926 | pix->pixelformat); |
958 | } | 927 | } |
959 | 928 | ||
960 | static int ov772x_try_fmt(struct soc_camera_device *icd, | 929 | static int ov772x_try_fmt(struct v4l2_subdev *sd, |
961 | struct v4l2_format *f) | 930 | struct v4l2_format *f) |
962 | { | 931 | { |
963 | struct v4l2_pix_format *pix = &f->fmt.pix; | 932 | struct v4l2_pix_format *pix = &f->fmt.pix; |
964 | const struct ov772x_win_size *win; | 933 | const struct ov772x_win_size *win; |
@@ -978,10 +947,9 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, | |||
978 | static int ov772x_video_probe(struct soc_camera_device *icd, | 947 | static int ov772x_video_probe(struct soc_camera_device *icd, |
979 | struct i2c_client *client) | 948 | struct i2c_client *client) |
980 | { | 949 | { |
981 | struct ov772x_priv *priv = i2c_get_clientdata(client); | 950 | struct ov772x_priv *priv = to_ov772x(client); |
982 | u8 pid, ver; | 951 | u8 pid, ver; |
983 | const char *devname; | 952 | const char *devname; |
984 | int ret; | ||
985 | 953 | ||
986 | /* | 954 | /* |
987 | * We must have a parent by now. And it cannot be a wrong one. | 955 | * We must have a parent by now. And it cannot be a wrong one. |
@@ -1003,11 +971,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, | |||
1003 | icd->formats = ov772x_fmt_lists; | 971 | icd->formats = ov772x_fmt_lists; |
1004 | icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); | 972 | icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); |
1005 | 973 | ||
1006 | /* Switch master clock on */ | ||
1007 | ret = soc_camera_video_start(icd, &client->dev); | ||
1008 | if (ret) | ||
1009 | return ret; | ||
1010 | |||
1011 | /* | 974 | /* |
1012 | * check and show product ID and manufacturer ID | 975 | * check and show product ID and manufacturer ID |
1013 | */ | 976 | */ |
@@ -1026,8 +989,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd, | |||
1026 | default: | 989 | default: |
1027 | dev_err(&icd->dev, | 990 | dev_err(&icd->dev, |
1028 | "Product ID error %x:%x\n", pid, ver); | 991 | "Product ID error %x:%x\n", pid, ver); |
1029 | ret = -ENODEV; | 992 | return -ENODEV; |
1030 | goto ever; | ||
1031 | } | 993 | } |
1032 | 994 | ||
1033 | dev_info(&icd->dev, | 995 | dev_info(&icd->dev, |
@@ -1038,34 +1000,38 @@ static int ov772x_video_probe(struct soc_camera_device *icd, | |||
1038 | i2c_smbus_read_byte_data(client, MIDH), | 1000 | i2c_smbus_read_byte_data(client, MIDH), |
1039 | i2c_smbus_read_byte_data(client, MIDL)); | 1001 | i2c_smbus_read_byte_data(client, MIDL)); |
1040 | 1002 | ||
1041 | soc_camera_video_stop(icd); | 1003 | return 0; |
1042 | |||
1043 | ever: | ||
1044 | return ret; | ||
1045 | } | 1004 | } |
1046 | 1005 | ||
1047 | static struct soc_camera_ops ov772x_ops = { | 1006 | static struct soc_camera_ops ov772x_ops = { |
1048 | .owner = THIS_MODULE, | ||
1049 | .init = ov772x_init, | ||
1050 | .release = ov772x_release, | ||
1051 | .start_capture = ov772x_start_capture, | ||
1052 | .stop_capture = ov772x_stop_capture, | ||
1053 | .set_crop = ov772x_set_crop, | 1007 | .set_crop = ov772x_set_crop, |
1054 | .set_fmt = ov772x_set_fmt, | ||
1055 | .try_fmt = ov772x_try_fmt, | ||
1056 | .set_bus_param = ov772x_set_bus_param, | 1008 | .set_bus_param = ov772x_set_bus_param, |
1057 | .query_bus_param = ov772x_query_bus_param, | 1009 | .query_bus_param = ov772x_query_bus_param, |
1058 | .controls = ov772x_controls, | 1010 | .controls = ov772x_controls, |
1059 | .num_controls = ARRAY_SIZE(ov772x_controls), | 1011 | .num_controls = ARRAY_SIZE(ov772x_controls), |
1060 | .get_control = ov772x_get_control, | 1012 | }; |
1061 | .set_control = ov772x_set_control, | 1013 | |
1062 | .get_chip_id = ov772x_get_chip_id, | 1014 | static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { |
1015 | .g_ctrl = ov772x_g_ctrl, | ||
1016 | .s_ctrl = ov772x_s_ctrl, | ||
1017 | .g_chip_ident = ov772x_g_chip_ident, | ||
1063 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1018 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1064 | .get_register = ov772x_get_register, | 1019 | .g_register = ov772x_g_register, |
1065 | .set_register = ov772x_set_register, | 1020 | .s_register = ov772x_s_register, |
1066 | #endif | 1021 | #endif |
1067 | }; | 1022 | }; |
1068 | 1023 | ||
1024 | static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { | ||
1025 | .s_stream = ov772x_s_stream, | ||
1026 | .s_fmt = ov772x_s_fmt, | ||
1027 | .try_fmt = ov772x_try_fmt, | ||
1028 | }; | ||
1029 | |||
1030 | static struct v4l2_subdev_ops ov772x_subdev_ops = { | ||
1031 | .core = &ov772x_subdev_core_ops, | ||
1032 | .video = &ov772x_subdev_video_ops, | ||
1033 | }; | ||
1034 | |||
1069 | /* | 1035 | /* |
1070 | * i2c_driver function | 1036 | * i2c_driver function |
1071 | */ | 1037 | */ |
@@ -1081,7 +1047,7 @@ static int ov772x_probe(struct i2c_client *client, | |||
1081 | int ret; | 1047 | int ret; |
1082 | 1048 | ||
1083 | if (!icd) { | 1049 | if (!icd) { |
1084 | dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); | 1050 | dev_err(&client->dev, "OV772X: missing soc-camera data!\n"); |
1085 | return -EINVAL; | 1051 | return -EINVAL; |
1086 | } | 1052 | } |
1087 | 1053 | ||
@@ -1102,8 +1068,9 @@ static int ov772x_probe(struct i2c_client *client, | |||
1102 | if (!priv) | 1068 | if (!priv) |
1103 | return -ENOMEM; | 1069 | return -ENOMEM; |
1104 | 1070 | ||
1105 | priv->info = info; | 1071 | priv->info = info; |
1106 | i2c_set_clientdata(client, priv); | 1072 | |
1073 | v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); | ||
1107 | 1074 | ||
1108 | icd->ops = &ov772x_ops; | 1075 | icd->ops = &ov772x_ops; |
1109 | icd->width_max = MAX_WIDTH; | 1076 | icd->width_max = MAX_WIDTH; |
@@ -1121,7 +1088,7 @@ static int ov772x_probe(struct i2c_client *client, | |||
1121 | 1088 | ||
1122 | static int ov772x_remove(struct i2c_client *client) | 1089 | static int ov772x_remove(struct i2c_client *client) |
1123 | { | 1090 | { |
1124 | struct ov772x_priv *priv = i2c_get_clientdata(client); | 1091 | struct ov772x_priv *priv = to_ov772x(client); |
1125 | struct soc_camera_device *icd = client->dev.platform_data; | 1092 | struct soc_camera_device *icd = client->dev.platform_data; |
1126 | 1093 | ||
1127 | icd->ops = NULL; | 1094 | icd->ops = NULL; |