* [PATCH v4 1/6] media: i2c: ov5693: Add OVTI5693 ACPI HID
2026-08-31 18:18 ` [PATCH v4 0/6] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
@ 2026-08-31 18:18 ` Fernando Rimoli
2026-08-31 18:18 ` [PATCH v4 2/6] media: ipu-bridge: Add OVTI5693 to the list of supported sensors Fernando Rimoli
` (5 subsequent siblings)
6 siblings, 0 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-08-31 18:18 UTC (permalink / raw)
To: Sakari Ailus, Daniel Scally, linux-media
Cc: Mauro Carvalho Chehab, Arsalan Naeem, Jakob Berg Jespersen,
linux-kernel, Fernando Rimoli
The ov5693 driver only matches the "INT33BE" ACPI HID. Some Intel IPU6
Surface devices (e.g. Microsoft Surface Pro 9) enumerate the OV5693
front camera with the ACPI HID "OVTI5693" instead, so the i2c core never
binds the driver.
Add "OVTI5693" to the ACPI match table. Devices that use "INT33BE"
(e.g. Surface Go 4) are unaffected.
Tested on Surface Pro 9 (IPU6): the sensor enumerates as OVTI5693:00
(ACPI path \_SB_.PC00.I2C3.CAMF) and binds with this change.
Link: https://github.com/linux-surface/linux-surface/pull/2171
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
---
drivers/media/i2c/ov5693.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
index 4cc796bbe..02236f3db 100644
--- a/drivers/media/i2c/ov5693.c
+++ b/drivers/media/i2c/ov5693.c
@@ -1396,6 +1396,7 @@ static const struct dev_pm_ops ov5693_pm_ops = {
static const struct acpi_device_id ov5693_acpi_match[] = {
{"INT33BE"},
+ {"OVTI5693"},
{},
};
MODULE_DEVICE_TABLE(acpi, ov5693_acpi_match);
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v4 2/6] media: ipu-bridge: Add OVTI5693 to the list of supported sensors
2026-08-31 18:18 ` [PATCH v4 0/6] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
2026-08-31 18:18 ` [PATCH v4 1/6] media: i2c: ov5693: Add OVTI5693 ACPI HID Fernando Rimoli
@ 2026-08-31 18:18 ` Fernando Rimoli
2026-08-31 18:18 ` [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock Fernando Rimoli
` (4 subsequent siblings)
6 siblings, 0 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-08-31 18:18 UTC (permalink / raw)
To: Sakari Ailus, Daniel Scally, linux-media
Cc: Mauro Carvalho Chehab, Arsalan Naeem, Jakob Berg Jespersen,
linux-kernel, Fernando Rimoli
The IPU bridge builds the firmware node graph only for sensors listed in
ipu_supported_sensors[]. The OV5693 is currently listed only under its
legacy "INT33BE" HID, so on Intel IPU6 Surface devices that enumerate it
as "OVTI5693" (e.g. Microsoft Surface Pro 9) the bridge never wires up
the sensor and the front camera is unusable.
Add an "OVTI5693" entry. The link frequency (419200000) matches the
existing INT33BE entry, as it is the same sensor.
Tested on Surface Pro 9 (IPU6).
Link: https://github.com/linux-surface/linux-surface/pull/2171
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
---
drivers/media/pci/intel/ipu-bridge.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index 1bb3a3e98..131c70844 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -95,6 +95,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = {
IPU_SENSOR_CONFIG("OVTI2680", 1, 331200000),
/* Omnivision OV5675 */
IPU_SENSOR_CONFIG("OVTI5675", 1, 450000000),
+ /* Omnivision OV5693 */
+ IPU_SENSOR_CONFIG("OVTI5693", 1, 419200000),
/* Omnivision OV8856 */
IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000),
/* Sony IMX471 */
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
2026-08-31 18:18 ` [PATCH v4 0/6] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
2026-08-31 18:18 ` [PATCH v4 1/6] media: i2c: ov5693: Add OVTI5693 ACPI HID Fernando Rimoli
2026-08-31 18:18 ` [PATCH v4 2/6] media: ipu-bridge: Add OVTI5693 to the list of supported sensors Fernando Rimoli
@ 2026-08-31 18:18 ` Fernando Rimoli
2026-09-01 9:32 ` Jakob Berg Jespersen
` (2 more replies)
2026-08-31 18:18 ` [PATCH v4 4/6] media: ipu-bridge: Assign endpoint property indices dynamically Fernando Rimoli
` (3 subsequent siblings)
6 siblings, 3 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-08-31 18:18 UTC (permalink / raw)
To: Sakari Ailus, Daniel Scally, linux-media
Cc: Mauro Carvalho Chehab, Arsalan Naeem, Jakob Berg Jespersen,
linux-kernel, Fernando Rimoli
The ov5693 never programs MIPI_CTRL00 (0x4800), leaving it at its 0x00
power-on default, which lets the MIPI clock run freely. The IPU3 CSI-2
receiver tolerates this, but the IPU6 receiver (e.g. on Microsoft
Surface Pro 8/9 and Surface Go 4) fails to lock onto the link, so the
sensor streams but capture times out with "stream stop time out" and no
frames arrive.
Parse the "clock-noncontinuous" endpoint property (which sets the
V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK flag) and, when it is present, gate
the clock lane while idle at stream on. Bit 5 of MIPI_CTRL00 has the
same meaning here as in ov5647, which sets it for the same purpose.
Unlike ov5647, which owns the register across its own stream on and off,
this is a read-modify-write of the single gate bit: the ov5693 otherwise
never touches MIPI_CTRL00, so preserving the rest of it keeps every
platform that does not ask for a non-continuous clock bit-for-bit as it
was. No counterpart is needed at stream off, as the link is down by then
and the register returns to its default when the sensor is powered off.
The "clock-noncontinuous" property is supplied by the ipu-bridge for the
affected IPU6 variants in a subsequent patch.
Link: https://github.com/linux-surface/linux-surface/pull/2171
Co-developed-by: Arsalan Naeem <naeemarsalan@gmail.com>
Signed-off-by: Arsalan Naeem <naeemarsalan@gmail.com>
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
---
drivers/media/i2c/ov5693.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
index 02236f3db..cedc6ea03 100644
--- a/drivers/media/i2c/ov5693.c
+++ b/drivers/media/i2c/ov5693.c
@@ -35,6 +35,11 @@
#define OV5693_STOP_STREAMING 0x00
#define OV5693_SW_RESET 0x01
+/* MIPI transmitter control */
+#define OV5693_MIPI_CTRL00_REG CCI_REG8(0x4800)
+/* Gate the clock lane when there is no packet to transmit */
+#define OV5693_MIPI_CTRL00_CLOCK_LANE_GATE BIT(5)
+
#define OV5693_REG_CHIP_ID CCI_REG16(0x300a)
/* Yes, this is right. The datasheet for the OV5693 gives its ID as 0x5690 */
#define OV5693_CHIP_ID 0x5690
@@ -144,6 +149,9 @@ struct ov5693_device {
struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];
struct clk *xvclk;
+ /* Gate the MIPI clock lane when idle (CSI-2 non-continuous clock) */
+ bool clock_ncont;
+
struct ov5693_mode {
struct v4l2_rect crop;
struct v4l2_mbus_framefmt format;
@@ -611,6 +619,19 @@ static int ov5693_enable_streaming(struct ov5693_device *ov5693, bool enable)
{
int ret = 0;
+ /*
+ * Gate the MIPI clock lane while idle if the CSI-2 link is configured
+ * for a non-continuous clock. Only that bit is touched, and only in
+ * that case, so the register keeps whatever the platform left in it
+ * and the clock stays free-running as before everywhere else. It
+ * needs no counterpart at stream off: the link is down by then, and
+ * the register returns to its default when the sensor is powered off.
+ */
+ if (enable && ov5693->clock_ncont)
+ cci_update_bits(ov5693->regmap, OV5693_MIPI_CTRL00_REG,
+ OV5693_MIPI_CTRL00_CLOCK_LANE_GATE,
+ OV5693_MIPI_CTRL00_CLOCK_LANE_GATE, &ret);
+
cci_write(ov5693->regmap, OV5693_SW_STREAM_REG,
enable ? OV5693_START_STREAMING : OV5693_STOP_STREAMING,
&ret);
@@ -1259,6 +1280,9 @@ static int ov5693_check_hwcfg(struct ov5693_device *ov5693)
goto out_free_bus_cfg;
}
+ ov5693->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
+ V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
+
out_free_bus_cfg:
v4l2_fwnode_endpoint_free(&bus_cfg);
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
2026-08-31 18:18 ` [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock Fernando Rimoli
@ 2026-09-01 9:32 ` Jakob Berg Jespersen
2026-09-01 9:56 ` Fernando Rimoli
2026-09-01 16:34 ` Fernando Rimoli
2026-09-01 18:46 ` Fil Dunsky
2026-09-02 7:27 ` Sakari Ailus
2 siblings, 2 replies; 50+ messages in thread
From: Jakob Berg Jespersen @ 2026-09-01 9:32 UTC (permalink / raw)
To: Fernando Rimoli
Cc: Sakari Ailus, Daniel Scally, linux-media, Mauro Carvalho Chehab,
Arsalan Naeem, linux-kernel
Hi, just did a new test, see below
On Monday, August 31st, 2026 at 20:19, Fernando Rimoli <fernandorimoli11@gmail.com> wrote:
...
> Parse the "clock-noncontinuous" endpoint property (which sets the
> V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK flag) and, when it is present, gate
> the clock lane while idle at stream on.
...
Tested-by: Jakob Berg Jespersen <dev@berg.pm> # Surface Pro 7+, IPU6 Tiger Lake
Retested on the Surface Pro 7+ now that both the value and the mechanism
have changed. This covers patches 3 to 6, so it exercises the bridge
matching on Tiger Lake rather than only the register value. Patches 1 and
2 are not exercised here: this machine enumerates the sensor as INT33BE.
Both kernels are v7.3-rc1, your base-commit, differing only by this
series. Front camera, 20 cold opens each, libcamera 0.7.1, full
resolution (sensor 2592x1944 BGGR-10):
v7.3-rc1 unpatched 3/20 runs delivered frames; the other 17 ended
in "stream stop time out" with zero frames
v7.3-rc1 + this series 20/20 runs at 28.64-28.65 fps, and one run of
600 frames with no drops
Reading MIPI_CTRL00 back over I2C during a live capture, on both kernels:
unpatched 0x4800 = 0x00
patched 0x4800 = 0x20
with 0x300a/0x300b reading 0x56/0x90 as a control that the bus and address
are right. So the bridge did supply clock-noncontinuous, the driver did act
on it, and the read-modify-write set bit 5 and nothing else.
Two things that may be worth having:
The unpatched register really is 0x00 on this machine, so your argument
that the whole-register write and the read-modify-write resolve to the
same value holds on Tiger Lake as well as on the Pro 9.
Zann580 asked on GitHub, when posting the 0x20 row, that the minimal
value be confirmed from a built module before the patch was narrowed
on the strength of a userspace poke. I think this does that.
(Surface Pro 7+, Fedora 44; kernel 7.3.0-rc1 versus 7.3.0-rc1 plus this
series; Tiger Lake IPU6 8086:9a19; ov5693 as INT33BE; libcamera 0.7.1.)
Regards,
Jakob
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
2026-09-01 9:32 ` Jakob Berg Jespersen
@ 2026-09-01 9:56 ` Fernando Rimoli
2026-09-01 16:34 ` Fernando Rimoli
1 sibling, 0 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-01 9:56 UTC (permalink / raw)
To: Jakob Berg Jespersen, Sakari Ailus, Daniel Scally, linux-media
Cc: Mauro Carvalho Chehab, Arsalan Naeem, linux-kernel
Hi Jakob,
Thank you, and thanks for re-testing rather than letting the old tag stand.
I will carry the tag on patches 3 to 6 as you scoped it, and not on 1 and
2, since your machine enumerates INT33BE and neither of those is exercised
there.
The register read-back is the most valuable part. Nobody
had shown the mechanism working end to end before: 0x4800 reading 0x00
unpatched and 0x20 patched, with the chip ID as a bus control, demonstrates
that the bridge really did supply clock-noncontinuous, that the driver
acted on it, and that the read-modify-write set bit 5 and disturbed nothing
else.
Your unpatched result also corrects something I should fix. You saw 3 of 20
runs deliver frames without the series; on my Pro 9 the unpatched case is a
hard zero every time. So the failure is intermittent on Tiger Lake rather
than absolute, and patch 3's commit message currently reads as though it
always fails.
That is too strong given your data. In v5 I will say the receiver usually
fails to lock, note that it is intermittent on some units, and cite your 3
of 20 alongside my 0 of N.
Two smaller things from your mail worth recording. Your read of 0x00 on the
unpatched Tiger Lake machine confirms on a second IPU generation that the
whole-register write and the read-modify-write resolve to the same value,
so that argument in the cover letter is no longer only about my Pro 9. And
you have answered the caveat Zann580 attached to the 0x20 row on GitHub,
which was that the minimal value should be confirmed from a built module
rather than from a userspace poke before the patch was narrowed on its
strength. It now has been.
Thanks again,
Fernando
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
2026-09-01 9:32 ` Jakob Berg Jespersen
2026-09-01 9:56 ` Fernando Rimoli
@ 2026-09-01 16:34 ` Fernando Rimoli
2026-09-01 18:32 ` Jakob Berg Jespersen
1 sibling, 1 reply; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-01 16:34 UTC (permalink / raw)
To: linux-media; +Cc: sakari.ailus, dan.scally, dev
Hi Jakob,
One follow-up question, because two later results bear on your unpatched
numbers and they do not agree with each other.
A Surface Pro 8 user ran the negative control, removing only the flagged
INT33BE entry for Tiger Lake. Without it his front camera streams on the
first capture after boot, with real image data, and every later capture in
that boot hangs at zero bytes. With the entry, every capture works.
A Surface Pro 7+ user then ran the same control on a machine that also
enumerates INT33BE on Tiger Lake, so the same configuration as yours, and
got the opposite: his first capture of that boot already returned zero
frames. He checked the journal to confirm nothing had opened the sensor
earlier in the boot.
So "works once per boot" describes one of those machines and not the other.
The Pro 8 user now suspects his own result is an artefact of how his machine
is set up: he streams an IR camera continuously for face unlock, so a
neighbouring CSI-2 port on the same ISYS was active during his first
capture. He is retesting with that stopped.
Your 3 of 20 is the measurement that would help separate these. Do you
remember whether your harness rebooted or power-cycled the sensor between
runs, or were all 20 opens inside a single boot?
Either answer is useful and neither needs a retest on your part. If all 20
were in one boot, then the machines genuinely differ and I will say so
rather than fold them into one story. If some followed a reboot or a power
cycle, that supports reading it as once per sensor power cycle, which I
would then describe as holding on some machines rather than as the general
behaviour.
I am only trying to describe the unpatched behaviour accurately, since the
current commit message says no frames arrive at all and all three results
contradict that in different ways.
Thanks,
Fernando
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
2026-09-01 16:34 ` Fernando Rimoli
@ 2026-09-01 18:32 ` Jakob Berg Jespersen
0 siblings, 0 replies; 50+ messages in thread
From: Jakob Berg Jespersen @ 2026-09-01 18:32 UTC (permalink / raw)
To: Fernando Rimoli; +Cc: linux-media, sakari.ailus, dan.scally
Hi Fernando,
For the front camera, ov5693: all 20 were inside a single boot, uptime 6
minutes at the start and 19 at the end. No reboot and no deliberate
power cycle anywhere in the run.
The part that bears on your question is which runs worked. It was runs
1, 7 and 14, not the first few. So on this machine it is not "works once
per boot" - runs 7 and 14 came well into the same boot, after several
failures each. I would expect a rerun to give a somewhat different
count.
Each run was an independent open and close of the camera rather than one
long capture, and the sensor runtime-suspends in between: on the patched
arm an i2c read a few seconds after a capture had finished returned
Remote I/O error, because the sensor had already powered down. So if the
behavior were once per sensor power cycle, I would have expected close
to 20 of 20 rather than 3.
For whatever it adds, I measured 1 of 20 on this machine in July, on
7.0.12. And last year, before I started developing on this, I made a few
comments on the randomness of the (unpatched) front camera on Fedora 42
and 43:
https://github.com/linux-surface/linux-surface/discussions/1354#discussioncomment-12863982
On the confound you mention: during my 20 runs the IR camera was not
merely idle, it was absent. ov7251 failed to probe with -121 on that
kernel, and libcamera enumerated two cameras, front and back only. So
nothing was streaming on a neighbouring port while I measured. For what
it adds, on the Pro 7+ the front camera sits on csi2-4 and the IR camera
on csi2-5, and those two share a D-PHY - so the Pro 8 user's suspicion
looks mechanically plausible on hardware laid out this way, though I
cannot say his mapping is the same.
Two details that may help you separate the machines. The ov5693 sensor
is genuinely up during the failures - the privacy LED lights - so it is
not a rail or a probe problem. And the successful runs log 10 to 11 csi2
errors while the failing runs log none at all, so the failure looks like
the receiver never locking rather than the sensor never starting.
Regards,
Jakob
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
2026-08-31 18:18 ` [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock Fernando Rimoli
2026-09-01 9:32 ` Jakob Berg Jespersen
@ 2026-09-01 18:46 ` Fil Dunsky
2026-09-02 7:27 ` Sakari Ailus
2 siblings, 0 replies; 50+ messages in thread
From: Fil Dunsky @ 2026-09-01 18:46 UTC (permalink / raw)
To: fernandorimoli11
Cc: dan.scally, dev, linux-kernel, linux-media, mchehab, naeemarsalan,
sakari.ailus
Tested-by: Fil Dunsky <filipp.dunsky@gmail.com>
Scope: patches 3-6. Patch 1 was already in my tree and this machine is
INT33BE, so patches 1 and 2 are not functionally exercised here.
Hardware: Surface Pro 8, IPU6 Tiger Lake (8086:9a19), OV5693 front
sensor at INT33BE:00, OV13858 rear, VD55G0 IR. Kernel 7.2.2 plus the
linux-surface patch set, not the v7.3-rc1 base the series declares;
patch 6 needed that tree's duplicate OVTI5693 entry dropped before it
would apply.
With the series applied, streaming from the ISYS capture node:
60 frames, SBGGR10 2592x1944, 604661760 bytes, 28.64 fps
MIPI_CTRL00 (0x4800) read back over i2c while streaming: 0x20
0x20 is the bit-5-only value patch 3 writes, so the clock-noncontinuous
property did reach the sensor driver: the path from the table entry in
patch 4 through to the register is exercised, not merely "the camera
works".
I also ran the negative control, with PCI_DEVICE_ID_INTEL_IPU6 dropped
from the INT33BE entries and nothing else changed. How it fails is
worth recording, because the obvious test misses it:
- the first capture after boot succeeds, 60 frames at 28.64 fps, with
0x4800 reading 0x00;
- every subsequent capture in that boot returns zero bytes and times
out, with nothing in dmesg;
- writing 0x20 to 0x4800 over i2c into a stalled stream starts frames
immediately, reproduced on three separate streams, while clearing
the bit again mid-stream does not stop them.
With bit 5 set, the same script captures three times in a row without
trouble; I measured that with our downstream driver, which writes 0x2d
unconditionally. So the entry is needed at stream start, and a single
capture after a reboot is not enough to tell whether it is present.
The free first capture appears to be particular to this machine: two
other testers of this series, on a Surface Pro 7+ and a Pro 9, get zero
bytes on the first attempt as well. I have not been able to explain the
difference. It only affects how the entry should be verified, not
whether it is needed.
Patch 5's precedence rule is exercised here as well: INT33BE appears
twice in the table, the generic entry and the Tiger Lake one, and the
bridge connects the sensor once - "Connected 3 cameras", no double
connect. The two sensors that take no flags, OV13858 and the VD55G0 IR
camera, are unaffected; the IR camera still does face authentication.
The teardown "stream stop time out" appears identically with and
without the series, so it is not introduced by it.
One note for out-of-tree builders: patch 4 grows struct ipu_sensor,
which moves the CRC of ipu_bridge_init() and ipu_bridge_parse_ssdb(),
so with CONFIG_MODVERSIONS ipu-bridge and intel-ipu6 have to be built
together. intel-ipu6-isys imports only ipu_bridge_instantiate_vcm,
whose CRC does not move; an unrebuilt intel-ipu6-isys loaded fine
against the new pair on 7.2.2.
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
2026-08-31 18:18 ` [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock Fernando Rimoli
2026-09-01 9:32 ` Jakob Berg Jespersen
2026-09-01 18:46 ` Fil Dunsky
@ 2026-09-02 7:27 ` Sakari Ailus
2 siblings, 0 replies; 50+ messages in thread
From: Sakari Ailus @ 2026-09-02 7:27 UTC (permalink / raw)
To: Fernando Rimoli
Cc: Daniel Scally, linux-media, Mauro Carvalho Chehab, Arsalan Naeem,
Jakob Berg Jespersen, linux-kernel
Hi Fernando,
On Mon, Aug 31, 2026 at 08:18:55PM +0200, Fernando Rimoli wrote:
> The ov5693 never programs MIPI_CTRL00 (0x4800), leaving it at its 0x00
> power-on default, which lets the MIPI clock run freely. The IPU3 CSI-2
> receiver tolerates this, but the IPU6 receiver (e.g. on Microsoft
> Surface Pro 8/9 and Surface Go 4) fails to lock onto the link, so the
> sensor streams but capture times out with "stream stop time out" and no
> frames arrive.
>
> Parse the "clock-noncontinuous" endpoint property (which sets the
> V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK flag) and, when it is present, gate
> the clock lane while idle at stream on. Bit 5 of MIPI_CTRL00 has the
I'd clip what's after the period above.
> same meaning here as in ov5647, which sets it for the same purpose.
>
> Unlike ov5647, which owns the register across its own stream on and off,
> this is a read-modify-write of the single gate bit: the ov5693 otherwise
> never touches MIPI_CTRL00, so preserving the rest of it keeps every
> platform that does not ask for a non-continuous clock bit-for-bit as it
> was. No counterpart is needed at stream off, as the link is down by then
> and the register returns to its default when the sensor is powered off.
>
> The "clock-noncontinuous" property is supplied by the ipu-bridge for the
> affected IPU6 variants in a subsequent patch.
>
> Link: https://github.com/linux-surface/linux-surface/pull/2171
> Co-developed-by: Arsalan Naeem <naeemarsalan@gmail.com>
> Signed-off-by: Arsalan Naeem <naeemarsalan@gmail.com>
> Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
> ---
> drivers/media/i2c/ov5693.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
> index 02236f3db..cedc6ea03 100644
> --- a/drivers/media/i2c/ov5693.c
> +++ b/drivers/media/i2c/ov5693.c
> @@ -35,6 +35,11 @@
> #define OV5693_STOP_STREAMING 0x00
> #define OV5693_SW_RESET 0x01
>
> +/* MIPI transmitter control */
> +#define OV5693_MIPI_CTRL00_REG CCI_REG8(0x4800)
> +/* Gate the clock lane when there is no packet to transmit */
> +#define OV5693_MIPI_CTRL00_CLOCK_LANE_GATE BIT(5)
> +
> #define OV5693_REG_CHIP_ID CCI_REG16(0x300a)
> /* Yes, this is right. The datasheet for the OV5693 gives its ID as 0x5690 */
> #define OV5693_CHIP_ID 0x5690
> @@ -144,6 +149,9 @@ struct ov5693_device {
> struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];
> struct clk *xvclk;
>
> + /* Gate the MIPI clock lane when idle (CSI-2 non-continuous clock) */
> + bool clock_ncont;
> +
> struct ov5693_mode {
> struct v4l2_rect crop;
> struct v4l2_mbus_framefmt format;
> @@ -611,6 +619,19 @@ static int ov5693_enable_streaming(struct ov5693_device *ov5693, bool enable)
> {
> int ret = 0;
>
> + /*
> + * Gate the MIPI clock lane while idle if the CSI-2 link is configured
> + * for a non-continuous clock. Only that bit is touched, and only in
> + * that case, so the register keeps whatever the platform left in it
> + * and the clock stays free-running as before everywhere else. It
> + * needs no counterpart at stream off: the link is down by then, and
> + * the register returns to its default when the sensor is powered off.
> + */
> + if (enable && ov5693->clock_ncont)
> + cci_update_bits(ov5693->regmap, OV5693_MIPI_CTRL00_REG,
> + OV5693_MIPI_CTRL00_CLOCK_LANE_GATE,
> + OV5693_MIPI_CTRL00_CLOCK_LANE_GATE, &ret);
> +
> cci_write(ov5693->regmap, OV5693_SW_STREAM_REG,
> enable ? OV5693_START_STREAMING : OV5693_STOP_STREAMING,
> &ret);
> @@ -1259,6 +1280,9 @@ static int ov5693_check_hwcfg(struct ov5693_device *ov5693)
> goto out_free_bus_cfg;
> }
>
> + ov5693->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
> + V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
Could you also make the change to the DT bindings, adding "clock-noncontinuous:
true" there?
> +
> out_free_bus_cfg:
> v4l2_fwnode_endpoint_free(&bus_cfg);
>
--
Regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v4 4/6] media: ipu-bridge: Assign endpoint property indices dynamically
2026-08-31 18:18 ` [PATCH v4 0/6] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
` (2 preceding siblings ...)
2026-08-31 18:18 ` [PATCH v4 3/6] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock Fernando Rimoli
@ 2026-08-31 18:18 ` Fernando Rimoli
2026-09-02 6:33 ` Sakari Ailus
2026-08-31 18:18 ` [PATCH v4 5/6] media: ipu-bridge: Match sensor configs per IPU and add config flags Fernando Rimoli
` (2 subsequent siblings)
6 siblings, 1 reply; 50+ messages in thread
From: Fernando Rimoli @ 2026-08-31 18:18 UTC (permalink / raw)
To: Sakari Ailus, Daniel Scally, linux-media
Cc: Mauro Carvalho Chehab, Arsalan Naeem, Jakob Berg Jespersen,
linux-kernel, Fernando Rimoli
The endpoint property array is populated with hardcoded indices, so a
property that is only set conditionally has to be placed at a fixed slot.
As the array is NULL-terminated, such a property is silently dropped when
an earlier optional slot is left empty: "link-frequencies" is skipped for
configs with nr_link_freqs == 0, which would truncate the array before
anything following it.
Name the endpoint property slots in an enum, size the array accordingly
and assign the indices through a bounds-checked running index, as done
for the MIPI DisCo for Imaging properties in mipi-disco-img.c. No
functional change intended: the same properties are set in the same
order.
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
---
drivers/media/pci/intel/ipu-bridge.c | 27 ++++++++++++++-------------
include/media/ipu-bridge.h | 19 ++++++++++++++++++-
2 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index 131c70844..cd3c36d44 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -449,6 +449,7 @@ static void ipu_bridge_create_fwnode_properties(
struct ipu_bridge *bridge,
const struct ipu_sensor_config *cfg)
{
+ unsigned int i = IPU_SENSOR_EP_BUS_TYPE;
struct ipu_property_names *names = &sensor->prop_names;
struct software_node *nodes = sensor->swnodes;
@@ -508,21 +509,21 @@ static void ipu_bridge_create_fwnode_properties(
PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref);
}
- sensor->ep_properties[0] = PROPERTY_ENTRY_U32(
- sensor->prop_names.bus_type,
- V4L2_FWNODE_BUS_TYPE_CSI2_DPHY);
- sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(
- sensor->prop_names.data_lanes,
- bridge->data_lanes, sensor->lanes);
- sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(
- sensor->prop_names.remote_endpoint,
- sensor->local_ref);
+ sensor->ep_properties[IPU_NEXT_EP_PROPERTY(i, NUM_OF)] =
+ PROPERTY_ENTRY_U32(names->bus_type,
+ V4L2_FWNODE_BUS_TYPE_CSI2_DPHY);
+ sensor->ep_properties[IPU_NEXT_EP_PROPERTY(i, NUM_OF)] =
+ PROPERTY_ENTRY_U32_ARRAY_LEN(names->data_lanes,
+ bridge->data_lanes, sensor->lanes);
+ sensor->ep_properties[IPU_NEXT_EP_PROPERTY(i, NUM_OF)] =
+ PROPERTY_ENTRY_REF_ARRAY(names->remote_endpoint,
+ sensor->local_ref);
if (cfg->nr_link_freqs > 0)
- sensor->ep_properties[3] = PROPERTY_ENTRY_U64_ARRAY_LEN(
- sensor->prop_names.link_frequencies,
- cfg->link_freqs,
- cfg->nr_link_freqs);
+ sensor->ep_properties[IPU_NEXT_EP_PROPERTY(i, NUM_OF)] =
+ PROPERTY_ENTRY_U64_ARRAY_LEN(names->link_frequencies,
+ cfg->link_freqs,
+ cfg->nr_link_freqs);
sensor->ipu_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(
sensor->prop_names.data_lanes,
diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h
index 16fac7654..61e10cef1 100644
--- a/include/media/ipu-bridge.h
+++ b/include/media/ipu-bridge.h
@@ -64,6 +64,23 @@ enum ipu_sensor_swnodes {
SWNODE_COUNT
};
+enum ipu_sensor_ep_props {
+ IPU_SENSOR_EP_BUS_TYPE,
+ IPU_SENSOR_EP_DATA_LANES,
+ IPU_SENSOR_EP_REMOTE_EP,
+ IPU_SENSOR_EP_LINK_FREQUENCIES,
+ IPU_SENSOR_EP_NUM_OF,
+ IPU_SENSOR_EP_NUM_ENTRIES
+};
+
+/*
+ * Get the index of the next endpoint property in the property array, with a
+ * given maximum value.
+ */
+#define IPU_NEXT_EP_PROPERTY(index, max) \
+ (WARN_ON((index) > IPU_SENSOR_EP_##max) ? \
+ IPU_SENSOR_EP_##max : (index)++)
+
/* Data representation as it is in ACPI SSDB buffer */
struct ipu_sensor_ssdb {
u8 version;
@@ -141,7 +158,7 @@ struct ipu_sensor {
const char *vcm_type;
struct ipu_property_names prop_names;
- struct property_entry ep_properties[5];
+ struct property_entry ep_properties[IPU_SENSOR_EP_NUM_ENTRIES];
struct property_entry dev_properties[5];
struct property_entry ipu_properties[3];
struct property_entry ivsc_properties[1];
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH v4 4/6] media: ipu-bridge: Assign endpoint property indices dynamically
2026-08-31 18:18 ` [PATCH v4 4/6] media: ipu-bridge: Assign endpoint property indices dynamically Fernando Rimoli
@ 2026-09-02 6:33 ` Sakari Ailus
0 siblings, 0 replies; 50+ messages in thread
From: Sakari Ailus @ 2026-09-02 6:33 UTC (permalink / raw)
To: Fernando Rimoli
Cc: Daniel Scally, linux-media, Mauro Carvalho Chehab, Arsalan Naeem,
Jakob Berg Jespersen, linux-kernel
On Mon, Aug 31, 2026 at 08:18:56PM +0200, Fernando Rimoli wrote:
> The endpoint property array is populated with hardcoded indices, so a
> property that is only set conditionally has to be placed at a fixed slot.
> As the array is NULL-terminated, such a property is silently dropped when
> an earlier optional slot is left empty: "link-frequencies" is skipped for
> configs with nr_link_freqs == 0, which would truncate the array before
> anything following it.
>
> Name the endpoint property slots in an enum, size the array accordingly
> and assign the indices through a bounds-checked running index, as done
> for the MIPI DisCo for Imaging properties in mipi-disco-img.c. No
> functional change intended: the same properties are set in the same
> order.
There's a lot of unneeded information here. For simple patches like this
there's no need to go deep in details that can be easily seen from the
code. How about:
Index the ep_properties array dynamically instead of plain numerical values
as is done in mipi-disco-img.c.
>
> Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
> ---
> drivers/media/pci/intel/ipu-bridge.c | 27 ++++++++++++++-------------
> include/media/ipu-bridge.h | 19 ++++++++++++++++++-
> 2 files changed, 32 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
> index 131c70844..cd3c36d44 100644
> --- a/drivers/media/pci/intel/ipu-bridge.c
> +++ b/drivers/media/pci/intel/ipu-bridge.c
> @@ -449,6 +449,7 @@ static void ipu_bridge_create_fwnode_properties(
> struct ipu_bridge *bridge,
> const struct ipu_sensor_config *cfg)
> {
> + unsigned int i = IPU_SENSOR_EP_BUS_TYPE;
You can just initialise this to 0.
> struct ipu_property_names *names = &sensor->prop_names;
> struct software_node *nodes = sensor->swnodes;
>
> @@ -508,21 +509,21 @@ static void ipu_bridge_create_fwnode_properties(
> PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref);
> }
>
> - sensor->ep_properties[0] = PROPERTY_ENTRY_U32(
> - sensor->prop_names.bus_type,
> - V4L2_FWNODE_BUS_TYPE_CSI2_DPHY);
> - sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(
> - sensor->prop_names.data_lanes,
> - bridge->data_lanes, sensor->lanes);
> - sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(
> - sensor->prop_names.remote_endpoint,
> - sensor->local_ref);
> + sensor->ep_properties[IPU_NEXT_EP_PROPERTY(i, NUM_OF)] =
You should use the maximum value of the property index here. Same below.
Right now it's fairly simple, but in more complicated cases it helps
keeping track of the properties.
> + PROPERTY_ENTRY_U32(names->bus_type,
> + V4L2_FWNODE_BUS_TYPE_CSI2_DPHY);
> + sensor->ep_properties[IPU_NEXT_EP_PROPERTY(i, NUM_OF)] =
> + PROPERTY_ENTRY_U32_ARRAY_LEN(names->data_lanes,
> + bridge->data_lanes, sensor->lanes);
> + sensor->ep_properties[IPU_NEXT_EP_PROPERTY(i, NUM_OF)] =
> + PROPERTY_ENTRY_REF_ARRAY(names->remote_endpoint,
> + sensor->local_ref);
>
> if (cfg->nr_link_freqs > 0)
> - sensor->ep_properties[3] = PROPERTY_ENTRY_U64_ARRAY_LEN(
> - sensor->prop_names.link_frequencies,
> - cfg->link_freqs,
> - cfg->nr_link_freqs);
> + sensor->ep_properties[IPU_NEXT_EP_PROPERTY(i, NUM_OF)] =
> + PROPERTY_ENTRY_U64_ARRAY_LEN(names->link_frequencies,
> + cfg->link_freqs,
> + cfg->nr_link_freqs);
>
> sensor->ipu_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(
> sensor->prop_names.data_lanes,
> diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h
> index 16fac7654..61e10cef1 100644
> --- a/include/media/ipu-bridge.h
> +++ b/include/media/ipu-bridge.h
> @@ -64,6 +64,23 @@ enum ipu_sensor_swnodes {
> SWNODE_COUNT
> };
>
> +enum ipu_sensor_ep_props {
> + IPU_SENSOR_EP_BUS_TYPE,
> + IPU_SENSOR_EP_DATA_LANES,
> + IPU_SENSOR_EP_REMOTE_EP,
> + IPU_SENSOR_EP_LINK_FREQUENCIES,
> + IPU_SENSOR_EP_NUM_OF,
> + IPU_SENSOR_EP_NUM_ENTRIES
> +};
> +
> +/*
> + * Get the index of the next endpoint property in the property array, with a
> + * given maximum value.
> + */
> +#define IPU_NEXT_EP_PROPERTY(index, max) \
The macro isn't limited to endpoint properties, how about calling it
e.g. IPU_BRIDGE_NEXT_PROPERTY?
> + (WARN_ON((index) > IPU_SENSOR_EP_##max) ? \
How about:
s/SENSOR_EP/BRIDGE/
> + IPU_SENSOR_EP_##max : (index)++)
> +
> /* Data representation as it is in ACPI SSDB buffer */
> struct ipu_sensor_ssdb {
> u8 version;
> @@ -141,7 +158,7 @@ struct ipu_sensor {
> const char *vcm_type;
>
> struct ipu_property_names prop_names;
> - struct property_entry ep_properties[5];
> + struct property_entry ep_properties[IPU_SENSOR_EP_NUM_ENTRIES];
> struct property_entry dev_properties[5];
> struct property_entry ipu_properties[3];
> struct property_entry ivsc_properties[1];
--
Regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v4 5/6] media: ipu-bridge: Match sensor configs per IPU and add config flags
2026-08-31 18:18 ` [PATCH v4 0/6] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
` (3 preceding siblings ...)
2026-08-31 18:18 ` [PATCH v4 4/6] media: ipu-bridge: Assign endpoint property indices dynamically Fernando Rimoli
@ 2026-08-31 18:18 ` Fernando Rimoli
2026-09-01 9:57 ` Fernando Rimoli
2026-09-02 6:42 ` Sakari Ailus
2026-08-31 18:18 ` [PATCH v4 6/6] media: ipu-bridge: Request non-continuous clock for ov5693 on IPU6 Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
6 siblings, 2 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-08-31 18:18 UTC (permalink / raw)
To: Sakari Ailus, Daniel Scally, linux-media
Cc: Mauro Carvalho Chehab, Arsalan Naeem, Jakob Berg Jespersen,
linux-kernel, Fernando Rimoli
Some sensors need different treatment depending on which IPU they are
connected to, so the sensor's ACPI HID alone is not always enough to
describe what the bridge has to set up.
Add an optional IPU PCI product ID and a set of flags to struct
ipu_sensor_config, along with an IPU_SENSOR_CONFIG_MATCH_FL() macro to
define such an entry. A config naming a PCI product ID only applies to
that IPU and takes precedence over a generic config for the same sensor,
so that a sensor covered by both is connected once, through the more
specific entry. Existing entries are unchanged and keep matching any IPU.
No flags are defined yet and no entry uses the new macro, so there is no
functional change.
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
---
drivers/media/pci/intel/ipu-bridge.c | 31 ++++++++++++++++++++++++++++
include/media/ipu-bridge.h | 29 +++++++++++++++++++++-----
2 files changed, 55 insertions(+), 5 deletions(-)
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index cd3c36d44..38ad3e54e 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -8,6 +8,7 @@
#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/mei_cl_bus.h>
+#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
@@ -853,6 +854,32 @@ static int ipu_bridge_connect_sensor(const struct ipu_sensor_config *cfg,
return ret;
}
+/*
+ * Whether a sensor config applies to the IPU the bridge sits on. A config
+ * naming a PCI product ID only applies to that IPU, and takes precedence over
+ * a generic config for the same sensor, which is skipped so that the sensor is
+ * not connected twice.
+ */
+static bool ipu_bridge_config_matches(const struct ipu_sensor_config *cfg,
+ struct ipu_bridge *bridge)
+{
+ unsigned int i;
+
+ if (cfg->pci_id)
+ return cfg->pci_id == bridge->pci_id;
+
+ for (i = 0; i < ARRAY_SIZE(ipu_supported_sensors); i++) {
+ const struct ipu_sensor_config *sp =
+ &ipu_supported_sensors[i];
+
+ if (sp->pci_id && sp->pci_id == bridge->pci_id &&
+ !strcmp(sp->hid, cfg->hid))
+ return false;
+ }
+
+ return true;
+}
+
static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge)
{
unsigned int i;
@@ -862,6 +889,9 @@ static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge)
const struct ipu_sensor_config *cfg =
&ipu_supported_sensors[i];
+ if (!ipu_bridge_config_matches(cfg, bridge))
+ continue;
+
ret = ipu_bridge_connect_sensor(cfg, bridge);
if (ret)
goto err_unregister_sensors;
@@ -948,6 +978,7 @@ int ipu_bridge_init(struct device *dev,
sizeof(bridge->ipu_node_name));
bridge->ipu_hid_node.name = bridge->ipu_node_name;
bridge->dev = dev;
+ bridge->pci_id = dev_is_pci(dev) ? to_pci_dev(dev)->device : 0;
bridge->parse_sensor_fwnode = parse_sensor_fwnode;
ret = software_node_register(&bridge->ipu_hid_node);
diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h
index 61e10cef1..d12e51336 100644
--- a/include/media/ipu-bridge.h
+++ b/include/media/ipu-bridge.h
@@ -17,13 +17,27 @@
#define IPU_SENSOR_ROTATION_NORMAL 0
#define IPU_SENSOR_ROTATION_INVERTED 1
-#define IPU_SENSOR_CONFIG(_HID, _NR, ...) \
- (const struct ipu_sensor_config) { \
- .hid = _HID, \
- .nr_link_freqs = _NR, \
- .link_freqs = { __VA_ARGS__ } \
+/* Flags for struct ipu_sensor_config */
+#define IPU_BR_FL_NONE 0
+
+/*
+ * Sensor config specific to a single IPU, identified by its PCI product ID,
+ * with flags describing what the sensor needs on that IPU. Where both a
+ * specific and a generic (IPU_SENSOR_CONFIG) entry exist for the same HID,
+ * the specific one takes precedence.
+ */
+#define IPU_SENSOR_CONFIG_MATCH_FL(_HID, _ID, _FLAGS, _NR, ...) \
+ (const struct ipu_sensor_config) { \
+ .hid = _HID, \
+ .pci_id = _ID, \
+ .flags = IPU_BR_FL_##_FLAGS, \
+ .nr_link_freqs = _NR, \
+ .link_freqs = { __VA_ARGS__ } \
}
+#define IPU_SENSOR_CONFIG(_HID, _NR, ...) \
+ IPU_SENSOR_CONFIG_MATCH_FL(_HID, 0, NONE, _NR, __VA_ARGS__)
+
#define NODE_SENSOR(_HID, _PROPS) \
(const struct software_node) { \
.name = _HID, \
@@ -132,6 +146,9 @@ struct ipu_node_names {
struct ipu_sensor_config {
const char *hid;
+ /* IPU PCI product ID this config is specific to, 0 for any */
+ const u16 pci_id;
+ const u32 flags;
const u8 nr_link_freqs;
const u64 link_freqs[MAX_NUM_LINK_FREQS];
};
@@ -177,6 +194,8 @@ typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev,
struct ipu_bridge {
struct device *dev;
+ /* PCI product ID of the IPU, 0 if it is not a PCI device */
+ u16 pci_id;
ipu_parse_sensor_fwnode_t parse_sensor_fwnode;
char ipu_node_name[ACPI_ID_LEN];
struct software_node ipu_hid_node;
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH v4 5/6] media: ipu-bridge: Match sensor configs per IPU and add config flags
2026-08-31 18:18 ` [PATCH v4 5/6] media: ipu-bridge: Match sensor configs per IPU and add config flags Fernando Rimoli
@ 2026-09-01 9:57 ` Fernando Rimoli
2026-09-02 6:42 ` Sakari Ailus
1 sibling, 0 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-01 9:57 UTC (permalink / raw)
To: Sakari Ailus, Daniel Scally, linux-media
Cc: Mauro Carvalho Chehab, Arsalan Naeem, Jakob Berg Jespersen,
linux-kernel
Sakari, Dan,
The semantic I asked you both to check in this patch, where a PCI-specific
entry wins and the generic entry for the same HID is skipped, now has
hardware confirmation rather than only my reasoning, so you may not need to
spend thought on it.
A linux-surface user tested the series on a Surface Pro 8 (Tiger Lake IPU6,
0x9a19, ov5693 as INT33BE) on a machine that has INT33BE in the table
twice, the generic entry plus the flagged one this patch adds, alongside
two other sensors on other ports. The bridge connects each sensor exactly
once:
intel-ipu6 0000:00:05.0: Found supported sensor INT33BE:00
intel-ipu6 0000:00:05.0: Found supported sensor OVTID858:00
intel-ipu6 0000:00:05.0: Found supported sensor SMO55F0:00
intel-ipu6 0000:00:05.0: Connected 3 cameras
Three sensors, three connections, no double-connect and no port consumed
twice, which is the failure I was trying to avoid. The other two sensors
take no flags and came up normally afterwards, including an IR sensor that
still streams and still serves face authentication on that machine, so the
filter does not perturb entries it should not touch.
He also read MIPI_CTRL00 back over I2C during a live capture and got 0x20,
which means the flagged INT33BE plus PCI_DEVICE_ID_INTEL_IPU6 entry is what
matched and the property reached the sensor endpoint. So the path from the
table through to the register is exercised, not only the end result. That
is a second Tiger Lake confirmation independent of Jakob's on a Surface Pro
7+ elsewhere in this thread.
Two caveats on how much this carries. His tree is 7.2.2 with the
linux-surface patches rather than the v7.3-rc1 base this series declares,
and that tree carries its own duplicate OVTI5693 entry which he had to drop
for patch 6 to apply, since patch 2 adds it properly. Jakob's test was on
the declared base. Both are good, but they are not the same tree so I just
wanted to have that on record.
He intends to send his own Tested-by, and has offered to run the negative
control, the same build with the PCI_DEVICE_ID_INTEL_IPU6 entry removed,
expecting no frames. I have asked him to do it. That would show the table
entry is what makes this work rather than something incidental, which is
the one thing none of the positive results establish. I will report the
outcome either way.
Thanks,
Fernando
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH v4 5/6] media: ipu-bridge: Match sensor configs per IPU and add config flags
2026-08-31 18:18 ` [PATCH v4 5/6] media: ipu-bridge: Match sensor configs per IPU and add config flags Fernando Rimoli
2026-09-01 9:57 ` Fernando Rimoli
@ 2026-09-02 6:42 ` Sakari Ailus
1 sibling, 0 replies; 50+ messages in thread
From: Sakari Ailus @ 2026-09-02 6:42 UTC (permalink / raw)
To: Fernando Rimoli
Cc: Daniel Scally, linux-media, Mauro Carvalho Chehab, Arsalan Naeem,
Jakob Berg Jespersen, linux-kernel
Hi Fernando,
On Mon, Aug 31, 2026 at 08:18:57PM +0200, Fernando Rimoli wrote:
> Some sensors need different treatment depending on which IPU they are
> connected to, so the sensor's ACPI HID alone is not always enough to
> describe what the bridge has to set up.
>
> Add an optional IPU PCI product ID and a set of flags to struct
> ipu_sensor_config, along with an IPU_SENSOR_CONFIG_MATCH_FL() macro to
> define such an entry. A config naming a PCI product ID only applies to
> that IPU and takes precedence over a generic config for the same sensor,
> so that a sensor covered by both is connected once, through the more
> specific entry. Existing entries are unchanged and keep matching any IPU.
>
> No flags are defined yet and no entry uses the new macro, so there is no
> functional change.
There's quite a bit of irrelevant information here.
>
> Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
> ---
> drivers/media/pci/intel/ipu-bridge.c | 31 ++++++++++++++++++++++++++++
> include/media/ipu-bridge.h | 29 +++++++++++++++++++++-----
> 2 files changed, 55 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
> index cd3c36d44..38ad3e54e 100644
> --- a/drivers/media/pci/intel/ipu-bridge.c
> +++ b/drivers/media/pci/intel/ipu-bridge.c
> @@ -8,6 +8,7 @@
> #include <linux/dmi.h>
> #include <linux/i2c.h>
> #include <linux/mei_cl_bus.h>
> +#include <linux/pci.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> #include <linux/property.h>
> @@ -853,6 +854,32 @@ static int ipu_bridge_connect_sensor(const struct ipu_sensor_config *cfg,
> return ret;
> }
>
> +/*
> + * Whether a sensor config applies to the IPU the bridge sits on. A config
> + * naming a PCI product ID only applies to that IPU, and takes precedence over
> + * a generic config for the same sensor, which is skipped so that the sensor is
> + * not connected twice.
> + */
> +static bool ipu_bridge_config_matches(const struct ipu_sensor_config *cfg,
> + struct ipu_bridge *bridge)
> +{
> + unsigned int i;
> +
> + if (cfg->pci_id)
> + return cfg->pci_id == bridge->pci_id;
> +
> + for (i = 0; i < ARRAY_SIZE(ipu_supported_sensors); i++) {
Is there really a need to go through the entire array for each entry? Can't
you simply arrange the entries with a pci_id before the generic one?
> + const struct ipu_sensor_config *sp =
> + &ipu_supported_sensors[i];
> +
> + if (sp->pci_id && sp->pci_id == bridge->pci_id &&
> + !strcmp(sp->hid, cfg->hid))
> + return false;
> + }
> +
> + return true;
> +}
> +
> static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge)
> {
> unsigned int i;
> @@ -862,6 +889,9 @@ static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge)
> const struct ipu_sensor_config *cfg =
> &ipu_supported_sensors[i];
>
> + if (!ipu_bridge_config_matches(cfg, bridge))
> + continue;
> +
> ret = ipu_bridge_connect_sensor(cfg, bridge);
> if (ret)
> goto err_unregister_sensors;
> @@ -948,6 +978,7 @@ int ipu_bridge_init(struct device *dev,
> sizeof(bridge->ipu_node_name));
> bridge->ipu_hid_node.name = bridge->ipu_node_name;
> bridge->dev = dev;
> + bridge->pci_id = dev_is_pci(dev) ? to_pci_dev(dev)->device : 0;
> bridge->parse_sensor_fwnode = parse_sensor_fwnode;
>
> ret = software_node_register(&bridge->ipu_hid_node);
> diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h
> index 61e10cef1..d12e51336 100644
> --- a/include/media/ipu-bridge.h
> +++ b/include/media/ipu-bridge.h
> @@ -17,13 +17,27 @@
> #define IPU_SENSOR_ROTATION_NORMAL 0
> #define IPU_SENSOR_ROTATION_INVERTED 1
>
> -#define IPU_SENSOR_CONFIG(_HID, _NR, ...) \
> - (const struct ipu_sensor_config) { \
> - .hid = _HID, \
> - .nr_link_freqs = _NR, \
> - .link_freqs = { __VA_ARGS__ } \
> +/* Flags for struct ipu_sensor_config */
> +#define IPU_BR_FL_NONE 0
> +
> +/*
> + * Sensor config specific to a single IPU, identified by its PCI product ID,
> + * with flags describing what the sensor needs on that IPU. Where both a
> + * specific and a generic (IPU_SENSOR_CONFIG) entry exist for the same HID,
> + * the specific one takes precedence.
> + */
> +#define IPU_SENSOR_CONFIG_MATCH_FL(_HID, _ID, _FLAGS, _NR, ...) \
> + (const struct ipu_sensor_config) { \
> + .hid = _HID, \
> + .pci_id = _ID, \
> + .flags = IPU_BR_FL_##_FLAGS, \
Please don't assume a flag; setting multiple flags also doesn't work this
way.
> + .nr_link_freqs = _NR, \
> + .link_freqs = { __VA_ARGS__ } \
> }
>
> +#define IPU_SENSOR_CONFIG(_HID, _NR, ...) \
> + IPU_SENSOR_CONFIG_MATCH_FL(_HID, 0, NONE, _NR, __VA_ARGS__)
> +
> #define NODE_SENSOR(_HID, _PROPS) \
> (const struct software_node) { \
> .name = _HID, \
> @@ -132,6 +146,9 @@ struct ipu_node_names {
>
> struct ipu_sensor_config {
> const char *hid;
> + /* IPU PCI product ID this config is specific to, 0 for any */
> + const u16 pci_id;
In later patches we already get two extra entries per sensor that only
differ on pci_id. How about making this a pointer to an array? Zero
termination should be fine here.
> + const u32 flags;
> const u8 nr_link_freqs;
> const u64 link_freqs[MAX_NUM_LINK_FREQS];
> };
> @@ -177,6 +194,8 @@ typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev,
>
> struct ipu_bridge {
> struct device *dev;
> + /* PCI product ID of the IPU, 0 if it is not a PCI device */
All IPUs are PCI devices. ipu_bridge_init() should fail if a device isn't.
I think I might just omit the check.
> + u16 pci_id;
> ipu_parse_sensor_fwnode_t parse_sensor_fwnode;
> char ipu_node_name[ACPI_ID_LEN];
> struct software_node ipu_hid_node;
--
Regards,
Sakari Ailus
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v4 6/6] media: ipu-bridge: Request non-continuous clock for ov5693 on IPU6
2026-08-31 18:18 ` [PATCH v4 0/6] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
` (4 preceding siblings ...)
2026-08-31 18:18 ` [PATCH v4 5/6] media: ipu-bridge: Match sensor configs per IPU and add config flags Fernando Rimoli
@ 2026-08-31 18:18 ` Fernando Rimoli
2026-09-02 4:42 ` Kengo Oki
2026-09-02 14:23 ` [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
6 siblings, 1 reply; 50+ messages in thread
From: Fernando Rimoli @ 2026-08-31 18:18 UTC (permalink / raw)
To: Sakari Ailus, Daniel Scally, linux-media
Cc: Mauro Carvalho Chehab, Arsalan Naeem, Jakob Berg Jespersen,
linux-kernel, Fernando Rimoli
The ov5693 (INT33BE / OVTI5693) needs its MIPI clock lane gated while
idle for the IPU6 CSI-2 receiver to lock onto the link; otherwise the
sensor streams but capture times out and no frames arrive. The sensor
driver gates the clock lane when the endpoint requests a non-continuous
clock, so the bridge has to supply that property.
The same sensor works with a free-running clock on the IPU3, so add
IPU_BR_FL_CSI2_CLK_NONCONTINUOUS and set it only for the ov5693 on the
IPU6 variants where the gate is known to be needed: IPU6 (Tiger Lake,
tested on a Surface Pro 7+) and IPU6EP_ADLP (Alder Lake-P, tested on a
Surface Pro 9). Other IPU6 product IDs are left out until someone can
confirm them on hardware; the generic entries continue to apply there
and on the IPU3.
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
---
drivers/media/pci/intel/ipu-bridge.c | 13 +++++++++++++
include/media/ipu-bridge.h | 3 +++
2 files changed, 16 insertions(+)
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index 38ad3e54e..7498531f2 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -16,6 +16,7 @@
#include <linux/workqueue.h>
#include <media/ipu-bridge.h>
+#include <media/ipu6-pci-table.h>
#include <media/v4l2-fwnode.h>
#define ADEV_DEV(adev) ACPI_PTR(&((adev)->dev))
@@ -62,6 +63,10 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = {
IPU_SENSOR_CONFIG("INT0310", 1, 55692000),
/* Omnivision OV5693 */
IPU_SENSOR_CONFIG("INT33BE", 1, 419200000),
+ IPU_SENSOR_CONFIG_MATCH_FL("INT33BE", PCI_DEVICE_ID_INTEL_IPU6,
+ CSI2_CLK_NONCONTINUOUS, 1, 419200000),
+ IPU_SENSOR_CONFIG_MATCH_FL("INT33BE", PCI_DEVICE_ID_INTEL_IPU6EP_ADLP,
+ CSI2_CLK_NONCONTINUOUS, 1, 419200000),
/* Onsemi MT9M114 */
IPU_SENSOR_CONFIG("INT33F0", 1, 384000000),
/* Omnivision OV2740 */
@@ -98,6 +103,10 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = {
IPU_SENSOR_CONFIG("OVTI5675", 1, 450000000),
/* Omnivision OV5693 */
IPU_SENSOR_CONFIG("OVTI5693", 1, 419200000),
+ IPU_SENSOR_CONFIG_MATCH_FL("OVTI5693", PCI_DEVICE_ID_INTEL_IPU6,
+ CSI2_CLK_NONCONTINUOUS, 1, 419200000),
+ IPU_SENSOR_CONFIG_MATCH_FL("OVTI5693", PCI_DEVICE_ID_INTEL_IPU6EP_ADLP,
+ CSI2_CLK_NONCONTINUOUS, 1, 419200000),
/* Omnivision OV8856 */
IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000),
/* Sony IMX471 */
@@ -526,6 +535,10 @@ static void ipu_bridge_create_fwnode_properties(
cfg->link_freqs,
cfg->nr_link_freqs);
+ if (cfg->flags & IPU_BR_FL_CSI2_CLK_NONCONTINUOUS)
+ sensor->ep_properties[IPU_NEXT_EP_PROPERTY(i, NUM_OF)] =
+ PROPERTY_ENTRY_BOOL("clock-noncontinuous");
+
sensor->ipu_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(
sensor->prop_names.data_lanes,
bridge->data_lanes, sensor->lanes);
diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h
index d12e51336..a5f8c5d4b 100644
--- a/include/media/ipu-bridge.h
+++ b/include/media/ipu-bridge.h
@@ -19,6 +19,8 @@
/* Flags for struct ipu_sensor_config */
#define IPU_BR_FL_NONE 0
+/* The sensor's CSI-2 transmitter needs a non-continuous clock */
+#define IPU_BR_FL_CSI2_CLK_NONCONTINUOUS BIT(0)
/*
* Sensor config specific to a single IPU, identified by its PCI product ID,
@@ -83,6 +85,7 @@ enum ipu_sensor_ep_props {
IPU_SENSOR_EP_DATA_LANES,
IPU_SENSOR_EP_REMOTE_EP,
IPU_SENSOR_EP_LINK_FREQUENCIES,
+ IPU_SENSOR_EP_CLOCK_NONCONTINUOUS,
IPU_SENSOR_EP_NUM_OF,
IPU_SENSOR_EP_NUM_ENTRIES
};
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH v4 6/6] media: ipu-bridge: Request non-continuous clock for ov5693 on IPU6
2026-08-31 18:18 ` [PATCH v4 6/6] media: ipu-bridge: Request non-continuous clock for ov5693 on IPU6 Fernando Rimoli
@ 2026-09-02 4:42 ` Kengo Oki
0 siblings, 0 replies; 50+ messages in thread
From: Kengo Oki @ 2026-09-02 4:42 UTC (permalink / raw)
To: fernandorimoli11
Cc: dan.scally, dev, linux-kernel, linux-media, mchehab, naeemarsalan,
sakari.ailus, Kengo Oki
Hi Fernando,
I completed the Surface Go 4 A/B test for the proposed Alder Lake-N entry.
Test system:
* Microsoft Surface Go 4
* IPU6: 8086:462e (Alder Lake-N)
* Front sensor: OV5693
* Sensor enumeration: INT33BE:00
* Kernel: Ubuntu 7.0.0-30-generic
I tested the v4 semantics as a minimal backport to Ubuntu 7.0.0-30.30. Patch 2 needed a small semantic backport because Ubuntu's sensor table differs from the upstream base.
Without the ADL-N INT33BE match, after a cold boot the first deliberate front-camera capture produced:
```
requested_frames=300
frame_count=0
exit_code=124
```
with:
```
intel_ipu6_isys.isys intel_ipu6.isys.40: stream stop time out
intel_ipu6_isys.isys intel_ipu6.isys.40: stream close time out
```
I then added only:
```
IPU_SENSOR_CONFIG_MATCH_FL("INT33BE",
PCI_DEVICE_ID_INTEL_IPU6EP_ADLN,
CSI2_CLK_NONCONTINUOUS, 1, 419200000),
```
After a full power-off and cold boot, with no earlier IPU6 stream activity in that boot, the same 300-frame test produced:
```
requested_frames=300
frame_count=300
exit_code=0
last sequence=000299
~28.64 fps
```
There were no relevant stream/CSI timeout or error messages during the successful run.
So on this Surface Go 4 the A/B result is:
```
v4 without ADL-N match: 0/300, timeout
v4 with ADL-N match: 300/300, success
```
This unit enumerates the OV5693 as INT33BE:00, not OVTI5693.
Full test/build evidence:
https://github.com/Fugu0141/Surface-Go4-IPU6-camera-linux/blob/main/tests/2026-09-01-ov5693-v4-adln/RESULT.md
For v5 with the ADL-N entry added:
Tested-by: Kengo Oki <dev.kengo.fugu0141@gmail.com> # Surface Go 4, IPU6 Alder Lake-N 8086:462e
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices
2026-08-31 18:18 ` [PATCH v4 0/6] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
` (5 preceding siblings ...)
2026-08-31 18:18 ` [PATCH v4 6/6] media: ipu-bridge: Request non-continuous clock for ov5693 on IPU6 Fernando Rimoli
@ 2026-09-02 14:23 ` Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 1/7] media: i2c: ov5693: Add OVTI5693 ACPI HID Fernando Rimoli
` (6 more replies)
6 siblings, 7 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-02 14:23 UTC (permalink / raw)
To: linux-media; +Cc: sakari.ailus, dan.scally, linux-kernel, Fernando Rimoli
The ov5693 front camera does not stream on IPU6 Surface devices. The sensor needs
its MIPI clock lane gated while idle, which needs a driver change and a way for
the ipu-bridge to ask for it per IPU.
v4 is at [1]. This addresses Sakari's review of patches 3, 4 and 5, adds the DT
bindings property he asked for, and adds an Alder Lake-N entry now that a Surface
Go 4 has been measured.
Changes since v4:
- New patch 3 adds "clock-noncontinuous" to the ov5693 DT bindings. The series is
now seven patches; v4's patches 3 to 6 are 4 to 7 here, and the Tested-by tags
are scoped to those four.
- Commit messages cut throughout, per your comments on v4. Patch 5 now carries
your wording and nothing else. Patch 4 lost the ov5647 comparison and the
per-machine failure detail, which is below instead. Patches 6 and 7 trimmed.
- Patch 5: the running index starts at 0, each call site passes its own property's
maximum index rather than a shared one, and the macro is IPU_BRIDGE_NEXT_PROPERTY
with the enum renamed to match, following mipi-disco-img.c more closely.
- Patch 6: struct ipu_sensor_config now carries a zero-terminated list of IPU PCI
product IDs rather than a single ID, so one entry covers several IPUs. The flags
macro argument is a plain value, so flags can be combined. The scan of the whole
table is gone: entries for one HID are adjacent with the IPU-specific ones first,
and the generic entry is skipped once a specific one has matched.
- Patch 7: the four entries collapse to one shared ID list, with Alder Lake-N added.
On the enum naming in patch 5: "s/SENSOR_EP/BRIDGE/" taken literally gives
IPU_BRIDGE_BUS_TYPE, but since the macro is not endpoint-specific and may later
serve dev_properties, I kept the group marker as IPU_BRIDGE_EP_*, which is also how
mipi-disco-img.c separates its EP and DEV entries. Say the word if you meant the
shorter form.
Unpatched behaviour, which patch 4 now only summarises:
Four people measured it on five machines and it is not uniform. It is absolute on
three (a Pro 9, a Pro 7+ and a Go 4). On another Pro 7+ it is intermittent, 3 of 20
opens delivering frames inside a single boot, with the successes at opens 1, 7 and
14 and the sensor runtime-suspending in between. On a Pro 8 the first capture after
a cold boot succeeds and every later one in that boot hangs. No mechanism explains
the spread: it is not once per boot, given where that machine's successes fell, and
it is not Tiger Lake versus Alder Lake, since two Tiger Lake machines fall on
opposite sides. The sensor is up during the failures on every machine checked: the
privacy LED lights, the failing runs log no CSI-2 errors where the working ones log
ten or more, and setting bit 5 over i2c on an already stalled stream starts delivery
immediately.
**If you verify this, capture twice.** On one of the five machines a single capture
immediately after a cold boot succeeds without the flagged entry, so the obvious
check gives a false negative. Both testers who hit this asked for it to be written
down.
Two other things worth knowing:
- The teardown "stream stop time out" appears identically with and without this
series, so it is pre-existing and not introduced here.
- checkpatch flags "Macros with complex values should be enclosed in parentheses" on
patch 6. The pristine header already trips it five times and the patched header
still trips it exactly five times, because IPU_SENSOR_CONFIG becomes a wrapper as
IPU_SENSOR_CONFIG_MATCH_FL takes over the compound literal. No net new instance.
Testing coverage, all scoped to patches 4 to 7. Patches 1 and 2 are not exercised by
the testers, whose machines enumerate INT33BE; the Pro 9 is the OVTI5693 machine.
Tiger Lake 0x9a19 Pro 7+ (Jakob), Pro 8 (Fil Dunsky), Pro 7+ (Lucas Lis)
Alder Lake-P 0x465d Pro 9 (mine)
Alder Lake-N 0x462e Go 4 (Kengo Oki), 0/300 without the entry, 300/300 with
Kengo Oki's Alder Lake-N result is what justifies the third ID in patch 7, and his
tag is given for the version that carries it.
The reworked bridge in patches 5 to 7 was also run on the Pro 9 with all three of
its sensors: three cameras connected once each with no double connect, link
frequencies unchanged, and the front camera streaming at 28.63 fps, which is only
possible if the flag reaches the sensor driver through the new per-IPU match.
The Pro 9 measurement of 300 consecutive opens predates the switch from a full write
to cci_update_bits(), but the register reads 0x00 first there, so it resolves to the
same write.
[1] https://lore.kernel.org/linux-media/20260831181858.325109-1-fernandorimoli11@gmail.com/
Fernando Rimoli (7):
media: i2c: ov5693: Add OVTI5693 ACPI HID
media: ipu-bridge: Add OVTI5693 to the list of supported sensors
dt-bindings: media: ov5693: Add clock-noncontinuous
media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
media: ipu-bridge: Assign endpoint property indices dynamically
media: ipu-bridge: Match sensor configs per IPU and add config flags
media: ipu-bridge: Request non-continuous clock for ov5693 on IPU6
.../bindings/media/i2c/ovti,ov5693.yaml | 2 +
drivers/media/i2c/ov5693.c | 25 ++++++
drivers/media/pci/intel/ipu-bridge.c | 83 ++++++++++++++++---
include/media/ipu-bridge.h | 50 +++++++++--
4 files changed, 141 insertions(+), 19 deletions(-)
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
--
2.43.0
^ permalink raw reply [flat|nested] 50+ messages in thread* [PATCH v5 1/7] media: i2c: ov5693: Add OVTI5693 ACPI HID
2026-09-02 14:23 ` [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
@ 2026-09-02 14:23 ` Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 2/7] media: ipu-bridge: Add OVTI5693 to the list of supported sensors Fernando Rimoli
` (5 subsequent siblings)
6 siblings, 0 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-02 14:23 UTC (permalink / raw)
To: linux-media
Cc: sakari.ailus, dan.scally, linux-kernel, Fernando Rimoli,
Mauro Carvalho Chehab
The ov5693 driver only matches the "INT33BE" ACPI HID. Some Intel IPU6
Surface devices (e.g. Microsoft Surface Pro 9) enumerate the OV5693
front camera with the ACPI HID "OVTI5693" instead, so the i2c core never
binds the driver.
Add "OVTI5693" to the ACPI match table. Devices that use "INT33BE"
(e.g. Surface Go 4) are unaffected.
Tested on Surface Pro 9 (IPU6): the sensor enumerates as OVTI5693:00
(ACPI path \_SB_.PC00.I2C3.CAMF) and binds with this change.
Link: https://github.com/linux-surface/linux-surface/pull/2171
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
---
drivers/media/i2c/ov5693.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
index 4cc796bbe..02236f3db 100644
--- a/drivers/media/i2c/ov5693.c
+++ b/drivers/media/i2c/ov5693.c
@@ -1396,6 +1396,7 @@ static const struct dev_pm_ops ov5693_pm_ops = {
static const struct acpi_device_id ov5693_acpi_match[] = {
{"INT33BE"},
+ {"OVTI5693"},
{},
};
MODULE_DEVICE_TABLE(acpi, ov5693_acpi_match);
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v5 2/7] media: ipu-bridge: Add OVTI5693 to the list of supported sensors
2026-09-02 14:23 ` [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 1/7] media: i2c: ov5693: Add OVTI5693 ACPI HID Fernando Rimoli
@ 2026-09-02 14:23 ` Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 3/7] dt-bindings: media: ov5693: Add clock-noncontinuous Fernando Rimoli
` (4 subsequent siblings)
6 siblings, 0 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-02 14:23 UTC (permalink / raw)
To: linux-media
Cc: sakari.ailus, dan.scally, linux-kernel, Fernando Rimoli,
Mauro Carvalho Chehab
The IPU bridge builds the firmware node graph only for sensors listed in
ipu_supported_sensors[]. The OV5693 is currently listed only under its
legacy "INT33BE" HID, so on Intel IPU6 Surface devices that enumerate it
as "OVTI5693" (e.g. Microsoft Surface Pro 9) the bridge never wires up
the sensor and the front camera is unusable.
Add an "OVTI5693" entry. The link frequency (419200000) matches the
existing INT33BE entry, as it is the same sensor.
Tested on Surface Pro 9 (IPU6).
Link: https://github.com/linux-surface/linux-surface/pull/2171
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
---
drivers/media/pci/intel/ipu-bridge.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index 1bb3a3e98..131c70844 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -95,6 +95,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = {
IPU_SENSOR_CONFIG("OVTI2680", 1, 331200000),
/* Omnivision OV5675 */
IPU_SENSOR_CONFIG("OVTI5675", 1, 450000000),
+ /* Omnivision OV5693 */
+ IPU_SENSOR_CONFIG("OVTI5693", 1, 419200000),
/* Omnivision OV8856 */
IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000),
/* Sony IMX471 */
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v5 3/7] dt-bindings: media: ov5693: Add clock-noncontinuous
2026-09-02 14:23 ` [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 1/7] media: i2c: ov5693: Add OVTI5693 ACPI HID Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 2/7] media: ipu-bridge: Add OVTI5693 to the list of supported sensors Fernando Rimoli
@ 2026-09-02 14:23 ` Fernando Rimoli
2026-09-02 17:27 ` Conor Dooley
2026-09-02 14:23 ` [PATCH v5 4/7] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock Fernando Rimoli
` (3 subsequent siblings)
6 siblings, 1 reply; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-02 14:23 UTC (permalink / raw)
To: linux-media
Cc: sakari.ailus, dan.scally, linux-kernel, Fernando Rimoli,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Tommaso Merciai, devicetree
The sensor can gate its MIPI clock lane while idle, which the CSI-2
receivers on some platforms require. Allow the endpoint property that
asks for it, as ov5647 already does.
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
---
Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml
index 3368b3bd8..0d8ca0a51 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov5693.yaml
@@ -82,6 +82,8 @@ properties:
unevaluatedProperties: false
properties:
+ clock-noncontinuous: true
+
link-frequencies: true
data-lanes:
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH v5 3/7] dt-bindings: media: ov5693: Add clock-noncontinuous
2026-09-02 14:23 ` [PATCH v5 3/7] dt-bindings: media: ov5693: Add clock-noncontinuous Fernando Rimoli
@ 2026-09-02 17:27 ` Conor Dooley
0 siblings, 0 replies; 50+ messages in thread
From: Conor Dooley @ 2026-09-02 17:27 UTC (permalink / raw)
To: Fernando Rimoli
Cc: linux-media, sakari.ailus, dan.scally, linux-kernel,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Tommaso Merciai, devicetree
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v5 4/7] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
2026-09-02 14:23 ` [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
` (2 preceding siblings ...)
2026-09-02 14:23 ` [PATCH v5 3/7] dt-bindings: media: ov5693: Add clock-noncontinuous Fernando Rimoli
@ 2026-09-02 14:23 ` Fernando Rimoli
2026-09-02 19:11 ` Fil Dunsky
2026-09-02 14:23 ` [PATCH v5 5/7] media: ipu-bridge: Assign endpoint property indices dynamically Fernando Rimoli
` (2 subsequent siblings)
6 siblings, 1 reply; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-02 14:23 UTC (permalink / raw)
To: linux-media
Cc: sakari.ailus, dan.scally, linux-kernel, Fernando Rimoli,
Arsalan Naeem, Jakob Berg Jespersen, Fil Dunsky, Lucas Lis,
Kengo Oki, Mauro Carvalho Chehab
The ov5693 never programs MIPI_CTRL00 (0x4800), leaving it at its 0x00
power-on default, which lets the MIPI clock run freely. The IPU3 CSI-2
receiver tolerates this, but the IPU6 receiver (e.g. on Microsoft
Surface Pro 7+, Pro 8, Pro 9 and Surface Go 4) fails to lock onto the
link, so the sensor streams but capture times out with "stream stop
time out". On most affected machines no frames arrive at all; on some
the failure is intermittent.
Gate the clock lane while idle at stream on when the endpoint requests a
non-continuous clock.
Only the gate bit is touched, so platforms that do not request it are
unaffected. No counterpart is needed at stream off, as the link is down
by then and the register returns to its default when the sensor is
powered off.
The property is supplied by the ipu-bridge in a subsequent patch.
Link: https://github.com/linux-surface/linux-surface/pull/2171
Co-developed-by: Arsalan Naeem <naeemarsalan@gmail.com>
Signed-off-by: Arsalan Naeem <naeemarsalan@gmail.com>
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Tested-by: Jakob Berg Jespersen <dev@berg.pm> # Surface Pro 7+, IPU6 Tiger Lake
Tested-by: Fil Dunsky <filipp.dunsky@gmail.com> # Surface Pro 8, IPU6 Tiger Lake (8086:9a19)
Tested-by: Lucas Lis <lucaseze.lis@gmail.com> # Surface Pro 7+, IPU6 Tiger Lake (0x9a19)
Tested-by: Kengo Oki <dev.kengo.fugu0141@gmail.com> # Surface Go 4, IPU6 Alder Lake-N 8086:462e
---
drivers/media/i2c/ov5693.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
index 02236f3db..cedc6ea03 100644
--- a/drivers/media/i2c/ov5693.c
+++ b/drivers/media/i2c/ov5693.c
@@ -35,6 +35,11 @@
#define OV5693_STOP_STREAMING 0x00
#define OV5693_SW_RESET 0x01
+/* MIPI transmitter control */
+#define OV5693_MIPI_CTRL00_REG CCI_REG8(0x4800)
+/* Gate the clock lane when there is no packet to transmit */
+#define OV5693_MIPI_CTRL00_CLOCK_LANE_GATE BIT(5)
+
#define OV5693_REG_CHIP_ID CCI_REG16(0x300a)
/* Yes, this is right. The datasheet for the OV5693 gives its ID as 0x5690 */
#define OV5693_CHIP_ID 0x5690
@@ -144,6 +149,9 @@ struct ov5693_device {
struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];
struct clk *xvclk;
+ /* Gate the MIPI clock lane when idle (CSI-2 non-continuous clock) */
+ bool clock_ncont;
+
struct ov5693_mode {
struct v4l2_rect crop;
struct v4l2_mbus_framefmt format;
@@ -611,6 +619,19 @@ static int ov5693_enable_streaming(struct ov5693_device *ov5693, bool enable)
{
int ret = 0;
+ /*
+ * Gate the MIPI clock lane while idle if the CSI-2 link is configured
+ * for a non-continuous clock. Only that bit is touched, and only in
+ * that case, so the register keeps whatever the platform left in it
+ * and the clock stays free-running as before everywhere else. It
+ * needs no counterpart at stream off: the link is down by then, and
+ * the register returns to its default when the sensor is powered off.
+ */
+ if (enable && ov5693->clock_ncont)
+ cci_update_bits(ov5693->regmap, OV5693_MIPI_CTRL00_REG,
+ OV5693_MIPI_CTRL00_CLOCK_LANE_GATE,
+ OV5693_MIPI_CTRL00_CLOCK_LANE_GATE, &ret);
+
cci_write(ov5693->regmap, OV5693_SW_STREAM_REG,
enable ? OV5693_START_STREAMING : OV5693_STOP_STREAMING,
&ret);
@@ -1259,6 +1280,9 @@ static int ov5693_check_hwcfg(struct ov5693_device *ov5693)
goto out_free_bus_cfg;
}
+ ov5693->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
+ V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
+
out_free_bus_cfg:
v4l2_fwnode_endpoint_free(&bus_cfg);
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH v5 4/7] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock
2026-09-02 14:23 ` [PATCH v5 4/7] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock Fernando Rimoli
@ 2026-09-02 19:11 ` Fil Dunsky
0 siblings, 0 replies; 50+ messages in thread
From: Fil Dunsky @ 2026-09-02 19:11 UTC (permalink / raw)
To: Fernando Rimoli, linux-media
Cc: sakari.ailus, dan.scally, linux-kernel, Arsalan Naeem,
Jakob Berg Jespersen, Lucas Lis, Kengo Oki, Mauro Carvalho Chehab
Tested-by: Fil Dunsky <filipp.dunsky@gmail.com> # Surface Pro 8, IPU6
Tiger Lake (8086:9a19)
Scope: patches 4-7, as in v4. Patches 1 and 2 are already in my tree and
this machine enumerates INT33BE, so neither is exercised here; patch 3 is
not either, there is no DT on this platform.
Retested rather than carried over, because patches 5 and 6 are not the
code I tagged in v4. Same machine and kernel as before: 7.2.2 plus the
linux-surface patch set. Patches 3 to 6 applied to it unchanged; patch 7
needed two hunks by hand, both because that tree's sensor table differs
from yours — it has no HIMX1092 entry, which the first hunk uses as
context, and it carries its own out-of-order OVTI5693 entry. I put the
flagged entry immediately before the generic one, as the new adjacency
rule requires.
Capture from the ISYS node, three times in a row with the sensor
runtime-suspending in between:
60 frames, SBGGR10 2592x1944, 604661760 bytes, 28.63-28.65 fps (x3)
MIPI_CTRL00 (0x4800) read over i2c while streaming: 0x20
MIPI_CTRL00 with no stream: i2c times out, the sensor is powered off
0x20 is bit 5 alone, so the property still reaches the sensor driver
through the reworked per-IPU match, and the whole path is exercised
rather than "the camera works". Three captures because of the warning in
your cover letter: on this machine the first one after a cold boot
succeeds even without the entry.
Patch 6's adjacency rule behaves as described. INT33BE appears twice in
this tree, the Tiger Lake entry and the generic one, and the sensor is
connected once: "Connected 3 cameras" and exactly one ov5693 subdev in
the media graph. I also ran it with the pristine upstream table, where
this machine has no third sensor: "Connected 2 cameras", one ov5693, and
the same three captures.
Patch 5 is exercised by the sensor probing at all. ov5693 refuses an
endpoint with no link frequencies, and then refuses one that does not
offer 419.2 MHz, so a probe that succeeds means the running index put
link-frequencies and clock-noncontinuous in the right slots and did not
displace anything. The other case, where nr_link_freqs is 0 and
clock-noncontinuous packs down into the freed slot, is not exercised
here: both flagged entries carry one frequency.
The other two sensors on this machine are unaffected: OV13858 rear
captures normally, and the VD55G0 IR camera still does face
authentication.
The "stream stop time out" and "stream close time out" at teardown appear
with and without the series, as you say.
Built clean, no new warnings.
One practical note for anyone testing this by swapping modules rather
than booting a whole kernel. With CONFIG_MODVERSIONS the series moves
symbol CRCs, because struct ipu_sensor changes size:
ipu_bridge_parse_ssdb 0x8730390b -> 0x222edd7f
ipu_bridge_init 0xbb0996a9 -> 0x573da924
So intel-ipu6 and intel-ipu6-isys have to come from the same build as
ipu-bridge. I compared Module.symvers before swapping and rebuilt all
three together, so I did not hit it, but installing ipu-bridge alone
would have left the other two refusing to load.
On 9/2/26 17:23, Fernando Rimoli wrote:
> The ov5693 never programs MIPI_CTRL00 (0x4800), leaving it at its 0x00
> power-on default, which lets the MIPI clock run freely. The IPU3 CSI-2
> receiver tolerates this, but the IPU6 receiver (e.g. on Microsoft
> Surface Pro 7+, Pro 8, Pro 9 and Surface Go 4) fails to lock onto the
> link, so the sensor streams but capture times out with "stream stop
> time out". On most affected machines no frames arrive at all; on some
> the failure is intermittent.
>
> Gate the clock lane while idle at stream on when the endpoint requests a
> non-continuous clock.
>
> Only the gate bit is touched, so platforms that do not request it are
> unaffected. No counterpart is needed at stream off, as the link is down
> by then and the register returns to its default when the sensor is
> powered off.
>
> The property is supplied by the ipu-bridge in a subsequent patch.
>
> Link: https://github.com/linux-surface/linux-surface/pull/2171
> Co-developed-by: Arsalan Naeem <naeemarsalan@gmail.com>
> Signed-off-by: Arsalan Naeem <naeemarsalan@gmail.com>
> Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
> Tested-by: Jakob Berg Jespersen <dev@berg.pm> # Surface Pro 7+, IPU6 Tiger Lake
> Tested-by: Fil Dunsky <filipp.dunsky@gmail.com> # Surface Pro 8, IPU6 Tiger Lake (8086:9a19)
> Tested-by: Lucas Lis <lucaseze.lis@gmail.com> # Surface Pro 7+, IPU6 Tiger Lake (0x9a19)
> Tested-by: Kengo Oki <dev.kengo.fugu0141@gmail.com> # Surface Go 4, IPU6 Alder Lake-N 8086:462e
> ---
> drivers/media/i2c/ov5693.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
> index 02236f3db..cedc6ea03 100644
> --- a/drivers/media/i2c/ov5693.c
> +++ b/drivers/media/i2c/ov5693.c
> @@ -35,6 +35,11 @@
> #define OV5693_STOP_STREAMING 0x00
> #define OV5693_SW_RESET 0x01
>
> +/* MIPI transmitter control */
> +#define OV5693_MIPI_CTRL00_REG CCI_REG8(0x4800)
> +/* Gate the clock lane when there is no packet to transmit */
> +#define OV5693_MIPI_CTRL00_CLOCK_LANE_GATE BIT(5)
> +
> #define OV5693_REG_CHIP_ID CCI_REG16(0x300a)
> /* Yes, this is right. The datasheet for the OV5693 gives its ID as 0x5690 */
> #define OV5693_CHIP_ID 0x5690
> @@ -144,6 +149,9 @@ struct ov5693_device {
> struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];
> struct clk *xvclk;
>
> + /* Gate the MIPI clock lane when idle (CSI-2 non-continuous clock) */
> + bool clock_ncont;
> +
> struct ov5693_mode {
> struct v4l2_rect crop;
> struct v4l2_mbus_framefmt format;
> @@ -611,6 +619,19 @@ static int ov5693_enable_streaming(struct ov5693_device *ov5693, bool enable)
> {
> int ret = 0;
>
> + /*
> + * Gate the MIPI clock lane while idle if the CSI-2 link is configured
> + * for a non-continuous clock. Only that bit is touched, and only in
> + * that case, so the register keeps whatever the platform left in it
> + * and the clock stays free-running as before everywhere else. It
> + * needs no counterpart at stream off: the link is down by then, and
> + * the register returns to its default when the sensor is powered off.
> + */
> + if (enable && ov5693->clock_ncont)
> + cci_update_bits(ov5693->regmap, OV5693_MIPI_CTRL00_REG,
> + OV5693_MIPI_CTRL00_CLOCK_LANE_GATE,
> + OV5693_MIPI_CTRL00_CLOCK_LANE_GATE, &ret);
> +
> cci_write(ov5693->regmap, OV5693_SW_STREAM_REG,
> enable ? OV5693_START_STREAMING : OV5693_STOP_STREAMING,
> &ret);
> @@ -1259,6 +1280,9 @@ static int ov5693_check_hwcfg(struct ov5693_device *ov5693)
> goto out_free_bus_cfg;
> }
>
> + ov5693->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
> + V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
> +
> out_free_bus_cfg:
> v4l2_fwnode_endpoint_free(&bus_cfg);
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH v5 5/7] media: ipu-bridge: Assign endpoint property indices dynamically
2026-09-02 14:23 ` [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
` (3 preceding siblings ...)
2026-09-02 14:23 ` [PATCH v5 4/7] media: i2c: ov5693: Gate the MIPI clock lane for non-continuous clock Fernando Rimoli
@ 2026-09-02 14:23 ` Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 6/7] media: ipu-bridge: Match sensor configs per IPU and add config flags Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 7/7] media: ipu-bridge: Request non-continuous clock for ov5693 on IPU6 Fernando Rimoli
6 siblings, 0 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-02 14:23 UTC (permalink / raw)
To: linux-media
Cc: sakari.ailus, dan.scally, linux-kernel, Fernando Rimoli,
Jakob Berg Jespersen, Fil Dunsky, Lucas Lis, Kengo Oki,
Mauro Carvalho Chehab
Index the ep_properties array dynamically instead of plain numerical
values as is done in mipi-disco-img.c.
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Tested-by: Jakob Berg Jespersen <dev@berg.pm> # Surface Pro 7+, IPU6 Tiger Lake
Tested-by: Fil Dunsky <filipp.dunsky@gmail.com> # Surface Pro 8, IPU6 Tiger Lake (8086:9a19)
Tested-by: Lucas Lis <lucaseze.lis@gmail.com> # Surface Pro 7+, IPU6 Tiger Lake (0x9a19)
Tested-by: Kengo Oki <dev.kengo.fugu0141@gmail.com> # Surface Go 4, IPU6 Alder Lake-N 8086:462e
---
drivers/media/pci/intel/ipu-bridge.c | 27 ++++++++++++++-------------
include/media/ipu-bridge.h | 19 ++++++++++++++++++-
2 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index 131c70844..eb7d1611b 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -451,6 +451,7 @@ static void ipu_bridge_create_fwnode_properties(
{
struct ipu_property_names *names = &sensor->prop_names;
struct software_node *nodes = sensor->swnodes;
+ unsigned int i = 0;
sensor->prop_names = prop_names;
@@ -508,21 +509,21 @@ static void ipu_bridge_create_fwnode_properties(
PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref);
}
- sensor->ep_properties[0] = PROPERTY_ENTRY_U32(
- sensor->prop_names.bus_type,
- V4L2_FWNODE_BUS_TYPE_CSI2_DPHY);
- sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(
- sensor->prop_names.data_lanes,
- bridge->data_lanes, sensor->lanes);
- sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(
- sensor->prop_names.remote_endpoint,
- sensor->local_ref);
+ sensor->ep_properties[IPU_BRIDGE_NEXT_PROPERTY(i, EP_BUS_TYPE)] =
+ PROPERTY_ENTRY_U32(names->bus_type,
+ V4L2_FWNODE_BUS_TYPE_CSI2_DPHY);
+ sensor->ep_properties[IPU_BRIDGE_NEXT_PROPERTY(i, EP_DATA_LANES)] =
+ PROPERTY_ENTRY_U32_ARRAY_LEN(names->data_lanes,
+ bridge->data_lanes, sensor->lanes);
+ sensor->ep_properties[IPU_BRIDGE_NEXT_PROPERTY(i, EP_REMOTE_EP)] =
+ PROPERTY_ENTRY_REF_ARRAY(names->remote_endpoint,
+ sensor->local_ref);
if (cfg->nr_link_freqs > 0)
- sensor->ep_properties[3] = PROPERTY_ENTRY_U64_ARRAY_LEN(
- sensor->prop_names.link_frequencies,
- cfg->link_freqs,
- cfg->nr_link_freqs);
+ sensor->ep_properties[IPU_BRIDGE_NEXT_PROPERTY(i, EP_LINK_FREQUENCIES)] =
+ PROPERTY_ENTRY_U64_ARRAY_LEN(names->link_frequencies,
+ cfg->link_freqs,
+ cfg->nr_link_freqs);
sensor->ipu_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(
sensor->prop_names.data_lanes,
diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h
index 16fac7654..06701d151 100644
--- a/include/media/ipu-bridge.h
+++ b/include/media/ipu-bridge.h
@@ -64,6 +64,23 @@ enum ipu_sensor_swnodes {
SWNODE_COUNT
};
+enum ipu_bridge_ep_props {
+ IPU_BRIDGE_EP_BUS_TYPE,
+ IPU_BRIDGE_EP_DATA_LANES,
+ IPU_BRIDGE_EP_REMOTE_EP,
+ IPU_BRIDGE_EP_LINK_FREQUENCIES,
+ IPU_BRIDGE_EP_NUM_OF,
+ IPU_BRIDGE_EP_NUM_ENTRIES
+};
+
+/*
+ * Get the index of the next property in a property array, with a given maximum
+ * value.
+ */
+#define IPU_BRIDGE_NEXT_PROPERTY(index, max) \
+ (WARN_ON((index) > IPU_BRIDGE_##max) ? \
+ IPU_BRIDGE_##max : (index)++)
+
/* Data representation as it is in ACPI SSDB buffer */
struct ipu_sensor_ssdb {
u8 version;
@@ -141,7 +158,7 @@ struct ipu_sensor {
const char *vcm_type;
struct ipu_property_names prop_names;
- struct property_entry ep_properties[5];
+ struct property_entry ep_properties[IPU_BRIDGE_EP_NUM_ENTRIES];
struct property_entry dev_properties[5];
struct property_entry ipu_properties[3];
struct property_entry ivsc_properties[1];
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v5 6/7] media: ipu-bridge: Match sensor configs per IPU and add config flags
2026-09-02 14:23 ` [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
` (4 preceding siblings ...)
2026-09-02 14:23 ` [PATCH v5 5/7] media: ipu-bridge: Assign endpoint property indices dynamically Fernando Rimoli
@ 2026-09-02 14:23 ` Fernando Rimoli
2026-09-02 14:23 ` [PATCH v5 7/7] media: ipu-bridge: Request non-continuous clock for ov5693 on IPU6 Fernando Rimoli
6 siblings, 0 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-02 14:23 UTC (permalink / raw)
To: linux-media
Cc: sakari.ailus, dan.scally, linux-kernel, Fernando Rimoli,
Jakob Berg Jespersen, Fil Dunsky, Lucas Lis, Kengo Oki,
Mauro Carvalho Chehab
Some sensors need different treatment depending on which IPU they are
connected to, so the ACPI HID alone is not enough.
Match on an optional list of IPU PCI product IDs. Entries for one HID
must be adjacent, IPU-specific ones first, so the generic entry is
skipped once a specific one has matched.
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Tested-by: Jakob Berg Jespersen <dev@berg.pm> # Surface Pro 7+, IPU6 Tiger Lake
Tested-by: Fil Dunsky <filipp.dunsky@gmail.com> # Surface Pro 8, IPU6 Tiger Lake (8086:9a19)
Tested-by: Lucas Lis <lucaseze.lis@gmail.com> # Surface Pro 7+, IPU6 Tiger Lake (0x9a19)
Tested-by: Kengo Oki <dev.kengo.fugu0141@gmail.com> # Surface Go 4, IPU6 Alder Lake-N 8086:462e
---
drivers/media/pci/intel/ipu-bridge.c | 35 ++++++++++++++++++++++++++++
include/media/ipu-bridge.h | 26 +++++++++++++++++----
2 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index eb7d1611b..5efdcb9c8 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -8,6 +8,7 @@
#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/mei_cl_bus.h>
+#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
@@ -853,8 +854,28 @@ static int ipu_bridge_connect_sensor(const struct ipu_sensor_config *cfg,
return ret;
}
+/*
+ * Whether a sensor config applies to the IPU this bridge sits on. A config
+ * listing PCI product IDs only applies to those IPUs.
+ */
+static bool ipu_bridge_config_matches(const struct ipu_sensor_config *cfg,
+ struct ipu_bridge *bridge)
+{
+ const u16 *id;
+
+ if (!cfg->pci_ids)
+ return true;
+
+ for (id = cfg->pci_ids; *id; id++)
+ if (*id == bridge->pci_id)
+ return true;
+
+ return false;
+}
+
static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge)
{
+ const char *done_hid = NULL;
unsigned int i;
int ret;
@@ -862,9 +883,22 @@ static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge)
const struct ipu_sensor_config *cfg =
&ipu_supported_sensors[i];
+ /*
+ * Entries for one HID are adjacent, IPU-specific ones first,
+ * so the generic entry is skipped once a specific one has
+ * matched and the sensor is not connected twice.
+ */
+ if (done_hid && !strcmp(cfg->hid, done_hid))
+ continue;
+
+ if (!ipu_bridge_config_matches(cfg, bridge))
+ continue;
+
ret = ipu_bridge_connect_sensor(cfg, bridge);
if (ret)
goto err_unregister_sensors;
+
+ done_hid = cfg->hid;
}
return 0;
@@ -948,6 +982,7 @@ int ipu_bridge_init(struct device *dev,
sizeof(bridge->ipu_node_name));
bridge->ipu_hid_node.name = bridge->ipu_node_name;
bridge->dev = dev;
+ bridge->pci_id = dev_is_pci(dev) ? to_pci_dev(dev)->device : 0;
bridge->parse_sensor_fwnode = parse_sensor_fwnode;
ret = software_node_register(&bridge->ipu_hid_node);
diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h
index 06701d151..aca76ff71 100644
--- a/include/media/ipu-bridge.h
+++ b/include/media/ipu-bridge.h
@@ -17,13 +17,24 @@
#define IPU_SENSOR_ROTATION_NORMAL 0
#define IPU_SENSOR_ROTATION_INVERTED 1
-#define IPU_SENSOR_CONFIG(_HID, _NR, ...) \
- (const struct ipu_sensor_config) { \
- .hid = _HID, \
- .nr_link_freqs = _NR, \
- .link_freqs = { __VA_ARGS__ } \
+/*
+ * Sensor config specific to one or more IPUs, identified by their PCI product
+ * IDs, with flags describing what the sensor needs there. Entries for one HID
+ * must be adjacent in ipu_supported_sensors[], with the IPU-specific ones
+ * before the generic one.
+ */
+#define IPU_SENSOR_CONFIG_MATCH_FL(_HID, _IDS, _FLAGS, _NR, ...) \
+ (const struct ipu_sensor_config) { \
+ .hid = _HID, \
+ .pci_ids = _IDS, \
+ .flags = _FLAGS, \
+ .nr_link_freqs = _NR, \
+ .link_freqs = { __VA_ARGS__ } \
}
+#define IPU_SENSOR_CONFIG(_HID, _NR, ...) \
+ IPU_SENSOR_CONFIG_MATCH_FL(_HID, NULL, 0, _NR, __VA_ARGS__)
+
#define NODE_SENSOR(_HID, _PROPS) \
(const struct software_node) { \
.name = _HID, \
@@ -132,6 +143,9 @@ struct ipu_node_names {
struct ipu_sensor_config {
const char *hid;
+ /* Zero-terminated list of IPU PCI product IDs, NULL for any IPU */
+ const u16 *pci_ids;
+ const u32 flags;
const u8 nr_link_freqs;
const u64 link_freqs[MAX_NUM_LINK_FREQS];
};
@@ -177,6 +191,8 @@ typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev,
struct ipu_bridge {
struct device *dev;
+ /* PCI product ID of the IPU, 0 if it is not a PCI device */
+ u16 pci_id;
ipu_parse_sensor_fwnode_t parse_sensor_fwnode;
char ipu_node_name[ACPI_ID_LEN];
struct software_node ipu_hid_node;
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH v5 7/7] media: ipu-bridge: Request non-continuous clock for ov5693 on IPU6
2026-09-02 14:23 ` [PATCH v5 0/7] media: Enable the OV5693 front camera on IPU6 Surface devices Fernando Rimoli
` (5 preceding siblings ...)
2026-09-02 14:23 ` [PATCH v5 6/7] media: ipu-bridge: Match sensor configs per IPU and add config flags Fernando Rimoli
@ 2026-09-02 14:23 ` Fernando Rimoli
6 siblings, 0 replies; 50+ messages in thread
From: Fernando Rimoli @ 2026-09-02 14:23 UTC (permalink / raw)
To: linux-media
Cc: sakari.ailus, dan.scally, linux-kernel, Fernando Rimoli,
Jakob Berg Jespersen, Fil Dunsky, Lucas Lis, Kengo Oki,
Mauro Carvalho Chehab
The ov5693 (INT33BE / OVTI5693) needs its MIPI clock lane gated while
idle for the IPU6 CSI-2 receiver to lock onto the link, which the sensor
driver does when the endpoint requests a non-continuous clock.
The same sensor works with a free-running clock on the IPU3, so request
it only for the IPU6 variants where it has been confirmed on hardware:
Tiger Lake, Alder Lake-P and Alder Lake-N.
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Tested-by: Jakob Berg Jespersen <dev@berg.pm> # Surface Pro 7+, IPU6 Tiger Lake
Tested-by: Fil Dunsky <filipp.dunsky@gmail.com> # Surface Pro 8, IPU6 Tiger Lake (8086:9a19)
Tested-by: Lucas Lis <lucaseze.lis@gmail.com> # Surface Pro 7+, IPU6 Tiger Lake (0x9a19)
Tested-by: Kengo Oki <dev.kengo.fugu0141@gmail.com> # Surface Go 4, IPU6 Alder Lake-N 8086:462e
---
drivers/media/pci/intel/ipu-bridge.c | 19 +++++++++++++++++++
include/media/ipu-bridge.h | 5 +++++
2 files changed, 24 insertions(+)
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index 5efdcb9c8..12f1cccd8 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -16,6 +16,7 @@
#include <linux/workqueue.h>
#include <media/ipu-bridge.h>
+#include <media/ipu6-pci-table.h>
#include <media/v4l2-fwnode.h>
#define ADEV_DEV(adev) ACPI_PTR(&((adev)->dev))
@@ -49,6 +50,14 @@
*
* Please keep the list sorted by ACPI HID.
*/
+/* IPU6 variants whose CSI-2 receiver needs the ov5693 clock lane gated */
+static const u16 ipu6_ov5693_ncont_clk[] = {
+ PCI_DEVICE_ID_INTEL_IPU6, /* Tiger Lake */
+ PCI_DEVICE_ID_INTEL_IPU6EP_ADLP, /* Alder Lake-P */
+ PCI_DEVICE_ID_INTEL_IPU6EP_ADLN, /* Alder Lake-N */
+ 0
+};
+
static const struct ipu_sensor_config ipu_supported_sensors[] = {
/* Himax HM1092 */
IPU_SENSOR_CONFIG("HIMX1092", 2, 180000000, 180480000),
@@ -61,6 +70,9 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = {
/* GalaxyCore GC0310 */
IPU_SENSOR_CONFIG("INT0310", 1, 55692000),
/* Omnivision OV5693 */
+ IPU_SENSOR_CONFIG_MATCH_FL("INT33BE", ipu6_ov5693_ncont_clk,
+ IPU_BR_FL_CSI2_CLK_NONCONTINUOUS,
+ 1, 419200000),
IPU_SENSOR_CONFIG("INT33BE", 1, 419200000),
/* Onsemi MT9M114 */
IPU_SENSOR_CONFIG("INT33F0", 1, 384000000),
@@ -97,6 +109,9 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = {
/* Omnivision OV5675 */
IPU_SENSOR_CONFIG("OVTI5675", 1, 450000000),
/* Omnivision OV5693 */
+ IPU_SENSOR_CONFIG_MATCH_FL("OVTI5693", ipu6_ov5693_ncont_clk,
+ IPU_BR_FL_CSI2_CLK_NONCONTINUOUS,
+ 1, 419200000),
IPU_SENSOR_CONFIG("OVTI5693", 1, 419200000),
/* Omnivision OV8856 */
IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000),
@@ -526,6 +541,10 @@ static void ipu_bridge_create_fwnode_properties(
cfg->link_freqs,
cfg->nr_link_freqs);
+ if (cfg->flags & IPU_BR_FL_CSI2_CLK_NONCONTINUOUS)
+ sensor->ep_properties[IPU_BRIDGE_NEXT_PROPERTY(i, EP_CLOCK_NONCONTINUOUS)] =
+ PROPERTY_ENTRY_BOOL("clock-noncontinuous");
+
sensor->ipu_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(
sensor->prop_names.data_lanes,
bridge->data_lanes, sensor->lanes);
diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h
index aca76ff71..eec8c4688 100644
--- a/include/media/ipu-bridge.h
+++ b/include/media/ipu-bridge.h
@@ -17,6 +17,10 @@
#define IPU_SENSOR_ROTATION_NORMAL 0
#define IPU_SENSOR_ROTATION_INVERTED 1
+/* Flags for struct ipu_sensor_config */
+/* The sensor's CSI-2 transmitter needs a non-continuous clock */
+#define IPU_BR_FL_CSI2_CLK_NONCONTINUOUS BIT(0)
+
/*
* Sensor config specific to one or more IPUs, identified by their PCI product
* IDs, with flags describing what the sensor needs there. Entries for one HID
@@ -80,6 +84,7 @@ enum ipu_bridge_ep_props {
IPU_BRIDGE_EP_DATA_LANES,
IPU_BRIDGE_EP_REMOTE_EP,
IPU_BRIDGE_EP_LINK_FREQUENCIES,
+ IPU_BRIDGE_EP_CLOCK_NONCONTINUOUS,
IPU_BRIDGE_EP_NUM_OF,
IPU_BRIDGE_EP_NUM_ENTRIES
};
--
2.43.0
^ permalink raw reply related [flat|nested] 50+ messages in thread