diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index 608a3b6a8e99206088ebd79df1ee50f3cbb8392a..25cdcb90768af0a1a8fe3d36e1f5ae19c89f2713 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/video/mt9t112.c @@ -78,11 +78,6 @@ /************************************************************************ struct ************************************************************************/ -struct mt9t112_frame_size { - u16 width; - u16 height; -}; - struct mt9t112_format { enum v4l2_mbus_pixelcode code; enum v4l2_colorspace colorspace; @@ -95,7 +90,7 @@ struct mt9t112_priv { struct mt9t112_camera_info *info; struct i2c_client *client; struct soc_camera_device icd; - struct mt9t112_frame_size frame; + struct v4l2_rect frame; const struct mt9t112_format *format; int model; u32 flags; @@ -348,13 +343,10 @@ static int mt9t112_clock_info(const struct i2c_client *client, u32 ext) } #endif -static void mt9t112_frame_check(u32 *width, u32 *height) +static void mt9t112_frame_check(u32 *width, u32 *height, u32 *left, u32 *top) { - if (*width > MAX_WIDTH) - *width = MAX_WIDTH; - - if (*height > MAX_HEIGHT) - *height = MAX_HEIGHT; + soc_camera_limit_side(left, width, 0, 0, MAX_WIDTH); + soc_camera_limit_side(top, height, 0, 0, MAX_HEIGHT); } 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) return ret; } -static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height, +static int mt9t112_set_params(struct mt9t112_priv *priv, + const struct v4l2_rect *rect, enum v4l2_mbus_pixelcode code) { - struct mt9t112_priv *priv = to_mt9t112(client); int i; - priv->format = NULL; - - /* - * frame size check - */ - mt9t112_frame_check(&width, &height); - /* * get color format */ @@ -872,8 +857,13 @@ static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height, if (i == ARRAY_SIZE(mt9t112_cfmts)) return -EINVAL; - priv->frame.width = (u16)width; - priv->frame.height = (u16)height; + priv->frame = *rect; + + /* + * frame size check + */ + mt9t112_frame_check(&priv->frame.width, &priv->frame.height, + &priv->frame.left, &priv->frame.top); priv->format = mt9t112_cfmts + i; @@ -884,9 +874,12 @@ static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) { a->bounds.left = 0; a->bounds.top = 0; - a->bounds.width = VGA_WIDTH; - a->bounds.height = VGA_HEIGHT; - a->defrect = a->bounds; + a->bounds.width = MAX_WIDTH; + a->bounds.height = MAX_HEIGHT; + a->defrect.left = 0; + a->defrect.top = 0; + a->defrect.width = VGA_WIDTH; + a->defrect.height = VGA_HEIGHT; a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; a->pixelaspect.numerator = 1; a->pixelaspect.denominator = 1; @@ -896,11 +889,11 @@ static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - a->c.left = 0; - a->c.top = 0; - a->c.width = VGA_WIDTH; - a->c.height = VGA_HEIGHT; - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct mt9t112_priv *priv = to_mt9t112(client); + + a->c = priv->frame; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; return 0; } @@ -908,10 +901,10 @@ static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); + struct mt9t112_priv *priv = to_mt9t112(client); struct v4l2_rect *rect = &a->c; - return mt9t112_set_params(client, rect->width, rect->height, - V4L2_MBUS_FMT_UYVY8_2X8); + return mt9t112_set_params(priv, rect, priv->format->code); } static int mt9t112_g_fmt(struct v4l2_subdev *sd, @@ -920,16 +913,9 @@ static int mt9t112_g_fmt(struct v4l2_subdev *sd, struct i2c_client *client = v4l2_get_subdevdata(sd); struct mt9t112_priv *priv = to_mt9t112(client); - if (!priv->format) { - int ret = mt9t112_set_params(client, VGA_WIDTH, VGA_HEIGHT, - V4L2_MBUS_FMT_UYVY8_2X8); - if (ret < 0) - return ret; - } - mf->width = priv->frame.width; mf->height = priv->frame.height; - /* TODO: set colorspace */ + mf->colorspace = priv->format->colorspace; mf->code = priv->format->code; mf->field = V4L2_FIELD_NONE; @@ -940,17 +926,42 @@ static int mt9t112_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { struct i2c_client *client = v4l2_get_subdevdata(sd); + struct mt9t112_priv *priv = to_mt9t112(client); + struct v4l2_rect rect = { + .width = mf->width, + .height = mf->height, + .left = priv->frame.left, + .top = priv->frame.top, + }; + int ret; + + ret = mt9t112_set_params(priv, &rect, mf->code); + + if (!ret) + mf->colorspace = priv->format->colorspace; - /* TODO: set colorspace */ - return mt9t112_set_params(client, mf->width, mf->height, mf->code); + return ret; } static int mt9t112_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { - mt9t112_frame_check(&mf->width, &mf->height); + unsigned int top, left; + int i; + + for (i = 0; i < ARRAY_SIZE(mt9t112_cfmts); i++) + if (mt9t112_cfmts[i].code == mf->code) + break; + + if (i == ARRAY_SIZE(mt9t112_cfmts)) { + mf->code = V4L2_MBUS_FMT_UYVY8_2X8; + mf->colorspace = V4L2_COLORSPACE_JPEG; + } else { + mf->colorspace = mt9t112_cfmts[i].colorspace; + } + + mt9t112_frame_check(&mf->width, &mf->height, &left, &top); - /* TODO: set colorspace */ mf->field = V4L2_FIELD_NONE; return 0; @@ -963,6 +974,7 @@ static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index, return -EINVAL; *code = mt9t112_cfmts[index].code; + return 0; } @@ -1055,10 +1067,16 @@ static int mt9t112_camera_probe(struct soc_camera_device *icd, static int mt9t112_probe(struct i2c_client *client, const struct i2c_device_id *did) { - struct mt9t112_priv *priv; - struct soc_camera_device *icd = client->dev.platform_data; - struct soc_camera_link *icl; - int ret; + struct mt9t112_priv *priv; + struct soc_camera_device *icd = client->dev.platform_data; + struct soc_camera_link *icl; + struct v4l2_rect rect = { + .width = VGA_WIDTH, + .height = VGA_HEIGHT, + .left = (MAX_WIDTH - VGA_WIDTH) / 2, + .top = (MAX_HEIGHT - VGA_HEIGHT) / 2, + }; + int ret; if (!icd) { dev_err(&client->dev, "mt9t112: missing soc-camera data!\n"); @@ -1083,6 +1101,9 @@ static int mt9t112_probe(struct i2c_client *client, if (ret) kfree(priv); + /* Cannot fail: using the default supported pixel code */ + mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8); + return ret; }