diff options
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; |