From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from lx20.hoststar.hosting (lx20.hoststar.hosting [168.119.41.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4256C3EC2E6; Tue, 24 Mar 2026 10:42:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=168.119.41.54 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774348932; cv=none; b=kUnugpH3NiL1NrjOGip7SyaL21Qshe+tOAUBVqV37XXb1WYzMbb4EPK+S3R+dHQyxpHUKe/qYdt6OAMLiAtIRogUx0/XbL/dlsjy2aSRABm72exiOMaCYGYvhbxmWMyUFZ1c/jqL2pCi38FL5MDIeyfdCWW9gxQ3cEze2PVw6sI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774348932; c=relaxed/simple; bh=fN6VySsURCQWMVtjg8/dz48NZHv3BhQj06urpFQP4Rc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=I3hUzzWcgkVP7h4nfSj1jBBi4yGVmp4wp1+eStfI4kctWkCuSdhDSiPsVI7ovY7eGh6hSgveoO8yLgeEOuN5oN0UwRKuFUZf6cR3UvSFE4XKLZHIAt9DRitsdCv/eTQxnHRfZXYv+xyYq6vXN8Qp1qmrQ0y5e92HKX6jEz6zqV8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=emfend.at; spf=pass smtp.mailfrom=emfend.at; dkim=pass (1024-bit key) header.d=emfend.at header.i=@emfend.at header.b=Uate+BHN; arc=none smtp.client-ip=168.119.41.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=emfend.at Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=emfend.at Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=emfend.at header.i=@emfend.at header.b="Uate+BHN" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=emfend.at; s=mail; h=Cc:To:In-Reply-To:References:Message-Id:Content-Transfer-Encoding: Content-Type:MIME-Version:Subject:Date:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=WlrlJbkbc6GmZ5841B7RnZB+zG8zrXt9wpDIkZ/6yWU=; b=Uate+BHNWlB+NSU4FX1b2OZQzF q7QQQ3x/rT/nmB84o7IHB6rndQiZ24DyEsPqxYn79zMgZBrphBxl6s8+eqrpnDb+hU6fgwPZXbOH5 7nyByX84MREpwFwCTf3kkuBpTDdsQ2TIBtorb6RIeyKpFECPcvHK7GrKOFcr3upSXO14=; Received: from 194-208-208-245.tele.net ([194.208.208.245]:55336 helo=[127.0.1.1]) by lx20.hoststar.hosting with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1w4zD5-00DIvK-5i; Tue, 24 Mar 2026 11:42:07 +0100 From: Matthias Fend Date: Tue, 24 Mar 2026 11:41:42 +0100 Subject: [PATCH v3 8/9] media: i2c: ov08d10: add support for reset and power management Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260324-ov08d10-v3-8-1e44069cf91e@emfend.at> References: <20260324-ov08d10-v3-0-1e44069cf91e@emfend.at> In-Reply-To: <20260324-ov08d10-v3-0-1e44069cf91e@emfend.at> To: Jimmy Su , Sakari Ailus , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Philipp Zabel Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Matthias Fend , bsp-development.geo@leica-geosystems.com X-Mailer: b4 0.14.2 X-Spam-Score: -1.0 X-Spam-Bar: - X-Spam-Report: Spam detection software, running on the system "lx20.hoststar.hosting", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: The OV08D10 can be used also on embedded designs using device tree so allow the sensor to bind to a device tree node. Signed-off-by: Matthias Fend --- drivers/media/i2c/ov08d10.c | 7 +++++++ 1 file changed, 7 insertions(+) Content analysis details: (-1.0 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP 0.0 TVD_RCVD_IP Message was received from an IP address 0.0 KAM_DMARC_STATUS Test Rule for DKIM or SPF Failure with Strict Alignment (older systems) 0.0 Local_hs_NotFromHoststar Sender is NOT hoststar.(ch|at|com) 0.0 Local_hs_NotToHoststar Recipient is NOT hoststar.(ch|at|com) Add support for the required power supplies as well as the control of an optional sensor reset. Signed-off-by: Matthias Fend --- drivers/media/i2c/ov08d10.c | 93 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c index ce0fa30a86129302b5dda0b8796e44054fd77c88..19035991e8bb164d4fca5d87ee4551191974e8bb 100644 --- a/drivers/media/i2c/ov08d10.c +++ b/drivers/media/i2c/ov08d10.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -513,9 +514,17 @@ static const char * const ov08d10_test_pattern_menu[] = { "Standard Color Bar", }; +static const char *const ov08d10_supply_names[] = { + "dovdd", /* Digital I/O power */ + "avdd", /* Analog power */ + "dvdd", /* Digital core power */ +}; + struct ov08d10 { struct device *dev; struct clk *clk; + struct reset_control *reset; + struct regulator_bulk_data supplies[ARRAY_SIZE(ov08d10_supply_names)]; struct v4l2_subdev sd; struct media_pad pad; @@ -1265,6 +1274,56 @@ static const struct v4l2_subdev_internal_ops ov08d10_internal_ops = { .open = ov08d10_open, }; +static int ov08d10_power_off(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct ov08d10 *ov08d10 = to_ov08d10(sd); + + reset_control_assert(ov08d10->reset); + + regulator_bulk_disable(ARRAY_SIZE(ov08d10->supplies), + ov08d10->supplies); + + clk_disable_unprepare(ov08d10->clk); + + return 0; +} + +static int ov08d10_power_on(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct ov08d10 *ov08d10 = to_ov08d10(sd); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ov08d10->supplies), + ov08d10->supplies); + if (ret < 0) { + dev_err(dev, "failed to enable regulators: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(ov08d10->clk); + if (ret < 0) { + regulator_bulk_disable(ARRAY_SIZE(ov08d10->supplies), + ov08d10->supplies); + + dev_err(dev, "failed to enable imaging clock: %d\n", ret); + return ret; + } + + if (ov08d10->reset) { + /* Delay from DVDD stable to sensor XSHUTDN pull up: 5ms */ + fsleep(5 * USEC_PER_MSEC); + + reset_control_deassert(ov08d10->reset); + + /* Delay from XSHUTDN pull up to SCCB start: 8ms */ + fsleep(8 * USEC_PER_MSEC); + } + + return 0; +} + static int ov08d10_identify_module(struct ov08d10 *ov08d10) { struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd); @@ -1371,6 +1430,10 @@ static void ov08d10_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); pm_runtime_disable(ov08d10->dev); + if (!pm_runtime_status_suspended(ov08d10->dev)) { + ov08d10_power_off(ov08d10->dev); + pm_runtime_set_suspended(ov08d10->dev); + } mutex_destroy(&ov08d10->mutex); } @@ -1378,6 +1441,7 @@ static int ov08d10_probe(struct i2c_client *client) { struct ov08d10 *ov08d10; unsigned long freq; + unsigned int i; int ret; ov08d10 = devm_kzalloc(&client->dev, sizeof(*ov08d10), GFP_KERNEL); @@ -1403,12 +1467,32 @@ static int ov08d10_probe(struct i2c_client *client) return ret; } + ov08d10->reset = devm_reset_control_get_optional_exclusive(ov08d10->dev, NULL); + if (IS_ERR(ov08d10->reset)) + return dev_err_probe(ov08d10->dev, PTR_ERR(ov08d10->reset), + "failed to get reset\n"); + reset_control_assert(ov08d10->reset); + + for (i = 0; i < ARRAY_SIZE(ov08d10_supply_names); i++) + ov08d10->supplies[i].supply = ov08d10_supply_names[i]; + + ret = devm_regulator_bulk_get(ov08d10->dev, + ARRAY_SIZE(ov08d10->supplies), + ov08d10->supplies); + if (ret) + return dev_err_probe(ov08d10->dev, ret, + "failed to get regulators\n"); + v4l2_i2c_subdev_init(&ov08d10->sd, client, &ov08d10_subdev_ops); + ret = ov08d10_power_on(ov08d10->dev); + if (ret) + return dev_err_probe(ov08d10->dev, ret, "failed to power on\n"); + ret = ov08d10_identify_module(ov08d10); if (ret) { dev_err(ov08d10->dev, "failed to find sensor: %d\n", ret); - return ret; + goto probe_error_power_off; } mutex_init(&ov08d10->mutex); @@ -1452,9 +1536,15 @@ static int ov08d10_probe(struct i2c_client *client) v4l2_ctrl_handler_free(ov08d10->sd.ctrl_handler); mutex_destroy(&ov08d10->mutex); +probe_error_power_off: + ov08d10_power_off(ov08d10->dev); + return ret; } +static DEFINE_RUNTIME_DEV_PM_OPS(ov08d10_pm_ops, + ov08d10_power_off, ov08d10_power_on, NULL); + #ifdef CONFIG_ACPI static const struct acpi_device_id ov08d10_acpi_ids[] = { { "OVTI08D1" }, @@ -1473,6 +1563,7 @@ MODULE_DEVICE_TABLE(of, ov08d10_of_match); static struct i2c_driver ov08d10_i2c_driver = { .driver = { .name = "ov08d10", + .pm = pm_ptr(&ov08d10_pm_ops), .acpi_match_table = ACPI_PTR(ov08d10_acpi_ids), .of_match_table = ov08d10_of_match, }, -- 2.34.1