aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9t112.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2011-08-03 12:42:31 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-11-03 16:28:19 -0400
commit377c9ba772b0c3f848c12810231eb103aad473eb (patch)
tree3f1e76ba7c3cb6b57cf99f089846124eb541f4fd /drivers/media/video/mt9t112.c
parentd839fe17a13562897e52e29c13d09ac0435dee85 (diff)
[media] V4L: mt9t112: fix broken cropping and scaling
G_CROP, S_CROP, CROPCAP, G_FMT, and S_FMT functionality in the mt9t112 driver was broken on many occasions. This patch allows consistent cropping for rectangles also larger than VGA and cleans up multiple other issues in this area. It still doesn't add support for proper scaling, using the sensor own scaler, so input window is still always equal to the output frame. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mt9t112.c')
-rw-r--r--drivers/media/video/mt9t112.c119
1 files changed, 70 insertions, 49 deletions
diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c
index 608a3b6a8e9..25cdcb90768 100644
--- a/drivers/media/video/mt9t112.c
+++ b/drivers/media/video/mt9t112.c
@@ -78,11 +78,6 @@
78/************************************************************************ 78/************************************************************************
79 struct 79 struct
80************************************************************************/ 80************************************************************************/
81struct mt9t112_frame_size {
82 u16 width;
83 u16 height;
84};
85
86struct mt9t112_format { 81struct mt9t112_format {
87 enum v4l2_mbus_pixelcode code; 82 enum v4l2_mbus_pixelcode code;
88 enum v4l2_colorspace colorspace; 83 enum v4l2_colorspace colorspace;
@@ -95,7 +90,7 @@ struct mt9t112_priv {
95 struct mt9t112_camera_info *info; 90 struct mt9t112_camera_info *info;
96 struct i2c_client *client; 91 struct i2c_client *client;
97 struct soc_camera_device icd; 92 struct soc_camera_device icd;
98 struct mt9t112_frame_size frame; 93 struct v4l2_rect frame;
99 const struct mt9t112_format *format; 94 const struct mt9t112_format *format;
100 int model; 95 int model;
101 u32 flags; 96 u32 flags;
@@ -348,13 +343,10 @@ static int mt9t112_clock_info(const struct i2c_client *client, u32 ext)
348} 343}
349#endif 344#endif
350 345
351static void mt9t112_frame_check(u32 *width, u32 *height) 346static void mt9t112_frame_check(u32 *width, u32 *height, u32 *left, u32 *top)
352{ 347{
353 if (*width > MAX_WIDTH) 348 soc_camera_limit_side(left, width, 0, 0, MAX_WIDTH);
354 *width = MAX_WIDTH; 349 soc_camera_limit_side(top, height, 0, 0, MAX_HEIGHT);
355
356 if (*height > MAX_HEIGHT)
357 *height = MAX_HEIGHT;
358} 350}
359 351
360static int mt9t112_set_a_frame_size(const struct i2c_client *client, 352static int mt9t112_set_a_frame_size(const struct i2c_client *client,
@@ -849,19 +841,12 @@ static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
849 return ret; 841 return ret;
850} 842}
851 843
852static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height, 844static int mt9t112_set_params(struct mt9t112_priv *priv,
845 const struct v4l2_rect *rect,
853 enum v4l2_mbus_pixelcode code) 846 enum v4l2_mbus_pixelcode code)
854{ 847{
855 struct mt9t112_priv *priv = to_mt9t112(client);
856 int i; 848 int i;
857 849
858 priv->format = NULL;
859
860 /*
861 * frame size check
862 */
863 mt9t112_frame_check(&width, &height);
864
865 /* 850 /*
866 * get color format 851 * get color format
867 */ 852 */
@@ -872,8 +857,13 @@ static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height,
872 if (i == ARRAY_SIZE(mt9t112_cfmts)) 857 if (i == ARRAY_SIZE(mt9t112_cfmts))
873 return -EINVAL; 858 return -EINVAL;
874 859
875 priv->frame.width = (u16)width; 860 priv->frame = *rect;
876 priv->frame.height = (u16)height; 861
862 /*
863 * frame size check
864 */
865 mt9t112_frame_check(&priv->frame.width, &priv->frame.height,
866 &priv->frame.left, &priv->frame.top);
877 867
878 priv->format = mt9t112_cfmts + i; 868 priv->format = mt9t112_cfmts + i;
879 869
@@ -884,9 +874,12 @@ static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
884{ 874{
885 a->bounds.left = 0; 875 a->bounds.left = 0;
886 a->bounds.top = 0; 876 a->bounds.top = 0;
887 a->bounds.width = VGA_WIDTH; 877 a->bounds.width = MAX_WIDTH;
888 a->bounds.height = VGA_HEIGHT; 878 a->bounds.height = MAX_HEIGHT;
889 a->defrect = a->bounds; 879 a->defrect.left = 0;
880 a->defrect.top = 0;
881 a->defrect.width = VGA_WIDTH;
882 a->defrect.height = VGA_HEIGHT;
890 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 883 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
891 a->pixelaspect.numerator = 1; 884 a->pixelaspect.numerator = 1;
892 a->pixelaspect.denominator = 1; 885 a->pixelaspect.denominator = 1;
@@ -896,11 +889,11 @@ static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
896 889
897static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 890static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
898{ 891{
899 a->c.left = 0; 892 struct i2c_client *client = v4l2_get_subdevdata(sd);
900 a->c.top = 0; 893 struct mt9t112_priv *priv = to_mt9t112(client);
901 a->c.width = VGA_WIDTH; 894
902 a->c.height = VGA_HEIGHT; 895 a->c = priv->frame;
903 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 896 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
904 897
905 return 0; 898 return 0;
906} 899}
@@ -908,10 +901,10 @@ static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
908static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 901static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
909{ 902{
910 struct i2c_client *client = v4l2_get_subdevdata(sd); 903 struct i2c_client *client = v4l2_get_subdevdata(sd);
904 struct mt9t112_priv *priv = to_mt9t112(client);
911 struct v4l2_rect *rect = &a->c; 905 struct v4l2_rect *rect = &a->c;
912 906
913 return mt9t112_set_params(client, rect->width, rect->height, 907 return mt9t112_set_params(priv, rect, priv->format->code);
914 V4L2_MBUS_FMT_UYVY8_2X8);
915} 908}
916 909
917static int mt9t112_g_fmt(struct v4l2_subdev *sd, 910static int mt9t112_g_fmt(struct v4l2_subdev *sd,
@@ -920,16 +913,9 @@ static int mt9t112_g_fmt(struct v4l2_subdev *sd,
920 struct i2c_client *client = v4l2_get_subdevdata(sd); 913 struct i2c_client *client = v4l2_get_subdevdata(sd);
921 struct mt9t112_priv *priv = to_mt9t112(client); 914 struct mt9t112_priv *priv = to_mt9t112(client);
922 915
923 if (!priv->format) {
924 int ret = mt9t112_set_params(client, VGA_WIDTH, VGA_HEIGHT,
925 V4L2_MBUS_FMT_UYVY8_2X8);
926 if (ret < 0)
927 return ret;
928 }
929
930 mf->width = priv->frame.width; 916 mf->width = priv->frame.width;
931 mf->height = priv->frame.height; 917 mf->height = priv->frame.height;
932 /* TODO: set colorspace */ 918 mf->colorspace = priv->format->colorspace;
933 mf->code = priv->format->code; 919 mf->code = priv->format->code;
934 mf->field = V4L2_FIELD_NONE; 920 mf->field = V4L2_FIELD_NONE;
935 921
@@ -940,17 +926,42 @@ static int mt9t112_s_fmt(struct v4l2_subdev *sd,
940 struct v4l2_mbus_framefmt *mf) 926 struct v4l2_mbus_framefmt *mf)
941{ 927{
942 struct i2c_client *client = v4l2_get_subdevdata(sd); 928 struct i2c_client *client = v4l2_get_subdevdata(sd);
929 struct mt9t112_priv *priv = to_mt9t112(client);
930 struct v4l2_rect rect = {
931 .width = mf->width,
932 .height = mf->height,
933 .left = priv->frame.left,
934 .top = priv->frame.top,
935 };
936 int ret;
937
938 ret = mt9t112_set_params(priv, &rect, mf->code);
939
940 if (!ret)
941 mf->colorspace = priv->format->colorspace;
943 942
944 /* TODO: set colorspace */ 943 return ret;
945 return mt9t112_set_params(client, mf->width, mf->height, mf->code);
946} 944}
947 945
948static int mt9t112_try_fmt(struct v4l2_subdev *sd, 946static int mt9t112_try_fmt(struct v4l2_subdev *sd,
949 struct v4l2_mbus_framefmt *mf) 947 struct v4l2_mbus_framefmt *mf)
950{ 948{
951 mt9t112_frame_check(&mf->width, &mf->height); 949 unsigned int top, left;
950 int i;
951
952 for (i = 0; i < ARRAY_SIZE(mt9t112_cfmts); i++)
953 if (mt9t112_cfmts[i].code == mf->code)
954 break;
955
956 if (i == ARRAY_SIZE(mt9t112_cfmts)) {
957 mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
958 mf->colorspace = V4L2_COLORSPACE_JPEG;
959 } else {
960 mf->colorspace = mt9t112_cfmts[i].colorspace;
961 }
962
963 mt9t112_frame_check(&mf->width, &mf->height, &left, &top);
952 964
953 /* TODO: set colorspace */
954 mf->field = V4L2_FIELD_NONE; 965 mf->field = V4L2_FIELD_NONE;
955 966
956 return 0; 967 return 0;
@@ -963,6 +974,7 @@ static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
963 return -EINVAL; 974 return -EINVAL;
964 975
965 *code = mt9t112_cfmts[index].code; 976 *code = mt9t112_cfmts[index].code;
977
966 return 0; 978 return 0;
967} 979}
968 980
@@ -1055,10 +1067,16 @@ static int mt9t112_camera_probe(struct soc_camera_device *icd,
1055static int mt9t112_probe(struct i2c_client *client, 1067static int mt9t112_probe(struct i2c_client *client,
1056 const struct i2c_device_id *did) 1068 const struct i2c_device_id *did)
1057{ 1069{
1058 struct mt9t112_priv *priv; 1070 struct mt9t112_priv *priv;
1059 struct soc_camera_device *icd = client->dev.platform_data; 1071 struct soc_camera_device *icd = client->dev.platform_data;
1060 struct soc_camera_link *icl; 1072 struct soc_camera_link *icl;
1061 int ret; 1073 struct v4l2_rect rect = {
1074 .width = VGA_WIDTH,
1075 .height = VGA_HEIGHT,
1076 .left = (MAX_WIDTH - VGA_WIDTH) / 2,
1077 .top = (MAX_HEIGHT - VGA_HEIGHT) / 2,
1078 };
1079 int ret;
1062 1080
1063 if (!icd) { 1081 if (!icd) {
1064 dev_err(&client->dev, "mt9t112: missing soc-camera data!\n"); 1082 dev_err(&client->dev, "mt9t112: missing soc-camera data!\n");
@@ -1083,6 +1101,9 @@ static int mt9t112_probe(struct i2c_client *client,
1083 if (ret) 1101 if (ret)
1084 kfree(priv); 1102 kfree(priv);
1085 1103
1104 /* Cannot fail: using the default supported pixel code */
1105 mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8);
1106
1086 return ret; 1107 return ret;
1087} 1108}
1088 1109