From: Robert Bozik <robertbozik@gmail.com>
To: linux-media@vger.kernel.org
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Robert Bozik <robertbozik@gmail.com>
Subject: [PATCH v4 0/3] media: Add OmniVision OV32C4 sensor driver
Date: Mon, 5 Oct 2026 09:10:07 +0200 [thread overview]
Message-ID: <20261005071010.7191-1-robertbozik@gmail.com> (raw)
Hi,
v4 of the OV32C4 sensor driver. v3 is at
https://lore.kernel.org/linux-media/20260829115832.8749-1-robertbozik@gmail.com/
The one open question from v1 and v2 was the second I2C address - the
write to 0x3e that the sensor needs before its main address answers -
and whether it belongs in a sensor driver. v3 could only say what it was
not. This version answers it with a measurement, and the design follows
from the answer.
The question that decides it is whether the block behind 0x3e lives and
dies with the sensor. Measured on the machine, polling 0x3e and 0x36
every 0.5 ms through a runtime power cycle and lining the polls up with
the kernel's regulator, gpio and i2c tracepoints:
- sensor off (AVDD disabled, reset asserted): 0x3e NACKs, as does 0x36
- AVDD on at t=1.0 ms, settled 3.5 ms; reset released 8.9 ms
- 0x3e first ACK at 10.1 ms, reading 0x1001 = 0x00; between AVDD and
the reset release it did not answer
- the driver's 0x1001 = 0x04 at 30.1 ms; 0x36 first ACK at 30.6 ms
- reset asserted and AVDD off at 4000.8 ms: 0x3e gone by 4001.9 ms,
0x36 by 4003.0 ms
So it is unreachable without power, appears only once the sensor's own
reset is released, forgets the value written to it over a power cycle,
and disappears with the sensor. It has no ACPI device of its own, 0x300a
there reads zero (it is not an alias of the main map), and 0x36 has
nothing at 0x1000. The same register pair exists in OV08X40 at that
sensor's main address, named AO_STANDBY (0x1000) and MS_SELECT (0x1001,
0x04 for streaming) in ov08x40.c. The vendor Windows driver writes it
from the sensor driver as well, once, after reset and before the chip id
read, and never reads it back. I take all of that to mean the block is
part of the sensor and the sensor driver is its owner.
What changed accordingly:
- The driver claims the second address with devm_i2c_new_dummy_device()
and writes it through a CCI regmap of its own; the bare i2c_transfer()
is gone.
- ipu-bridge no longer instantiates a VCM for this sensor. The SSDB
says vcmtype 2 and the bridge would put a dw9714 on 0x3e; dw9714 has
no id register and binds to anything, and that client would hold the
address the sensor driver needs. Patch 3 carries the exception, so
patches 2 and 3 go together.
Two smaller things turned up while re-reading the driver for this:
- The 10 ms after the software reset was a busy wait. The reset sat in
the mode table with a delay_us, and regmap_multi_reg_write() turns
that into udelay() on a regmap without can_sleep, which the CCI one
is. The driver now issues the stream-off and the reset itself and
sleeps; the table is the vendor's sequence minus those two entries.
- power_on() returned 0 when the enable write failed. It now fails and
undoes the clock, the supply and the reset.
The power-up timing, your "0 and 5 ms" on v1: I did not follow it then,
and I think I do now - nothing after the supply, because the regulator
core waits for it, and 5 ms after reset. The measurement above agrees:
the block answers about 1 ms after reset release and the main address
within 1 ms of the enable write. v4 uses 0, 5 ms and 1 ms, verified over
a cold boot, 20 runtime power cycles and 15 stream starts without a
failure.
Where the numbers come from, stated plainly this time, because v3 said
both "copied 1:1" and "measured by me" about the same table:
From the vendor Windows driver (ov32c4.sys, FileVersion
70.26100.2.18255):
- the mode register table (1787 writes, at file offset 0x31300), of
which the driver drops the first two entries, stream-off and reset,
and issues them itself;
- the 400 MHz link frequency, carried there as bits per second;
- the chip id 0x563243;
- the write of 0x04 to 0x1001 at the second address;
- the registers the controls use (exposure 0x3500, analogue gain
0x3508, digital gain 0x350a, VTS 0x380e) and the rule
exposure_max = VTS - 32.
Measured on the sensor:
- the chip id, the register meanings above and the exposure rule,
confirmed against what the chip reports;
- the gain ranges: analogue exactly proportional between 0x100 and
0x7c0 (1x to 7.75x, 0x100 being the power-up value), digital
proportional with 1024 as unity, clipping to black one step above
16383 - the obvious donor, ov13b10 on the same registers, puts
analogue unity at 0x80, which is wrong here;
- the timings: 320000000 / (4080 * 2614) = 30.005 fps against a
measured 30.00; the power-up sequence as above;
- flips preserve the Bayer order, so the media bus code never changes
and the crop compensation ov13b10 does would introduce the shift it
undoes there;
- the 6560x4928 array and 6528x4896 active area, from the window
registers of the table, agreeing with the vendor's product brief;
- the second address, as above.
The rest of the series is as before. It adds a driver for the OmniVision
OV32C4, a 32 megapixel RGBC CMOS image sensor. It ships as the
under-display camera in the Lenovo Yoga Slim 9 14ILL10, where it is
enumerated through ACPI (_HID "OVTI32C4") and feeds an Intel IPU7. The
driver supports 3264x1840 at 30 fps, 10-bit Bayer, 4 CSI-2 lanes at a
400 MHz link frequency, with exposure, analogue gain, digital gain,
vblank, hblank and flip controls, runtime PM and .get_selection. Tested
on that machine: the sensor probes, streams at a measured 30.00 fps,
frames arrive complete, and the full path to a processed image runs
through libcamera's software ISP. The driver has what libcamera's sensor
driver requirements ask for: the five mandatory controls, the crop
selection targets, flips that keep the Bayer order, and the orientation
and rotation properties.
v4l2-compliance on the subdev, kernel 7.0.0-38:
Total for device /dev/v4l-subdev4: 46, Succeeded: 46, Failed: 0, Warnings: 0
Static checks: checkpatch.pl --strict, sparse (C=1), W=1 and
dt_binding_check.
The series applies to media_stage.git; base-commit is below.
Thanks,
Robert
Robert Bozik (3):
dt-bindings: media: i2c: Add OmniVision OV32C4
media: i2c: Add driver for OmniVision OV32C4
media: ipu-bridge: Add OmniVision OV32C4
.../bindings/media/i2c/ovti,ov32c4.yaml | 105 +
MAINTAINERS | 8 +
drivers/media/i2c/Kconfig | 10 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/ov32c4.c | 2716 +++++++++++++++++
drivers/media/pci/intel/ipu-bridge.c | 26 +-
6 files changed, 2865 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/media/i2c/ovti,ov32c4.yaml
create mode 100644 drivers/media/i2c/ov32c4.c
base-commit: 4900cad020c0580dfb1be27776ff10a4ef110cfa
--
2.53.0
next reply other threads:[~2026-10-05 7:10 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-05 7:10 Robert Bozik [this message]
2026-10-05 7:10 ` [PATCH v4 1/3] dt-bindings: media: i2c: Add OmniVision OV32C4 Robert Bozik
2026-10-05 8:11 ` Sakari Ailus
2026-10-05 8:36 ` Robert Bozik
2026-10-05 11:02 ` Conor Dooley
2026-10-05 12:01 ` Robert Bozik
2026-10-05 7:10 ` [PATCH v4 2/3] media: i2c: Add driver for " Robert Bozik
2026-10-05 9:23 ` Sakari Ailus
2026-10-05 10:14 ` Robert Bozik
2026-10-05 10:36 ` Sakari Ailus
2026-10-05 10:46 ` Robert Bozik
2026-10-05 7:10 ` [PATCH v4 3/3] media: ipu-bridge: Add " Robert Bozik
2026-10-05 8:04 ` [PATCH v4 0/3] media: Add OmniVision OV32C4 sensor driver Sakari Ailus
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261005071010.7191-1-robertbozik@gmail.com \
--to=robertbozik@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=robh@kernel.org \
--cc=sakari.ailus@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®