Skip to content

Commit

Permalink
[media] V4L: mt9t112: fix broken cropping and scaling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Guennadi Liakhovetski authored and Mauro Carvalho Chehab committed Nov 3, 2011
1 parent d839fe1 commit 377c9ba
Showing 1 changed file with 70 additions and 49 deletions.
119 changes: 70 additions & 49 deletions drivers/media/video/mt9t112.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
*/
Expand All @@ -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;

Expand All @@ -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;
Expand All @@ -896,22 +889,22 @@ 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;
}

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,
Expand All @@ -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;

Expand All @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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");
Expand All @@ -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;
}

Expand Down

0 comments on commit 377c9ba

Please sign in to comment.