diff options
author | Javier Martin <javier.martin@vista-silicon.com> | 2012-01-31 03:23:46 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-08 10:06:56 -0500 |
commit | 963ddc63e20d5ee8a45503e078e09d0cc086b59d (patch) | |
tree | fc6556f23b4403fd1f49aab999c668fc66084c0e | |
parent | d994c46d4309df85aea86049024cadfcbf523116 (diff) |
[media] media: tvp5150: Add cropping support
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/tvp5150.c | 127 |
1 files changed, 122 insertions, 5 deletions
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index f1fcedd29eb4..907d560dd2b2 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c | |||
@@ -17,6 +17,13 @@ | |||
17 | 17 | ||
18 | #include "tvp5150_reg.h" | 18 | #include "tvp5150_reg.h" |
19 | 19 | ||
20 | #define TVP5150_H_MAX 720 | ||
21 | #define TVP5150_V_MAX_525_60 480 | ||
22 | #define TVP5150_V_MAX_OTHERS 576 | ||
23 | #define TVP5150_MAX_CROP_LEFT 511 | ||
24 | #define TVP5150_MAX_CROP_TOP 127 | ||
25 | #define TVP5150_CROP_SHIFT 2 | ||
26 | |||
20 | MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); | 27 | MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); |
21 | MODULE_AUTHOR("Mauro Carvalho Chehab"); | 28 | MODULE_AUTHOR("Mauro Carvalho Chehab"); |
22 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
@@ -29,6 +36,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); | |||
29 | struct tvp5150 { | 36 | struct tvp5150 { |
30 | struct v4l2_subdev sd; | 37 | struct v4l2_subdev sd; |
31 | struct v4l2_ctrl_handler hdl; | 38 | struct v4l2_ctrl_handler hdl; |
39 | struct v4l2_rect rect; | ||
32 | 40 | ||
33 | v4l2_std_id norm; /* Current set standard */ | 41 | v4l2_std_id norm; /* Current set standard */ |
34 | u32 input; | 42 | u32 input; |
@@ -732,6 +740,13 @@ static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
732 | if (decoder->norm == std) | 740 | if (decoder->norm == std) |
733 | return 0; | 741 | return 0; |
734 | 742 | ||
743 | /* Change cropping height limits */ | ||
744 | if (std & V4L2_STD_525_60) | ||
745 | decoder->rect.height = TVP5150_V_MAX_525_60; | ||
746 | else | ||
747 | decoder->rect.height = TVP5150_V_MAX_OTHERS; | ||
748 | |||
749 | |||
735 | return tvp5150_set_std(sd, std); | 750 | return tvp5150_set_std(sd, std); |
736 | } | 751 | } |
737 | 752 | ||
@@ -828,11 +843,8 @@ static int tvp5150_mbus_fmt(struct v4l2_subdev *sd, | |||
828 | else | 843 | else |
829 | std = decoder->norm; | 844 | std = decoder->norm; |
830 | 845 | ||
831 | f->width = 720; | 846 | f->width = decoder->rect.width; |
832 | if (std & V4L2_STD_525_60) | 847 | f->height = decoder->rect.height; |
833 | f->height = 480; | ||
834 | else | ||
835 | f->height = 576; | ||
836 | 848 | ||
837 | f->code = V4L2_MBUS_FMT_YUYV8_2X8; | 849 | f->code = V4L2_MBUS_FMT_YUYV8_2X8; |
838 | f->field = V4L2_FIELD_SEQ_TB; | 850 | f->field = V4L2_FIELD_SEQ_TB; |
@@ -843,6 +855,99 @@ static int tvp5150_mbus_fmt(struct v4l2_subdev *sd, | |||
843 | return 0; | 855 | return 0; |
844 | } | 856 | } |
845 | 857 | ||
858 | static int tvp5150_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
859 | { | ||
860 | struct v4l2_rect rect = a->c; | ||
861 | struct tvp5150 *decoder = to_tvp5150(sd); | ||
862 | v4l2_std_id std; | ||
863 | int hmax; | ||
864 | |||
865 | v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n", | ||
866 | __func__, rect.left, rect.top, rect.width, rect.height); | ||
867 | |||
868 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
869 | return -EINVAL; | ||
870 | |||
871 | /* tvp5150 has some special limits */ | ||
872 | rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT); | ||
873 | rect.width = clamp(rect.width, | ||
874 | TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left, | ||
875 | TVP5150_H_MAX - rect.left); | ||
876 | rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP); | ||
877 | |||
878 | /* Calculate height based on current standard */ | ||
879 | if (decoder->norm == V4L2_STD_ALL) | ||
880 | std = tvp5150_read_std(sd); | ||
881 | else | ||
882 | std = decoder->norm; | ||
883 | |||
884 | if (std & V4L2_STD_525_60) | ||
885 | hmax = TVP5150_V_MAX_525_60; | ||
886 | else | ||
887 | hmax = TVP5150_V_MAX_OTHERS; | ||
888 | |||
889 | rect.height = clamp(rect.height, | ||
890 | hmax - TVP5150_MAX_CROP_TOP - rect.top, | ||
891 | hmax - rect.top); | ||
892 | |||
893 | tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top); | ||
894 | tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, | ||
895 | rect.top + rect.height - hmax); | ||
896 | tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB, | ||
897 | rect.left >> TVP5150_CROP_SHIFT); | ||
898 | tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB, | ||
899 | rect.left | (1 << TVP5150_CROP_SHIFT)); | ||
900 | tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB, | ||
901 | (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >> | ||
902 | TVP5150_CROP_SHIFT); | ||
903 | tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB, | ||
904 | rect.left + rect.width - TVP5150_MAX_CROP_LEFT); | ||
905 | |||
906 | decoder->rect = rect; | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
912 | { | ||
913 | struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); | ||
914 | |||
915 | a->c = decoder->rect; | ||
916 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
917 | |||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | ||
922 | { | ||
923 | struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); | ||
924 | v4l2_std_id std; | ||
925 | |||
926 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
927 | return -EINVAL; | ||
928 | |||
929 | a->bounds.left = 0; | ||
930 | a->bounds.top = 0; | ||
931 | a->bounds.width = TVP5150_H_MAX; | ||
932 | |||
933 | /* Calculate height based on current standard */ | ||
934 | if (decoder->norm == V4L2_STD_ALL) | ||
935 | std = tvp5150_read_std(sd); | ||
936 | else | ||
937 | std = decoder->norm; | ||
938 | |||
939 | if (std & V4L2_STD_525_60) | ||
940 | a->bounds.height = TVP5150_V_MAX_525_60; | ||
941 | else | ||
942 | a->bounds.height = TVP5150_V_MAX_OTHERS; | ||
943 | |||
944 | a->defrect = a->bounds; | ||
945 | a->pixelaspect.numerator = 1; | ||
946 | a->pixelaspect.denominator = 1; | ||
947 | |||
948 | return 0; | ||
949 | } | ||
950 | |||
846 | /**************************************************************************** | 951 | /**************************************************************************** |
847 | I2C Command | 952 | I2C Command |
848 | ****************************************************************************/ | 953 | ****************************************************************************/ |
@@ -998,6 +1103,9 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { | |||
998 | .enum_mbus_fmt = tvp5150_enum_mbus_fmt, | 1103 | .enum_mbus_fmt = tvp5150_enum_mbus_fmt, |
999 | .s_mbus_fmt = tvp5150_mbus_fmt, | 1104 | .s_mbus_fmt = tvp5150_mbus_fmt, |
1000 | .try_mbus_fmt = tvp5150_mbus_fmt, | 1105 | .try_mbus_fmt = tvp5150_mbus_fmt, |
1106 | .s_crop = tvp5150_s_crop, | ||
1107 | .g_crop = tvp5150_g_crop, | ||
1108 | .cropcap = tvp5150_cropcap, | ||
1001 | }; | 1109 | }; |
1002 | 1110 | ||
1003 | static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { | 1111 | static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { |
@@ -1083,6 +1191,15 @@ static int tvp5150_probe(struct i2c_client *c, | |||
1083 | } | 1191 | } |
1084 | v4l2_ctrl_handler_setup(&core->hdl); | 1192 | v4l2_ctrl_handler_setup(&core->hdl); |
1085 | 1193 | ||
1194 | /* Default is no cropping */ | ||
1195 | core->rect.top = 0; | ||
1196 | if (tvp5150_read_std(sd) & V4L2_STD_525_60) | ||
1197 | core->rect.height = TVP5150_V_MAX_525_60; | ||
1198 | else | ||
1199 | core->rect.height = TVP5150_V_MAX_OTHERS; | ||
1200 | core->rect.left = 0; | ||
1201 | core->rect.width = TVP5150_H_MAX; | ||
1202 | |||
1086 | if (debug > 1) | 1203 | if (debug > 1) |
1087 | tvp5150_log_status(sd); | 1204 | tvp5150_log_status(sd); |
1088 | return 0; | 1205 | return 0; |