diff options
-rw-r--r-- | drivers/media/video/mt9t112.c | 119 |
1 files changed, 70 insertions, 49 deletions
diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index 608a3b6a8e99..25cdcb90768a 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 | ************************************************************************/ |
81 | struct mt9t112_frame_size { | ||
82 | u16 width; | ||
83 | u16 height; | ||
84 | }; | ||
85 | |||
86 | struct mt9t112_format { | 81 | struct 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 | ||
351 | static void mt9t112_frame_check(u32 *width, u32 *height) | 346 | static 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 | ||
360 | static int mt9t112_set_a_frame_size(const struct i2c_client *client, | 352 | static 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 | ||
852 | static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height, | 844 | static 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 | ||
897 | static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 890 | static 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) | |||
908 | static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 901 | static 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 | ||
917 | static int mt9t112_g_fmt(struct v4l2_subdev *sd, | 910 | static 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 | ||
948 | static int mt9t112_try_fmt(struct v4l2_subdev *sd, | 946 | static 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, | |||
1055 | static int mt9t112_probe(struct i2c_client *client, | 1067 | static 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 | ||