From patchwork Thu Nov 4 19:02:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 12603675 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D11DBC433F5 for ; Thu, 4 Nov 2021 19:02:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BAC8B61051 for ; Thu, 4 Nov 2021 19:02:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234177AbhKDTEz (ORCPT ); Thu, 4 Nov 2021 15:04:55 -0400 Received: from mail.kernel.org ([198.145.29.99]:45640 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234113AbhKDTEu (ORCPT ); Thu, 4 Nov 2021 15:04:50 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id E074161241; Thu, 4 Nov 2021 19:02:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1636052531; bh=1EZx2skIv3gidB+okmu2aSt5UCRLWsBkMqEWZ/9Pu8Q=; h=From:To:Cc:Subject:Date:From; b=cpArnTU3+eEIP9kQwQgEmnLBzcLgOcL4NrFIQvI9itG9DZT9st/yQzaEFSS+aDusn VMqI2MI1bB15r9d1UntF2Q8KwElLNa3I+LmjuMWXCe14w9+Vna1MQ6m06joLk21ehB NwTyskkU7273ZbxxpuMcNSsVVrfqDrsYpvy6ozme9xLKsVBZbrhruWbEh0/yoRlJHR +B+rHp1xeeE+EfjquQy82xtlSZPc/FvRKogLk1t/4kIG3siqGTysAXoDDJ6uTrtmSe Z82Mzwu86meYjKwo0i6xZHpUOM+ZT4NUJenJ8SdNH4hMZaxNPR5YNdKw6p/xofHts6 xOO/+5Fu+RguA== Received: by mail.kernel.org with local (Exim 4.94.2) (envelope-from ) id 1mihzw-006bKE-DH; Thu, 04 Nov 2021 19:02:04 +0000 From: Mauro Carvalho Chehab Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mauro Carvalho Chehab , Filip Kolev , Greg Kroah-Hartman , Hans Verkuil , Martiros Shakhzadyan , Mauro Carvalho Chehab , Sakari Ailus , Tomi Valkeinen , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linux-staging@lists.linux.dev Subject: [PATCH 1/4] media: atomisp-ov2722: use v4l2_find_nearest_size() Date: Thu, 4 Nov 2021 19:02:00 +0000 Message-Id: X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Sender: Mauro Carvalho Chehab To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Instead of reinventing the wheel, use v4l2_find_nearest_size() in order to get the closest resolution. This should address a bug where the wrong resolution was selected. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2722.c | 118 ++++-------------- drivers/staging/media/atomisp/i2c/ov2722.h | 3 +- 2 files changed, 22 insertions(+), 99 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c index 90d0871a78a3..da98094d7094 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c @@ -557,7 +557,7 @@ static int ov2722_g_volatile_ctrl(struct v4l2_ctrl *ctrl) ret = ov2722_g_fnumber_range(&dev->sd, &ctrl->val); break; case V4L2_CID_LINK_FREQ: - val = ov2722_res[dev->fmt_idx].mipi_freq; + val = dev->res->mipi_freq; if (val == 0) return -EINVAL; @@ -782,76 +782,6 @@ static int ov2722_s_power(struct v4l2_subdev *sd, int on) return ret; } -/* - * distance - calculate the distance - * @res: resolution - * @w: width - * @h: height - * - * Get the gap between resolution and w/h. - * res->width/height smaller than w/h wouldn't be considered. - * Returns the value of gap or -1 if fail. - */ -#define LARGEST_ALLOWED_RATIO_MISMATCH 800 -static int distance(struct ov2722_resolution *res, u32 w, u32 h) -{ - unsigned int w_ratio = (res->width << 13) / w; - unsigned int h_ratio; - int match; - - if (h == 0) - return -1; - h_ratio = (res->height << 13) / h; - if (h_ratio == 0) - return -1; - match = abs(((w_ratio << 13) / h_ratio) - 8192); - - if ((w_ratio < 8192) || (h_ratio < 8192) || - (match > LARGEST_ALLOWED_RATIO_MISMATCH)) - return -1; - - return w_ratio + h_ratio; -} - -/* Return the nearest higher resolution index */ -static int nearest_resolution_index(int w, int h) -{ - int i; - int idx = -1; - int dist; - int min_dist = INT_MAX; - struct ov2722_resolution *tmp_res = NULL; - - for (i = 0; i < N_RES; i++) { - tmp_res = &ov2722_res[i]; - dist = distance(tmp_res, w, h); - if (dist == -1) - continue; - if (dist < min_dist) { - min_dist = dist; - idx = i; - } - } - - return idx; -} - -static int get_resolution_index(int w, int h) -{ - int i; - - for (i = 0; i < N_RES; i++) { - if (w != ov2722_res[i].width) - continue; - if (h != ov2722_res[i].height) - continue; - - return i; - } - - return -1; -} - /* TODO: remove it. */ static int startup(struct v4l2_subdev *sd) { @@ -866,7 +796,7 @@ static int startup(struct v4l2_subdev *sd) return ret; } - ret = ov2722_write_reg_array(client, ov2722_res[dev->fmt_idx].regs); + ret = ov2722_write_reg_array(client, dev->res->regs); if (ret) { dev_err(&client->dev, "ov2722 write register err.\n"); return ret; @@ -882,9 +812,9 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt = &format->format; struct ov2722_device *dev = to_ov2722_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2722_resolution *res; struct camera_mipi_info *ov2722_info = NULL; int ret = 0; - int idx; if (format->pad) return -EINVAL; @@ -895,15 +825,16 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, return -EINVAL; mutex_lock(&dev->input_lock); - idx = nearest_resolution_index(fmt->width, fmt->height); - if (idx == -1) { - /* return the largest resolution */ - fmt->width = ov2722_res[N_RES - 1].width; - fmt->height = ov2722_res[N_RES - 1].height; - } else { - fmt->width = ov2722_res[idx].width; - fmt->height = ov2722_res[idx].height; - } + res = v4l2_find_nearest_size(ov2722_res_preview, + ARRAY_SIZE(ov2722_res_preview), width, + height, fmt->width, fmt->height); + if (!res) + res = &ov2722_res_preview[N_RES - 1]; + + fmt->width = res->width; + fmt->height = res->height; + dev->res = res; + fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; if (format->which == V4L2_SUBDEV_FORMAT_TRY) { sd_state->pads->try_fmt = *fmt; @@ -911,15 +842,9 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, return 0; } - dev->fmt_idx = get_resolution_index(fmt->width, fmt->height); - if (dev->fmt_idx == -1) { - dev_err(&client->dev, "get resolution fail\n"); - mutex_unlock(&dev->input_lock); - return -EINVAL; - } - dev->pixels_per_line = ov2722_res[dev->fmt_idx].pixels_per_line; - dev->lines_per_frame = ov2722_res[dev->fmt_idx].lines_per_frame; + dev->pixels_per_line = dev->res->pixels_per_line; + dev->lines_per_frame = dev->res->lines_per_frame; ret = startup(sd); if (ret) { @@ -950,8 +875,7 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, } } - ret = ov2722_get_intg_factor(client, ov2722_info, - &ov2722_res[dev->fmt_idx]); + ret = ov2722_get_intg_factor(client, ov2722_info, dev->res); if (ret) dev_err(&client->dev, "failed to get integration_factor\n"); @@ -972,8 +896,8 @@ static int ov2722_get_fmt(struct v4l2_subdev *sd, if (!fmt) return -EINVAL; - fmt->width = ov2722_res[dev->fmt_idx].width; - fmt->height = ov2722_res[dev->fmt_idx].height; + fmt->width = dev->res->width; + fmt->height = dev->res->height; fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; return 0; @@ -1098,7 +1022,7 @@ static int ov2722_g_frame_interval(struct v4l2_subdev *sd, struct ov2722_device *dev = to_ov2722_sensor(sd); interval->interval.numerator = 1; - interval->interval.denominator = ov2722_res[dev->fmt_idx].fps; + interval->interval.denominator = dev->res->fps; return 0; } @@ -1136,7 +1060,7 @@ static int ov2722_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) struct ov2722_device *dev = to_ov2722_sensor(sd); mutex_lock(&dev->input_lock); - *frames = ov2722_res[dev->fmt_idx].skip_frames; + *frames = dev->res->skip_frames; mutex_unlock(&dev->input_lock); return 0; @@ -1220,7 +1144,7 @@ static int ov2722_probe(struct i2c_client *client) mutex_init(&dev->input_lock); - dev->fmt_idx = 0; + dev->res = &ov2722_res_preview[0]; v4l2_i2c_subdev_init(&dev->sd, client, &ov2722_ops); ovpdev = gmin_camera_platform_data(&dev->sd, diff --git a/drivers/staging/media/atomisp/i2c/ov2722.h b/drivers/staging/media/atomisp/i2c/ov2722.h index 7b0debb6c53d..d6e2510bc01c 100644 --- a/drivers/staging/media/atomisp/i2c/ov2722.h +++ b/drivers/staging/media/atomisp/i2c/ov2722.h @@ -201,14 +201,13 @@ struct ov2722_device { struct media_pad pad; struct v4l2_mbus_framefmt format; struct mutex input_lock; + struct ov2722_resolution *res; struct camera_sensor_platform_data *platform_data; int vt_pix_clk_freq_mhz; - int fmt_idx; int run_mode; u16 pixels_per_line; u16 lines_per_frame; - u8 res; u8 type; struct v4l2_ctrl_handler ctrl_handler; From patchwork Thu Nov 4 19:02:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 12603669 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 306A7C433EF for ; Thu, 4 Nov 2021 19:02:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 120C261220 for ; Thu, 4 Nov 2021 19:02:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234060AbhKDTEs (ORCPT ); Thu, 4 Nov 2021 15:04:48 -0400 Received: from mail.kernel.org ([198.145.29.99]:45516 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231732AbhKDTEr (ORCPT ); Thu, 4 Nov 2021 15:04:47 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 350DC61051; Thu, 4 Nov 2021 19:02:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1636052529; bh=4j4HtgJYLeoXx4wc8k7GJKoZhBpleOSnZLSVCMvidWA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tTXg713n7Hw0GbrT3W/w3wdutWSxOHc3rjpr6R2zhBSAaEqVboD3Yvd0VJuZCO4qx bHkIiUowdwym1MF2kHYz6KktV9sQQR1/o1trWe+BEh1bVjW0AvhfOvZrYQJJetACXD VdcQ4gNW6L1DXTjCx92rO+X8asRoMPks9LEHm61tSy32dCqtgIkFhdOiX4dmVrWAgx BgeIimJGuK+ApImyGMh2hVVqBm2rvt2NxschvHSJOVC6nyJtiD7Ev+6W64h8lWjV3K C5scDrHxMO0uwz8dRn2OShOx+ZEYagSicLIBzE0ay22m3kHdIKp6NVWEpEW75y3boU nImFXrqbvMnzA== Received: by mail.kernel.org with local (Exim 4.94.2) (envelope-from ) id 1mihzw-006bKH-Dq; Thu, 04 Nov 2021 19:02:04 +0000 From: Mauro Carvalho Chehab Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mauro Carvalho Chehab , Deepak R Varma , Greg Kroah-Hartman , Hans Verkuil , Leonid Kushnir , Mauro Carvalho Chehab , Sakari Ailus , Tomi Valkeinen , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linux-staging@lists.linux.dev Subject: [PATCH 2/4] media: atomisp-gc0310: use v4l2_find_nearest_size() Date: Thu, 4 Nov 2021 19:02:01 +0000 Message-Id: <96baf0373e727971cf25e922c122384b3acd4ef6.1636052511.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Sender: Mauro Carvalho Chehab To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Instead of reinventing the wheel, use v4l2_find_nearest_size() in order to get the closest resolution. This should address a bug where the wrong resolution was selected. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-gc0310.c | 119 ++++-------------- drivers/staging/media/atomisp/i2c/gc0310.h | 3 +- 2 files changed, 22 insertions(+), 100 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index 687888d643df..cbc8b1d91995 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -266,7 +266,7 @@ static int gc0310_g_bin_factor_x(struct v4l2_subdev *sd, s32 *val) { struct gc0310_device *dev = to_gc0310_sensor(sd); - *val = gc0310_res[dev->fmt_idx].bin_factor_x; + *val = dev->res->bin_factor_x; return 0; } @@ -275,7 +275,7 @@ static int gc0310_g_bin_factor_y(struct v4l2_subdev *sd, s32 *val) { struct gc0310_device *dev = to_gc0310_sensor(sd); - *val = gc0310_res[dev->fmt_idx].bin_factor_y; + *val = dev->res->bin_factor_y; return 0; } @@ -878,76 +878,6 @@ static int gc0310_s_power(struct v4l2_subdev *sd, int on) return gc0310_init(sd); } -/* - * distance - calculate the distance - * @res: resolution - * @w: width - * @h: height - * - * Get the gap between resolution and w/h. - * res->width/height smaller than w/h wouldn't be considered. - * Returns the value of gap or -1 if fail. - */ -#define LARGEST_ALLOWED_RATIO_MISMATCH 800 -static int distance(struct gc0310_resolution *res, u32 w, u32 h) -{ - unsigned int w_ratio = (res->width << 13) / w; - unsigned int h_ratio; - int match; - - if (h == 0) - return -1; - h_ratio = (res->height << 13) / h; - if (h_ratio == 0) - return -1; - match = abs(((w_ratio << 13) / h_ratio) - 8192); - - if ((w_ratio < 8192) || (h_ratio < 8192) || - (match > LARGEST_ALLOWED_RATIO_MISMATCH)) - return -1; - - return w_ratio + h_ratio; -} - -/* Return the nearest higher resolution index */ -static int nearest_resolution_index(int w, int h) -{ - int i; - int idx = -1; - int dist; - int min_dist = INT_MAX; - struct gc0310_resolution *tmp_res = NULL; - - for (i = 0; i < N_RES; i++) { - tmp_res = &gc0310_res[i]; - dist = distance(tmp_res, w, h); - if (dist == -1) - continue; - if (dist < min_dist) { - min_dist = dist; - idx = i; - } - } - - return idx; -} - -static int get_resolution_index(int w, int h) -{ - int i; - - for (i = 0; i < N_RES; i++) { - if (w != gc0310_res[i].width) - continue; - if (h != gc0310_res[i].height) - continue; - - return i; - } - - return -1; -} - /* TODO: remove it. */ static int startup(struct v4l2_subdev *sd) { @@ -955,7 +885,7 @@ static int startup(struct v4l2_subdev *sd) struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; - ret = gc0310_write_reg_array(client, gc0310_res[dev->fmt_idx].regs); + ret = gc0310_write_reg_array(client, dev->res->regs); if (ret) { dev_err(&client->dev, "gc0310 write register err.\n"); return ret; @@ -972,8 +902,8 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd, struct gc0310_device *dev = to_gc0310_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); struct camera_mipi_info *gc0310_info = NULL; + struct gc0310_resolution *res; int ret = 0; - int idx = 0; if (format->pad) return -EINVAL; @@ -987,15 +917,16 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd, mutex_lock(&dev->input_lock); - idx = nearest_resolution_index(fmt->width, fmt->height); - if (idx == -1) { - /* return the largest resolution */ - fmt->width = gc0310_res[N_RES - 1].width; - fmt->height = gc0310_res[N_RES - 1].height; - } else { - fmt->width = gc0310_res[idx].width; - fmt->height = gc0310_res[idx].height; - } + res = v4l2_find_nearest_size(gc0310_res_preview, + ARRAY_SIZE(gc0310_res_preview), width, + height, fmt->width, fmt->height); + if (!res) + res = &gc0310_res_preview[N_RES - 1]; + + fmt->width = res->width; + fmt->height = res->height; + dev->res = res; + fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8; if (format->which == V4L2_SUBDEV_FORMAT_TRY) { @@ -1004,23 +935,15 @@ static int gc0310_set_fmt(struct v4l2_subdev *sd, return 0; } - dev->fmt_idx = get_resolution_index(fmt->width, fmt->height); - if (dev->fmt_idx == -1) { - dev_err(&client->dev, "get resolution fail\n"); - mutex_unlock(&dev->input_lock); - return -EINVAL; - } - dev_dbg(&client->dev, "%s: before gc0310_write_reg_array %s\n", - __func__, gc0310_res[dev->fmt_idx].desc); + __func__, dev->res->desc); ret = startup(sd); if (ret) { dev_err(&client->dev, "gc0310 startup err\n"); goto err; } - ret = gc0310_get_intg_factor(client, gc0310_info, - &gc0310_res[dev->fmt_idx]); + ret = gc0310_get_intg_factor(client, gc0310_info, dev->res); if (ret) { dev_err(&client->dev, "failed to get integration_factor\n"); goto err; @@ -1044,8 +967,8 @@ static int gc0310_get_fmt(struct v4l2_subdev *sd, if (!fmt) return -EINVAL; - fmt->width = gc0310_res[dev->fmt_idx].width; - fmt->height = gc0310_res[dev->fmt_idx].height; + fmt->width = dev->res->width; + fmt->height = dev->res->height; fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8; return 0; @@ -1199,7 +1122,7 @@ static int gc0310_g_frame_interval(struct v4l2_subdev *sd, struct gc0310_device *dev = to_gc0310_sensor(sd); interval->interval.numerator = 1; - interval->interval.denominator = gc0310_res[dev->fmt_idx].fps; + interval->interval.denominator = dev->res->fps; return 0; } @@ -1237,7 +1160,7 @@ static int gc0310_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) struct gc0310_device *dev = to_gc0310_sensor(sd); mutex_lock(&dev->input_lock); - *frames = gc0310_res[dev->fmt_idx].skip_frames; + *frames = dev->res->skip_frames; mutex_unlock(&dev->input_lock); return 0; @@ -1301,7 +1224,7 @@ static int gc0310_probe(struct i2c_client *client) mutex_init(&dev->input_lock); - dev->fmt_idx = 0; + dev->res = &gc0310_res_preview[0]; v4l2_i2c_subdev_init(&dev->sd, client, &gc0310_ops); pdata = gmin_camera_platform_data(&dev->sd, diff --git a/drivers/staging/media/atomisp/i2c/gc0310.h b/drivers/staging/media/atomisp/i2c/gc0310.h index 2fe3de115083..db643ebc3909 100644 --- a/drivers/staging/media/atomisp/i2c/gc0310.h +++ b/drivers/staging/media/atomisp/i2c/gc0310.h @@ -150,8 +150,7 @@ struct gc0310_device { struct camera_sensor_platform_data *platform_data; int vt_pix_clk_freq_mhz; - int fmt_idx; - u8 res; + struct gc0310_resolution *res; u8 type; }; From patchwork Thu Nov 4 19:02:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 12603671 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 43F37C433F5 for ; Thu, 4 Nov 2021 19:02:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1835861053 for ; Thu, 4 Nov 2021 19:02:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234085AbhKDTEt (ORCPT ); Thu, 4 Nov 2021 15:04:49 -0400 Received: from mail.kernel.org ([198.145.29.99]:45538 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234052AbhKDTEs (ORCPT ); Thu, 4 Nov 2021 15:04:48 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id E508761215; Thu, 4 Nov 2021 19:02:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1636052529; bh=jeGb7KDr9H9aYgpc5GqB5nCNFONEG93gCA4GSQUlK5k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ws9Uj9wQKIns5SfykPCfhIlXn68DXNrRRkK3mKF1j0TPf3ytRXyhVUsdxmV3XIq5f QLwZrBwyT8W4Euv9ldLaZsHNRCx/4NsnGpTCV4Gny8E+2Pka4f6qKyU/d9mMNdmBbx 1J6lHHrnXGnSPUfkrnsFYzexHCy74biAAzRWxkkqVDYK9z83pf+10w3Qj7cJli1VCq dheBlkj0V8ScigE7M1ZKBTL+gxWIMRPV799+UhXII7GX/j9Q0CtyTJWI9g4/ZrN2rS WYn8r5rHF0f9wz6ZptLWtCNcW6GlyhB9rMMDvdojvKejcb4amcoBcWYnv5dMLJIUrv qMl0SKRcUWlPA== Received: by mail.kernel.org with local (Exim 4.94.2) (envelope-from ) id 1mihzw-006bKK-EO; Thu, 04 Nov 2021 19:02:04 +0000 From: Mauro Carvalho Chehab Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mauro Carvalho Chehab , Beatriz Martins de Carvalho , Bhaskar Chowdhury , Deepak R Varma , Greg Kroah-Hartman , Hans Verkuil , Mauro Carvalho Chehab , Randy Dunlap , Sakari Ailus , Tom Rix , Tomi Valkeinen , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linux-staging@lists.linux.dev Subject: [PATCH 3/4] media: atomisp-gc2235: use v4l2_find_nearest_size() Date: Thu, 4 Nov 2021 19:02:02 +0000 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Sender: Mauro Carvalho Chehab To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Instead of reinventing the wheel, use v4l2_find_nearest_size() in order to get the closest resolution. This should address a bug where the wrong resolution was selected. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-gc2235.c | 113 +++--------------- drivers/staging/media/atomisp/i2c/gc2235.h | 3 +- 2 files changed, 20 insertions(+), 96 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c index 4d769590f2d3..5e7085264189 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c @@ -670,76 +670,6 @@ static int gc2235_s_power(struct v4l2_subdev *sd, int on) return ret; } -/* - * distance - calculate the distance - * @res: resolution - * @w: width - * @h: height - * - * Get the gap between resolution and w/h. - * res->width/height smaller than w/h wouldn't be considered. - * Returns the value of gap or -1 if fail. - */ -#define LARGEST_ALLOWED_RATIO_MISMATCH 800 -static int distance(struct gc2235_resolution *res, u32 w, u32 h) -{ - unsigned int w_ratio = (res->width << 13) / w; - unsigned int h_ratio; - int match; - - if (h == 0) - return -1; - h_ratio = (res->height << 13) / h; - if (h_ratio == 0) - return -1; - match = abs(((w_ratio << 13) / h_ratio) - 8192); - - if ((w_ratio < 8192) || (h_ratio < 8192) || - (match > LARGEST_ALLOWED_RATIO_MISMATCH)) - return -1; - - return w_ratio + h_ratio; -} - -/* Return the nearest higher resolution index */ -static int nearest_resolution_index(int w, int h) -{ - int i; - int idx = -1; - int dist; - int min_dist = INT_MAX; - struct gc2235_resolution *tmp_res = NULL; - - for (i = 0; i < N_RES; i++) { - tmp_res = &gc2235_res[i]; - dist = distance(tmp_res, w, h); - if (dist == -1) - continue; - if (dist < min_dist) { - min_dist = dist; - idx = i; - } - } - - return idx; -} - -static int get_resolution_index(int w, int h) -{ - int i; - - for (i = 0; i < N_RES; i++) { - if (w != gc2235_res[i].width) - continue; - if (h != gc2235_res[i].height) - continue; - - return i; - } - - return -1; -} - static int startup(struct v4l2_subdev *sd) { struct gc2235_device *dev = to_gc2235_sensor(sd); @@ -758,7 +688,7 @@ static int startup(struct v4l2_subdev *sd) gc2235_write_reg_array(client, gc2235_init_settings); } - ret = gc2235_write_reg_array(client, gc2235_res[dev->fmt_idx].regs); + ret = gc2235_write_reg_array(client, dev->res->regs); if (ret) { dev_err(&client->dev, "gc2235 write register err.\n"); return ret; @@ -776,8 +706,8 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd, struct gc2235_device *dev = to_gc2235_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); struct camera_mipi_info *gc2235_info = NULL; + struct gc2235_resolution *res; int ret = 0; - int idx; gc2235_info = v4l2_get_subdev_hostdata(sd); if (!gc2235_info) @@ -786,16 +716,18 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd, return -EINVAL; if (!fmt) return -EINVAL; + mutex_lock(&dev->input_lock); - idx = nearest_resolution_index(fmt->width, fmt->height); - if (idx == -1) { - /* return the largest resolution */ - fmt->width = gc2235_res[N_RES - 1].width; - fmt->height = gc2235_res[N_RES - 1].height; - } else { - fmt->width = gc2235_res[idx].width; - fmt->height = gc2235_res[idx].height; - } + res = v4l2_find_nearest_size(gc2235_res_preview, + ARRAY_SIZE(gc2235_res_preview), width, + height, fmt->width, fmt->height); + if (!res) + res = &gc2235_res_preview[N_RES - 1]; + + fmt->width = res->width; + fmt->height = res->height; + dev->res = res; + fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; if (format->which == V4L2_SUBDEV_FORMAT_TRY) { sd_state->pads->try_fmt = *fmt; @@ -803,13 +735,6 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd, return 0; } - dev->fmt_idx = get_resolution_index(fmt->width, fmt->height); - if (dev->fmt_idx == -1) { - dev_err(&client->dev, "get resolution fail\n"); - mutex_unlock(&dev->input_lock); - return -EINVAL; - } - ret = startup(sd); if (ret) { dev_err(&client->dev, "gc2235 startup err\n"); @@ -817,7 +742,7 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd, } ret = gc2235_get_intg_factor(client, gc2235_info, - &gc2235_res[dev->fmt_idx]); + dev->res); if (ret) dev_err(&client->dev, "failed to get integration_factor\n"); @@ -839,8 +764,8 @@ static int gc2235_get_fmt(struct v4l2_subdev *sd, if (!fmt) return -EINVAL; - fmt->width = gc2235_res[dev->fmt_idx].width; - fmt->height = gc2235_res[dev->fmt_idx].height; + fmt->width = dev->res->width; + fmt->height = dev->res->height; fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; return 0; @@ -953,7 +878,7 @@ static int gc2235_g_frame_interval(struct v4l2_subdev *sd, struct gc2235_device *dev = to_gc2235_sensor(sd); interval->interval.numerator = 1; - interval->interval.denominator = gc2235_res[dev->fmt_idx].fps; + interval->interval.denominator = dev->res->fps; return 0; } @@ -991,7 +916,7 @@ static int gc2235_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) struct gc2235_device *dev = to_gc2235_sensor(sd); mutex_lock(&dev->input_lock); - *frames = gc2235_res[dev->fmt_idx].skip_frames; + *frames = dev->res->skip_frames; mutex_unlock(&dev->input_lock); return 0; @@ -1055,7 +980,7 @@ static int gc2235_probe(struct i2c_client *client) mutex_init(&dev->input_lock); - dev->fmt_idx = 0; + dev->res = &gc2235_res_preview[0]; v4l2_i2c_subdev_init(&dev->sd, client, &gc2235_ops); gcpdev = gmin_camera_platform_data(&dev->sd, diff --git a/drivers/staging/media/atomisp/i2c/gc2235.h b/drivers/staging/media/atomisp/i2c/gc2235.h index ba5db1230033..806be5dff7a5 100644 --- a/drivers/staging/media/atomisp/i2c/gc2235.h +++ b/drivers/staging/media/atomisp/i2c/gc2235.h @@ -158,11 +158,10 @@ struct gc2235_device { struct v4l2_mbus_framefmt format; struct mutex input_lock; struct v4l2_ctrl_handler ctrl_handler; + struct gc2235_resolution *res; struct camera_sensor_platform_data *platform_data; int vt_pix_clk_freq_mhz; - int fmt_idx; - u8 res; u8 type; }; From patchwork Thu Nov 4 19:02:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 12603673 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B629C433EF for ; Thu, 4 Nov 2021 19:02:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4EE6C61157 for ; Thu, 4 Nov 2021 19:02:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234122AbhKDTEv (ORCPT ); Thu, 4 Nov 2021 15:04:51 -0400 Received: from mail.kernel.org ([198.145.29.99]:45604 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231732AbhKDTEt (ORCPT ); Thu, 4 Nov 2021 15:04:49 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 60B0F61221; Thu, 4 Nov 2021 19:02:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1636052531; bh=IduDkzBJsIVclmwQ6Q4Bi2nRgfJSw41FlZNeqKWHBs4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PcEBKJojsu9Un3e4vwYWTjROSoWckJnkdW7MiKcCPMbVLLZKBv7fiFumAMHXXklBn SK5bjSg7SXPvTep+0XHyuT1nGjSMYvO+P3rsjDinlkzhyCE0owNptisdD8pUnmvJUM hKcKuWi+fmy6i6MlOO15hk/CaACQgJKRVkr8AboziTAJ1LK1GgnToveErlvHrtQPix Dve2NretERsaTy6CondD/f55gDEaU4bigpmSYZyu2GWJEjvEe5Rw6KLW3XuynSe0df b+xKevqeSPtWsR9B8OEoOmF6/ng7v+aSZZnVuFV9zHybTPh3qZImnMATNTr378tOGk 1AWhM8TcMY2VA== Received: by mail.kernel.org with local (Exim 4.94.2) (envelope-from ) id 1mihzw-006bKN-F1; Thu, 04 Nov 2021 19:02:04 +0000 From: Mauro Carvalho Chehab Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mauro Carvalho Chehab , Deepak R Varma , Greg Kroah-Hartman , Hans Verkuil , Martiros Shakhzadyan , Mauro Carvalho Chehab , Sakari Ailus , Tomi Valkeinen , Yizhuo , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linux-staging@lists.linux.dev Subject: [PATCH 4/4] media: atomisp-mt9m114: use v4l2_find_nearest_size() Date: Thu, 4 Nov 2021 19:02:03 +0000 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Sender: Mauro Carvalho Chehab To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Instead of reinventing the wheel, use v4l2_find_nearest_size() in order to get the closest resolution. This should address a bug where the wrong resolution was selected. Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-mt9m114.c | 130 ++---------------- 1 file changed, 15 insertions(+), 115 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c index 49f4090856d3..00d6842c07d6 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c @@ -579,107 +579,6 @@ static int mt9m114_s_power(struct v4l2_subdev *sd, int power) return mt9m114_init_common(sd); } -/* - * distance - calculate the distance - * @res: resolution - * @w: width - * @h: height - * - * Get the gap between resolution and w/h. - * res->width/height smaller than w/h wouldn't be considered. - * Returns the value of gap or -1 if fail. - */ -#define LARGEST_ALLOWED_RATIO_MISMATCH 600 -static int distance(struct mt9m114_res_struct const *res, u32 w, u32 h) -{ - unsigned int w_ratio; - unsigned int h_ratio; - int match; - - if (w == 0) - return -1; - w_ratio = (res->width << 13) / w; - if (h == 0) - return -1; - h_ratio = (res->height << 13) / h; - if (h_ratio == 0) - return -1; - match = abs(((w_ratio << 13) / h_ratio) - 8192); - - if ((w_ratio < 8192) || (h_ratio < 8192) || - (match > LARGEST_ALLOWED_RATIO_MISMATCH)) - return -1; - - return w_ratio + h_ratio; -} - -/* Return the nearest higher resolution index */ -static int nearest_resolution_index(int w, int h) -{ - int i; - int idx = -1; - int dist; - int min_dist = INT_MAX; - const struct mt9m114_res_struct *tmp_res = NULL; - - for (i = 0; i < ARRAY_SIZE(mt9m114_res); i++) { - tmp_res = &mt9m114_res[i]; - dist = distance(tmp_res, w, h); - if (dist == -1) - continue; - if (dist < min_dist) { - min_dist = dist; - idx = i; - } - } - - return idx; -} - -static int mt9m114_try_res(u32 *w, u32 *h) -{ - int idx = 0; - - if ((*w > MT9M114_RES_960P_SIZE_H) - || (*h > MT9M114_RES_960P_SIZE_V)) { - *w = MT9M114_RES_960P_SIZE_H; - *h = MT9M114_RES_960P_SIZE_V; - } else { - idx = nearest_resolution_index(*w, *h); - - /* - * nearest_resolution_index() doesn't return smaller - * resolutions. If it fails, it means the requested - * resolution is higher than wecan support. Fallback - * to highest possible resolution in this case. - */ - if (idx == -1) - idx = ARRAY_SIZE(mt9m114_res) - 1; - - *w = mt9m114_res[idx].width; - *h = mt9m114_res[idx].height; - } - - return 0; -} - -static struct mt9m114_res_struct *mt9m114_to_res(u32 w, u32 h) -{ - int index; - - for (index = 0; index < N_RES; index++) { - if ((mt9m114_res[index].width == w) && - (mt9m114_res[index].height == h)) - break; - } - - /* No mode found */ - if (index >= N_RES) - return NULL; - - return &mt9m114_res[index]; -} - static int mt9m114_res2size(struct v4l2_subdev *sd, int *h_size, int *v_size) { struct mt9m114_device *dev = to_mt9m114_sensor(sd); @@ -829,7 +728,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt = &format->format; struct i2c_client *c = v4l2_get_subdevdata(sd); struct mt9m114_device *dev = to_mt9m114_sensor(sd); - struct mt9m114_res_struct *res_index; + struct mt9m114_res_struct *res; u32 width = fmt->width; u32 height = fmt->height; struct camera_mipi_info *mt9m114_info = NULL; @@ -845,20 +744,21 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, if (!mt9m114_info) return -EINVAL; - mt9m114_try_res(&width, &height); + res = v4l2_find_nearest_size(mt9m114_res, + ARRAY_SIZE(mt9m114_res), width, + height, fmt->width, fmt->height); + if (!res) + res = &mt9m114_res[N_RES - 1]; + + fmt->width = res->width; + fmt->height = res->height; + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { sd_state->pads->try_fmt = *fmt; return 0; } - res_index = mt9m114_to_res(width, height); - /* Sanity check */ - if (unlikely(!res_index)) { - WARN_ON(1); - return -EINVAL; - } - - switch (res_index->res) { + switch (res->res) { case MT9M114_RES_736P: ret = mt9m114_write_reg_array(c, mt9m114_736P_init, NO_POLLING); ret += misensor_rmw_reg(c, MISENSOR_16BIT, MISENSOR_READ_MODE, @@ -876,7 +776,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, MISENSOR_R_MODE_MASK, MISENSOR_NORMAL_SET); break; default: - v4l2_err(sd, "set resolution: %d failed!\n", res_index->res); + v4l2_err(sd, "set resolution: %d failed!\n", res->res); return -EINVAL; } @@ -890,7 +790,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, if (mt9m114_set_suspend(sd)) return -EINVAL; - if (dev->res != res_index->res) { + if (dev->res != res->res) { int index; /* Switch to different size */ @@ -922,7 +822,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, } } ret = mt9m114_get_intg_factor(c, mt9m114_info, - &mt9m114_res[res_index->res]); + &mt9m114_res[res->res]); if (ret) { dev_err(&c->dev, "failed to get integration_factor\n"); return -EINVAL; @@ -931,7 +831,7 @@ static int mt9m114_set_fmt(struct v4l2_subdev *sd, * mt9m114 - we don't poll for context switch * because it does not happen with streaming disabled. */ - dev->res = res_index->res; + dev->res = res->res; fmt->width = width; fmt->height = height;