Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Javier Martin and committed by
Mauro Carvalho Chehab
963ddc63 d994c46d

+122 -5
+122 -5
drivers/media/video/tvp5150.c
··· 17 17 18 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 27 MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); 21 28 MODULE_AUTHOR("Mauro Carvalho Chehab"); 22 29 MODULE_LICENSE("GPL"); ··· 36 29 struct tvp5150 { 37 30 struct v4l2_subdev sd; 38 31 struct v4l2_ctrl_handler hdl; 32 + struct v4l2_rect rect; 39 33 40 34 v4l2_std_id norm; /* Current set standard */ 41 35 u32 input; ··· 740 732 if (decoder->norm == std) 741 733 return 0; 742 734 735 + /* Change cropping height limits */ 736 + if (std & V4L2_STD_525_60) 737 + decoder->rect.height = TVP5150_V_MAX_525_60; 738 + else 739 + decoder->rect.height = TVP5150_V_MAX_OTHERS; 740 + 741 + 743 742 return tvp5150_set_std(sd, std); 744 743 } 745 744 ··· 843 828 else 844 829 std = decoder->norm; 845 830 846 - f->width = 720; 847 - if (std & V4L2_STD_525_60) 848 - f->height = 480; 849 - else 850 - f->height = 576; 831 + f->width = decoder->rect.width; 832 + f->height = decoder->rect.height; 851 833 852 834 f->code = V4L2_MBUS_FMT_YUYV8_2X8; 853 835 f->field = V4L2_FIELD_SEQ_TB; ··· 852 840 853 841 v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width, 854 842 f->height); 843 + return 0; 844 + } 845 + 846 + static int tvp5150_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 847 + { 848 + struct v4l2_rect rect = a->c; 849 + struct tvp5150 *decoder = to_tvp5150(sd); 850 + v4l2_std_id std; 851 + int hmax; 852 + 853 + v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n", 854 + __func__, rect.left, rect.top, rect.width, rect.height); 855 + 856 + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 857 + return -EINVAL; 858 + 859 + /* tvp5150 has some special limits */ 860 + rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT); 861 + rect.width = clamp(rect.width, 862 + TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left, 863 + TVP5150_H_MAX - rect.left); 864 + rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP); 865 + 866 + /* Calculate height based on current standard */ 867 + if (decoder->norm == V4L2_STD_ALL) 868 + std = tvp5150_read_std(sd); 869 + else 870 + std = decoder->norm; 871 + 872 + if (std & V4L2_STD_525_60) 873 + hmax = TVP5150_V_MAX_525_60; 874 + else 875 + hmax = TVP5150_V_MAX_OTHERS; 876 + 877 + rect.height = clamp(rect.height, 878 + hmax - TVP5150_MAX_CROP_TOP - rect.top, 879 + hmax - rect.top); 880 + 881 + tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top); 882 + tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 883 + rect.top + rect.height - hmax); 884 + tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB, 885 + rect.left >> TVP5150_CROP_SHIFT); 886 + tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB, 887 + rect.left | (1 << TVP5150_CROP_SHIFT)); 888 + tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB, 889 + (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >> 890 + TVP5150_CROP_SHIFT); 891 + tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB, 892 + rect.left + rect.width - TVP5150_MAX_CROP_LEFT); 893 + 894 + decoder->rect = rect; 895 + 896 + return 0; 897 + } 898 + 899 + static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 900 + { 901 + struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); 902 + 903 + a->c = decoder->rect; 904 + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 905 + 906 + return 0; 907 + } 908 + 909 + static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 910 + { 911 + struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); 912 + v4l2_std_id std; 913 + 914 + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 915 + return -EINVAL; 916 + 917 + a->bounds.left = 0; 918 + a->bounds.top = 0; 919 + a->bounds.width = TVP5150_H_MAX; 920 + 921 + /* Calculate height based on current standard */ 922 + if (decoder->norm == V4L2_STD_ALL) 923 + std = tvp5150_read_std(sd); 924 + else 925 + std = decoder->norm; 926 + 927 + if (std & V4L2_STD_525_60) 928 + a->bounds.height = TVP5150_V_MAX_525_60; 929 + else 930 + a->bounds.height = TVP5150_V_MAX_OTHERS; 931 + 932 + a->defrect = a->bounds; 933 + a->pixelaspect.numerator = 1; 934 + a->pixelaspect.denominator = 1; 935 + 855 936 return 0; 856 937 } 857 938 ··· 1103 998 .enum_mbus_fmt = tvp5150_enum_mbus_fmt, 1104 999 .s_mbus_fmt = tvp5150_mbus_fmt, 1105 1000 .try_mbus_fmt = tvp5150_mbus_fmt, 1001 + .s_crop = tvp5150_s_crop, 1002 + .g_crop = tvp5150_g_crop, 1003 + .cropcap = tvp5150_cropcap, 1106 1004 }; 1107 1005 1108 1006 static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { ··· 1190 1082 return err; 1191 1083 } 1192 1084 v4l2_ctrl_handler_setup(&core->hdl); 1085 + 1086 + /* Default is no cropping */ 1087 + core->rect.top = 0; 1088 + if (tvp5150_read_std(sd) & V4L2_STD_525_60) 1089 + core->rect.height = TVP5150_V_MAX_525_60; 1090 + else 1091 + core->rect.height = TVP5150_V_MAX_OTHERS; 1092 + core->rect.left = 0; 1093 + core->rect.width = TVP5150_H_MAX; 1193 1094 1194 1095 if (debug > 1) 1195 1096 tvp5150_log_status(sd);