* [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements
@ 2026-03-24 10:41 Matthias Fend
2026-03-24 10:41 ` [PATCH v3 1/9] media: i2c: ov08d10: fix runtime PM handling in probe Matthias Fend
` (8 more replies)
0 siblings, 9 replies; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo, Krzysztof Kozlowski
This series provides basic device tree support and handling for power
supplies, an optional reset, and the option to use a 24MHz input clock.
In addition to a few minor fixes, a major problem with the configuration of
the sensor modes has also been resolved.
The changes have been tested on an i.MX8MP platform. Originally, the sensor
was apparently only used with ACPI - unfortunately, I do not have such a
hardware setup available.
Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
---
Changes in v3:
- List me as maintainer in bindings (Sakari)
- Added myself as reviewer (Sakari)
- Rebased
- Link to v2: https://lore.kernel.org/r/20260309-ov08d10-v2-0-81f8b5d99984@emfend.at
Changes in v2:
- Drop 'YAML' in bindings commit message (Krzysztof)
- Use devm_reset_control_get_optional_exclusive() (Philipp)
- Separate commit to fix PM handling in probe (Sakari)
- Added two 'Fixes' tags
- Resort series to get fixes first
- Link to v1: https://lore.kernel.org/r/20260226-ov08d10-v1-0-c3a916368123@emfend.at
---
Matthias Fend (9):
media: i2c: ov08d10: fix runtime PM handling in probe
media: i2c: ov08d10: fix image vertical start setting
media: i2c: ov08d10: remove duplicate register write
media: i2c: ov08d10: fix some typos in comments
media: i2c: ov08d10: add missing newline to prints
dt-bindings: media: i2c: document Omnivision OV08D10 CMOS image sensor
media: i2c: ov08d10: add support for binding via device tree
media: i2c: ov08d10: add support for reset and power management
media: i2c: ov08d10: add support for 24 MHz input clock
.../bindings/media/i2c/ovti,ov08d10.yaml | 101 +++++++++
MAINTAINERS | 2 +
drivers/media/i2c/ov08d10.c | 246 ++++++++++++++++-----
3 files changed, 298 insertions(+), 51 deletions(-)
---
base-commit: 0e2c4117c3512cf6b8f54c2c3d37564bfa3ccd67
change-id: 20260225-ov08d10-7b198f492bd4
Best regards,
--
Matthias Fend <matthias.fend@emfend.at>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 1/9] media: i2c: ov08d10: fix runtime PM handling in probe
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
@ 2026-03-24 10:41 ` Matthias Fend
2026-03-24 10:41 ` [PATCH v3 2/9] media: i2c: ov08d10: fix image vertical start setting Matthias Fend
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo
Set the device's runtime PM status and enable runtime PM before registering
the async sub-device. This is needed to avoid the case where the device is
runtime PM resumed while runtime PM has not been enabled yet.
Remove the related, non-driver-specific comment while at it.
Fixes: 7be91e02ed57 ("media: i2c: Add ov08d10 camera sensor driver")
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
---
drivers/media/i2c/ov08d10.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index 43ec2a1f2fcffb7fa11a6268af3c2edc4df129f3..5b02f61e359fa900da9290c1c151aa01b9d70e6e 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -1430,6 +1430,9 @@ static int ov08d10_probe(struct i2c_client *client)
goto probe_error_v4l2_ctrl_handler_free;
}
+ pm_runtime_set_active(ov08d10->dev);
+ pm_runtime_enable(ov08d10->dev);
+
ret = v4l2_async_register_subdev_sensor(&ov08d10->sd);
if (ret < 0) {
dev_err(ov08d10->dev, "failed to register V4L2 subdev: %d",
@@ -1437,17 +1440,13 @@ static int ov08d10_probe(struct i2c_client *client)
goto probe_error_media_entity_cleanup;
}
- /*
- * Device is already turned on by i2c-core with ACPI domain PM.
- * Enable runtime PM and turn off the device.
- */
- pm_runtime_set_active(ov08d10->dev);
- pm_runtime_enable(ov08d10->dev);
pm_runtime_idle(ov08d10->dev);
return 0;
probe_error_media_entity_cleanup:
+ pm_runtime_disable(ov08d10->dev);
+ pm_runtime_set_suspended(ov08d10->dev);
media_entity_cleanup(&ov08d10->sd.entity);
probe_error_v4l2_ctrl_handler_free:
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 2/9] media: i2c: ov08d10: fix image vertical start setting
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
2026-03-24 10:41 ` [PATCH v3 1/9] media: i2c: ov08d10: fix runtime PM handling in probe Matthias Fend
@ 2026-03-24 10:41 ` Matthias Fend
2026-03-24 10:41 ` [PATCH v3 3/9] media: i2c: ov08d10: remove duplicate register write Matthias Fend
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo
The current settings for the "image vertical start" register appear to be
incorrect. While this only results in an incorrect start line for native
modes, this faulty setting causes actual problems in binning mode. At least
on an i.MX8MP test system, only corrupted frames could be received.
To correct this, the recommended settings from the reference register sets
are used for all modes. Since this shifts the start by one line, the Bayer
pattern also changes, which has also been corrected.
Fixes: 7be91e02ed57 ("media: i2c: Add ov08d10 camera sensor driver")
Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
---
drivers/media/i2c/ov08d10.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index 5b02f61e359fa900da9290c1c151aa01b9d70e6e..5e1b8b58b3d64bcf20a7b1a4e47f547d2fd82998 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -217,7 +217,7 @@ static const struct ov08d10_reg lane_2_mode_3280x2460[] = {
{0x9a, 0x30},
{0xa8, 0x02},
{0xfd, 0x02},
- {0xa1, 0x01},
+ {0xa1, 0x00},
{0xa2, 0x09},
{0xa3, 0x9c},
{0xa5, 0x00},
@@ -335,7 +335,7 @@ static const struct ov08d10_reg lane_2_mode_3264x2448[] = {
{0x9a, 0x30},
{0xa8, 0x02},
{0xfd, 0x02},
- {0xa1, 0x09},
+ {0xa1, 0x08},
{0xa2, 0x09},
{0xa3, 0x90},
{0xa5, 0x08},
@@ -467,7 +467,7 @@ static const struct ov08d10_reg lane_2_mode_1632x1224[] = {
{0xaa, 0xd0},
{0xab, 0x06},
{0xac, 0x68},
- {0xa1, 0x09},
+ {0xa1, 0x04},
{0xa2, 0x04},
{0xa3, 0xc8},
{0xa5, 0x04},
@@ -613,8 +613,8 @@ static const struct ov08d10_lane_cfg lane_cfg_2 = {
static u32 ov08d10_get_format_code(struct ov08d10 *ov08d10)
{
static const u32 codes[2][2] = {
- { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10},
- { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10},
+ { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10 },
+ { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10 },
};
return codes[ov08d10->vflip->val][ov08d10->hflip->val];
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 3/9] media: i2c: ov08d10: remove duplicate register write
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
2026-03-24 10:41 ` [PATCH v3 1/9] media: i2c: ov08d10: fix runtime PM handling in probe Matthias Fend
2026-03-24 10:41 ` [PATCH v3 2/9] media: i2c: ov08d10: fix image vertical start setting Matthias Fend
@ 2026-03-24 10:41 ` Matthias Fend
2026-03-24 10:41 ` [PATCH v3 4/9] media: i2c: ov08d10: fix some typos in comments Matthias Fend
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo
Register P1:0x33 is written twice with the same value in the
'lane_2_mode_1632x1224' sequence. Remove one unnecessary write access.
Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
---
drivers/media/i2c/ov08d10.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index 5e1b8b58b3d64bcf20a7b1a4e47f547d2fd82998..9d54170cdf7da6fe4f03dbf64d5e8976df247846 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -381,7 +381,6 @@ static const struct ov08d10_reg lane_2_mode_1632x1224[] = {
{0x07, 0x05},
{0x21, 0x02},
{0x24, 0x30},
- {0x33, 0x03},
{0x31, 0x06},
{0x33, 0x03},
{0x01, 0x03},
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 4/9] media: i2c: ov08d10: fix some typos in comments
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
` (2 preceding siblings ...)
2026-03-24 10:41 ` [PATCH v3 3/9] media: i2c: ov08d10: remove duplicate register write Matthias Fend
@ 2026-03-24 10:41 ` Matthias Fend
2026-03-24 10:41 ` [PATCH v3 5/9] media: i2c: ov08d10: add missing newline to prints Matthias Fend
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo
Fix some spelling errors in comments.
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
---
drivers/media/i2c/ov08d10.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index 9d54170cdf7da6fe4f03dbf64d5e8976df247846..fd1e0769eebe99ec2e827e9bfd0d0a7731116669 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -88,13 +88,13 @@ struct ov08d10_mode {
/* Frame height in pixels */
u32 height;
- /* Horizontal timining size */
+ /* Horizontal timing size */
u32 hts;
- /* Default vertical timining size */
+ /* Default vertical timing size */
u32 vts_def;
- /* Min vertical timining size */
+ /* Min vertical timing size */
u32 vts_min;
/* Link frequency needed for this resolution */
@@ -533,7 +533,7 @@ struct ov08d10 {
/* Current mode */
const struct ov08d10_mode *cur_mode;
- /* To serialize asynchronus callbacks */
+ /* To serialize asynchronous callbacks */
struct mutex mutex;
/* lanes index */
@@ -863,7 +863,7 @@ static int ov08d10_set_ctrl(struct v4l2_ctrl *ctrl)
exposure_max);
}
- /* V4L2 controls values will be applied only when power is already up */
+ /* V4L2 control values will be applied only when power is already up */
if (!pm_runtime_get_if_in_use(ov08d10->dev))
return 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 5/9] media: i2c: ov08d10: add missing newline to prints
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
` (3 preceding siblings ...)
2026-03-24 10:41 ` [PATCH v3 4/9] media: i2c: ov08d10: fix some typos in comments Matthias Fend
@ 2026-03-24 10:41 ` Matthias Fend
2026-03-24 10:41 ` [PATCH v3 6/9] dt-bindings: media: i2c: document Omnivision OV08D10 CMOS image sensor Matthias Fend
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo
Add trailing \n to dev_* prints where missing.
Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
---
drivers/media/i2c/ov08d10.c | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index fd1e0769eebe99ec2e827e9bfd0d0a7731116669..f2276f49506028c582e49a5b7cab3b07f6ca4e0d 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -664,7 +664,7 @@ static int ov08d10_write_reg_list(struct ov08d10 *ov08d10,
r_list->regs[i].val);
if (ret) {
dev_err_ratelimited(ov08d10->dev,
- "failed to write reg 0x%2.2x. error = %d",
+ "failed to write reg 0x%2.2x. error = %d\n",
r_list->regs[i].address, ret);
return ret;
}
@@ -1024,32 +1024,32 @@ static int ov08d10_start_streaming(struct ov08d10 *ov08d10)
/* soft reset */
ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);
if (ret < 0) {
- dev_err(ov08d10->dev, "failed to reset sensor");
+ dev_err(ov08d10->dev, "failed to reset sensor\n");
return ret;
}
ret = i2c_smbus_write_byte_data(client, 0x20, 0x0e);
if (ret < 0) {
- dev_err(ov08d10->dev, "failed to reset sensor");
+ dev_err(ov08d10->dev, "failed to reset sensor\n");
return ret;
}
usleep_range(3000, 4000);
ret = i2c_smbus_write_byte_data(client, 0x20, 0x0b);
if (ret < 0) {
- dev_err(ov08d10->dev, "failed to reset sensor");
+ dev_err(ov08d10->dev, "failed to reset sensor\n");
return ret;
}
/* update sensor setting */
ret = ov08d10_write_reg_list(ov08d10, reg_list);
if (ret) {
- dev_err(ov08d10->dev, "failed to set plls");
+ dev_err(ov08d10->dev, "failed to set plls\n");
return ret;
}
reg_list = &ov08d10->cur_mode->reg_list;
ret = ov08d10_write_reg_list(ov08d10, reg_list);
if (ret) {
- dev_err(ov08d10->dev, "failed to set mode");
+ dev_err(ov08d10->dev, "failed to set mode\n");
return ret;
}
@@ -1076,19 +1076,19 @@ static void ov08d10_stop_streaming(struct ov08d10 *ov08d10)
ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);
if (ret < 0) {
- dev_err(ov08d10->dev, "failed to stop streaming");
+ dev_err(ov08d10->dev, "failed to stop streaming\n");
return;
}
ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MODE_SELECT,
OV08D10_MODE_STANDBY);
if (ret < 0) {
- dev_err(ov08d10->dev, "failed to stop streaming");
+ dev_err(ov08d10->dev, "failed to stop streaming\n");
return;
}
ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);
if (ret < 0) {
- dev_err(ov08d10->dev, "failed to stop streaming");
+ dev_err(ov08d10->dev, "failed to stop streaming\n");
return;
}
}
@@ -1324,7 +1324,7 @@ static int ov08d10_get_hwcfg(struct ov08d10 *ov08d10)
/* Get number of data lanes */
if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) {
- dev_err(dev, "number of CSI2 data lanes %d is not supported",
+ dev_err(dev, "number of CSI2 data lanes %d is not supported\n",
bus_cfg.bus.mipi_csi2.num_data_lanes);
ret = -EINVAL;
goto check_hwcfg_error;
@@ -1336,7 +1336,7 @@ static int ov08d10_get_hwcfg(struct ov08d10 *ov08d10)
ov08d10->modes_size = ov08d10_modes_num(ov08d10);
if (!bus_cfg.nr_of_link_frequencies) {
- dev_err(dev, "no link frequencies defined");
+ dev_err(dev, "no link frequencies defined\n");
ret = -EINVAL;
goto check_hwcfg_error;
}
@@ -1349,7 +1349,7 @@ static int ov08d10_get_hwcfg(struct ov08d10 *ov08d10)
}
if (j == bus_cfg.nr_of_link_frequencies) {
- dev_err(dev, "no link frequency %lld supported",
+ dev_err(dev, "no link frequency %lld supported\n",
ov08d10->priv_lane->link_freq_menu[i]);
ret = -EINVAL;
goto check_hwcfg_error;
@@ -1398,7 +1398,7 @@ static int ov08d10_probe(struct i2c_client *client)
ret = ov08d10_get_hwcfg(ov08d10);
if (ret) {
- dev_err(ov08d10->dev, "failed to get HW configuration: %d",
+ dev_err(ov08d10->dev, "failed to get HW configuration: %d\n",
ret);
return ret;
}
@@ -1407,7 +1407,7 @@ static int ov08d10_probe(struct i2c_client *client)
ret = ov08d10_identify_module(ov08d10);
if (ret) {
- dev_err(ov08d10->dev, "failed to find sensor: %d", ret);
+ dev_err(ov08d10->dev, "failed to find sensor: %d\n", ret);
return ret;
}
@@ -1415,7 +1415,7 @@ static int ov08d10_probe(struct i2c_client *client)
ov08d10->cur_mode = &ov08d10->priv_lane->sp_modes[0];
ret = ov08d10_init_controls(ov08d10);
if (ret) {
- dev_err(ov08d10->dev, "failed to init controls: %d", ret);
+ dev_err(ov08d10->dev, "failed to init controls: %d\n", ret);
goto probe_error_v4l2_ctrl_handler_free;
}
@@ -1425,7 +1425,7 @@ static int ov08d10_probe(struct i2c_client *client)
ov08d10->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&ov08d10->sd.entity, 1, &ov08d10->pad);
if (ret) {
- dev_err(ov08d10->dev, "failed to init entity pads: %d", ret);
+ dev_err(ov08d10->dev, "failed to init entity pads: %d\n", ret);
goto probe_error_v4l2_ctrl_handler_free;
}
@@ -1434,7 +1434,7 @@ static int ov08d10_probe(struct i2c_client *client)
ret = v4l2_async_register_subdev_sensor(&ov08d10->sd);
if (ret < 0) {
- dev_err(ov08d10->dev, "failed to register V4L2 subdev: %d",
+ dev_err(ov08d10->dev, "failed to register V4L2 subdev: %d\n",
ret);
goto probe_error_media_entity_cleanup;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 6/9] dt-bindings: media: i2c: document Omnivision OV08D10 CMOS image sensor
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
` (4 preceding siblings ...)
2026-03-24 10:41 ` [PATCH v3 5/9] media: i2c: ov08d10: add missing newline to prints Matthias Fend
@ 2026-03-24 10:41 ` Matthias Fend
2026-03-24 10:41 ` [PATCH v3 7/9] media: i2c: ov08d10: add support for binding via device tree Matthias Fend
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo, Krzysztof Kozlowski
Add bindings for the Omnivision OV08D10 CMOS image sensor.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
---
.../bindings/media/i2c/ovti,ov08d10.yaml | 101 +++++++++++++++++++++
MAINTAINERS | 2 +
2 files changed, 103 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov08d10.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov08d10.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6f2017c7512566d47fc04fbd4c672cb9633ca990
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov08d10.yaml
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ovti,ov08d10.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Omnivision OV08D10 1/4-Inch 8MP CMOS color image sensor
+
+maintainers:
+ - Matthias Fend <matthias.fend@emfend.at>
+
+description:
+ The Omnivision OV08D10 is a 1/4-Inch 8MP CMOS color image sensor with an
+ active array size of 3280 x 2464. It is programmable through I2C
+ interface. Image data is transmitted via MIPI CSI-2 using 2 lanes.
+
+allOf:
+ - $ref: /schemas/media/video-interface-devices.yaml#
+
+properties:
+ compatible:
+ const: ovti,ov08d10
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description: MCLK input clock (6 - 27 MHz)
+ maxItems: 1
+
+ reset-gpios:
+ description: Active low XSHUTDN pin
+ maxItems: 1
+
+ dovdd-supply:
+ description: IO power supply (1.8V)
+
+ avdd-supply:
+ description: Analog power supply (2.8V)
+
+ dvdd-supply:
+ description: Core power supply (1.2V)
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ additionalProperties: false
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ required:
+ - data-lanes
+ - link-frequencies
+
+ required:
+ - endpoint
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/media/video-interfaces.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sensor@36 {
+ compatible = "ovti,ov08d10";
+ reg = <0x36>;
+
+ clocks = <&ov08d10_clk>;
+
+ dovdd-supply = <&ov08d10_vdddo_1v8>;
+ avdd-supply = <&ov08d10_vdda_2v8>;
+ dvdd-supply = <&ov08d10_vddd_1v2>;
+
+ orientation = <2>;
+ rotation = <0>;
+
+ reset-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
+
+ port {
+ ov08d10_output: endpoint {
+ data-lanes = <1 2>;
+ link-frequencies = /bits/ 64 <360000000 720000000>;
+ remote-endpoint = <&csi_input>;
+ };
+ };
+ };
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 750ac8c4a7b00cc6668d80fff60a2b54838bfa7c..f91dbc3f3ed0e5b303882c2f3893b70d154a5bef 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19502,9 +19502,11 @@ F: drivers/media/i2c/ov02e10.c
OMNIVISION OV08D10 SENSOR DRIVER
M: Jimmy Su <jimmy.su@intel.com>
+R: Matthias Fend <matthias.fend@emfend.at>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media.git
+F: Documentation/devicetree/bindings/media/i2c/ovti,ov08d10.yaml
F: drivers/media/i2c/ov08d10.c
OMNIVISION OV08X40 SENSOR DRIVER
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 7/9] media: i2c: ov08d10: add support for binding via device tree
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
` (5 preceding siblings ...)
2026-03-24 10:41 ` [PATCH v3 6/9] dt-bindings: media: i2c: document Omnivision OV08D10 CMOS image sensor Matthias Fend
@ 2026-03-24 10:41 ` Matthias Fend
2026-03-24 10:41 ` [PATCH v3 8/9] media: i2c: ov08d10: add support for reset and power management Matthias Fend
2026-03-24 10:41 ` [PATCH v3 9/9] media: i2c: ov08d10: add support for 24 MHz input clock Matthias Fend
8 siblings, 0 replies; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo
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 <matthias.fend@emfend.at>
---
drivers/media/i2c/ov08d10.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index f2276f49506028c582e49a5b7cab3b07f6ca4e0d..ce0fa30a86129302b5dda0b8796e44054fd77c88 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -1464,10 +1464,17 @@ static const struct acpi_device_id ov08d10_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, ov08d10_acpi_ids);
#endif
+static const struct of_device_id ov08d10_of_match[] = {
+ { .compatible = "ovti,ov08d10" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ov08d10_of_match);
+
static struct i2c_driver ov08d10_i2c_driver = {
.driver = {
.name = "ov08d10",
.acpi_match_table = ACPI_PTR(ov08d10_acpi_ids),
+ .of_match_table = ov08d10_of_match,
},
.probe = ov08d10_probe,
.remove = ov08d10_remove,
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 8/9] media: i2c: ov08d10: add support for reset and power management
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
` (6 preceding siblings ...)
2026-03-24 10:41 ` [PATCH v3 7/9] media: i2c: ov08d10: add support for binding via device tree Matthias Fend
@ 2026-03-24 10:41 ` Matthias Fend
2026-03-26 13:26 ` Sakari Ailus
2026-03-24 10:41 ` [PATCH v3 9/9] media: i2c: ov08d10: add support for 24 MHz input clock Matthias Fend
8 siblings, 1 reply; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo
Add support for the required power supplies as well as the control of an
optional sensor reset.
Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
---
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 <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
@@ -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
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 9/9] media: i2c: ov08d10: add support for 24 MHz input clock
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
` (7 preceding siblings ...)
2026-03-24 10:41 ` [PATCH v3 8/9] media: i2c: ov08d10: add support for reset and power management Matthias Fend
@ 2026-03-24 10:41 ` Matthias Fend
8 siblings, 0 replies; 11+ messages in thread
From: Matthias Fend @ 2026-03-24 10:41 UTC (permalink / raw)
To: Jimmy Su, Sakari Ailus, Mauro Carvalho Chehab, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-kernel, devicetree, Matthias Fend,
bsp-development.geo
The sensor supports an input clock in the range of 6 to 27 MHz. Currently,
the driver only supports a 19.2 MHz clock. Extend the driver so that at
least 24 MHz, which is a typical frequency for this sensor, can also be
used.
Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
---
drivers/media/i2c/ov08d10.c | 80 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 64 insertions(+), 16 deletions(-)
diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c
index 19035991e8bb164d4fca5d87ee4551191974e8bb..9adef5446a61f3204fb809ca3f077c1afb5f7a47 100644
--- a/drivers/media/i2c/ov08d10.c
+++ b/drivers/media/i2c/ov08d10.c
@@ -14,7 +14,6 @@
#include <media/v4l2-fwnode.h>
#define OV08D10_SCLK 144000000ULL
-#define OV08D10_XVCLK_19_2 19200000
#define OV08D10_ROWCLK 36000
#define OV08D10_DATA_LANES 2
#define OV08D10_RGB_DEPTH 10
@@ -78,8 +77,13 @@ struct ov08d10_reg_list {
const struct ov08d10_reg *regs;
};
+static const u32 ov08d10_xvclk_freqs[] = {
+ 19200000,
+ 24000000
+};
+
struct ov08d10_link_freq_config {
- const struct ov08d10_reg_list reg_list;
+ const struct ov08d10_reg_list reg_list[ARRAY_SIZE(ov08d10_xvclk_freqs)];
};
struct ov08d10_mode {
@@ -108,8 +112,8 @@ struct ov08d10_mode {
u8 data_lanes;
};
-/* 3280x2460, 3264x2448 need 720Mbps/lane, 2 lanes */
-static const struct ov08d10_reg mipi_data_rate_720mbps[] = {
+/* 3280x2460, 3264x2448 need 720Mbps/lane, 2 lanes - 19.2 MHz */
+static const struct ov08d10_reg mipi_data_rate_720mbps_19_2[] = {
{0xfd, 0x00},
{0x11, 0x2a},
{0x14, 0x43},
@@ -119,8 +123,8 @@ static const struct ov08d10_reg mipi_data_rate_720mbps[] = {
{0xb7, 0x02}
};
-/* 1632x1224 needs 360Mbps/lane, 2 lanes */
-static const struct ov08d10_reg mipi_data_rate_360mbps[] = {
+/* 1632x1224 needs 360Mbps/lane, 2 lanes - 19.2 MHz */
+static const struct ov08d10_reg mipi_data_rate_360mbps_19_2[] = {
{0xfd, 0x00},
{0x1a, 0x04},
{0x1b, 0xe1},
@@ -132,6 +136,30 @@ static const struct ov08d10_reg mipi_data_rate_360mbps[] = {
{0xb7, 0x02}
};
+/* 3280x2460, 3264x2448 need 720Mbps/lane, 2 lanes - 24 MHz */
+static const struct ov08d10_reg mipi_data_rate_720mbps_24_0[] = {
+ {0xfd, 0x00},
+ {0x11, 0x2a},
+ {0x14, 0x43},
+ {0x1a, 0x04},
+ {0x1b, 0xb4},
+ {0x1e, 0x13},
+ {0xb7, 0x02}
+};
+
+/* 1632x1224 needs 360Mbps/lane, 2 lanes - 24 MHz */
+static const struct ov08d10_reg mipi_data_rate_360mbps_24_0[] = {
+ {0xfd, 0x00},
+ {0x1a, 0x04},
+ {0x1b, 0xb4},
+ {0x1d, 0x00},
+ {0x1c, 0x19},
+ {0x11, 0x2a},
+ {0x14, 0x54},
+ {0x1e, 0x13},
+ {0xb7, 0x02}
+};
+
static const struct ov08d10_reg lane_2_mode_3280x2460[] = {
/* 3280x2460 resolution */
{0xfd, 0x01},
@@ -525,6 +553,7 @@ struct ov08d10 {
struct clk *clk;
struct reset_control *reset;
struct regulator_bulk_data supplies[ARRAY_SIZE(ov08d10_supply_names)];
+ u8 xvclk_index;
struct v4l2_subdev sd;
struct media_pad pad;
@@ -565,17 +594,29 @@ static const struct ov08d10_lane_cfg lane_cfg_2 = {
},
{{
.reg_list = {
+ {
.num_of_regs =
- ARRAY_SIZE(mipi_data_rate_720mbps),
- .regs = mipi_data_rate_720mbps,
- }
+ ARRAY_SIZE(mipi_data_rate_720mbps_19_2),
+ .regs = mipi_data_rate_720mbps_19_2,
+ },
+ {
+ .num_of_regs =
+ ARRAY_SIZE(mipi_data_rate_720mbps_24_0),
+ .regs = mipi_data_rate_720mbps_24_0,
+ }}
},
{
.reg_list = {
+ {
.num_of_regs =
- ARRAY_SIZE(mipi_data_rate_360mbps),
- .regs = mipi_data_rate_360mbps,
- }
+ ARRAY_SIZE(mipi_data_rate_360mbps_19_2),
+ .regs = mipi_data_rate_360mbps_19_2,
+ },
+ {
+ .num_of_regs =
+ ARRAY_SIZE(mipi_data_rate_360mbps_24_0),
+ .regs = mipi_data_rate_360mbps_24_0,
+ }}
}},
{{
.width = 3280,
@@ -1028,7 +1069,8 @@ static int ov08d10_start_streaming(struct ov08d10 *ov08d10)
link_freq_index = ov08d10->cur_mode->link_freq_index;
reg_list =
- &ov08d10->priv_lane->link_freq_configs[link_freq_index].reg_list;
+ &ov08d10->priv_lane->link_freq_configs[link_freq_index]
+ .reg_list[ov08d10->xvclk_index];
/* soft reset */
ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);
@@ -1456,9 +1498,15 @@ static int ov08d10_probe(struct i2c_client *client)
"failed to get clock\n");
freq = clk_get_rate(ov08d10->clk);
- if (freq != OV08D10_XVCLK_19_2)
- dev_warn(ov08d10->dev,
- "external clock rate %lu is not supported\n", freq);
+ for (i = 0; i < ARRAY_SIZE(ov08d10_xvclk_freqs); i++) {
+ if (freq == ov08d10_xvclk_freqs[i])
+ break;
+ }
+ if (i >= ARRAY_SIZE(ov08d10_xvclk_freqs))
+ return dev_err_probe(ov08d10->dev, -EINVAL,
+ "external clock rate %lu is not supported\n",
+ freq);
+ ov08d10->xvclk_index = i;
ret = ov08d10_get_hwcfg(ov08d10);
if (ret) {
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v3 8/9] media: i2c: ov08d10: add support for reset and power management
2026-03-24 10:41 ` [PATCH v3 8/9] media: i2c: ov08d10: add support for reset and power management Matthias Fend
@ 2026-03-26 13:26 ` Sakari Ailus
0 siblings, 0 replies; 11+ messages in thread
From: Sakari Ailus @ 2026-03-26 13:26 UTC (permalink / raw)
To: Matthias Fend
Cc: Jimmy Su, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, linux-media, linux-kernel,
devicetree, bsp-development.geo
Hi Matthias,
A few more minor comments.
On Tue, Mar 24, 2026 at 11:41:42AM +0100, Matthias Fend wrote:
> Add support for the required power supplies as well as the control of an
> optional sensor reset.
>
> Signed-off-by: Matthias Fend <matthias.fend@emfend.at>
> ---
> 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 <linux/module.h>
> #include <linux/pm_runtime.h>
> #include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> #include <media/v4l2-ctrls.h>
> #include <media/v4l2-device.h>
> #include <media/v4l2-fwnode.h>
> @@ -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);
Don't you need the fsleep()'s (or at least the latter one) even if you have
no reset GPIO?
> + }
> +
> + 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);
This is a bit long.
I'll take the set now but please post a fix on top.
> + 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,
> },
>
--
Regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-03-26 13:26 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-24 10:41 [PATCH v3 0/9] drivers: media: i2c: Omnivision OV08D10 improvements Matthias Fend
2026-03-24 10:41 ` [PATCH v3 1/9] media: i2c: ov08d10: fix runtime PM handling in probe Matthias Fend
2026-03-24 10:41 ` [PATCH v3 2/9] media: i2c: ov08d10: fix image vertical start setting Matthias Fend
2026-03-24 10:41 ` [PATCH v3 3/9] media: i2c: ov08d10: remove duplicate register write Matthias Fend
2026-03-24 10:41 ` [PATCH v3 4/9] media: i2c: ov08d10: fix some typos in comments Matthias Fend
2026-03-24 10:41 ` [PATCH v3 5/9] media: i2c: ov08d10: add missing newline to prints Matthias Fend
2026-03-24 10:41 ` [PATCH v3 6/9] dt-bindings: media: i2c: document Omnivision OV08D10 CMOS image sensor Matthias Fend
2026-03-24 10:41 ` [PATCH v3 7/9] media: i2c: ov08d10: add support for binding via device tree Matthias Fend
2026-03-24 10:41 ` [PATCH v3 8/9] media: i2c: ov08d10: add support for reset and power management Matthias Fend
2026-03-26 13:26 ` Sakari Ailus
2026-03-24 10:41 ` [PATCH v3 9/9] media: i2c: ov08d10: add support for 24 MHz input clock Matthias Fend
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox