aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJavier Martin <javier.martin@vista-silicon.com>2012-01-31 03:23:46 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-03-08 10:06:56 -0500
commit963ddc63e20d5ee8a45503e078e09d0cc086b59d (patch)
treefc6556f23b4403fd1f49aab999c668fc66084c0e
parentd994c46d4309df85aea86049024cadfcbf523116 (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.c127
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
20MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); 27MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver");
21MODULE_AUTHOR("Mauro Carvalho Chehab"); 28MODULE_AUTHOR("Mauro Carvalho Chehab");
22MODULE_LICENSE("GPL"); 29MODULE_LICENSE("GPL");
@@ -29,6 +36,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
29struct tvp5150 { 36struct 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
858static 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
911static 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
921static 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
1003static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { 1111static 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;