diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-12-12 06:45:22 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:31:50 -0400 |
commit | cf6832afe59f37b154bf0e41bf5e59cfd7f46d24 (patch) | |
tree | cdcf384327617060c060c5acc5a8dbf80af60968 | |
parent | e3d5ef0410806d94cf58afd87a753ad5932ca8a8 (diff) |
[media] tvp514x: use the control framework
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/tvp514x.c | 236 |
1 files changed, 57 insertions, 179 deletions
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index 45bcf0358a1d..9b3e828b0775 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
38 | #include <media/v4l2-mediabus.h> | 38 | #include <media/v4l2-mediabus.h> |
39 | #include <media/v4l2-chip-ident.h> | 39 | #include <media/v4l2-chip-ident.h> |
40 | #include <media/v4l2-ctrls.h> | ||
40 | #include <media/tvp514x.h> | 41 | #include <media/tvp514x.h> |
41 | 42 | ||
42 | #include "tvp514x_regs.h" | 43 | #include "tvp514x_regs.h" |
@@ -97,6 +98,7 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable); | |||
97 | */ | 98 | */ |
98 | struct tvp514x_decoder { | 99 | struct tvp514x_decoder { |
99 | struct v4l2_subdev sd; | 100 | struct v4l2_subdev sd; |
101 | struct v4l2_ctrl_handler hdl; | ||
100 | struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)]; | 102 | struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)]; |
101 | const struct tvp514x_platform_data *pdata; | 103 | const struct tvp514x_platform_data *pdata; |
102 | 104 | ||
@@ -238,6 +240,11 @@ static inline struct tvp514x_decoder *to_decoder(struct v4l2_subdev *sd) | |||
238 | return container_of(sd, struct tvp514x_decoder, sd); | 240 | return container_of(sd, struct tvp514x_decoder, sd); |
239 | } | 241 | } |
240 | 242 | ||
243 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | ||
244 | { | ||
245 | return &container_of(ctrl->handler, struct tvp514x_decoder, hdl)->sd; | ||
246 | } | ||
247 | |||
241 | 248 | ||
242 | /** | 249 | /** |
243 | * tvp514x_read_reg() - Read a value from a register in an TVP5146/47. | 250 | * tvp514x_read_reg() - Read a value from a register in an TVP5146/47. |
@@ -719,213 +726,54 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd, | |||
719 | } | 726 | } |
720 | 727 | ||
721 | /** | 728 | /** |
722 | * tvp514x_queryctrl() - V4L2 decoder interface handler for queryctrl | ||
723 | * @sd: pointer to standard V4L2 sub-device structure | ||
724 | * @qctrl: standard V4L2 v4l2_queryctrl structure | ||
725 | * | ||
726 | * If the requested control is supported, returns the control information. | ||
727 | * Otherwise, returns -EINVAL if the control is not supported. | ||
728 | */ | ||
729 | static int | ||
730 | tvp514x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) | ||
731 | { | ||
732 | int err = -EINVAL; | ||
733 | |||
734 | if (qctrl == NULL) | ||
735 | return err; | ||
736 | |||
737 | switch (qctrl->id) { | ||
738 | case V4L2_CID_BRIGHTNESS: | ||
739 | /* Brightness supported is (0-255), */ | ||
740 | err = v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); | ||
741 | break; | ||
742 | case V4L2_CID_CONTRAST: | ||
743 | case V4L2_CID_SATURATION: | ||
744 | /** | ||
745 | * Saturation and Contrast supported is - | ||
746 | * Contrast: 0 - 255 (Default - 128) | ||
747 | * Saturation: 0 - 255 (Default - 128) | ||
748 | */ | ||
749 | err = v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); | ||
750 | break; | ||
751 | case V4L2_CID_HUE: | ||
752 | /* Hue Supported is - | ||
753 | * Hue - -180 - +180 (Default - 0, Step - +180) | ||
754 | */ | ||
755 | err = v4l2_ctrl_query_fill(qctrl, -180, 180, 180, 0); | ||
756 | break; | ||
757 | case V4L2_CID_AUTOGAIN: | ||
758 | /** | ||
759 | * Auto Gain supported is - | ||
760 | * 0 - 1 (Default - 1) | ||
761 | */ | ||
762 | err = v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); | ||
763 | break; | ||
764 | default: | ||
765 | v4l2_err(sd, "invalid control id %d\n", qctrl->id); | ||
766 | return err; | ||
767 | } | ||
768 | |||
769 | v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d\n", | ||
770 | qctrl->name, qctrl->minimum, qctrl->maximum, | ||
771 | qctrl->default_value); | ||
772 | |||
773 | return err; | ||
774 | } | ||
775 | |||
776 | /** | ||
777 | * tvp514x_g_ctrl() - V4L2 decoder interface handler for g_ctrl | ||
778 | * @sd: pointer to standard V4L2 sub-device structure | ||
779 | * @ctrl: pointer to v4l2_control structure | ||
780 | * | ||
781 | * If the requested control is supported, returns the control's current | ||
782 | * value from the decoder. Otherwise, returns -EINVAL if the control is not | ||
783 | * supported. | ||
784 | */ | ||
785 | static int | ||
786 | tvp514x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
787 | { | ||
788 | struct tvp514x_decoder *decoder = to_decoder(sd); | ||
789 | |||
790 | if (ctrl == NULL) | ||
791 | return -EINVAL; | ||
792 | |||
793 | switch (ctrl->id) { | ||
794 | case V4L2_CID_BRIGHTNESS: | ||
795 | ctrl->value = decoder->tvp514x_regs[REG_BRIGHTNESS].val; | ||
796 | break; | ||
797 | case V4L2_CID_CONTRAST: | ||
798 | ctrl->value = decoder->tvp514x_regs[REG_CONTRAST].val; | ||
799 | break; | ||
800 | case V4L2_CID_SATURATION: | ||
801 | ctrl->value = decoder->tvp514x_regs[REG_SATURATION].val; | ||
802 | break; | ||
803 | case V4L2_CID_HUE: | ||
804 | ctrl->value = decoder->tvp514x_regs[REG_HUE].val; | ||
805 | if (ctrl->value == 0x7F) | ||
806 | ctrl->value = 180; | ||
807 | else if (ctrl->value == 0x80) | ||
808 | ctrl->value = -180; | ||
809 | else | ||
810 | ctrl->value = 0; | ||
811 | |||
812 | break; | ||
813 | case V4L2_CID_AUTOGAIN: | ||
814 | ctrl->value = decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val; | ||
815 | if ((ctrl->value & 0x3) == 3) | ||
816 | ctrl->value = 1; | ||
817 | else | ||
818 | ctrl->value = 0; | ||
819 | |||
820 | break; | ||
821 | default: | ||
822 | v4l2_err(sd, "invalid control id %d\n", ctrl->id); | ||
823 | return -EINVAL; | ||
824 | } | ||
825 | |||
826 | v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d\n", | ||
827 | ctrl->id, ctrl->value); | ||
828 | return 0; | ||
829 | } | ||
830 | |||
831 | /** | ||
832 | * tvp514x_s_ctrl() - V4L2 decoder interface handler for s_ctrl | 729 | * tvp514x_s_ctrl() - V4L2 decoder interface handler for s_ctrl |
833 | * @sd: pointer to standard V4L2 sub-device structure | 730 | * @ctrl: pointer to v4l2_ctrl structure |
834 | * @ctrl: pointer to v4l2_control structure | ||
835 | * | 731 | * |
836 | * If the requested control is supported, sets the control's current | 732 | * If the requested control is supported, sets the control's current |
837 | * value in HW. Otherwise, returns -EINVAL if the control is not supported. | 733 | * value in HW. Otherwise, returns -EINVAL if the control is not supported. |
838 | */ | 734 | */ |
839 | static int | 735 | static int tvp514x_s_ctrl(struct v4l2_ctrl *ctrl) |
840 | tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
841 | { | 736 | { |
737 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
842 | struct tvp514x_decoder *decoder = to_decoder(sd); | 738 | struct tvp514x_decoder *decoder = to_decoder(sd); |
843 | int err = -EINVAL, value; | 739 | int err = -EINVAL, value; |
844 | 740 | ||
845 | if (ctrl == NULL) | 741 | value = ctrl->val; |
846 | return err; | ||
847 | |||
848 | value = ctrl->value; | ||
849 | 742 | ||
850 | switch (ctrl->id) { | 743 | switch (ctrl->id) { |
851 | case V4L2_CID_BRIGHTNESS: | 744 | case V4L2_CID_BRIGHTNESS: |
852 | if (ctrl->value < 0 || ctrl->value > 255) { | 745 | err = tvp514x_write_reg(sd, REG_BRIGHTNESS, value); |
853 | v4l2_err(sd, "invalid brightness setting %d\n", | 746 | if (!err) |
854 | ctrl->value); | 747 | decoder->tvp514x_regs[REG_BRIGHTNESS].val = value; |
855 | return -ERANGE; | ||
856 | } | ||
857 | err = tvp514x_write_reg(sd, REG_BRIGHTNESS, | ||
858 | value); | ||
859 | if (err) | ||
860 | return err; | ||
861 | |||
862 | decoder->tvp514x_regs[REG_BRIGHTNESS].val = value; | ||
863 | break; | 748 | break; |
864 | case V4L2_CID_CONTRAST: | 749 | case V4L2_CID_CONTRAST: |
865 | if (ctrl->value < 0 || ctrl->value > 255) { | ||
866 | v4l2_err(sd, "invalid contrast setting %d\n", | ||
867 | ctrl->value); | ||
868 | return -ERANGE; | ||
869 | } | ||
870 | err = tvp514x_write_reg(sd, REG_CONTRAST, value); | 750 | err = tvp514x_write_reg(sd, REG_CONTRAST, value); |
871 | if (err) | 751 | if (!err) |
872 | return err; | 752 | decoder->tvp514x_regs[REG_CONTRAST].val = value; |
873 | |||
874 | decoder->tvp514x_regs[REG_CONTRAST].val = value; | ||
875 | break; | 753 | break; |
876 | case V4L2_CID_SATURATION: | 754 | case V4L2_CID_SATURATION: |
877 | if (ctrl->value < 0 || ctrl->value > 255) { | ||
878 | v4l2_err(sd, "invalid saturation setting %d\n", | ||
879 | ctrl->value); | ||
880 | return -ERANGE; | ||
881 | } | ||
882 | err = tvp514x_write_reg(sd, REG_SATURATION, value); | 755 | err = tvp514x_write_reg(sd, REG_SATURATION, value); |
883 | if (err) | 756 | if (!err) |
884 | return err; | 757 | decoder->tvp514x_regs[REG_SATURATION].val = value; |
885 | |||
886 | decoder->tvp514x_regs[REG_SATURATION].val = value; | ||
887 | break; | 758 | break; |
888 | case V4L2_CID_HUE: | 759 | case V4L2_CID_HUE: |
889 | if (value == 180) | 760 | if (value == 180) |
890 | value = 0x7F; | 761 | value = 0x7F; |
891 | else if (value == -180) | 762 | else if (value == -180) |
892 | value = 0x80; | 763 | value = 0x80; |
893 | else if (value == 0) | ||
894 | value = 0; | ||
895 | else { | ||
896 | v4l2_err(sd, "invalid hue setting %d\n", ctrl->value); | ||
897 | return -ERANGE; | ||
898 | } | ||
899 | err = tvp514x_write_reg(sd, REG_HUE, value); | 764 | err = tvp514x_write_reg(sd, REG_HUE, value); |
900 | if (err) | 765 | if (!err) |
901 | return err; | 766 | decoder->tvp514x_regs[REG_HUE].val = value; |
902 | |||
903 | decoder->tvp514x_regs[REG_HUE].val = value; | ||
904 | break; | 767 | break; |
905 | case V4L2_CID_AUTOGAIN: | 768 | case V4L2_CID_AUTOGAIN: |
906 | if (value == 1) | 769 | err = tvp514x_write_reg(sd, REG_AFE_GAIN_CTRL, value ? 0x0f : 0x0c); |
907 | value = 0x0F; | 770 | if (!err) |
908 | else if (value == 0) | 771 | decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value; |
909 | value = 0x0C; | ||
910 | else { | ||
911 | v4l2_err(sd, "invalid auto gain setting %d\n", | ||
912 | ctrl->value); | ||
913 | return -ERANGE; | ||
914 | } | ||
915 | err = tvp514x_write_reg(sd, REG_AFE_GAIN_CTRL, value); | ||
916 | if (err) | ||
917 | return err; | ||
918 | |||
919 | decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value; | ||
920 | break; | 772 | break; |
921 | default: | ||
922 | v4l2_err(sd, "invalid control id %d\n", ctrl->id); | ||
923 | return err; | ||
924 | } | 773 | } |
925 | 774 | ||
926 | v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n", | 775 | v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n", |
927 | ctrl->id, ctrl->value); | 776 | ctrl->id, ctrl->val); |
928 | |||
929 | return err; | 777 | return err; |
930 | } | 778 | } |
931 | 779 | ||
@@ -1104,10 +952,18 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) | |||
1104 | return err; | 952 | return err; |
1105 | } | 953 | } |
1106 | 954 | ||
1107 | static const struct v4l2_subdev_core_ops tvp514x_core_ops = { | 955 | static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = { |
1108 | .queryctrl = tvp514x_queryctrl, | ||
1109 | .g_ctrl = tvp514x_g_ctrl, | ||
1110 | .s_ctrl = tvp514x_s_ctrl, | 956 | .s_ctrl = tvp514x_s_ctrl, |
957 | }; | ||
958 | |||
959 | static const struct v4l2_subdev_core_ops tvp514x_core_ops = { | ||
960 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, | ||
961 | .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, | ||
962 | .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, | ||
963 | .g_ctrl = v4l2_subdev_g_ctrl, | ||
964 | .s_ctrl = v4l2_subdev_s_ctrl, | ||
965 | .queryctrl = v4l2_subdev_queryctrl, | ||
966 | .querymenu = v4l2_subdev_querymenu, | ||
1111 | .s_std = tvp514x_s_std, | 967 | .s_std = tvp514x_s_std, |
1112 | }; | 968 | }; |
1113 | 969 | ||
@@ -1190,6 +1046,27 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1190 | sd = &decoder->sd; | 1046 | sd = &decoder->sd; |
1191 | v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); | 1047 | v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); |
1192 | 1048 | ||
1049 | v4l2_ctrl_handler_init(&decoder->hdl, 5); | ||
1050 | v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, | ||
1051 | V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); | ||
1052 | v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, | ||
1053 | V4L2_CID_CONTRAST, 0, 255, 1, 128); | ||
1054 | v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, | ||
1055 | V4L2_CID_SATURATION, 0, 255, 1, 128); | ||
1056 | v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, | ||
1057 | V4L2_CID_HUE, -180, 180, 180, 0); | ||
1058 | v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops, | ||
1059 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | ||
1060 | sd->ctrl_handler = &decoder->hdl; | ||
1061 | if (decoder->hdl.error) { | ||
1062 | int err = decoder->hdl.error; | ||
1063 | |||
1064 | v4l2_ctrl_handler_free(&decoder->hdl); | ||
1065 | kfree(decoder); | ||
1066 | return err; | ||
1067 | } | ||
1068 | v4l2_ctrl_handler_setup(&decoder->hdl); | ||
1069 | |||
1193 | v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); | 1070 | v4l2_info(sd, "%s decoder driver registered !!\n", sd->name); |
1194 | 1071 | ||
1195 | return 0; | 1072 | return 0; |
@@ -1209,6 +1086,7 @@ static int tvp514x_remove(struct i2c_client *client) | |||
1209 | struct tvp514x_decoder *decoder = to_decoder(sd); | 1086 | struct tvp514x_decoder *decoder = to_decoder(sd); |
1210 | 1087 | ||
1211 | v4l2_device_unregister_subdev(sd); | 1088 | v4l2_device_unregister_subdev(sd); |
1089 | v4l2_ctrl_handler_free(&decoder->hdl); | ||
1212 | kfree(decoder); | 1090 | kfree(decoder); |
1213 | return 0; | 1091 | return 0; |
1214 | } | 1092 | } |