From patchwork Wed Apr 14 14:23:07 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 92413 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o3EEN1ho022571 for ; Wed, 14 Apr 2010 14:23:01 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755695Ab0DNOXA (ORCPT ); Wed, 14 Apr 2010 10:23:00 -0400 Received: from mail.gmx.net ([213.165.64.20]:53696 "HELO mail.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1755594Ab0DNOW7 (ORCPT ); Wed, 14 Apr 2010 10:22:59 -0400 Received: (qmail invoked by alias); 14 Apr 2010 14:22:57 -0000 Received: from p57BD2070.dip0.t-ipconnect.de (EHLO axis700.grange) [87.189.32.112] by mail.gmx.net (mp002) with SMTP; 14 Apr 2010 16:22:57 +0200 X-Authenticated: #20450766 X-Provags-ID: V01U2FsdGVkX1+ua8QMVMeubxZb1NG7pTyyyED7MoXHiA65/+1ega 9TwZFvF+YCpQwM Received: from lyakh (helo=localhost) by axis700.grange with local-esmtp (Exim 4.63) (envelope-from ) id 1O23Uh-0002Wc-Tb; Wed, 14 Apr 2010 16:23:07 +0200 Date: Wed, 14 Apr 2010 16:23:07 +0200 (CEST) From: Guennadi Liakhovetski To: Linux Media Mailing List cc: Valentin Longchamp Subject: [PATCH] mt9t031: preserve output format on VIDIOC_S_CROP Message-ID: MIME-Version: 1.0 X-Y-GMX-Trusted: 0 X-FuHaFi: 0.45000000000000001 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 14 Apr 2010 14:23:01 +0000 (UTC) diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index a9061bf..a604fa0 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -63,6 +63,8 @@ struct mt9t031 { struct v4l2_subdev subdev; struct v4l2_rect rect; /* Sensor window */ + unsigned int out_width; + unsigned int out_height; int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ u16 xskip; u16 yskip; @@ -284,6 +286,26 @@ static u16 mt9t031_skip(s32 *source, s32 target, s32 max) return skip; } +static u16 mt9t031_skip_out(s32 *source, s32 *target) +{ + unsigned int skip; + + if (*source < *target + *target / 2) { + *target = *source; + return 1; + } + + skip = (*source + *target / 2) / *target; + if (skip > 8) { + skip = 8; + *target = (*source + 4) / 8; + } + /* We try to preserve input, but with division we have to adjust it too */ + *source = *target * skip; + + return skip; +} + /* rect is the sensor rectangle, the caller guarantees parameter validity */ static int mt9t031_set_params(struct i2c_client *client, struct v4l2_rect *rect, u16 xskip, u16 yskip) @@ -393,6 +415,7 @@ static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) struct v4l2_rect rect = a->c; struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); + u16 xskip, yskip; rect.width = ALIGN(rect.width, 2); rect.height = ALIGN(rect.height, 2); @@ -403,7 +426,10 @@ static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) soc_camera_limit_side(&rect.top, &rect.height, MT9T031_ROW_SKIP, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT); - return mt9t031_set_params(client, &rect, mt9t031->xskip, mt9t031->yskip); + xskip = mt9t031_skip_out(&rect.width, &mt9t031->out_width); + yskip = mt9t031_skip_out(&rect.height, &mt9t031->out_height); + + return mt9t031_set_params(client, &rect, xskip, yskip); } static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) @@ -437,8 +463,8 @@ static int mt9t031_g_fmt(struct v4l2_subdev *sd, struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); - mf->width = mt9t031->rect.width / mt9t031->xskip; - mf->height = mt9t031->rect.height / mt9t031->yskip; + mf->width = mt9t031->out_width; + mf->height = mt9t031->out_height; mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; mf->colorspace = V4L2_COLORSPACE_SRGB; mf->field = V4L2_FIELD_NONE; @@ -455,8 +481,9 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_rect rect = mt9t031->rect; /* - * try_fmt has put width and height within limits. - * S_FMT: use binning and skipping for scaling + * try_fmt has put width and height within limits. Note: when converting + * to a generic v4l2-subdev driver, try_fmt will have to be called + * explicitly. S_FMT: use binning and skipping for scaling. */ xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH); yskip = mt9t031_skip(&rect.height, mf->height, MT9T031_MAX_HEIGHT); @@ -464,6 +491,9 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; mf->colorspace = V4L2_COLORSPACE_SRGB; + mt9t031->out_width = mf->width; + mt9t031->out_height = mf->height; + /* mt9t031_set_params() doesn't change width and height */ return mt9t031_set_params(client, &rect, xskip, yskip); } @@ -807,6 +837,9 @@ static int mt9t031_probe(struct i2c_client *client, mt9t031->rect.width = MT9T031_MAX_WIDTH; mt9t031->rect.height = MT9T031_MAX_HEIGHT; + mt9t031->out_width = MT9T031_MAX_WIDTH; + mt9t031->out_height = MT9T031_MAX_HEIGHT; + /* * Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width