From patchwork Mon Dec 11 17:50:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752864 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hShG54bi" Received: from mail-lf1-x12a.google.com (mail-lf1-x12a.google.com [IPv6:2a00:1450:4864:20::12a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DD19793; Mon, 11 Dec 2023 09:50:46 -0800 (PST) Received: by mail-lf1-x12a.google.com with SMTP id 2adb3069b0e04-50bf69afa99so6052929e87.3; Mon, 11 Dec 2023 09:50:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317044; x=1702921844; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tVL1A/XuQPswwKjRrHcQ3Q+mQNKL8W1neWWaIk0mGMo=; b=hShG54bigAXEIv7Qbg2NHieK/LptHaQj8iXPKw2ocIY0kY/OBsIWqHrHBzmLsHg4gd NkyLrxpJ54CsJr0MLtzZy3tFJXlOuBJ6bx032Do6iuV9yyZh0zSh79QIUwMhFQ/Jy+AI uSpFC6hrYoF9fhNaGokKovO15he3hcTD/27esxBxVdJk9p16GFllz5RNLef7uQyUQdzj PrMVzXPCtXnxhK2EwxPQhGzYWaWMdDoqLakqcY5QObQ9gLShlTeNNL1rtWC9zqlrwl58 wJcL1vOuiEzRSmhre9kzXpQ4pEh67u0SeO5OBf3N2V1Lxi6hpHs+2J7sNS5J/dWlUKzJ uZog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317044; x=1702921844; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tVL1A/XuQPswwKjRrHcQ3Q+mQNKL8W1neWWaIk0mGMo=; b=B2v098CaDzrLzX2w0Ml1i97cc7+6Gw8JmWKu91MpDPoB7ZDCS8LjtonoJ0J8XoUYbe BYwyG+AN488gWHz0ryvORyyhjA19UeA28ArW56UFrL/Eydv1e9I9Dy+2Fvct5v0PkT5q 82FxyD6coghrnus0itdZ75IgAbgm4zIJgfAKsPzH2pXYFdMLd6HkhMCS2npyybXU/OF1 c134/4NqSAa3zNBaetR1tZmY1ONtq31VlIyJ8DZgFpaf7hwwvDjt9iHwMKLhWHuhJj9T ND+s7tLUw4LDIbqsxuTATBT+p7vqnRXq638qw7gHK7XIr8XR60+/335h5UYjTCYbcXq6 NqEw== X-Gm-Message-State: AOJu0Ywg5SsM98QQ78B4BmtTN/dCUF//TPG78A5r8JUWslTPiVgfo68n kRXphV0qXKIASDqiJMsR4272yPTUbRo+v9R0 X-Google-Smtp-Source: AGHT+IF4tVmQSQ35mI4v3I2tcKoJpRf6N0w6CjNwhrJYpIBT5hxg8+3fYQOJPj2vwq1zR49a8c7RVw== X-Received: by 2002:a05:6512:2316:b0:50b:f30b:5499 with SMTP id o22-20020a056512231600b0050bf30b5499mr3065839lfu.80.1702317044420; Mon, 11 Dec 2023 09:50:44 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id h4-20020a056512350400b0050d14ce3958sm1077170lfs.81.2023.12.11.09.50.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:50:43 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 02/19] media: i2c: ov4689: Fix typo in a comment Date: Mon, 11 Dec 2023 20:50:05 +0300 Message-ID: <20231211175023.1680247-3-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Fix a spelling error in a comment. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index ff5213862974..53dcfc8685d4 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -692,7 +692,7 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: - /* 4 least significant bits of expsoure are fractional part */ + /* 4 least significant bits of exposure are fractional part */ ret = ov4689_write_reg(ov4689->client, OV4689_REG_EXPOSURE, OV4689_REG_VALUE_24BIT, ctrl->val << 4); break; From patchwork Mon Dec 11 17:50:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752863 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hHPlHfyw" Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 34AFF93; Mon, 11 Dec 2023 09:50:50 -0800 (PST) Received: by mail-lf1-x133.google.com with SMTP id 2adb3069b0e04-50be4f03b06so4519835e87.0; Mon, 11 Dec 2023 09:50:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317047; x=1702921847; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Jt3HgKogia1ukkriZaYijzD0Deb4LMT0CLdQl1sk2DA=; b=hHPlHfyw0AzvWUbPe8NBRnzUX0bJ2b0jN/eXDf5ikcbLDplZlZkaNcBuMnx5R0RiN7 n8QT/9aOgZ/JwfQ/6fwM4E6KquAdwk6FjS1KapIrQ5T3tAhBNoWJL7JZgo+s7TpbHGq7 fun6BBDgGSN5UFf8p7Jl/XVKRM4j5DGfUSKh+pDfVV0xWb4+gZe9GmQY/wZA2rqUO6Gt 75JnzSVWloqDEgg7CMLB1YPf9/4soNSu+bi8dcizsA1QNE2enHfoAUw8Ytm1YUOH6/U+ 7gH13IcpJtEs4DkdEO2AmPABprukI0GRoRdL9yaJCkmGHwjZPXkbwCqHhSIqwCGeocLU 3G2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317047; x=1702921847; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Jt3HgKogia1ukkriZaYijzD0Deb4LMT0CLdQl1sk2DA=; b=uwZ3f+Iim/pnlyckCHXK7D4VPQDIZGoORRbdho2rr7gvGPVayyBCIIfV85M0v5FH6E vQG2DQ4beOGHMBDOi6/Ahtzm7z4oBcXw8CvrlxLtxrXc9wFJ2H5yGYzm515+/hOevO30 fBvZw/FWjL5cLGLpk7nHHVY7b9LrfaYnhfDrdBdwoPP0oSwRt+zjbIZJRx4x04iILDEm JATljndpdjGEM0naUziacI/gSuVtG0lcy+W0j+khnl06lALZut06M+xIsPuHCu+SLldJ AtD74XitGRydWgp6q//f13HyTYs0aHvyWsYXxlWoWfcI1vF5qMiLYgdkvF3PhaLI4Zsv GE0g== X-Gm-Message-State: AOJu0YznVG4IdJ/iNLH3aEhVjLodC4u6mOy9irNVqPrA37TWM/lrmS6B 9XS37Cwhc8PqMG3sguc1H5w0JJCXlIxiHOVN X-Google-Smtp-Source: AGHT+IHGtRxg62XsLtnV8YDpkrlqiE8FmzxAdThxxu6GtQ+CP6LvFmkhtHLA9Y0xQg28KtVhJxxQoA== X-Received: by 2002:ac2:5e3a:0:b0:50b:f30b:534d with SMTP id o26-20020ac25e3a000000b0050bf30b534dmr1323845lfg.57.1702317047409; Mon, 11 Dec 2023 09:50:47 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id i24-20020a0565123e1800b0050bfdc711b8sm1088996lfv.15.2023.12.11.09.50.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:50:46 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 04/19] media: i2c: ov4689: Remove i2c_client from ov4689 struct Date: Mon, 11 Dec 2023 20:50:07 +0300 Message-ID: <20231211175023.1680247-5-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The 'client' field within the 'ov4689' structure is solely used to access its 'dev' member. This commit removes the 'client' field and directly stores a pointer to the 'struct device'. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index 51a15810cb1d..8c120d7f7830 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -78,7 +78,7 @@ struct ov4689_mode { }; struct ov4689 { - struct i2c_client *client; + struct device *dev; struct regmap *regmap; struct clk *xvclk; struct gpio_desc *reset_gpio; @@ -409,13 +409,13 @@ static int ov4689_get_selection(struct v4l2_subdev *sd, static int ov4689_s_stream(struct v4l2_subdev *sd, int on) { struct ov4689 *ov4689 = to_ov4689(sd); - struct i2c_client *client = ov4689->client; + struct device *dev = ov4689->dev; int ret = 0; mutex_lock(&ov4689->mutex); if (on) { - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) goto unlock_and_return; @@ -424,26 +424,26 @@ static int ov4689_s_stream(struct v4l2_subdev *sd, int on) ov4689->cur_mode->num_regs, NULL); if (ret) { - pm_runtime_put(&client->dev); + pm_runtime_put(dev); goto unlock_and_return; } ret = __v4l2_ctrl_handler_setup(&ov4689->ctrl_handler); if (ret) { - pm_runtime_put(&client->dev); + pm_runtime_put(dev); goto unlock_and_return; } ret = cci_write(ov4689->regmap, OV4689_REG_CTRL_MODE, OV4689_MODE_STREAMING, NULL); if (ret) { - pm_runtime_put(&client->dev); + pm_runtime_put(dev); goto unlock_and_return; } } else { cci_write(ov4689->regmap, OV4689_REG_CTRL_MODE, OV4689_MODE_SW_STANDBY, NULL); - pm_runtime_put(&client->dev); + pm_runtime_put(dev); } unlock_and_return: @@ -557,7 +557,6 @@ static const struct v4l2_subdev_ops ov4689_subdev_ops = { */ static int ov4689_map_gain(struct ov4689 *ov4689, int logical_gain, int *result) { - const struct device *dev = &ov4689->client->dev; const struct ov4689_gain_range *range; unsigned int n; @@ -568,7 +567,8 @@ static int ov4689_map_gain(struct ov4689 *ov4689, int logical_gain, int *result) } if (n == ARRAY_SIZE(ov4689_gain_ranges)) { - dev_warn_ratelimited(dev, "no mapping found for gain %d\n", + dev_warn_ratelimited(ov4689->dev, + "no mapping found for gain %d\n", logical_gain); return -EINVAL; } @@ -584,7 +584,7 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) { struct ov4689 *ov4689 = container_of(ctrl->handler, struct ov4689, ctrl_handler); - struct i2c_client *client = ov4689->client; + struct device *dev = ov4689->dev; int sensor_gain; s64 max_expo; int ret; @@ -601,7 +601,7 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) break; } - if (!pm_runtime_get_if_in_use(&client->dev)) + if (!pm_runtime_get_if_in_use(dev)) return 0; switch (ctrl->id) { @@ -629,13 +629,13 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) ret = ov4689_enable_test_pattern(ov4689, ctrl->val); break; default: - dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", + dev_warn(dev, "%s Unhandled id:0x%x, val:0x%x\n", __func__, ctrl->id, ctrl->val); ret = -EINVAL; break; } - pm_runtime_put(&client->dev); + pm_runtime_put(dev); return ret; } @@ -700,8 +700,7 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689) if (handler->error) { ret = handler->error; - dev_err(&ov4689->client->dev, "Failed to init controls(%d)\n", - ret); + dev_err(ov4689->dev, "Failed to init controls(%d)\n", ret); goto err_free_handler; } @@ -727,7 +726,7 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689) static int ov4689_check_sensor_id(struct ov4689 *ov4689, struct i2c_client *client) { - struct device *dev = &ov4689->client->dev; + struct device *dev = ov4689->dev; u64 id = 0; int ret; @@ -755,7 +754,7 @@ static int ov4689_configure_regulators(struct ov4689 *ov4689) for (i = 0; i < ARRAY_SIZE(ov4689_supply_names); i++) ov4689->supplies[i].supply = ov4689_supply_names[i]; - return devm_regulator_bulk_get(&ov4689->client->dev, + return devm_regulator_bulk_get(ov4689->dev, ARRAY_SIZE(ov4689_supply_names), ov4689->supplies); } @@ -824,7 +823,8 @@ static int ov4689_probe(struct i2c_client *client) if (!ov4689) return -ENOMEM; - ov4689->client = client; + ov4689->dev = dev; + ov4689->cur_mode = &supported_modes[OV4689_MODE_2688_1520]; ov4689->xvclk = devm_clk_get_optional(dev, NULL); From patchwork Mon Dec 11 17:50:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752862 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hg/i0+kd" Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BFA9BC7; Mon, 11 Dec 2023 09:50:52 -0800 (PST) Received: by mail-lj1-x22d.google.com with SMTP id 38308e7fff4ca-2c9ea37ac87so65520551fa.3; Mon, 11 Dec 2023 09:50:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317050; x=1702921850; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vPJtRqKNEOg0N5Ytto1LWF17klynRrR8m/oK9rsOY4A=; b=hg/i0+kdPHNu4Q1yaFRuUqpcqAmXiphnA43I6syZ/t3dKBwF5WDgXypTfxuTC9CB/g 4c60x43Z7nQVGftfs+kIiYXGLStgTPpFvduztz5Al+x8ZINUQKBu2Lu9IPCRZINMjjY0 6rw35P5UUifAZqI03SufKRWGB6BAw/JAVQwx71HAoCBympbN+qKOAXp1tvW4fyWKK+GK ARZn305BwYElt3tH3mk/+4hYxGseF+SrZijo7UV9Lf5a8pyQKdoTi99JQukev4B6FAbQ wOcG45M2qKBMxebAi7B/bRttzcQfYCiiQFZ4oG9VoVDaNYi81m9Ox/SqlUL1R2aH9aUh vAdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317050; x=1702921850; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vPJtRqKNEOg0N5Ytto1LWF17klynRrR8m/oK9rsOY4A=; b=RcUT+AeH5QnwMiCw8o6/EY9f7aD6tkAGhcbMLuqZXWU4NwQgAWrCjBEINsKQYQb6sq dq3ON0zZfEuJl7f4As2odd5+FpcY14RqfPRALBxiTEgNEae+G2XvDSEr3NYpTyPz7CDr iQgL0hI5EtGZ+8VXYKNVM2UbtB7z7Xw5c5uNTgS3o4Y54povhTKdiTK6fZD5RFDP0Onn 8QPZMc/hWm2APRgYbDQV//46k5LD6nbPd75xRGeS+uZfNktQG4kIZ22F+KDSp0oZnCAp Y3+r5gy+P2ZKzA3Yv9qYvglw6YpDznpdYs5sXmR99NDY/eHb3ealafDefof7JWIxI0af 6Jyg== X-Gm-Message-State: AOJu0YyFifiEAXI2rbr0K8qlUhpEHQrGfQ7fujQJm9UlgGm+tC6sYM/8 cyMZODGXl8YcSW48PJbRf/xCcnp68i2ZivNr X-Google-Smtp-Source: AGHT+IFmFc6F2lJ+weBv3c+S5+3heR+vSx9u4e7CpgdwzlyIVuDCv5/VZwXJkwdv0CP5fk8fw6pAGw== X-Received: by 2002:a2e:a907:0:b0:2cc:2751:a6b7 with SMTP id j7-20020a2ea907000000b002cc2751a6b7mr815528ljq.21.1702317050576; Mon, 11 Dec 2023 09:50:50 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id h23-20020a2ea497000000b002c9c21d01c2sm1261702lji.101.2023.12.11.09.50.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:50:50 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 06/19] media: i2c: ov4689: Set gain in one 16 bit write Date: Mon, 11 Dec 2023 20:50:09 +0300 Message-ID: <20231211175023.1680247-7-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 According to the datasheet, bits 0-7 of the AEC LONG GAIN register (0x3508) map to bits 8-15 of the gain value and no masking is required. Thus set analogue gain in a single 16-bit write instead of two 8-bit writes. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index 42700ecfbe0e..5392f650960c 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -32,11 +32,7 @@ #define OV4689_EXPOSURE_STEP 1 #define OV4689_VTS_MAX 0x7fff -#define OV4689_REG_GAIN_H CCI_REG8(0x3508) -#define OV4689_REG_GAIN_L CCI_REG8(0x3509) -#define OV4689_GAIN_H_MASK 0x07 -#define OV4689_GAIN_H_SHIFT 8 -#define OV4689_GAIN_L_MASK 0xff +#define OV4689_REG_GAIN CCI_REG16(0x3508) #define OV4689_GAIN_STEP 1 #define OV4689_GAIN_DEFAULT 0x80 @@ -613,14 +609,7 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: ret = ov4689_map_gain(ov4689, val, &sensor_gain); - - cci_write(regmap, OV4689_REG_GAIN_H, - (sensor_gain >> OV4689_GAIN_H_SHIFT) & - OV4689_GAIN_H_MASK, &ret); - - cci_write(regmap, OV4689_REG_GAIN_L, - sensor_gain & OV4689_GAIN_L_MASK, - &ret); + cci_write(regmap, OV4689_REG_GAIN, sensor_gain, &ret); break; case V4L2_CID_VBLANK: cci_write(regmap, OV4689_REG_VTS, From patchwork Mon Dec 11 17:50:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752861 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eWLScynt" Received: from mail-lj1-x22c.google.com (mail-lj1-x22c.google.com [IPv6:2a00:1450:4864:20::22c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 21ACFD8; Mon, 11 Dec 2023 09:50:54 -0800 (PST) Received: by mail-lj1-x22c.google.com with SMTP id 38308e7fff4ca-2c9f7fe6623so59317491fa.3; Mon, 11 Dec 2023 09:50:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317052; x=1702921852; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wNY858fptfzHBCj2MypAYw/Wf6IpNmLWS0ucyNJkm2A=; b=eWLScynttCeFKklww37oAkdqxr3wBwT2+pBCyDOTRqUKxPoOrXq1EUt+zdFnqAx6Zc 6Zp8BwLzCM1tkBUew7uqhtEDSsB+xYOt9a5KnfwyrZMslxfihiroXdpQiMLzLNE6IwPN XVeJ1aQ9gLDxAEDCq2sb4/Il/wqIrZ3ZXzdH4AjlQrBoL2pJuZOUAqgNKYIg9FEBFQDd p99ydF7l5qcqrnBRBsJk91Wt32Xh787GT1PMIPef8WRaa65MqTUSJQDwQRZrOrOQPnCR HrGzCpAbC4PHiecnJtXuamTvpcMTNDdzZn0Ywf//tvYzikEmBOE5vBQpCP7bwBebpMiG OZFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317052; x=1702921852; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wNY858fptfzHBCj2MypAYw/Wf6IpNmLWS0ucyNJkm2A=; b=HmFBsbMi56YrGIICwnCndgUSCuCx0E38Ac4a6p9J1W6/sb3mT98x4O2Cexulo0QTdC nvMAdHWfUeUj76ZVUsskSy/Fjg0m0vVlQrOdczKsSS+mMaWMwbr4SaaYzGcXIuK1ja1F oa01saVB3q9HvujK3y+5Gur8lEAFrjd70JLb+vXFzJUCy18tadaUwL+W44YklR3LxMaF CEFCJ0uDooCtBcHpQKSo0fmd420SW1ab/d+l/Q3FlOeCe0cJv5cJkrF0Wqau3rmtWbUk uawJYq/t4fhMr6KWKVyE7YjUVaVLKoXsbod0O7uBbhbff2AK2CegwoKw/rUuZX88iUUa uyUA== X-Gm-Message-State: AOJu0YyCm5547Stu1AZ59ZM7SvWJ33ZRh9pFCcdo9PHfNoWIS3etPbfQ eEWL2FS7uRU7vR4r1EkZzvn0M0ZRH2cnHxIZ X-Google-Smtp-Source: AGHT+IH26GtRvX/KgEuwocMcOiixU+UU/MaEbyQx18L+a9Mob6SQ0CLGoU2SnAAFJy/Z4duQpho9dw== X-Received: by 2002:a19:655a:0:b0:50b:fe63:ef9 with SMTP id c26-20020a19655a000000b0050bfe630ef9mr1413617lfj.73.1702317051775; Mon, 11 Dec 2023 09:50:51 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id b4-20020a056512060400b0050bfdb13929sm1130734lfe.73.2023.12.11.09.50.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:50:51 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 07/19] media: i2c: ov4689: Use sub-device active state Date: Mon, 11 Dec 2023 20:50:10 +0300 Message-ID: <20231211175023.1680247-8-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Use sub-device active state. Employ control handler lock to synchronize access to the active state and s_stream. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 68 +++++++++++++++----------------------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index 5392f650960c..2eef64cd0070 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -86,7 +86,6 @@ struct ov4689 { u32 clock_rate; - struct mutex mutex; /* lock to protect ctrls and cur_mode */ struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *exposure; @@ -319,19 +318,6 @@ static int ov4689_set_fmt(struct v4l2_subdev *sd, return 0; } -static int ov4689_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format; - struct ov4689 *ov4689 = to_ov4689(sd); - - /* only one mode supported for now */ - ov4689_fill_fmt(ov4689->cur_mode, mbus_fmt); - - return 0; -} - static int ov4689_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) @@ -405,10 +391,11 @@ static int ov4689_get_selection(struct v4l2_subdev *sd, static int ov4689_s_stream(struct v4l2_subdev *sd, int on) { struct ov4689 *ov4689 = to_ov4689(sd); + struct v4l2_subdev_state *sd_state; struct device *dev = ov4689->dev; int ret = 0; - mutex_lock(&ov4689->mutex); + sd_state = v4l2_subdev_lock_and_get_active_state(&ov4689->subdev); if (on) { ret = pm_runtime_resume_and_get(dev); @@ -443,7 +430,7 @@ static int ov4689_s_stream(struct v4l2_subdev *sd, int on) } unlock_and_return: - mutex_unlock(&ov4689->mutex); + v4l2_subdev_unlock_state(sd_state); return ret; } @@ -506,19 +493,15 @@ static int __maybe_unused ov4689_power_off(struct device *dev) return 0; } -static int ov4689_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +static int ov4689_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state) { - struct ov4689 *ov4689 = to_ov4689(sd); - struct v4l2_mbus_framefmt *try_fmt; - - mutex_lock(&ov4689->mutex); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_state_get_format(sd_state, 0); - try_fmt = v4l2_subdev_state_get_format(fh->state, 0); /* Initialize try_fmt */ ov4689_fill_fmt(&supported_modes[OV4689_MODE_2688_1520], try_fmt); - mutex_unlock(&ov4689->mutex); - return 0; } @@ -526,18 +509,15 @@ static const struct dev_pm_ops ov4689_pm_ops = { SET_RUNTIME_PM_OPS(ov4689_power_off, ov4689_power_on, NULL) }; -static const struct v4l2_subdev_internal_ops ov4689_internal_ops = { - .open = ov4689_open, -}; - static const struct v4l2_subdev_video_ops ov4689_video_ops = { .s_stream = ov4689_s_stream, }; static const struct v4l2_subdev_pad_ops ov4689_pad_ops = { + .init_cfg = ov4689_init_cfg, .enum_mbus_code = ov4689_enum_mbus_code, .enum_frame_size = ov4689_enum_frame_sizes, - .get_fmt = ov4689_get_fmt, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = ov4689_set_fmt, .get_selection = ov4689_get_selection, }; @@ -649,7 +629,6 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689) ret = v4l2_ctrl_handler_init(handler, 10); if (ret) return ret; - handler->lock = &ov4689->mutex; ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, 0, 0, link_freq_menu_items); @@ -862,13 +841,14 @@ static int ov4689_probe(struct i2c_client *client) return dev_err_probe(dev, ret, "Failed to get power regulators\n"); - mutex_init(&ov4689->mutex); - sd = &ov4689->subdev; v4l2_i2c_subdev_init(sd, client, &ov4689_subdev_ops); + ret = ov4689_initialize_controls(ov4689); - if (ret) - goto err_destroy_mutex; + if (ret) { + dev_err(dev, "Failed to initialize controls\n"); + return ret; + } ret = ov4689_power_on(dev); if (ret) @@ -878,19 +858,26 @@ static int ov4689_probe(struct i2c_client *client) if (ret) goto err_power_off; - sd->internal_ops = &ov4689_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; ov4689->pad.flags = MEDIA_PAD_FL_SOURCE; - sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; ret = media_entity_pads_init(&sd->entity, 1, &ov4689->pad); if (ret < 0) goto err_power_off; + sd->state_lock = ov4689->ctrl_handler.lock; + ret = v4l2_subdev_init_finalize(sd); + + if (ret) { + dev_err(dev, "Could not register v4l2 device\n"); + goto err_clean_entity; + } + ret = v4l2_async_register_subdev_sensor(sd); if (ret) { dev_err(dev, "v4l2 async register subdev failed\n"); - goto err_clean_entity; + goto err_clean_subdev; } pm_runtime_set_active(dev); @@ -899,14 +886,14 @@ static int ov4689_probe(struct i2c_client *client) return 0; +err_clean_subdev: + v4l2_subdev_cleanup(sd); err_clean_entity: media_entity_cleanup(&sd->entity); err_power_off: ov4689_power_off(dev); err_free_handler: v4l2_ctrl_handler_free(&ov4689->ctrl_handler); -err_destroy_mutex: - mutex_destroy(&ov4689->mutex); return ret; } @@ -918,9 +905,8 @@ static void ov4689_remove(struct i2c_client *client) v4l2_async_unregister_subdev(sd); media_entity_cleanup(&sd->entity); - + v4l2_subdev_cleanup(sd); v4l2_ctrl_handler_free(&ov4689->ctrl_handler); - mutex_destroy(&ov4689->mutex); pm_runtime_disable(&client->dev); if (!pm_runtime_status_suspended(&client->dev)) From patchwork Mon Dec 11 17:50:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752860 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ikL22BnH" Received: from mail-lj1-x22b.google.com (mail-lj1-x22b.google.com [IPv6:2a00:1450:4864:20::22b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6700FC7; Mon, 11 Dec 2023 09:50:56 -0800 (PST) Received: by mail-lj1-x22b.google.com with SMTP id 38308e7fff4ca-2ca0d14976aso63332731fa.2; Mon, 11 Dec 2023 09:50:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317054; x=1702921854; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SSLorSrmwJkpM8Qw+vtX+TJSDohLzn/aN7e/ge7Qmsg=; b=ikL22BnHK4Vla7jiqEVbE/smiIIHLZ3A/hqmCsK+cJyfFWOhctUEqM/wjeYybnoYHP dNuCmlnNdd6bD194+Fga/ywjzgWc7qYQP3AHQvDA9Ik2NrbtHllzfQwUTcpw/GvRZxTv vK5IqUS6wAbM4VAdgg9znPclUkE1RalM5z8Yecu/Opy/wGgtcwUaDrxGLlHcWOUPg2OH kfON1bTySuaJ1DaznrzpTWOiOJXW9jhG3xmvKlM5LSUVUpFfC1hrMVILpZuRiYVDwjQS HN9PT2m7FcEi4WwodP2UM5gfZcEOz9A/uD2Dv79vg3/UVD5M1IsiEG23HYlcvaWuWneK pKRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317054; x=1702921854; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SSLorSrmwJkpM8Qw+vtX+TJSDohLzn/aN7e/ge7Qmsg=; b=jSF/WLgy47mp5bQPtQu44LhO+ElRgfTvZ2zlQ2Dy1JJa8XnSPu81JKufBx9903ro56 q7dFYHYE2bodKl2FBK2Im0qPeDFfTaoMuEf9a63bWhSOePkT9icH0XUcknrlJeE3SwE1 ZJ4e9Ul/2nbC5gGrB6ZiYwj12DUxVvTXKzEMvbB2vudG1q0yHyfYReUnFkQqQFOgSqpW JjnlEkAhbrZjxGnIJ46Eqtff/4nmAwp2SUEp/vvTatfvNJH/RjTdQEbD0eznbE1ZUOYA SGA6Ijo7w5AW1d2HqjQsbrdfq4tEPrVQZZlohrIz4NUryGJlvocCqTZA/koHmUV7FhCO sz5g== X-Gm-Message-State: AOJu0Yw8ejmhunmZ4c3lUvHSxB0skgTFpXN5soE0Sns82JX6O5XBh68V hrVAavrdsdSDntEOWJs3lSLm0Tgl6tcF7sT7 X-Google-Smtp-Source: AGHT+IEjRjqFvVPuCtszQaaZCq9Xh/DE8LO9Gs+FtbYntjTfD6EC2/nB0YQlQEmyQKcszpY80GRmVw== X-Received: by 2002:a2e:a545:0:b0:2cc:202f:6266 with SMTP id e5-20020a2ea545000000b002cc202f6266mr917704ljn.96.1702317053973; Mon, 11 Dec 2023 09:50:53 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id 13-20020a2e154d000000b002ca03d01360sm1360796ljv.23.2023.12.11.09.50.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:50:53 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 09/19] media: i2c: ov4689: Remove max_fps field from struct ov4689_mode Date: Mon, 11 Dec 2023 20:50:12 +0300 Message-ID: <20231211175023.1680247-10-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 max_fps field of struct ov4689_mode is unused in this driver, so remove it. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index ba33b0ced532..9fa06941a0e5 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -60,7 +60,6 @@ struct ov4689_mode { enum ov4689_mode_id id; u32 width; u32 height; - u32 max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -237,7 +236,6 @@ static const struct ov4689_mode supported_modes[] = { .sensor_height = 1536, .crop_top = 8, .crop_left = 16, - .max_fps = 30, .exp_def = 1536, .hts_def = 4 * 2574, .vts_def = 1554, From patchwork Mon Dec 11 17:50:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752859 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jstO4TdZ" Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 368A8C3; Mon, 11 Dec 2023 09:50:59 -0800 (PST) Received: by mail-lf1-x134.google.com with SMTP id 2adb3069b0e04-50bf8843a6fso4723373e87.0; Mon, 11 Dec 2023 09:50:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317057; x=1702921857; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lRa38RGEmz27i+dqJIZM7KN8VTKbmG28KhKh8WuCaJ4=; b=jstO4TdZZqBVGzJ5soti4kqLyfE9JLFOqDNGcG5tSa9CvL3Ke5Pr9VKIucgIkd552d Gp7hIMTJt9DK/UhNuJkm0Iqjuf4TEqo7VdC5DkiU/uBX7o3JnZgRmdvf0EfKbSPOtnf5 nUfUu5OI8fSQKNm/Y+VIwPIvMYiloNzBZV8NGIMXtaxzM801ckaRGoXYIL+bsXUkwJER 5DIzdH8+0lI7v3EYyrqkInMRUc9RB1DxqMNf49751HMFqVJij2J/5eQurwVaTsJr8VNM hWnOoSEBshmyHzTVcEf47gl+rQKH9/Ha87LFZDEzX9n2hz4E7bwHtMKk0Zannl09kWpm LQ0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317057; x=1702921857; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lRa38RGEmz27i+dqJIZM7KN8VTKbmG28KhKh8WuCaJ4=; b=M5GC+oG610jNrBFI/05HRPYMAM5PNyOUaSYOyktZVSZnB487V4bS+NSEfE0YdcZpov z/h2Dtmv9g1SVCBi3YRObvgdrsGaFXqSnmUtGnLn1SDlrKyIEm6OTc3F4AsC6SD1tLna EakJJgVP7gb4EuajcmEYby9oh1gLX6EowwBWPr0Xd+wkXb17GGxMQR3ynmv9MqZ5tNA+ EQHcjH+hO86S+yi2/5m7LCCJeyvBs5hBRlifMaol1Y+tvHjhofYcGFSaBLXugW7l4vjL T9mO9j2m+qXkh62k8xp4Lc31SbZ5oR3e+VhSvk/uZ7tpw8D34yGVLtfRTqu97/xLPA19 HbFw== X-Gm-Message-State: AOJu0YygqOcQB3cmQaI5unqd/40a5febeQwmUVUEV5zFOM117gXlrxMt WEpFhMtxfjiHHeAC3nWH78zJ7AU6E7IADVSU X-Google-Smtp-Source: AGHT+IEvo0fhC92MBtgDiBCjKsHeXq9ZlNGlX/1YBBRYosWGMcHiwVUoMAmpTTiLySpueO62rD2Fgw== X-Received: by 2002:ac2:548d:0:b0:50b:f706:81cd with SMTP id t13-20020ac2548d000000b0050bf70681cdmr2409825lfk.19.1702317056754; Mon, 11 Dec 2023 09:50:56 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id r14-20020ac25a4e000000b0050bfd883f56sm1141079lfn.129.2023.12.11.09.50.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:50:56 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 11/19] media: i2c: ov4689: Implement vflip/hflip controls Date: Mon, 11 Dec 2023 20:50:14 +0300 Message-ID: <20231211175023.1680247-12-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The OV4689 sensor supports horizontal and vertical flipping. Add appropriate controls to the driver. Toggling both array flip and digital flip bits allows to achieve flipping while maintaining output Bayer order. Note that the default value of hflip control corresponds to both bits set, as it was before this patch. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index 67d4004bdcfb..62aeae43d749 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -46,6 +46,14 @@ #define OV4689_HTS_DIVIDER 4 #define OV4689_HTS_MAX 0x7fff +#define OV4689_REG_TIMING_FORMAT1 CCI_REG8(0x3820) +#define OV4689_REG_TIMING_FORMAT2 CCI_REG8(0x3821) +#define OV4689_TIMING_FLIP_MASK GENMASK(2, 1) +#define OV4689_TIMING_FLIP_ARRAY BIT(1) +#define OV4689_TIMING_FLIP_DIGITAL BIT(2) +#define OV4689_TIMING_FLIP_BOTH (OV4689_TIMING_FLIP_ARRAY |\ + OV4689_TIMING_FLIP_DIGITAL) + #define OV4689_LANES 4 #define OV4689_XVCLK_FREQ 24000000 @@ -183,7 +191,6 @@ static const struct cci_reg_sequence ov4689_2688x1520_regs[] = { {CCI_REG8(0x3811), 0x08}, /* H_WIN_OFF_L h_win_off[7:0] = 0x08*/ {CCI_REG8(0x3813), 0x04}, /* V_WIN_OFF_L v_win_off[7:0] = 0x04 */ {CCI_REG8(0x3819), 0x01}, /* VSYNC_END_L vsync_end_point[7:0] = 0x01 */ - {CCI_REG8(0x3821), 0x06}, /* TIMING_FORMAT2 array_h_mirror = 1, digital_h_mirror = 1 */ /* OTP control */ {CCI_REG8(0x3d85), 0x36}, /* OTP_REG85 OTP_power_up_load_setting_enable = 1, @@ -605,6 +612,16 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) (val + ov4689->cur_mode->width) / OV4689_HTS_DIVIDER, &ret); break; + case V4L2_CID_VFLIP: + cci_update_bits(regmap, OV4689_REG_TIMING_FORMAT1, + OV4689_TIMING_FLIP_MASK, + val ? OV4689_TIMING_FLIP_BOTH : 0, &ret); + break; + case V4L2_CID_HFLIP: + cci_update_bits(regmap, OV4689_REG_TIMING_FORMAT2, + OV4689_TIMING_FLIP_MASK, + val ? 0 : OV4689_TIMING_FLIP_BOTH, &ret); + break; default: dev_warn(dev, "%s Unhandled id:0x%x, val:0x%x\n", __func__, ctrl->id, val); @@ -633,7 +650,7 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689) handler = &ov4689->ctrl_handler; mode = ov4689->cur_mode; - ret = v4l2_ctrl_handler_init(handler, 11); + ret = v4l2_ctrl_handler_init(handler, 13); if (ret) return ret; @@ -673,6 +690,9 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689) ARRAY_SIZE(ov4689_test_pattern_menu) - 1, 0, 0, ov4689_test_pattern_menu); + v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); + if (handler->error) { ret = handler->error; dev_err(ov4689->dev, "Failed to init controls(%d)\n", ret); From patchwork Mon Dec 11 17:50:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752858 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nXddlOjK" Received: from mail-lj1-x229.google.com (mail-lj1-x229.google.com [IPv6:2a00:1450:4864:20::229]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D41A4F4; Mon, 11 Dec 2023 09:51:02 -0800 (PST) Received: by mail-lj1-x229.google.com with SMTP id 38308e7fff4ca-2c9bd3ec4f6so59262231fa.2; Mon, 11 Dec 2023 09:51:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317060; x=1702921860; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZV+qykvCHEWTicA8pud0kxh1xP8XT+s6VE1pgxnwgAs=; b=nXddlOjKA7x/J0WEj/achhmSAow85xddAX76If+PlbriwksNZ194VYPuAJgnIPY00u H0HCZX0YCZlB9VsezCuazu/Ru6fS8z887AcTy48Tr7fZxVEirHLp0kthBgH4SAfczUMf LpeY/3GyULA/FC1C26QoiDLE6J78P8KElouljtsV4NhzaT7A+jcE+/ohsBP/ydm0T2V6 3y3LbfhY17p6fxL5hKZrdDWbVDPKUxsBaKIaXmKGhzCjq3NDubt2oDxSZ1Fd/Gs/Fovz eu61bRQhVOmef/pPklBhI5GAPHhI7nVovhFlYzn0QoNuqgkj9ObnBFCQxfkNs0uWkp7D 1DOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317060; x=1702921860; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZV+qykvCHEWTicA8pud0kxh1xP8XT+s6VE1pgxnwgAs=; b=URr/RQAcwL3t+ClsjbKcGBY8EM0hBvQgRBh8WSZ1rIb0HAXpGRSacsFFoH0Pks/RIq HktgDl3gcK5WBtQkQb4xjGQuESbjbc7F5RLovkOx7bkMb9XHFLcCkh0IR0/etRjU9Q1G vRwoXJQar14Hb5E77CRrTrXyfZDWMc4d8z0mh1zz0Z35GLNClsCMzKI9uiUwQX3mwnue 3m/R4TPKhFXMNK3Od+P4w87jlgtckwCaCgKY58W+7aBLVHZOaP5XEuiWKty3rJlPI1Jc Hh/fUosu08FLWXCeR1zD+jFUZKOafPNlQJrAFDhgqeCIJATSN7TcuqrRH38OHrWbGI5x BpSg== X-Gm-Message-State: AOJu0YwLFfqEPVqkMMkFCSO8k694ItczbQL/XCFcGcachrSNBkdteG1S FIWXqqXH9WI58ll4OkVXR6lm5V2L8jwDSwIV X-Google-Smtp-Source: AGHT+IEccW+UpLdSJWpoAvmT80r9rc8lBNJIOQ/CbsEYPYa9E0E5gq2P8EHnKFR5xIY7HoxeUXzViQ== X-Received: by 2002:a2e:a178:0:b0:2c9:fa32:4261 with SMTP id u24-20020a2ea178000000b002c9fa324261mr1222745ljl.60.1702317059731; Mon, 11 Dec 2023 09:50:59 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id s14-20020a05651c200e00b002c9f3e0a075sm1296088ljo.55.2023.12.11.09.50.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:50:59 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 13/19] media: i2c: ov4689: Implement manual color balance controls Date: Mon, 11 Dec 2023 20:50:16 +0300 Message-ID: <20231211175023.1680247-14-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The OV4689 sensor has separate red and blue gain settings (up to 4x). Implement appropriate controls in the driver. Default gain values are not modified. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index ed0ce1b9e55b..18e1fd564ec0 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -41,6 +41,13 @@ #define OV4689_DIG_GAIN_STEP 1 #define OV4689_DIG_GAIN_DEFAULT 0x800 +#define OV4689_REG_WB_GAIN_RED CCI_REG16(0x500c) +#define OV4689_REG_WB_GAIN_BLUE CCI_REG16(0x5010) +#define OV4689_WB_GAIN_MIN 1 +#define OV4689_WB_GAIN_MAX 0xfff +#define OV4689_WB_GAIN_STEP 1 +#define OV4689_WB_GAIN_DEFAULT 0x400 + #define OV4689_REG_TEST_PATTERN CCI_REG8(0x5040) #define OV4689_TEST_PATTERN_ENABLE 0x80 #define OV4689_TEST_PATTERN_DISABLE 0x0 @@ -630,6 +637,12 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_DIGITAL_GAIN: cci_write(regmap, OV4689_REG_DIG_GAIN, val, &ret); break; + case V4L2_CID_RED_BALANCE: + cci_write(regmap, OV4689_REG_WB_GAIN_RED, val, &ret); + break; + case V4L2_CID_BLUE_BALANCE: + cci_write(regmap, OV4689_REG_WB_GAIN_BLUE, val, &ret); + break; default: dev_warn(dev, "%s Unhandled id:0x%x, val:0x%x\n", __func__, ctrl->id, val); @@ -658,7 +671,7 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689) handler = &ov4689->ctrl_handler; mode = ov4689->cur_mode; - ret = v4l2_ctrl_handler_init(handler, 14); + ret = v4l2_ctrl_handler_init(handler, 16); if (ret) return ret; @@ -705,6 +718,14 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689) OV4689_DIG_GAIN_MIN, OV4689_DIG_GAIN_MAX, OV4689_DIG_GAIN_STEP, OV4689_DIG_GAIN_DEFAULT); + v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_RED_BALANCE, + OV4689_WB_GAIN_MIN, OV4689_WB_GAIN_MAX, + OV4689_WB_GAIN_STEP, OV4689_WB_GAIN_DEFAULT); + + v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_BLUE_BALANCE, + OV4689_WB_GAIN_MIN, OV4689_WB_GAIN_MAX, + OV4689_WB_GAIN_STEP, OV4689_WB_GAIN_DEFAULT); + if (handler->error) { ret = handler->error; dev_err(ov4689->dev, "Failed to init controls(%d)\n", ret); From patchwork Mon Dec 11 17:50:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752857 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="iLtXiiIH" Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 43E2211D; Mon, 11 Dec 2023 09:51:05 -0800 (PST) Received: by mail-lj1-x22d.google.com with SMTP id 38308e7fff4ca-2ca1e6a94a4so61519651fa.0; Mon, 11 Dec 2023 09:51:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317062; x=1702921862; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NtvsS5+cD5ElkCe7WN7GeNxLAQrSXFq4ofwLsevoTLU=; b=iLtXiiIHrCiYoyz45znkkLJQR8eDQwz4HgSVJ7/SxEyZEVIwmDykW1GRfbbA5qAtmW hR8kVJBPXenltCtbcZDDQ79GlcHQRUX6wFSxcdHtaxf38Dfwpairk603UTJo6eoBzkLV hYpr0MWpGVJFn3imihF45tymfLyj7X6AuACO7x33+5gFeP3Csb5t8H/uT+8bIF/vzoBN r3e2KJxmqafJkprENuPB4D+lZOTps0VqmyrhtcxrB6rfjHVWBPYsTL8DpgCLVDRPwtrL tJzOSQ5nha7YHfK9k8TWN6vLxsJ6vjHYGOpPpTUelYDR7jLA0T1PEtbAxVcLVWcoT/wZ iRYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317062; x=1702921862; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NtvsS5+cD5ElkCe7WN7GeNxLAQrSXFq4ofwLsevoTLU=; b=TxodND3FXDt6WQIzCmQWXF/fU86eUt+BO3QoGrTBmclJjZlcez6zZyn3iF4AMGeGi7 0N4EJTGRYeu3bVdTIAtGTsz0+am+z9ByyFIG0aobqqnP8iCb45QUuKQbEiPkpE9sJxTb UxsqJ/Dv7c/7j1OPeTLwu1ngT74D9CXGPRVQ4RyjjUE1wZJD9cOolsYmNXIiXAZliBJk lpq9tDmV/BlssvxtdpA0SES0nhLO/DLj8DMODqMt6OhpeQF5r8C7sLPZjsg+SoG2AGs6 bSRvbdbfQFF/j5FEKFgAI3yV5CCc/tupELiuIEqfv4MlLSg2Qkz0pgPZZzjuwgnM5Eq/ F0VA== X-Gm-Message-State: AOJu0YzQ/7AyJxlHmnT/FE5Ncn70g0RPJVvbfGpXDerBmCAC+1qte08N NWl23R6lpJFs1LTsC19kZVw+05bCoOwVuOzj X-Google-Smtp-Source: AGHT+IH/ZthI3yG2Fr7v2ykhYv8bI10WLuD7jRBZm/KlH+KkQSlkDpmriA3ba2M6pw6GNxHasUrv9Q== X-Received: by 2002:a05:651c:158b:b0:2cc:1eb1:b43f with SMTP id h11-20020a05651c158b00b002cc1eb1b43fmr1884874ljq.68.1702317062572; Mon, 11 Dec 2023 09:51:02 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id r6-20020a2e9946000000b002c9f71e61f3sm1293441ljj.6.2023.12.11.09.51.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:51:02 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 15/19] media: i2c: ov4689: Set timing registers programmatically Date: Mon, 11 Dec 2023 20:50:18 +0300 Message-ID: <20231211175023.1680247-16-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Set timing-related and BLC anchor registers via cci calls instead of hardcoding them in the register table. This prepares the driver for implementation of configurable analogue crop and binning. No functional change intended. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 82 +++++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 15 deletions(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index 5acdf9e1b670..9088b4c61cab 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -52,6 +52,15 @@ #define OV4689_TEST_PATTERN_ENABLE 0x80 #define OV4689_TEST_PATTERN_DISABLE 0x0 +#define OV4689_REG_H_CROP_START CCI_REG16(0x3800) +#define OV4689_REG_V_CROP_START CCI_REG16(0x3802) +#define OV4689_REG_H_CROP_END CCI_REG16(0x3804) +#define OV4689_REG_V_CROP_END CCI_REG16(0x3806) +#define OV4689_REG_H_OUTPUT_SIZE CCI_REG16(0x3808) +#define OV4689_REG_V_OUTPUT_SIZE CCI_REG16(0x380a) +#define OV4689_REG_H_WIN_OFF CCI_REG16(0x3810) +#define OV4689_REG_V_WIN_OFF CCI_REG16(0x3812) + #define OV4689_REG_VTS CCI_REG16(0x380e) #define OV4689_VTS_MAX 0x7fff @@ -67,6 +76,17 @@ #define OV4689_TIMING_FLIP_BOTH (OV4689_TIMING_FLIP_ARRAY |\ OV4689_TIMING_FLIP_DIGITAL) +#define OV4689_REG_ANCHOR_LEFT_START CCI_REG16(0x4020) +#define OV4689_ANCHOR_LEFT_START_DEF 576 +#define OV4689_REG_ANCHOR_LEFT_END CCI_REG16(0x4022) +#define OV4689_ANCHOR_LEFT_END_DEF 831 +#define OV4689_REG_ANCHOR_RIGHT_START CCI_REG16(0x4024) +#define OV4689_ANCHOR_RIGHT_START_DEF 1984 +#define OV4689_REG_ANCHOR_RIGHT_END CCI_REG16(0x4026) +#define OV4689_ANCHOR_RIGHT_END_DEF 2239 + +#define OV4689_REG_VFIFO_CTRL_01 CCI_REG8(0x4601) + #define OV4689_LANES 4 #define OV4689_XVCLK_FREQ 24000000 @@ -199,10 +219,6 @@ static const struct cci_reg_sequence ov4689_2688x1520_regs[] = { {CCI_REG8(0x3798), 0x1b}, /* Timing control */ - {CCI_REG8(0x3801), 0x08}, /* H_CROP_START_L h_crop_start[7:0] = 0x08 */ - {CCI_REG8(0x3805), 0x97}, /* H_CROP_END_L h_crop_end[7:0] = 0x97 */ - {CCI_REG8(0x3811), 0x08}, /* H_WIN_OFF_L h_win_off[7:0] = 0x08*/ - {CCI_REG8(0x3813), 0x04}, /* V_WIN_OFF_L v_win_off[7:0] = 0x04 */ {CCI_REG8(0x3819), 0x01}, /* VSYNC_END_L vsync_end_point[7:0] = 0x01 */ /* OTP control */ @@ -218,22 +234,11 @@ static const struct cci_reg_sequence ov4689_2688x1520_regs[] = { {CCI_REG8(0x401b), 0x00}, /* DEBUG_MODE */ {CCI_REG8(0x401d), 0x00}, /* DEBUG_MODE */ {CCI_REG8(0x401f), 0x00}, /* DEBUG_MODE */ - {CCI_REG8(0x4020), 0x00}, /* ANCHOR_LEFT_START_H anchor_left_start[11:8] = 0 */ - {CCI_REG8(0x4021), 0x10}, /* ANCHOR_LEFT_START_L anchor_left_start[7:0] = 0x10 */ - {CCI_REG8(0x4022), 0x07}, /* ANCHOR_LEFT_END_H anchor_left_end[11:8] = 0x07 */ - {CCI_REG8(0x4023), 0xcf}, /* ANCHOR_LEFT_END_L anchor_left_end[7:0] = 0xcf */ - {CCI_REG8(0x4024), 0x09}, /* ANCHOR_RIGHT_START_H anchor_right_start[11:8] = 0x09 */ - {CCI_REG8(0x4025), 0x60}, /* ANCHOR_RIGHT_START_L anchor_right_start[7:0] = 0x60 */ - {CCI_REG8(0x4026), 0x09}, /* ANCHOR_RIGHT_END_H anchor_right_end[11:8] = 0x09 */ - {CCI_REG8(0x4027), 0x6f}, /* ANCHOR_RIGHT_END_L anchor_right_end[7:0] = 0x6f */ /* ADC sync control */ {CCI_REG8(0x4500), 0x6c}, /* ADC_SYNC_CTRL */ {CCI_REG8(0x4503), 0x01}, /* ADC_SYNC_CTRL */ - /* VFIFO */ - {CCI_REG8(0x4601), 0xa7}, /* VFIFO_CTRL_01 r_vfifo_read_start[7:0] = 0xa7 */ - /* Temperature monitor */ {CCI_REG8(0x4d00), 0x04}, /* TPM_CTRL_00 tmp_slope[15:8] = 0x04 */ {CCI_REG8(0x4d01), 0x42}, /* TPM_CTRL_01 tmp_slope[7:0] = 0x42 */ @@ -406,6 +411,41 @@ static int ov4689_get_selection(struct v4l2_subdev *sd, return -EINVAL; } +static int ov4689_setup_timings(struct ov4689 *ov4689) +{ + const struct ov4689_mode *mode = ov4689->cur_mode; + struct regmap *rm = ov4689->regmap; + int ret = 0; + + cci_write(rm, OV4689_REG_H_CROP_START, 8, &ret); + cci_write(rm, OV4689_REG_V_CROP_START, 8, &ret); + cci_write(rm, OV4689_REG_H_CROP_END, 2711, &ret); + cci_write(rm, OV4689_REG_V_CROP_END, 1531, &ret); + + cci_write(rm, OV4689_REG_H_OUTPUT_SIZE, mode->width, &ret); + cci_write(rm, OV4689_REG_V_OUTPUT_SIZE, mode->height, &ret); + + cci_write(rm, OV4689_REG_H_WIN_OFF, 8, &ret); + cci_write(rm, OV4689_REG_V_WIN_OFF, 4, &ret); + + cci_write(rm, OV4689_REG_VFIFO_CTRL_01, 167, &ret); + + return ret; +} + +static int ov4689_setup_blc_anchors(struct ov4689 *ov4689) +{ + struct regmap *rm = ov4689->regmap; + int ret = 0; + + cci_write(rm, OV4689_REG_ANCHOR_LEFT_START, 16, &ret); + cci_write(rm, OV4689_REG_ANCHOR_LEFT_END, 1999, &ret); + cci_write(rm, OV4689_REG_ANCHOR_RIGHT_START, 2400, &ret); + cci_write(rm, OV4689_REG_ANCHOR_RIGHT_END, 2415, &ret); + + return ret; +} + static int ov4689_s_stream(struct v4l2_subdev *sd, int on) { struct ov4689 *ov4689 = to_ov4689(sd); @@ -429,6 +469,18 @@ static int ov4689_s_stream(struct v4l2_subdev *sd, int on) goto unlock_and_return; } + ret = ov4689_setup_timings(ov4689); + if (ret) { + pm_runtime_put(dev); + goto unlock_and_return; + } + + ret = ov4689_setup_blc_anchors(ov4689); + if (ret) { + pm_runtime_put(dev); + goto unlock_and_return; + } + ret = __v4l2_ctrl_handler_setup(&ov4689->ctrl_handler); if (ret) { pm_runtime_put(dev); From patchwork Mon Dec 11 17:50:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752856 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nR1cUa+6" Received: from mail-lf1-x131.google.com (mail-lf1-x131.google.com [IPv6:2a00:1450:4864:20::131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 397B793; Mon, 11 Dec 2023 09:51:08 -0800 (PST) Received: by mail-lf1-x131.google.com with SMTP id 2adb3069b0e04-50bf8843a6fso4723550e87.0; Mon, 11 Dec 2023 09:51:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317065; x=1702921865; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/C0YbxXisOYuGkb4hmqJPNMzEyl5yI/OtRTBBpCRGRE=; b=nR1cUa+6WZo2E9ss+pRTKFpsiycvFZyTfqS5Yh1E5F2yT+Lnx5Gyh9f/q29dTHnGSd g1zShF9IYc0Vp+LDreFI8rXOh55R7lrR0PBwR/ZrkI/lcZRokIIDih4qRe1EAbJbTe+G mZnJSPawgcFMWTuvgCtZpOrTt6qy3DsrrxeD0JYU0hoV3S/dBSQxYfL1E2JotM7Cyc4Y gleyvONvuJErwOUIg0/K3MpZ81TBFGPslzr3Q5VeYTSqS9h2ZNWnx42QLWJ2zJaXIL8B RGr8dgu/tp0moqlBRZZWqM/62vSgOGRuBvRhSZOVcxt6f/AaaVnpBp2Ua5Xpf3HbJ7vd zm3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317065; x=1702921865; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/C0YbxXisOYuGkb4hmqJPNMzEyl5yI/OtRTBBpCRGRE=; b=ojtILzkw5K7Gr87ykYJxfzNsRu47tfnOoT6T7rzC1Y5o2mm2jES3INsPswMc9d0bZA 0fYpJwsXLL2tiIW39XgHtai1hjjAQrSoUDabhzXquFKCp2N/0aM6Yuq5LpFC6PFU2OMb kp2CZ2tu6RA5nMwIGLpDcp7O1IBSQxGqE8c8XciseSYd32IrtBrdSSA+i7gae/b8Jrug M8UP3Dm4j/nm5JZUbb6Vi3XFv+/ZXFu0mwM5niuX7V6hIC8z67CeUgIJGBapkx2NH+rd 8RvbU+UsjzBrxRTmkI0kJohNLu1SYJpPfCeKaXd+6lzmQqF5eFzdpuGFaxEzYsBRONjp uYuQ== X-Gm-Message-State: AOJu0YxAuCgpZwMdMmL+yEBb4ANXpqMlgG9bwRJXxWvTyDDa9uO5vfM8 hzF1twTu6j/mkR9zPI763Cs3SWk8s45+yMQX X-Google-Smtp-Source: AGHT+IH/WwveD5m32+W0pb29xLp3NW32L7ZcSid1R5ABHEAu3lehqPxBav3DaWHPLLjNoAaKNq9CFg== X-Received: by 2002:ac2:4e0a:0:b0:50b:cafc:bd70 with SMTP id e10-20020ac24e0a000000b0050bcafcbd70mr4285598lfr.0.1702317065101; Mon, 11 Dec 2023 09:51:05 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id m21-20020a0565120a9500b0050d1d8674d2sm722733lfu.292.2023.12.11.09.51.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:51:04 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 17/19] media: i2c: ov4689: Eliminate struct ov4689_mode Date: Mon, 11 Dec 2023 20:50:20 +0300 Message-ID: <20231211175023.1680247-18-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 With the output frame size now controlled by selection rather than cur_mode, this commit relocates pixel rate and default VTS to defines. Consequently, it removes struct ov4689_mode and the cur_mode field from struct ov4689. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 70 +++++++++----------------------------- 1 file changed, 17 insertions(+), 53 deletions(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index f3071e661f4a..e21527ae0b10 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -67,6 +67,8 @@ #define OV4689_REG_V_WIN_OFF CCI_REG16(0x3812) #define OV4689_REG_VTS CCI_REG16(0x380e) +/* Default VTS corresponds to 30 fps at default crop and minimal HTS */ +#define OV4689_VTS_DEF 4683 #define OV4689_VTS_MAX 0x7fff #define OV4689_REG_HTS CCI_REG16(0x380c) @@ -94,6 +96,7 @@ #define OV4689_LANES 4 #define OV4689_XVCLK_FREQ 24000000 +#define OV4689_PIXEL_RATE 480000000 #define OV4689_PIXEL_ARRAY_WIDTH 2720 #define OV4689_PIXEL_ARRAY_HEIGHT 1536 @@ -119,24 +122,6 @@ static const char *const ov4689_supply_names[] = { "dvdd", /* Digital core power */ }; -enum ov4689_mode_id { - OV4689_MODE_2688_1520 = 0, - OV4689_NUM_MODES, -}; - -struct ov4689_mode { - enum ov4689_mode_id id; - u32 width; - u32 height; - u32 hts_def; - u32 hts_min; - u32 vts_def; - u32 exp_def; - u32 pixel_rate; - const struct cci_reg_sequence *reg_list; - unsigned int num_regs; -}; - struct ov4689 { struct device *dev; struct regmap *regmap; @@ -152,8 +137,6 @@ struct ov4689 { struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *exposure, *hblank, *vblank; - - const struct ov4689_mode *cur_mode; }; #define to_ov4689(sd) container_of(sd, struct ov4689, subdev) @@ -172,7 +155,7 @@ struct ov4689_gain_range { * max_framerate 90fps * mipi_datarate per lane 1008Mbps */ -static const struct cci_reg_sequence ov4689_2688x1520_regs[] = { +static const struct cci_reg_sequence ov4689_common_regs[] = { /* System control*/ {CCI_REG8(0x0103), 0x01}, /* SC_CTRL0103 software_reset = 1 */ {CCI_REG8(0x3000), 0x20}, /* SC_CMMN_PAD_OEN0 FSIN_output_enable = 1 */ @@ -273,21 +256,6 @@ static const struct cci_reg_sequence ov4689_2688x1520_regs[] = { {CCI_REG8(0x5503), 0x0f}, /* OTP_DPC_END_L otp_end_address[7:0] = 0x0f */ }; -static const struct ov4689_mode supported_modes[] = { - { - .id = OV4689_MODE_2688_1520, - .width = 2688, - .height = 1520, - .exp_def = 1536, - .hts_def = 10296, - .hts_min = 3432, - .vts_def = 1554, - .pixel_rate = 480000000, - .reg_list = ov4689_2688x1520_regs, - .num_regs = ARRAY_SIZE(ov4689_2688x1520_regs), - }, -}; - static const u64 link_freq_menu_items[] = { 504000000 }; static const char *const ov4689_test_pattern_menu[] = { @@ -584,8 +552,8 @@ static int ov4689_s_stream(struct v4l2_subdev *sd, int on) goto unlock_and_return; ret = cci_multi_reg_write(ov4689->regmap, - ov4689->cur_mode->reg_list, - ov4689->cur_mode->num_regs, + ov4689_common_regs, + ARRAY_SIZE(ov4689_common_regs), NULL); if (ret) { pm_runtime_put(dev); @@ -858,14 +826,12 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689) struct i2c_client *client = v4l2_get_subdevdata(&ov4689->subdev); struct v4l2_fwnode_device_properties props; struct v4l2_ctrl_handler *handler; - const struct ov4689_mode *mode; s64 exposure_max, vblank_def; - s64 hblank_def, hblank_min; struct v4l2_ctrl *ctrl; + s64 hblank_def; int ret; handler = &ov4689->ctrl_handler; - mode = ov4689->cur_mode; ret = v4l2_ctrl_handler_init(handler, 16); if (ret) return ret; @@ -876,26 +842,26 @@ static int ov4689_initialize_controls(struct ov4689 *ov4689) ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 0, - mode->pixel_rate, 1, mode->pixel_rate); + OV4689_PIXEL_RATE, 1, OV4689_PIXEL_RATE); - hblank_def = mode->hts_def - mode->width; - hblank_min = mode->hts_min - mode->width; + hblank_def = ov4689_hts_min(OV4689_H_OUTPUT_SIZE_DEFAULT) - + OV4689_H_OUTPUT_SIZE_DEFAULT; ov4689->hblank = v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, - V4L2_CID_HBLANK, hblank_min, - OV4689_HTS_MAX - mode->width, + V4L2_CID_HBLANK, hblank_def, + OV4689_HTS_MAX - OV4689_H_OUTPUT_SIZE_DEFAULT, OV4689_HTS_DIVIDER, hblank_def); - vblank_def = mode->vts_def - mode->height; + vblank_def = OV4689_VTS_DEF - OV4689_V_OUTPUT_SIZE_DEFAULT; ov4689->vblank = v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_VBLANK, OV4689_VBLANK_MIN, - OV4689_VTS_MAX - mode->height, 1, - vblank_def); + OV4689_VTS_MAX - OV4689_V_OUTPUT_SIZE_DEFAULT, + 1, vblank_def); - exposure_max = mode->vts_def - 4; + exposure_max = OV4689_VTS_DEF - 4; ov4689->exposure = v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_EXPOSURE, OV4689_EXPOSURE_MIN, exposure_max, - OV4689_EXPOSURE_STEP, mode->exp_def); + OV4689_EXPOSURE_STEP, exposure_max); v4l2_ctrl_new_std(handler, &ov4689_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, ov4689_gain_ranges[0].logical_min, @@ -1050,8 +1016,6 @@ static int ov4689_probe(struct i2c_client *client) ov4689->dev = dev; - ov4689->cur_mode = &supported_modes[OV4689_MODE_2688_1520]; - ov4689->xvclk = devm_clk_get_optional(dev, NULL); if (IS_ERR(ov4689->xvclk)) return dev_err_probe(dev, PTR_ERR(ov4689->xvclk), From patchwork Mon Dec 11 17:50:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Rudenko X-Patchwork-Id: 752855 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="V0NTn7Ae" Received: from mail-lj1-x22f.google.com (mail-lj1-x22f.google.com [IPv6:2a00:1450:4864:20::22f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 43CE3F4; Mon, 11 Dec 2023 09:51:11 -0800 (PST) Received: by mail-lj1-x22f.google.com with SMTP id 38308e7fff4ca-2ca09601127so63403581fa.1; Mon, 11 Dec 2023 09:51:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702317068; x=1702921868; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=xnEjGpYqb0K7tittd+dUy5/SHqg4UXSF+hRs5s4lNiU=; b=V0NTn7AegTR/N6P6knaLaKJSPKAMjGSD9R1rHHZjFwKA1xefdr1R4tUO/VY4Z9sBJ9 OTsIWgtHVmADErnl4e2CXLzjgKPf4fuGk7ZHYt5WBH3j3lWGL2/V2soCMOlyZhDZ0uY6 Dz/tU4Z03wSEinBBjKzMwu6+CLviB6KwNieKvBmYH/hyzXOPO1JaXlSKDNjZpC2ftUtD X3FJIbBT2t3OF0MwTQCOYxa56EZVES0ahPNKGqzeQFTBoOlJ5WIN209kkP4J1EDllUAW x2juxzbKIT4bcurTWov+v+9DTeNMiq6WgRJIBvOZO/+wByq2FFCoHzHbReKuc+M5Qc9N TgGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702317068; x=1702921868; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xnEjGpYqb0K7tittd+dUy5/SHqg4UXSF+hRs5s4lNiU=; b=Tg7Be8UQjCnKqbfy86tehPsi3XNAdCNCMLyk+Wck3lIe4T49IZx1KwiH067S8roa1j OVkgUF960cxWO/6T4hiyFuJwFdAV6VtI0QlQeWQLmx6WqTDjCmCf9fxJKtiGPRFouTve T3BGQOU8PA1D9AuIcx4bC+U3Fraew+tCzDYqg4LhxB0bYWx3pLuZVt8EobU3+p1cUiJs II7DdjExU07RF2JW0zuTASARh1nR7z/rVG3ZQSuu43IIWWbk1Q8U/Yug450kSm8/Pl+d t/Y9dWp/8JaA0wl7TgfQLk9Js6u59hGt6+MgNajavnp/KabnQmt/EsXb3tf3O23Rz+ML 7RyQ== X-Gm-Message-State: AOJu0Yw5FW5VNcLmM+9ZdiyvsVzVZc1vTDn/B3UEAAaH3Jg0wQyVR+8e tIk+ypQK2AlT9azCE8ovqFaDUUmfmpuqjK7D X-Google-Smtp-Source: AGHT+IEIxjIusrdZxXE48QL3l6bFqRK3VBhCxRbV7yzFOcXCv5oMcUbay46/rhcadR9x/dv7hp8pNg== X-Received: by 2002:a2e:a585:0:b0:2cc:1d21:80a0 with SMTP id m5-20020a2ea585000000b002cc1d2180a0mr1257989ljp.107.1702317068111; Mon, 11 Dec 2023 09:51:08 -0800 (PST) Received: from localhost ([83.149.246.185]) by smtp.gmail.com with ESMTPSA id p7-20020a2e9a87000000b002cc238645aesm303879lji.61.2023.12.11.09.51.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 Dec 2023 09:51:07 -0800 (PST) From: Mikhail Rudenko To: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sakari Ailus , Laurent Pinchart , Jacopo Mondi , Tommaso Merciai , Christophe JAILLET , Dave Stevenson , Mauro Carvalho Chehab , Mikhail Rudenko Subject: [PATCH 19/19] media: i2c: ov4689: Implement 2x2 binning Date: Mon, 11 Dec 2023 20:50:22 +0300 Message-ID: <20231211175023.1680247-20-mike.rudenko@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231211175023.1680247-1-mike.rudenko@gmail.com> References: <20231211175023.1680247-1-mike.rudenko@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Implement 2x2 binning support. Compute best binning mode (none or 2x2) from pad crop and pad format in ov4689_set_fmt. Use output frame size instead of analogue crop to compute control ranges and BLC anchors. Also move ov4689_hts_min and ov4689_update_ctrl_ranges, since they are now also called from ov4689_set_fmt. Update frame timings to accommodate the requirements of binning mode and avoid visual artefacts. Additionally, report 2x2 binned mode in addition to non-binned one in ov4689_enum_frame_sizes. Signed-off-by: Mikhail Rudenko --- drivers/media/i2c/ov4689.c | 192 +++++++++++++++++++++++++------------ 1 file changed, 130 insertions(+), 62 deletions(-) diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index 034bd9077a3a..2967fbfb81e4 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -114,7 +114,7 @@ * Minimum working vertical blanking value. Found experimentally at * minimum HTS values. */ -#define OV4689_VBLANK_MIN 31 +#define OV4689_VBLANK_MIN 35 static const char *const ov4689_supply_names[] = { "avdd", /* Analog power */ @@ -256,6 +256,18 @@ static const struct cci_reg_sequence ov4689_common_regs[] = { {CCI_REG8(0x5503), 0x0f}, /* OTP_DPC_END_L otp_end_address[7:0] = 0x0f */ }; +static const struct cci_reg_sequence ov4689_2x2_binning_regs[] = { + {CCI_REG8(0x3632), 0x05}, /* ADC */ + {CCI_REG8(0x376b), 0x40}, /* Sensor control */ + {CCI_REG8(0x3814), 0x03}, /* H_INC_ODD */ + {CCI_REG8(0x3821), 0x07}, /* TIMING_FORMAT_2 hor_binning = 1*/ + {CCI_REG8(0x382a), 0x03}, /* V_INC_ODD */ + {CCI_REG8(0x3830), 0x08}, /* BLC_NUM_OPTION blc_use_num_2 = 1 */ + {CCI_REG8(0x3836), 0x02}, /* TIMING_REG_36 r_zline_use_num_2 = 1 */ + {CCI_REG8(0x4001), 0x50}, /* BLC DEBUG MODE */ + {CCI_REG8(0x4502), 0x44}, /* ADC synch control*/ +}; + static const u64 link_freq_menu_items[] = { 504000000 }; static const char *const ov4689_test_pattern_menu[] = { @@ -305,18 +317,96 @@ static const struct ov4689_gain_range ov4689_gain_ranges[] = { }, }; +/* + * For now, only 2x2 binning implemented in this driver. + */ +static int ov4689_best_binning(struct ov4689 *ov4689, + const struct v4l2_mbus_framefmt *format, + const struct v4l2_rect *crop, + unsigned int *binning) +{ + const struct v4l2_area candidates[] = { + { crop->width, crop->height }, + { crop->width / 2, crop->height / 2 }, + }; + + const struct v4l2_area *best; + int index; + + best = v4l2_find_nearest_size(candidates, ARRAY_SIZE(candidates), width, + height, format->width, format->height); + if (!best) { + dev_err(ov4689->dev, + "failed to find best binning for requested mode\n"); + return -EINVAL; + } + + index = best - candidates; + *binning = index + 1; + + dev_dbg(ov4689->dev, + "best_binning: crop=%dx%d format=%dx%d binning=%d\n", + crop->width, crop->height, format->width, format->height, + *binning); + + return 0; +} + +/* + * Minimum working HTS value for given output width (found + * experimentally). + */ +static unsigned int ov4689_hts_min(unsigned int width) +{ + return max_t(unsigned int, 3156, 224 + width * 19 / 16); +} + +static void ov4689_update_ctrl_ranges(struct ov4689 *ov4689, unsigned int width, + unsigned int height) +{ + struct v4l2_ctrl *exposure = ov4689->exposure; + struct v4l2_ctrl *vblank = ov4689->vblank; + struct v4l2_ctrl *hblank = ov4689->hblank; + s64 def_val, min_val, max_val; + + min_val = ov4689_hts_min(width) - width; + max_val = OV4689_HTS_MAX - width; + def_val = clamp_t(s64, hblank->default_value, min_val, max_val); + __v4l2_ctrl_modify_range(hblank, min_val, max_val, hblank->step, + def_val); + + min_val = OV4689_VBLANK_MIN; + max_val = OV4689_HTS_MAX - width; + def_val = clamp_t(s64, vblank->default_value, min_val, max_val); + __v4l2_ctrl_modify_range(vblank, min_val, max_val, vblank->step, + def_val); + + min_val = exposure->minimum; + max_val = height + vblank->val - 4; + def_val = clamp_t(s64, exposure->default_value, min_val, max_val); + __v4l2_ctrl_modify_range(exposure, min_val, max_val, exposure->step, + def_val); +} + static int ov4689_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { + struct ov4689 *ov4689 = to_ov4689(sd); struct v4l2_mbus_framefmt *format; struct v4l2_rect *crop; + unsigned int binning; + int ret; crop = v4l2_subdev_state_get_crop(sd_state, fmt->pad); format = v4l2_subdev_state_get_format(sd_state, fmt->pad); - format->width = crop->width; - format->height = crop->height; + ret = ov4689_best_binning(ov4689, &fmt->format, crop, &binning); + if (ret) + return ret; + + format->width = crop->width / binning; + format->height = crop->height / binning; format->code = MEDIA_BUS_FMT_SBGGR10_1X10; format->field = V4L2_FIELD_NONE; @@ -327,6 +417,9 @@ static int ov4689_set_fmt(struct v4l2_subdev *sd, fmt->format = *format; + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) + ov4689_update_ctrl_ranges(ov4689, format->width, format->height); + return 0; } @@ -346,8 +439,9 @@ static int ov4689_enum_frame_sizes(struct v4l2_subdev *sd, struct v4l2_subdev_frame_size_enum *fse) { const struct v4l2_rect *crop; + int binning; - if (fse->index >= 1) + if (fse->index >= 2) return -EINVAL; if (fse->code != MEDIA_BUS_FMT_SBGGR10_1X10) @@ -355,10 +449,11 @@ static int ov4689_enum_frame_sizes(struct v4l2_subdev *sd, crop = v4l2_subdev_state_get_crop(sd_state, 0); - fse->min_width = crop->width; - fse->max_width = crop->width; - fse->max_height = crop->height; - fse->min_height = crop->height; + binning = fse->index + 1; + fse->min_width = crop->width / binning; + fse->max_width = crop->width / binning; + fse->max_height = crop->height / binning; + fse->min_height = crop->height / binning; return 0; } @@ -398,42 +493,6 @@ static int ov4689_get_selection(struct v4l2_subdev *sd, return -EINVAL; } -/* - * Minimum working HTS value for given output width (found - * experimentally). - */ -static unsigned int ov4689_hts_min(unsigned int width) -{ - return max_t(unsigned int, 3156, 224 + width * 19 / 16); -} - -static void ov4689_update_ctrl_ranges(struct ov4689 *ov4689, - struct v4l2_rect *crop) -{ - struct v4l2_ctrl *exposure = ov4689->exposure; - struct v4l2_ctrl *vblank = ov4689->vblank; - struct v4l2_ctrl *hblank = ov4689->hblank; - s64 def_val, min_val, max_val; - - min_val = ov4689_hts_min(crop->width) - crop->width; - max_val = OV4689_HTS_MAX - crop->width; - def_val = clamp_t(s64, hblank->default_value, min_val, max_val); - __v4l2_ctrl_modify_range(hblank, min_val, max_val, hblank->step, - def_val); - - min_val = OV4689_VBLANK_MIN; - max_val = OV4689_HTS_MAX - crop->width; - def_val = clamp_t(s64, vblank->default_value, min_val, max_val); - __v4l2_ctrl_modify_range(vblank, min_val, max_val, vblank->step, - def_val); - - min_val = exposure->minimum; - max_val = crop->height + vblank->val - 4; - def_val = clamp_t(s64, exposure->default_value, min_val, max_val); - __v4l2_ctrl_modify_range(exposure, min_val, max_val, exposure->step, - def_val); -} - static int ov4689_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel) @@ -470,7 +529,8 @@ static int ov4689_set_selection(struct v4l2_subdev *sd, format->height = rect.height; if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) - ov4689_update_ctrl_ranges(ov4689, &rect); + ov4689_update_ctrl_ranges(ov4689, rect.width, + rect.height); } *crop = rect; @@ -485,21 +545,27 @@ static int ov4689_setup_timings(struct ov4689 *ov4689, const struct v4l2_mbus_framefmt *format; struct regmap *rm = ov4689->regmap; const struct v4l2_rect *crop; + const int v_offset = 2; + unsigned int binning; int ret = 0; format = v4l2_subdev_state_get_format(state, 0); crop = v4l2_subdev_state_get_crop(state, 0); + ret = ov4689_best_binning(ov4689, format, crop, &binning); + if (ret) + return ret; + cci_write(rm, OV4689_REG_H_CROP_START, crop->left, &ret); - cci_write(rm, OV4689_REG_V_CROP_START, crop->top, &ret); - cci_write(rm, OV4689_REG_H_CROP_END, crop->left + crop->width + 1, &ret); - cci_write(rm, OV4689_REG_V_CROP_END, crop->top + crop->height + 1, &ret); + cci_write(rm, OV4689_REG_V_CROP_START, crop->top - v_offset, &ret); + cci_write(rm, OV4689_REG_H_CROP_END, crop->left + crop->width + 3, &ret); + cci_write(rm, OV4689_REG_V_CROP_END, crop->top + crop->height + 7, &ret); cci_write(rm, OV4689_REG_H_OUTPUT_SIZE, format->width, &ret); cci_write(rm, OV4689_REG_V_OUTPUT_SIZE, format->height, &ret); cci_write(rm, OV4689_REG_H_WIN_OFF, 0, &ret); - cci_write(rm, OV4689_REG_V_WIN_OFF, 0, &ret); + cci_write(rm, OV4689_REG_V_WIN_OFF, v_offset, &ret); /* * Maximum working value of vfifo_read_start for given output @@ -507,6 +573,10 @@ static int ov4689_setup_timings(struct ov4689 *ov4689, */ cci_write(rm, OV4689_REG_VFIFO_CTRL_01, format->width / 16 - 1, &ret); + if (binning == 2) + cci_multi_reg_write(ov4689->regmap, ov4689_2x2_binning_regs, + ARRAY_SIZE(ov4689_2x2_binning_regs), + &ret); return ret; } @@ -519,20 +589,20 @@ static int ov4689_setup_blc_anchors(struct ov4689 *ov4689, struct v4l2_subdev_state *state) { unsigned int width_def = OV4689_H_OUTPUT_SIZE_DEFAULT; + const struct v4l2_mbus_framefmt *format; struct regmap *rm = ov4689->regmap; - const struct v4l2_rect *crop; int ret = 0; - crop = v4l2_subdev_state_get_crop(state, 0); + format = v4l2_subdev_state_get_format(state, 0); cci_write(rm, OV4689_REG_ANCHOR_LEFT_START, - OV4689_ANCHOR_LEFT_START_DEF * crop->width / width_def, &ret); + OV4689_ANCHOR_LEFT_START_DEF * format->width / width_def, &ret); cci_write(rm, OV4689_REG_ANCHOR_LEFT_END, - OV4689_ANCHOR_LEFT_END_DEF * crop->width / width_def, &ret); + OV4689_ANCHOR_LEFT_END_DEF * format->width / width_def, &ret); cci_write(rm, OV4689_REG_ANCHOR_RIGHT_START, - OV4689_ANCHOR_RIGHT_START_DEF * crop->width / width_def, &ret); + OV4689_ANCHOR_RIGHT_START_DEF * format->width / width_def, &ret); cci_write(rm, OV4689_REG_ANCHOR_RIGHT_END, - OV4689_ANCHOR_RIGHT_END_DEF * crop->width / width_def, &ret); + OV4689_ANCHOR_RIGHT_END_DEF * format->width / width_def, &ret); return ret; } @@ -730,20 +800,20 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) struct regmap *regmap = ov4689->regmap; struct v4l2_subdev_state *sd_state; struct device *dev = ov4689->dev; - struct v4l2_rect *crop; + struct v4l2_mbus_framefmt *fmt; s32 val = ctrl->val; int sensor_gain; s64 max_expo, def_expo; int ret; sd_state = v4l2_subdev_get_locked_active_state(&ov4689->subdev); - crop = v4l2_subdev_state_get_crop(sd_state, 0); + fmt = v4l2_subdev_state_get_format(sd_state, 0); /* Propagate change of current control to all related controls */ switch (ctrl->id) { case V4L2_CID_VBLANK: /* Update max exposure while meeting expected vblanking */ - max_expo = crop->height + val - 4; + max_expo = fmt->height + val - 4; def_expo = clamp_t(s64, ov4689->exposure->default_value, ov4689->exposure->minimum, max_expo); @@ -767,16 +837,14 @@ static int ov4689_set_ctrl(struct v4l2_ctrl *ctrl) cci_write(regmap, OV4689_REG_GAIN, sensor_gain, &ret); break; case V4L2_CID_VBLANK: - cci_write(regmap, OV4689_REG_VTS, - val + crop->height, &ret); + cci_write(regmap, OV4689_REG_VTS, val + fmt->height, &ret); break; case V4L2_CID_TEST_PATTERN: ret = ov4689_enable_test_pattern(ov4689, val); break; case V4L2_CID_HBLANK: cci_write(regmap, OV4689_REG_HTS, - (val + crop->width) / - OV4689_HTS_DIVIDER, &ret); + (val + fmt->width) / OV4689_HTS_DIVIDER, &ret); break; case V4L2_CID_VFLIP: cci_update_bits(regmap, OV4689_REG_TIMING_FORMAT1,