Skip to content

cameras: ov5693: make the IPU6 Surface front cameras stream (Pro 8/9, Go 4) - #2171

Open
naeemarsalan wants to merge 2 commits into
linux-surface:masterfrom
naeemarsalan:ov5693-ipu6-sp8-front-camera
Open

naeemarsalan wants to merge 2 commits into
linux-surface:masterfrom
naeemarsalan:ov5693-ipu6-sp8-front-camera

Conversation

@naeemarsalan

@naeemarsalan naeemarsalan commented Jun 11, 2026 •

Copy link
Copy Markdown

What

Adds one commit to the cameras patchset (patches/6.19/0013-cameras.patch) that programs MIPI_CTRL00 (register 0x4800) = 0x2d before stream-on in the ov5693 driver. With this, the front camera streams on IPU6 on:

No ACPI match-table change is needed for the Pro 9 in this repo: the OVTI5693 HID is already added by the "Add camera support for Surface Pro 9" patch earlier in this same patchset (#1867, shipped in every 6.19 release since 6.19.7-1) — both in ov5693_acpi_match[] and in ipu-bridge.c. Mainline v6.19 has neither, so the HID does still need to go to linux-media separately (@femito1 is planning to send that).

Why it was broken

Mainline ov5693.c never writes MIPI_CTRL00, leaving it at the 0x00 power-on default. That default is fine on the IPU3 Surface devices (Pro 5/6/7), where this sensor already works. On the IPU6 devices the same sensor is wired to an IPU6, and with 0x4800 == 0x00 the D-PHY never locks: the sensor reports streaming, the PHY powers up, but the receiver gets zero CSI-2 packets (no SOT/CRC errors at all) and capture ends in stream stop time out. Writing 0x2d configures the clock-lane behaviour the IPU6 expects and frames flow.

How it was found

Reverse-engineered from the Surface Pro 8 Windows driver (ov5693.sys register table) — 0x2d is the value Windows programs. Diffing the Windows init against mainline made MIPI_CTRL00 the obvious omission, and setting it alone fixes streaming.

Honest caveats (feedback very welcome)

I want to be upfront — parts of this were experimental / AI-assisted and I'd really appreciate review:

  • Not tested on IPU3 (SP5/6/7). The write is currently unconditional, and those devices use the same driver with the 0x00 default today. It should be confirmed there before merge — or gated if it regresses them.
  • The 0x2d bit meaning is taken from the vendor driver, not a datasheet — I know empirically it works, not the precise semantics of every bit.
  • There's a residual, rate-limited CSI-2 FIFO-overflow message during capture on the SP8; frames still flow fine. Windows also writes companion registers (0x4806/0x4816/0x4831/0x4d00/0x4d01); 0x2d alone is sufficient to stream so I left them out, but they (or an IPU6-side watermark tweak) may clean up the overflow.
  • Only added to patches/6.19/. Happy to reformat, split, target the linux-surface/kernel tree instead, or propagate to other version dirs — whatever you prefer.

Refs

Verified on: Surface Pro 8, kernel-surface 6.19.8-3, Fedora 44, libcamera 0.7.1 — plus the Go 4 and Pro 9 confirmations linked above.

…on IPU6

Add a commit to the cameras patchset that writes MIPI_CTRL00 (0x4800)=0x2d
before stream-on in the ov5693 driver. Without it the Surface Pro 8 front
camera (ov5693 on IPU6) powers up and 'streams' but the IPU6 D-PHY receives
no CSI-2 data and capture times out. The same driver/sensor works on the
IPU3 Surface devices with the 0x00 default, so the write is currently
unconditional and wants checking on those before being relied upon there.

Reverse-engineered from the SP8 Windows ov5693.sys; verified on a Surface
Pro 8 (kernel 6.19). See the patch commit message for details.

Link: linux-surface#1893
Signed-off-by: Arsalan Naeem <naeemarsalan@gmail.com>
@naeemarsalan

Copy link
Copy Markdown
Author

For anyone who wants to apply this on a Surface Pro 8 before it lands here, I wrote up a step-by-step guide (build + MOK-sign the patched ov5693 module, plus an optional v4l2loopback bridge so Chrome/Zoom/OBS see it as a normal /dev/video device):

📄 https://gist.github.com/naeemarsalan/3194a838a7bfb66671bc90d6de6734dd

Same honesty caveats as the PR: reverse-engineered from the Windows driver, verified only on SP8/IPU6 (kernel 6.19.8), not tested on the IPU3 Surface devices that share this driver. Feedback very welcome.

@Fugu0141

Copy link
Copy Markdown

Thanks for working on this patch!

I tested it on my Microsoft Surface Go 4, and it looks like the front OV5693 camera now streams successfully here as well.

My environment:

  • Device: Microsoft Surface Go 4
  • Kernel: 7.0.0-15-generic
  • libcamera: 0.7.0
  • Front camera: OV5693 on IPU6
  • Camera ID: \_SB_.PC00.I2C3.CAMF
  • Secure Boot enabled, with the patched module MOK-signed locally

Before applying the patch, the camera was detected, but capture did not actually start receiving frames:

Using camera \_SB_.PC00.I2C3.CAMF as cam0
cam0: Capture 5 frames
^C

dmesg showed:

intel_ipu6_isys.isys intel_ipu6.isys.40: stream stop time out
intel_ipu6_isys.isys intel_ipu6.isys.40: stream close time out

After applying the MIPI_CTRL00 = 0x2d change, the patched module was loaded correctly:

filename:       /lib/modules/7.0.0-15-generic/updates/ov5693.ko
signer:         Surface Go 4 ov5693 local test
sig_hashalgo:   sha256

Then cam -c '\_SB_.PC00.I2C3.CAMF' -C10 was able to capture frames:

cam0: Capture 10 frames
241.654190 (0.00 fps) cam0-stream0 seq: 000000 bytesused: 20404224
241.689015 (28.72 fps) cam0-stream0 seq: 000001 bytesused: 20404224
241.723925 (28.65 fps) cam0-stream0 seq: 000002 bytesused: 20404224
241.758838 (28.64 fps) cam0-stream0 seq: 000003 bytesused: 20404224
241.793745 (28.65 fps) cam0-stream0 seq: 000004 bytesused: 20404224
241.828656 (28.64 fps) cam0-stream0 seq: 000005 bytesused: 20404224
241.863566 (28.65 fps) cam0-stream0 seq: 000006 bytesused: 20404224
241.898479 (28.64 fps) cam0-stream0 seq: 000007 bytesused: 20404224
241.933387 (28.65 fps) cam0-stream0 seq: 000008 bytesused: 20404224
241.968298 (28.64 fps) cam0-stream0 seq: 000009 bytesused: 20404224

I still saw a few CSI warnings in dmesg:

intel_ipu6_isys.isys intel_ipu6.isys.40: csi2-1 error: Transfer FIFO overflow
intel_ipu6_isys.isys intel_ipu6.isys.40: csi2-1 error: Inter-frame long packet discarded
intel_ipu6_isys.isys intel_ipu6.isys.40: csi2-1 error: Inter-frame short packet discarded

But unlike before, capture no longer hangs at stream start, and frames are received at around 28.6 fps.

So from my test, this patch also seems to fix the front OV5693 streaming issue on the Surface Go 4. Thanks again!

@Fugu0141

Fugu0141 commented Jun 14, 2026 •

Copy link
Copy Markdown

Here are the full logs:

  • Before applying the patch:
Full logs
[0:35:52.031066493] [10695]  INFO Camera camera_manager.cpp:340 libcamera v0.7.0
[0:35:52.058104549] [10703]  WARN CameraSensor camera_sensor_legacy.cpp:502 'ov5693 2-0036': No sensor delays found in static properties. Assuming unverified defaults.
[0:35:52.058248481] [10703] ERROR V4L2 v4l2_device.cpp:92 'dw9714 4-000c': Failed to open V4L2 device '': No such file or directory
[0:35:52.058259218] [10703] ERROR CameraSensor camera_sensor_legacy.cpp:663 'ov8865 4-0010': Lens initialisation failed, lens disabled
[0:35:52.058266788] [10703]  WARN CameraSensor camera_sensor_legacy.cpp:502 'ov8865 4-0010': No sensor delays found in static properties. Assuming unverified defaults.
[0:35:52.059377033] [10703]  WARN IPAProxy ipa_proxy.cpp:192 Configuration file 'ov5693.yaml' not found for IPA module 'simple', falling back to '/usr/share/libcamera/ipa/simple/uncalibrated.yaml'
[0:35:52.059570972] [10703]  INFO Camera camera_manager.cpp:223 Adding camera '\_SB_.PC00.I2C3.CAMF' for pipeline handler simple
[0:35:52.060156682] [10703]  WARN IPAProxy ipa_proxy.cpp:192 Configuration file 'ov8865.yaml' not found for IPA module 'simple', falling back to '/usr/share/libcamera/ipa/simple/uncalibrated.yaml'
[0:35:52.060348658] [10703]  INFO Camera camera_manager.cpp:223 Adding camera '\_SB_.PC00.I2C5.CAMR' for pipeline handler simple

Using camera \_SB_.PC00.I2C3.CAMF as cam0

[0:35:52.060498996] [10695]  INFO Camera camera.cpp:1215 configuring streams: (0) 2584x1944-ABGR8888/sRGB
[0:35:52.060552405] [10703]  INFO IPASoft soft_simple.cpp:258 IPASoft: Exposure 1-2070, gain 0.0625-7.9375 (0.07875)
[0:35:52.116099034] [10710]  INFO eGL egl.cpp:305 EGL: EGL_VERSION: 1.5
[0:35:52.116120776] [10710]  INFO eGL egl.cpp:306 EGL: EGL_VENDOR: Mesa Project
[0:35:52.116124392] [10710]  INFO eGL egl.cpp:307 EGL: EGL_CLIENT_APIS: OpenGL OpenGL_ES
[0:35:52.116127267] [10710]  INFO eGL egl.cpp:308 EGL: EGL_EXTENSIONS: EGL_ANDROID_blob_cache EGL_ANDROID_native_fence_sync EGL_EXT_config_select_group EGL_EXT_create_context_robustness EGL_EXT_image_dma_buf_import EGL_EXT_image_dma_buf_import_modifiers EGL_EXT_protected_content EGL_EXT_query_reset_notification_strategy EGL_EXT_surface_compression EGL_IMG_context_priority EGL_KHR_cl_event2 EGL_KHR_config_attribs EGL_KHR_context_flush_control EGL_KHR_create_context EGL_KHR_create_context_no_error EGL_KHR_fence_sync EGL_KHR_get_all_proc_addresses EGL_KHR_gl_colorspace EGL_KHR_gl_renderbuffer_image EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_3D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_image_base EGL_KHR_no_config_context EGL_KHR_partial_update EGL_KHR_reusable_sync EGL_KHR_surfaceless_context EGL_EXT_pixel_format_float EGL_KHR_wait_sync EGL_MESA_configless_context EGL_MESA_gl_interop EGL_MESA_image_dma_buf_export EGL_MESA_query_driver EGL_MESA_x11_native_visual_id
[0:35:52.118518304] [10710]  INFO eGL egl.cpp:349 EGL: GL_VERSION: OpenGL ES 3.2 Mesa 26.0.3-1ubuntu1

cam0: Capture 5 frames
^C

[ 6月14日(日) 20:14:10 2026] SCSI subsystem initialized
[ 6月14日(日) 20:14:10 2026] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 242)
[ 6月14日(日) 20:14:11 2026] scsi host0: ufshcd
[ 6月14日(日) 20:14:11 2026] scsi 0:0:0:49488: Well-known LUN    SKhynix  HN8G962EHKX037   A801 PQ: 0 ANSI: 6
[ 6月14日(日) 20:14:11 2026] ufs_device_wlun 0:0:0:49488: Attached scsi generic sg0 type 30
[ 6月14日(日) 20:14:11 2026] scsi 0:0:0:49476: Well-known LUN    SKhynix  HN8G962EHKX037   A801 PQ: 0 ANSI: 6
[ 6月14日(日) 20:14:11 2026] scsi 0:0:0:49476: Attached scsi generic sg1 type 30
[ 6月14日(日) 20:14:11 2026] scsi 0:0:0:49456: Well-known LUN    SKhynix  HN8G962EHKX037   A801 PQ: 0 ANSI: 6
[ 6月14日(日) 20:14:11 2026] scsi 0:0:0:49456: Attached scsi generic sg2 type 30
[ 6月14日(日) 20:14:11 2026] scsi 0:0:0:0: Direct-Access     SKhynix  HN8G962EHKX037   A801 PQ: 0 ANSI: 6
[ 6月14日(日) 20:14:11 2026] sd 0:0:0:0: Attached scsi generic sg3 type 0
[ 6月14日(日) 20:14:11 2026] sd 0:0:0:0: [sda] Attached SCSI disk
[ 6月14日(日) 20:14:14 2026] intel-ipu6 0000:00:05.0: enabling device (0000 -> 0002)
[ 6月14日(日) 20:14:14 2026] intel-ipu6 0000:00:05.0: Found supported sensor INT33BE:00
[ 6月14日(日) 20:14:14 2026] intel-ipu6 0000:00:05.0: Found supported sensor INT347A:00
[ 6月14日(日) 20:14:14 2026] intel-ipu6 0000:00:05.0: Found supported sensor INT347E:00
[ 6月14日(日) 20:14:14 2026] intel-ipu6 0000:00:05.0: Connected 3 cameras
[ 6月14日(日) 20:14:14 2026] intel-ipu6 0000:00:05.0: Sending BOOT_LOAD to CSE
[ 6月14日(日) 20:14:14 2026] intel-ipu6 0000:00:05.0: Sending AUTHENTICATE_RUN to CSE
[ 6月14日(日) 20:14:14 2026] intel-ipu6 0000:00:05.0: CSE authenticate_run done
[ 6月14日(日) 20:14:14 2026] intel-ipu6 0000:00:05.0: IPU6-v3[462e] hardware version 5
[ 6月14日(日) 20:14:15 2026] ov5693 i2c-INT33BE:00: supply dovdd not found, using dummy regulator
[ 6月14日(日) 20:14:15 2026] ov5693 i2c-INT33BE:00: supply dvdd not found, using dummy regulator
[ 6月14日(日) 21:24:08 2026] intel-ipu6 0000:00:05.0: IPU6 in secure mode
[ 6月14日(日) 22:16:52 2026] intel-ipu6 0000:00:05.0: IPU6 in secure mode
[ 6月14日(日) 22:19:45 2026] intel-ipu6 0000:00:05.0: IPU6 in secure mode
[ 6月14日(日) 22:30:52 2026] intel-ipu6 0000:00:05.0: IPU6 in secure mode
[ 6月14日(日) 23:14:14 2026] intel-ipu6 0000:00:05.0: IPU6 in secure mode
[ 6月17日(水) 08:23:05 2026] intel-ipu6 0000:00:05.0: IPU6 in secure mode
[ 6月17日(水) 08:32:25 2026] intel_ipu6_isys.isys intel_ipu6.isys.40: stream stop time out
[ 6月17日(水) 08:32:27 2026] intel_ipu6_isys.isys intel_ipu6.isys.40: stream close time out

total 8.0K
-rw-rw-r-- 1 ko ko 2.7K Jun 14 20:50 dmesg-before.log
-rw-rw-r-- 1 ko ko 2.9K Jun 14 20:50 front-before.log

  • After applying the patch:
Full logs

Note: the “failed to open file ~/...” messages seem to be caused by my output path using ~, not by the camera stream itself. The frames were still received successfully, as shown by the non-zero bytesused values.

[0:04:01.308658572] [5539]  INFO Camera camera_manager.cpp:340 libcamera v0.7.0
[0:04:01.345693813] [5551]  WARN CameraSensor camera_sensor_legacy.cpp:502 'ov5693 2-0036': No sensor delays found in static properties. Assuming unverified defaults.
[0:04:01.345987888] [5551] ERROR V4L2 v4l2_device.cpp:92 'dw9714 4-000c': Failed to open V4L2 device '': No such file or directory
[0:04:01.346029224] [5551] ERROR CameraSensor camera_sensor_legacy.cpp:663 'ov8865 4-0010': Lens initialisation failed, lens disabled
[0:04:01.346047726] [5551]  WARN CameraSensor camera_sensor_legacy.cpp:502 'ov8865 4-0010': No sensor delays found in static properties. Assuming unverified defaults.
[0:04:01.348653694] [5551]  WARN IPAProxy ipa_proxy.cpp:192 Configuration file 'ov5693.yaml' not found for IPA module 'simple', falling back to '/usr/share/libcamera/ipa/simple/uncalibrated.yaml'
[0:04:01.349111504] [5551]  INFO Camera camera_manager.cpp:223 Adding camera '\_SB_.PC00.I2C3.CAMF' for pipeline handler simple
[0:04:01.350567964] [5551]  WARN IPAProxy ipa_proxy.cpp:192 Configuration file 'ov8865.yaml' not found for IPA module 'simple', falling back to '/usr/share/libcamera/ipa/simple/uncalibrated.yaml'
[0:04:01.351071628] [5551]  INFO Camera camera_manager.cpp:223 Adding camera '\_SB_.PC00.I2C5.CAMR' for pipeline handler simple

Using camera \_SB_.PC00.I2C3.CAMF as cam0

[0:04:01.353246784] [5539]  INFO Camera camera.cpp:1215 configuring streams: (0) 2584x1944-ABGR8888/sRGB
[0:04:01.353419713] [5551]  INFO IPASoft soft_simple.cpp:258 IPASoft: Exposure 1-2070, gain 0.0625-7.9375 (0.07875)
[0:04:01.464111714] [5556]  INFO eGL egl.cpp:305 EGL: EGL_VERSION: 1.5
[0:04:01.464155068] [5556]  INFO eGL egl.cpp:306 EGL: EGL_VENDOR: Mesa Project
[0:04:01.464162656] [5556]  INFO eGL egl.cpp:307 EGL: EGL_CLIENT_APIS: OpenGL OpenGL_ES
[0:04:01.464168251] [5556]  INFO eGL egl.cpp:308 EGL: EGL_EXTENSIONS: EGL_ANDROID_blob_cache EGL_ANDROID_native_fence_sync EGL_EXT_config_select_group EGL_EXT_create_context_robustness EGL_EXT_image_dma_buf_import EGL_EXT_image_dma_buf_import_modifiers EGL_EXT_protected_content EGL_EXT_query_reset_notification_strategy EGL_EXT_surface_compression EGL_IMG_context_priority EGL_KHR_cl_event2 EGL_KHR_config_attribs EGL_KHR_context_flush_control EGL_KHR_create_context EGL_KHR_create_context_no_error EGL_KHR_fence_sync EGL_KHR_get_all_proc_addresses EGL_KHR_gl_colorspace EGL_KHR_gl_renderbuffer_image EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_3D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_image_base EGL_KHR_no_config_context EGL_KHR_partial_update EGL_KHR_reusable_sync EGL_KHR_surfaceless_context EGL_EXT_pixel_format_float EGL_KHR_wait_sync EGL_MESA_configless_context EGL_MESA_gl_interop EGL_MESA_image_dma_buf_export EGL_MESA_query_driver EGL_MESA_x11_native_visual_id
[0:04:01.468680919] [5556]  INFO eGL egl.cpp:349 EGL: GL_VERSION: OpenGL ES 3.2 Mesa 26.0.3-1ubuntu1

cam0: Capture 10 frames

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000000.bin: No such file or directory
241.654190 (0.00 fps) cam0-stream0 seq: 000000 bytesused: 20404224

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000001.bin: No such file or directory
241.689015 (28.72 fps) cam0-stream0 seq: 000001 bytesused: 20404224

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000002.bin: No such file or directory
241.723925 (28.65 fps) cam0-stream0 seq: 000002 bytesused: 20404224

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000003.bin: No such file or directory
241.758838 (28.64 fps) cam0-stream0 seq: 000003 bytesused: 20404224

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000004.bin: No such file or directory
241.793745 (28.65 fps) cam0-stream0 seq: 000004 bytesused: 20404224

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000005.bin: No such file or directory
241.828656 (28.64 fps) cam0-stream0 seq: 000005 bytesused: 20404224

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000006.bin: No such file or directory
241.863566 (28.65 fps) cam0-stream0 seq: 000006 bytesused: 20404224

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000007.bin: No such file or directory
241.898479 (28.64 fps) cam0-stream0 seq: 000007 bytesused: 20404224

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000008.bin: No such file or directory
241.933387 (28.65 fps) cam0-stream0 seq: 000008 bytesused: 20404224

failed to open file ~/sg4-ov5693-test/after/front-after-cam0-stream0-000009.bin: No such file or directory
241.968298 (28.64 fps) cam0-stream0 seq: 000009 bytesused: 20404224

[ 6月14日(日) 21:08:37 2026] SCSI subsystem initialized
[ 6月14日(日) 21:08:37 2026] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 242)
[ 6月14日(日) 21:08:37 2026] integrity: Loaded X.509 cert 'Surface Go 4 ov5693 local test: 37f0a53794144d8c1ec90d62a5dcf66097721def'
[ 6月14日(日) 21:08:38 2026] scsi host0: ufshcd
[ 6月14日(日) 21:08:38 2026] scsi 0:0:0:49488: Well-known LUN    SKhynix  HN8G962EHKX037   A801 PQ: 0 ANSI: 6
[ 6月14日(日) 21:08:38 2026] ufs_device_wlun 0:0:0:49488: Attached scsi generic sg0 type 30
[ 6月14日(日) 21:08:38 2026] scsi 0:0:0:49476: Well-known LUN    SKhynix  HN8G962EHKX037   A801 PQ: 0 ANSI: 6
[ 6月14日(日) 21:08:38 2026] scsi 0:0:0:49476: Attached scsi generic sg1 type 30
[ 6月14日(日) 21:08:38 2026] scsi 0:0:0:49456: Well-known LUN    SKhynix  HN8G962EHKX037   A801 PQ: 0 ANSI: 6
[ 6月14日(日) 21:08:38 2026] scsi 0:0:0:49456: Attached scsi generic sg2 type 30
[ 6月14日(日) 21:08:38 2026] scsi 0:0:0:0: Direct-Access     SKhynix  HN8G962EHKX037   A801 PQ: 0 ANSI: 6
[ 6月14日(日) 21:08:38 2026] sd 0:0:0:0: Attached scsi generic sg3 type 0
[ 6月14日(日) 21:08:38 2026] sd 0:0:0:0: [sda] Attached SCSI disk
[ 6月14日(日) 21:08:41 2026] intel-ipu6 0000:00:05.0: enabling device (0000 -> 0002)
[ 6月14日(日) 21:08:41 2026] intel-ipu6 0000:00:05.0: Found supported sensor INT33BE:00
[ 6月14日(日) 21:08:41 2026] intel-ipu6 0000:00:05.0: Found supported sensor INT347A:00
[ 6月14日(日) 21:08:41 2026] intel-ipu6 0000:00:05.0: Found supported sensor INT347E:00
[ 6月14日(日) 21:08:41 2026] intel-ipu6 0000:00:05.0: Connected 3 cameras
[ 6月14日(日) 21:08:41 2026] intel-ipu6 0000:00:05.0: Sending BOOT_LOAD to CSE
[ 6月14日(日) 21:08:41 2026] intel-ipu6 0000:00:05.0: Sending AUTHENTICATE_RUN to CSE
[ 6月14日(日) 21:08:41 2026] ov5693: loading out-of-tree module taints kernel.
[ 6月14日(日) 21:08:41 2026] ov5693 i2c-INT33BE:00: supply dovdd not found, using dummy regulator
[ 6月14日(日) 21:08:41 2026] ov5693 i2c-INT33BE:00: supply dvdd not found, using dummy regulator
[ 6月14日(日) 21:08:41 2026] intel-ipu6 0000:00:05.0: CSE authenticate_run done
[ 6月14日(日) 21:08:41 2026] intel-ipu6 0000:00:05.0: IPU6-v3[462e] hardware version 5
[ 6月14日(日) 21:12:39 2026] intel_ipu6_isys.isys intel_ipu6.isys.40: csi2-1 error: Transfer FIFO overflow
[ 6月14日(日) 21:12:39 2026] intel_ipu6_isys.isys intel_ipu6.isys.40: csi2-1 error: Inter-frame long packet discarded
[ 6月14日(日) 21:12:39 2026] intel_ipu6_isys.isys intel_ipu6.isys.40: csi2-1 error: Inter-frame short packet discarded
[ 6月14日(日) 21:12:39 2026] intel_ipu6_isys.isys intel_ipu6.isys.40: csi2-1 error: Inter-frame long packet discarded

total 12K
-rw-rw-r-- 1 ko ko 2.7K Jun 14 21:12 dmesg-after.log
-rw-rw-r-- 1 ko ko 4.6K Jun 14 21:12 front-after.log
@femito1

femito1 commented Jul 8, 2026

Copy link
Copy Markdown

Also confirmed working on the Surface Pro 9 (IPU6), but with one difference: my Pro 9 enumerates the sensor as OVTI5693, not INT33BE. Mainline ov5693.c only matches INT33BE, so on the Pro 9 the driver doesn't bind at all until that HID is added, so the MIPI_CTRL00 write alone isn't enough here.

(The Go 4 logs above from @Fugu0141 show it binding as i2c-INT33BE:00, which is why the register write was sufficient there.)

Two ways to handle the Pro 9: add {"OVTI5693"} to ov5693_acpi_match[], or a modprobe alias (alias acpi*:OVTI5693:* ov5693). Might be worth folding the HID into this PR so IPU6 Surfaces that use the OVTI5693 ID work end-to-end. Happy to send a patch for that part.

@femito1

femito1 commented Jul 8, 2026

Copy link
Copy Markdown

@naeemarsalan, since the OVTI5693 HID is separate from your MIPI_CTRL00 change, how would you like to handle it?

I could add {"OVTI5693"} to your patch here, so IPU6 Surfaces that use that HID (Pro 9) work end-to-end in one go, or send it as a follow-up patch on top of yours, crediting this PR.

Either's fine by me, I don't want to step on your work. I've got it tested and ready on a Pro 9 (kernel 6.19). Lmk which you'd prefer.

@naeemarsalan

Copy link
Copy Markdown
Author

@femito1 Hey! Happy you got it working, yea can do what ever you like! Which ever is easier, I'd be happy to add it! Thanks

@femito1

femito1 commented Jul 8, 2026

Copy link
Copy Markdown

Awesome, thanks! Easiest for right now is probably to just fold the HID into your patch here so Pro 9 users get it in the linux-surface kernel. It's a one-liner in the
acpi_match table:

    static const struct acpi_device_id ov5693_acpi_match[] = {
            {"INT33BE"},
            {"OVTI5693"},
            {},
    };
    MODULE_DEVICE_TABLE(acpi, ov5693_acpi_match);

That's what the Pro 9 enumerates as (OVTI5693 instead of INT33BE), so with this + your MIPI_CTRL00 write the front camera binds and streams end-to-end on IPU6. Tested on Pro 9, kernel 6.19.

Separately I'm going to try sending the HID bits upstream to linux-media (it also needs a matching entry in ipu-bridge.c's supported-sensors list to enumerate on a stock kernel). I'll keep your MIPI_CTRL00 work credited, happy to coordinate if you want to send that part too. Thanks for putting this together!

…patch

The MIPI_CTRL00=0x2d fix has been confirmed on the Surface Go 4 (ov5693
at INT33BE, by Fugu0141) and the Surface Pro 9 (ov5693 at OVTI5693, by
femito1) in the PR thread. The Pro 9's OVTI5693 ACPI HID is already
added by the 'Add camera support for Surface Pro 9' patch earlier in
this patchset (from linux-surface#1867), so no match-table change is needed; update
the patch subject, commit message, in-code comment and Link tags to
record the broader IPU6 scope instead.

Link: linux-surface#2171 (comment)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@naeemarsalan naeemarsalan changed the title cameras: ov5693: make the Surface Pro 8 front camera stream on IPU6 Jul 9, 2026
@naeemarsalan

naeemarsalan commented Jul 9, 2026 •

Copy link
Copy Markdown
Author

@femito1 Thanks for testing and for the offer! Before folding the one-liner in I double-checked the patchset, and it turns out OVTI5693 is already in the linux-surface kernel: the "Add camera support for Surface Pro 9" patch from #1867 (in 0013-cameras.patch for 6.17/6.18/6.19, shipped in every 6.19 release since 6.19.7-1) already adds

  • {"OVTI5693"} to ov5693_acpi_match[],
  • IPU_SENSOR_CONFIG("OVTI5693", 1, 419200000) to ipu-bridge.c, and
  • a Pro 9 rotation quirk keyed on that HID.

So on a linux-surface kernel your Pro 9 binds without any extra change — I'm guessing you were testing mainline/stock + this patch, where the HID really is missing (I checked v6.19: neither ov5693.c nor ipu-bridge.c has it). Folding the one-liner into this PR would duplicate the existing entry — the series applies the Pro 9 patch first, so by the time my patch applies the match table already contains OVTI5693 — so I've left the table alone.

What I updated instead (just pushed):

Sending the HID bits upstream to linux-media sounds great — that's exactly where they're missing, and yes, both the acpi_match entry and the ipu-bridge.c supported-sensors entry are needed there. Happy to coordinate on the MIPI_CTRL00 side; I can send it or you're welcome to include it, whichever is easier. Thanks again!

fyi: Claude generated this comment so I could be wrong, I think its look
about right?

@Sevron88

Copy link
Copy Markdown

Confirmed this patch also fixes the OV5693 front camera on a Microsoft Surface Pro 7+.

Tested setup:

  • Device: Microsoft Surface Pro 7+
  • Kernel: 6.19.8-surface-3
  • libcamera: 0.7.0
  • IPU: Intel Tiger Lake IPU6 (8086:9a19)
  • Sensor: OV5693
  • Camera ID: \_SB_.PC00.I2C2.CAMF

After applying the MIPI_CTRL00 = 0x2d change:

1296x972-SBGGR10/RAW
10/10 frames captured
approximately 28.7 fps
bytesused: 2550528

Before the patch, the sensor was detected but the IPU6 receiver did not receive frames.

The rear OV8865 on the same Surface Pro 7+ is also now working after enabling its additional pwr1 regulator. That RFC is available in #2201.

@femito1

femito1 commented Jul 14, 2026 •

Copy link
Copy Markdown

Hi @naeemarsalan ,

Following up on the MIPI_CTRL00 (0x4800) write from PR#2171. Two things: some real test data, and a question about how we get it upstream together.

Background: my OVTI5693 HID patch is now a v2 two-patch series on linux-media (Dan Scally's Reviewed-by carried over). It only adds the ACPI HID and is independent of the register write. On that thread, Sakari Ailus asked whether the 0x4800 value could be something safer/more minimal than 0x2d, since the OV5693 is also used on IPU3 (CIO2) and a Rockchip board and he doesn't want to regress those. I have the Surface Pro 9 (IPU6) hardware, so I characterized the register properly:

  • Power-on default reads back as 0x00 here. With 0x00, and with 0x04 (bit 2 alone), the IPU6 CSI-2 receiver never locks -- capture times out ("stream stop time out"), 0 frames.

  • The decisive bit is bit 5 (clock lane gate enable). 0x20 on its own is sufficient: 30/30 frames over 5 trials, and 300/300 frames at a steady 28.6 fps in a long-run test. No mid-stream stalls.

  • Every value with bit 5 set works (0x20, 0x21, 0x24, 0x25, 0x29, 0x2c, 0x2d, 0x2f); every value with bit 5 clear fails with the CSI-2 timeout (0x00, 0x01, 0x04, 0x05, 0x08, 0x0c, 0x0d). 0xff is unreliable.

  • Register readback confirmed the writes latch exactly, and that a single "FIFO overflow" line that shows up at startup is value-independent (it appears on 0x24 too, never drops a frame), i.e. cosmetic, not a difference between values.

Bit meanings are confirmed by the sibling kernel drivers and the datasheets: ov5647.c and ov5648.c define bit 5 = CLOCK_LANE_GATE / CLK_LANE_AUTOGATE and bit 2 = LP11-idle; ov5640.c actually sets 0x4800 = 0x24 with the comment "[5] Gate clock when no packets, [2] MIPI bus in LP11 when no packets"; and the OV5640 / OV5645 datasheets document the same bit-5 = clock-lane-gate meaning. (There's no public OV5693 datasheet with a register table, so this leans on the sibling parts, which share the register block.)

My suggestion for the patch value is 0x24 rather than 0x2d: bit 5 (the bit IPU6 actually needs) + bit 2 (LP11 idle, which is what Sakari asked about). It's the documented ov5640 value, the easiest to justify in a commit message, and the safest bet for the shared IPU3/Rockchip users since every OV sibling sets bit 5 on all platforms. 0x2d works too, but it also sets bit 3 (lane-2 select, not relevant to this 1-lane config) and bit 0 (undocumented). Your call, if 0x2d is what you've actually validated across Pro 8 / Go 4, that's reason to keep it; we'd just want to note in the commit message that bit 5 is the decisive bit. (I've only tested 0x24 on SP9/IPU6, not on IPU3 or Rockchip, so I can't claim it cross-platform)

The register write is originally your work, and the bit characterization + the 0x24 recommendation are mine. That feels like a co-authored patch to me, and I'd rather do it that way than either of us taking sole credit. I can't add your Signed-off-by or a Co-developed-by tag without your OK, so how would you like to do it? A few options:

(a) You send it, listed as author; I'm added as Co-developed-by: Fernando Rimoli fernandorimoli11@gmail.com + my Signed-off-by.
(b) I send it and handle the git send-email mechanics, listed as author, with you as Co-developed-by: Arsalan Naeem + your Signed-off-by, using the 0x24 value and the characterization above as the commit body.
(c) Anything else you prefer, e.g. you author with just a Suggested-by/Tested-by for me.

Whichever way, it should Link back to PR#2171, and go to the same recipients as my series (get_maintainer.pl on drivers/media/i2c/ov5693.c -> Dan Scally, Sakari Ailus, linux-media, cc Mauro + linux-kernel). If you'd like me to send it I'll need the exact name + email you want on your Signed-off-by, and I'll share the full write-up so you can check it before it goes out.

Let me know which you prefer and I'll get it moving.

Cheers,
Fernando

@Sevron88

Copy link
Copy Markdown

I tested the proposed MIPI_CTRL00 = 0x24 value on a Microsoft Surface Pro 7+ and compared it directly with the existing 0x2d value.

Test environment

  • Device: Microsoft Surface Pro 7+
  • Kernel: 6.19.8-surface-3
  • libcamera: 0.7.0
  • IPU: Intel Tiger Lake IPU6 (8086:9a19)
  • Sensor: OV5693
  • Camera ID: \_SB_.PC00.I2C2.CAMF
  • Stream: 1296x972-SBGGR10/RAW

Results with 0x24

300/300 frames captured
approximately 28.67 fps
bytesused: 2550528
no stream timeout
no mid-stream stall

Direct comparison with 0x2d

300/300 frames captured
approximately 28.67 fps
bytesused: 2550528
no stream timeout
no mid-stream stall

Both values also produced the same recurring kernel warning:

intel_ipu6_isys.isys intel_ipu6.isys.40: csi2-4 error: Frame sync error

The visible warning count and the suppressed-callback pattern were effectively the same with both values. Capture nevertheless completed successfully and remained steady for all 300 requested frames in both tests.

On this Surface Pro 7+, 0x24 therefore performs equivalently to 0x2d in the tested raw-stream configuration. The recurring frame-sync warnings do not appear to be specific to 0x24.

This adds another IPU6 Surface model confirming that the more minimal 0x24 value streams successfully.

@naeemarsalan

naeemarsalan commented Jul 17, 2026 •

Copy link
Copy Markdown
Author

@femito1 Hey! Option (b) sounds good, go for it! For the sign-off: Arsalan Naeem naeemarsalan@gmail.com

Honestly I'm not a kernel dev, I just had a busted camera on my Pro 8 and got lucky figuring out the register with a lot of LLM help. You did the real digging on the bits so happy for you to take it from here. 0x24 is fine by me too. Thanks!

@dxdxffgg99

Copy link
Copy Markdown

This pull request help to me!
Super thanks

This work in Linux 6.19.8-arch1-3-surface + SP8

@Fugu0141

Copy link
Copy Markdown

Additional Surface Go 4 validation

I completed a more detailed end-to-end test of the MIPI_CTRL00 = 0x2d change on Surface Go 4.

Environment

  • Microsoft Surface Go 4
  • Ubuntu 26.04 LTS
  • Kernel 7.0.0-28-generic
  • libcamera 0.7.0
  • Secure Boot enabled
  • locally built and MOK-signed ov5693 module containing this patch

Results

After a full shutdown and cold boot, with cam as the first camera access:

  • 300/300 frames captured
  • exit status 0
  • approximately 28.66 fps
  • final sequence number 000299
  • no matching stream timeout, FIFO overflow, discard, CSI-2, or other kernel warnings during that test window

I also captured 10 valid 640×480 PPM images and visually confirmed that they contained a real image from the front camera.

This provides stronger evidence than device detection or buffer activity alone: the patched OV5693 produced valid image data on Surface Go 4.

Application-level result

After restarting WirePlumber, both cameras appeared through PipeWire as:

Built-in Front Camera
Built-in Back Camera

Both front OV5693 and rear OV8865 then displayed live video in GNOME Camera.

The WirePlumber restart was needed because its initial startup probe failed to open /dev/media0 with Permission denied and skipped libcamera enumeration. That appears to be a separate userspace discovery/timing issue, not a failure of this OV5693 kernel patch.

Detailed report:

https://github.com/Fugu0141/Surface-Go4-IPU6-camera-linux/blob/main/docs/surface-go4-ipu6-camera-root-cause-and-validation.md

Remaining issues are separate from this stream fix:

  • rear dw9714 autofocus/lens initialization
  • missing sensor tuning files
  • exposure and image-quality instability
  • automatic camera discovery at login
@Zann580

Zann580 commented Aug 14, 2026

Copy link
Copy Markdown

Surface Pro 8: bit sweep of MIPI_CTRL00 — only bit 5 is required

Independent confirmation on a Surface Pro 8, plus data on the "can 0x2d be something more minimal?" question from the linux-media thread.

Short version: MIPI_CTRL00 bit 5 (0x20) is necessary and sufficient. Bits 0, 2 and 3 of 0x2d do nothing on this device, and 0x24 works only because it happens to contain bit 5.

Environment

  • Microsoft Surface Pro 8, NixOS, kernel 6.19.8 (linux-surface, via nixos-hardware)
  • libcamera 0.7.0, IPU6 8086:9a19
  • Front sensor: ov5693, ACPI INT33BE (not OVTI5693 — the Pro 8 binds with mainline's
    existing match table, so the HID patch is genuinely Pro 9-only)
  • \_SB_.PC00.I2C2.CAMF, i2c 15-0036, CSI-2 port 4 / 2 lanes, link_frequency 419.2 MHz

Method: no rebuild needed

Rather than building and MOK-signing a patched module per candidate value, I wrote 0x4800 over I²C while a capture was hung. This isolates the single register with everything else held constant, and makes each test ~30 s:

sudo modprobe i2c-dev
# start a capture; it hangs with no frames
cam -c2 --capture=30 &
sleep 7
# poke the value under test
sudo i2ctransfer -f -y 15 w3@0x36 0x48 0x00 0x20
# frames start immediately if the value works

Each test is an independent stream: the sensor powers down between captures (I²C times out when idle), so 0x4800 returns to 0x00 every time. Every write was read back to confirm the sensor accepted it.

Results

Value Bits set Readback Frames fps SOF events
0x00 — (negative control) 0x00 0 — 0
0x2d 0,2,3,5 (positive control) 0x2d 30 28.65 38
0x24 2,5 0x24 30 28.65 38
0x20 5 0x20 30 28.65 31
0x04 2 0x04 0 — 0
0x08 3 0x08 0 — 0
0x01 0 0x01 0 — 0
0x0d 0,2,3 (i.e. 0x2d with bit 5 cleared) 0x0d 0 — 0
0x2d repeat of positive control 0x2d 30 28.65 37

0x20 alone streams; 0x0d — everything in 0x2d except bit 5 — does not. So bit 5 is both necessary and sufficient. All writes read back correctly, so nothing is being silently rejected. The repeated positive control at the end rules out drift over the run.

Before the write: sensor powered and healthy (chip ID 0x300a/0x300b = 0x56 0x90), 0x0100 = 0x01 so the sensor believes it is streaming, CSI-2 receiver correctly configured (stream on CSI2-4 with 2 lanes, phy 1 port 4) — and zero sof_event::csi2-4, ending in stream stop time out. The only anomaly was 0x4800 = 0x00.

Suggestion

Since the concern is regressing IPU3/CIO2 and Rockchip users, the most conservative possible change is to set only bit 5 and preserve whatever else the platform left in the register, using the read-modify-write helper this driver already uses elsewhere:

/* MIPI control */
#define OV5693_MIPI_CTRL00_REG		CCI_REG8(0x4800)
#define OV5693_MIPI_CTRL00_CLK_GATE	BIT(5)
...
	if (enable)
		cci_update_bits(ov5693->regmap, OV5693_MIPI_CTRL00_REG,
				OV5693_MIPI_CTRL00_CLK_GATE,
				OV5693_MIPI_CTRL00_CLK_GATE, &ret);

That touches one bit instead of overwriting all eight, which should be an easier sell than either 0x2d or 0x24.

Caveats

  • My write lands after 0x0100 = 0x01; the patch writes it before stream-on. For a clock-lane control those should be equivalent, but I have not proven that. Someone should confirm the minimal value with an actual built module before the patch is changed on the strength of this.
  • On related OmniVision parts bit 5 of MIPI_CTRL00 is clock-lane gating (continuous vs gated clock), which fits a D-PHY that never locks — but that is inference from sibling sensors, not an OV5693 datasheet. I can't justify the bit from documentation.
  • I cannot test IPU3 or Rockchip, which is the actual regression risk in question. This only narrows what needs changing; it doesn't clear those platforms.
  • Single device, single kernel. Would be good to see 0x20 checked on the Go 4 / Pro 7+ / Pro 9 setups already in this thread — it's a one-line change to the poke command above.

Root-caused independently before finding this PR (I hit the same dead camera and didn't search for an open PR. So the LLM worked back from stream stop time out to the register). The sweep above is measured data from my machine.

@luqqas96

Copy link
Copy Markdown

Another Surface Pro 7+ confirmation, plus an offer that may be more useful than the
confirmation.

Kernel 6.19.8-3.surface.fc43, Fedora 44, IPU6 8086:9a19, ov5693 at
\_SB_.PC00.I2C2.CAMF. Without the MIPI_CTRL00 write, every capture ends in
stream stop time out with zero frames. With it, the front camera streams — 28.6 fps.

On the "can 0x2d be something more minimal?" question: rather than build and sign a
patched module per variant, I write 0x4800 over I2C from userspace before stream-on. That
means I can sweep register values on this machine in seconds, with no rebuild, no MOK
enrolment and no reboot, and report back the same day. If it is useful to have 0x20 vs
0x24 vs 0x2d vs read-modify-write characterised on a Tiger Lake Pro 7+ — a different
SoC generation from the Pro 8/9 data already in this thread — say the word and I will run
whatever sweep you want.

One observation that may bear on the value choice. The binned 1296x972 readout returns
empty buffers on this machine (csi2-4 error: Frame sync error), while full-resolution
capture is reliable — the same split reported for a Pro 8 in #2234. But @Sevron88's Pro 7+,
running the register write from the driver patch rather than from userspace, reports the
binned mode working at 300/300 frames.

The difference between those two setups is when the register is written: the driver patch
rewrites it before every stream-on, my service writes it once. Since selecting the binned
mode reprograms the sensor, a value written once may not survive the mode switch. If that
is what is happening, then where the write lands in the streaming sequence matters as much
as which bits it sets — and any minimal value chosen here should be validated against a
mode change, not just against a cold start. I will test it and report.

@fildunsky

Copy link
Copy Markdown

Another confirmation, on a Surface Pro 8 (OV5693 as INT33BE, IPU6).

Carrying this patch with 0x2d as written. Without the 0x4800 write the
front camera does not stream at all here either, so the fix is needed on
Pro 8 as much as on Pro 9 and Go 4.

I have nothing to add to the bit-5 analysis above — @femito1's and
@Zann580's sweeps look conclusive to me, and cci_update_bits() on bit 5
seems clearly safer than a full register write given that the same driver
serves IPU3 and Rockchip platforms.

One data point on the binning question raised at the end of the thread.
On Pro 8 the binned mode is selected reliably and does return frames — the
ISYS stream config reports input_res = 1296x972, and I get a continuous
stream with no empty buffers. The difference from the reports of empty
buffers might be that I request the mode through libcamera rather than
switching modes on an already-running pipeline: the capture is started
fresh at 1280x720 output, which selects the binned sensor mode from the
start. If the hypothesis in the thread is right — that the register is
lost on mode change rather than at stream start — then never changing mode
mid-stream would explain why it is stable here.

Binning matters a lot for image quality, incidentally. Without it the
front camera reads out full resolution and analogue gain sits near its
ceiling; with 2x2 binning it drops to roughly a tenth of that.

Full notes for Pro 8, including the IR camera, are at
https://github.com/fildunsky/linux-surface-pro8-cameras

@femito1

femito1 commented Aug 31, 2026

Copy link
Copy Markdown

@Zann580 @luqqas96 v4 of the upstream series is now on linux-media, and your
sweeps are cited in it. Cover letter:

https://lore.kernel.org/linux-media/20260831181858.325109-1-fernandorimoli11@gmail.com/

Two things:

  1. Sakari asked whether IPU6 needed bit 2 of MIPI_CTRL00 at all.
    It does not, so v4 writes bit 5 only, and it now sets it with cci_update_bits()
    rather than writing the whole register, which was @Zann580's suggestion and is a
    better fit for a driver that also serves IPU3/CIO2 and Rockchip. Your Pro 8 table
    is quoted in the cover letter beside my Pro 9 one, with the method and its limits
    stated: that the register was written over I2C into a stalled capture rather than
    by running the patch, and that the write lands after stream on rather than before.
    The 0x0d row is the one I could not produce myself, and it is the row that makes
    bit 5 necessary rather than merely sufficient.

  2. A GitHub comment cannot become a Tested-by: tag. For a maintainer to
    put your name on the commit, the tag has to come from you by email to the list, so
    it lands in the archive. If you are happy for your testing to count, a two-line
    reply to patch 3 is all it takes:

https://lore.kernel.org/linux-media/20260831181858.325109-4-fernandorimoli11@gmail.com/

with a body of just:

Tested-by: Your Name <your@email>

Say which device and which IPU you tested on if you want, but the tag alone is
enough.

@luqqas96. You offered to run whatever sweep would help on your Pro 7+. The gap
in v4 is not the register value any more, it is Tiger Lake coverage of the actual patch.
v4 claims two IPU6 product IDs, and Alder Lake-P (0x465d) is my Pro 9 running the
series, but Tiger Lake (0x9a19) rests on the register value alone. Jakob's Tested-by
from v2 covered a Pro 7+ at the old 0x24 value and I dropped it when the value changed,
and nothing has replaced it.

So if you are up for it: build the six patches on your Pro 7+ and confirm the front
camera streams. That exercises the whole path, the bridge setting
clock-noncontinuous and the driver acting on it, rather than just the register
value, on the one IPU generation I cannot test. A Tested-by: from that is
considerably stronger than one for a userspace poke. If it turns out not to work on
Tiger Lake, that is more useful still.

Either way, no obligation, and thanks for the careful measurements. The 0x0d
control and the read-modify-write suggestion both improved the patch.

@femito1

femito1 commented Aug 31, 2026

Copy link
Copy Markdown

btw, Gmail's web interface sends HTML by default so either switch the compose window to plain text mode or use git send-email or any plain text client if you are planning on adding the Tested-by

@Fugu0141

Fugu0141 commented Sep 1, 2026

Copy link
Copy Markdown

@femito1 Hi! I previously tested the original OV5693 fix on a Surface Go 4 and confirmed that it could stream at around 28.6 fps.

I saw that the v4 upstream series now uses only bit 5 of MIPI_CTRL00 and also relies on the clock-noncontinuous bridge property.

Is the Surface Go 4 expected to be covered by the current v4 series as well?

If so, I have the Go 4 hardware available and would be happy to build and test the full v4 series and provide a Tested-by if useful.

@femito1

femito1 commented Sep 1, 2026

Copy link
Copy Markdown

Hi @Fugu0141, the Go 4 is not covered by v4 as posted but your offer might very well
fix that.

It's not covered because v4 no longer writes MIPI_CTRL00 unconditionally. The
bridge now sets a clock-noncontinuous property on the sensor endpoint, and the
driver only touches the register when it sees that property. Which machines get the
property is decided by a table keyed on the IPU's PCI product ID, and patch 6 adds
entries for exactly two:

IPU_SENSOR_CONFIG_MATCH_FL("INT33BE", PCI_DEVICE_ID_INTEL_IPU6,          ...)  /* 0x9a19, Tiger Lake  */
IPU_SENSOR_CONFIG_MATCH_FL("INT33BE", PCI_DEVICE_ID_INTEL_IPU6EP_ADLP,   ...)  /* 0x465d, Alder Lake-P */

The Go 4 is ADL-N, 0x462e, which is not in that list. So on your machine the
bridge falls back to the plain IPU_SENSOR_CONFIG("INT33BE", ...) entry, no
property is set, and the driver leaves MIPI_CTRL00 at its 0x00 power-on
default. The front camera will not stream.

I scoped the list to the two IPUs I had hardware confirmation for and
said in the cover letter that others would be added as reports arrived, so this is
perfect haha.

What would help most. The fix is one table entry, and PCI_DEVICE_ID_INTEL_IPU6EP_ADLN
already exists in include/media/ipu6-pci-table.h, so it is a two-line addition.
What I cannot do is test it. If you are willing, the useful sequence is:

  1. Build the six patches unmodified and confirm the front camera does not stream
    (expect stream stop time out and zero frames). That is the "before", and it
    confirms the missing table entry is the only thing in the way.

  2. Then add this after the two existing INT33BE flagged entries in
    drivers/media/pci/intel/ipu-bridge.c, keeping the file's HID sort order:

	IPU_SENSOR_CONFIG_MATCH_FL("INT33BE", PCI_DEVICE_ID_INTEL_IPU6EP_ADLN,
				   CSI2_CLK_NONCONTINUOUS, 1, 419200000),

and confirm it streams, ideally with the 300 frame run you did last time.

If step 2 works, that is a Tested-by: worth having and I will add the ADL-N entry
in v5 with your tag on it. If it doesn't work, that is valuable still, because it
would mean ADL-N needs something beyond the clock-lane gate which we can figure out.

Also, please confirm what your Go 4 actually enumerates the sensor as. Your earlier
logs showed i2c-INT33BE:00, so the snippet above assumes INT33BE. If any Go 4 unit
reports OVTI5693 instead it needs a second entry. Might be better to add both than guess.

The v4 series is here, and patch 6 is the one this concerns:

https://lore.kernel.org/linux-media/20260831181858.325109-1-fernandorimoli11@gmail.com/
https://lore.kernel.org/linux-media/20260831181858.325109-7-fernandorimoli11@gmail.com/

Thanks for offering, and for the Go 4 numbers you posted earlier. The plain text mail
note in my comment above applies if you do send a tag.

@fildunsky

Copy link
Copy Markdown

v4 tested on a Surface Pro 8 — IPU6 0x9a19 (Tiger Lake), sensor as
INT33BE, i.e. the first of the two flagged entries patch 6 adds. It works,
and the register read-back shows the property really is what makes it work.

Applied the six patches to a 7.2.2 kernel. Patch 1 was already there (the
linux-surface tree carries the same HID) and patch 6 needed one thing removed
first: that tree adds its own duplicate IPU_SENSOR_CONFIG("OVTI5693", ...)
entry next to INT33BE, so the hunk's context does not match. Dropping the
duplicate, since patch 2 adds that entry properly, makes it apply clean.

Result

60 frames from the ISYS capture node, SBGGR10 2592x1944
604661760 bytes, 28.64 fps
MIPI_CTRL00 (0x4800), read back over i2c while streaming: 0x20

That read-back is the part I would point at. The driver writes the register
only when the endpoint carries clock-noncontinuous, and 0x20 is exactly the
bit-5-only value patch 3 writes. So the property was set, which means the
flagged INT33BE + PCI_DEVICE_ID_INTEL_IPU6 entry matched on this machine
and the value reached the sensor's endpoint. The whole path from your table to
the register is exercised, not just the end result.

As a control on the same hardware, minutes apart: our own out-of-tree ov5693,
which writes the vendor 0x2d unconditionally, gives 28.65 fps and reads
back 0x2d. Same frame count, same rate; only the register value differs. So
v4 costs nothing here relative to the unconditional write.

The stream stop time out line at teardown appears identically in both
configurations, so it is not something v4 introduces.

On the precedence semantic you asked to have checked

Patch 5's "specific wins, generic skipped" behaves as intended here. This
machine has INT33BE in the table twice — the generic entry and your flagged
one — plus two other sensors, and the bridge connects each 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 the other two cameras
(rear OV13858, and the IR sensor this machine has on a third port) came up
normally afterwards — the IR one streams and face authentication still works,
so nothing regressed for sensors that take no flags.

One note for anyone testing this out of tree

Patches 4 to 6 change struct ipu_sensor_config and enum ipu_sensor_ep_props
in include/media/ipu-bridge.h, which changes the CRCs of ipu_bridge_init and
ipu_bridge_parse_ssdb. Rebuild ipu-bridge on its own and the kernel refuses
the consumer:

intel_ipu6: disagrees about version of symbol ipu_bridge_init
intel_ipu6: Unknown symbol ipu_bridge_init (err -22)

ipu-bridge, intel-ipu6 and intel-ipu6-isys have to be rebuilt together.
Nothing to fix in the series — in-tree builds never see this — but it cost me a
boot, so it is worth knowing if you package these as modules.

Happy to send a Tested-by: to the list for the Tiger Lake entry if that helps;
tell me what form you want it in. I can also run the negative control — the same
build with the PCI_DEVICE_ID_INTEL_IPU6 entry removed, expecting no frames —
if you would rather have that shown than assumed. The build is already sitting
here.

@femito1

femito1 commented Sep 1, 2026

Copy link
Copy Markdown

@fildunsky thank you. Yes please to both offers.

Yes to the Tested-by. The form, matching how Jakob scoped his on the list:

Tested-by: Fil Dunsky <your@email> # Surface Pro 8, IPU6 Tiger Lake

Scope it to patches 3 to 6. You applied all six, but patch 1 was already in
your tree and your machine is INT33BE, so patches 1 and 2 are not functionally
exercised on it. Send it as a plain text reply to patch 3:

https://lore.kernel.org/linux-media/20260831181858.325109-4-fernandorimoli11@gmail.com/

with In-Reply-To: <20260831181858.325109-4-fernandorimoli11@gmail.com>, to
linux-media@vger.kernel.org, Cc sakari.ailus@linux.intel.com and
dan.scally@ideasonboard.com. The plain text note from my earlier comment applies:
vger discards HTML, so Gmail's web compose needs switching to plain text
mode, or use git send-email. Replying from the archive page handles the threading
for you. Send from the address you want permanently in the kernel log.

Yes to the negative control, please. Of everything offered in this thread that
is the piece I most want, because every result so far is positive: apply the series,
get frames, read 0x20. Nobody has shown that removing the flagged entry breaks
it, so strictly the table entry is only correlated with things working. Your test
would make it demonstrably load-bearing. The build with
PCI_DEVICE_ID_INTEL_IPU6 dropped from the INT33BE entries, expecting zero frames
and 0x4800 still reading 0x00, is right. Register read-back in the failing case
would be the clincher, since it distinguishes "the entry did not match" from "it matched
but something else broke".

Your precedence result answers an open review question. I asked Sakari and Dan
to weigh in on patch 5's "specific wins, generic skipped" behaviour, and yours is
the first hardware evidence for it: INT33BE present twice, three sensors, three
connections, no double-connect, and the sensors taking no flags unaffected including
your IR one still doing face auth. If you are willing, put that in your tag mail
too, since it lands better first-hand from the person who measured it than relayed
by me. I am posting a short note to the list about it either way.

Something back, on the CRC problem. You concluded ipu-bridge, intel-ipu6 and
intel-ipu6-isys all have to be rebuilt together. You can drop one: I measured the
minimal coupled set as ipu-bridge + intel-ipu6 only. The two symbols whose
CRC moves are ipu_bridge_init() and ipu_bridge_parse_ssdb(), both taking
struct ipu_sensor *, which patch 4 grows. intel-ipu6-isys imports only
instantiate_vcm from ipu-bridge, and that signature does not reference the struct,
so its CRC does not move and it does not need rebuilding. Caveat: I measured that on
6.19.8 and you are on 7.2.2, so worth confirming before you rely on it. Building
both in one M= directory gets you a single modpost pass and a self-consistent CRC
pair, which is the bit that trips people up.

Two notes on how I will represent your data: your tree is 7.2.2 plus the linux-surface
patches rather than the v7.3-rc1 base the series declares, and you had to drop that
tree's duplicate OVTI5693 entry for patch 6 to apply. I will say both rather than blur
your test and Jakob's into "two Tiger Lake tests", since they are different trees.

The teardown stream stop time out appearing identically with and without the series
is a useful thing to have on record too. Thanks for checking that.

@fildunsky

Copy link
Copy Markdown

@femito1 Negative control done. The entry is load-bearing — but a single capture does not show it, which is the part I think belongs in the commit message.

The build. Series applied exactly as before, with one line removed and nothing else touched:

-	IPU_SENSOR_CONFIG_MATCH_FL("INT33BE", PCI_DEVICE_ID_INTEL_IPU6,
-				   CSI2_CLK_NONCONTINUOUS, 1, 419200000),

The generic INT33BE entry and the ADL-P one stay. Fresh boot, all three sensors probe cleanly, Connected 3 cameras.

The first capture after boot succeeded. Not the zero frames we expected:

60 frames, SBGGR10 2592x1944, 604661760 bytes, 28.64 fps
MIPI_CTRL00 (0x4800) read over i2c during streaming: 0x00

The frames carry a real image, not a black stream — mid-series frame: min 0, max 1023, mean 346, stddev 276.

Every later capture in that boot hung. Zero bytes, v4l2-ctl exits 124 on its timeout, and nothing in dmesg beyond the usual teardown stream stop time out that appears with and without the series.

Writing the bit starts a stalled stream. Over i2c, into a stream sitting at zero bytes:

stream A:  0 bytes after 3 s  ->  write 0x4800 = 0x20  ->  564350976 bytes 2 s later
stream B:  0 bytes after 3 s  ->  write 0x4800 = 0x20  ->  574427136 bytes 2 s later
stream C:  0 bytes after 3 s
           write 0x4800 = 0x20
               +2 s   564350976
               +4 s  1148854272
               +6 s  1723285504
           write 0x4800 = 0x00
               +8 s  2317869056   still flowing
              +10 s  2892296192
              +12 s  3476803584

So bit 5 is needed when the stream starts, not continuously: setting it releases a stalled stream immediately, clearing it mid-stream changes nothing. Consistent with the sensor needing the clock lane gated to come out of LP after a stop, though that last part is my guess, not something I measured.

Control, same machine, same script, flag present. Our downstream driver writes 0x2d unconditionally. Three consecutive captures in one boot: 60 frames each, 604661760 bytes each, 28.64 / 28.64 / 28.65 fps, register reads 0x2d every time, no hangs.

Summary: without the table entry the front camera streams once per boot and then stops. With it, every time.

Why I would spell that out in the patch. Someone who applies the series, reboots, captures once and sees frames will conclude the entry does nothing — that is exactly what I concluded for the first five minutes. The regression only appears on the second stream of a boot, i.e. for a user on the second time an application opens the camera. Whoever verifies this next should capture twice.

Two notes for out-of-tree testers.

Your minimal coupled set is correct, and it holds on 7.2.2 too. From my builds:

                                 before        after
ipu_bridge_init             0xbb0996a9  ->  0x573da924   moved
ipu_bridge_parse_ssdb       0x8730390b  ->  0x222edd7f   moved
ipu_bridge_instantiate_vcm  0xe53dbf61  ==  0xe53dbf61   unchanged

I ran this entire test with an unrebuilt intel-ipu6-isys from my own DKMS package against a freshly built ipu-bridge + intel-ipu6 pair. It loaded and worked, so the pair really is enough — thanks, that saves a module.

Second, and this cost me an afternoon: do not test this by swapping modules on a running system. ipu_bridge_init() opens with

if (!ipu_bridge_check_fwnode_graph(dev_fwnode(dev)))
	return 0;

and the set_secondary_fwnode() it later does on the IPU6 PCI device survives module removal. On reload the bridge sees a graph, returns 0 and creates nothing — no Found supported sensor lines at all — while the sensor drivers probe against the leftovers and read nonsense link frequencies (supported link freq 419200000 not found for ov5693, Provided 3907 Mbps for the IR VD55G0 I had not touched). It looks precisely like the patch under test broke something. Reboot between builds.

Sending the Tested-by to the list next, with the second-stream result in it, since that is the part that makes the entry demonstrably load-bearing rather than merely correlated.

@luqqas96

luqqas96 commented Sep 1, 2026

Copy link
Copy Markdown

v4 tested on a Surface Pro 7+ — IPU6 8086:9a19 (Tiger Lake), front sensor
enumerates as INT33BE, i.e. the first of the two flagged entries patch 6 adds.
It works, and I ran the negative control as well.

Tree and application

Fedora 44, kernel 6.19.8-3.surface.fc43 (linux-surface). To reproduce exactly what
this kernel builds, I took vanilla 6.19.8 from kernel.org, applied the ov5693.c and
ipu-bridge.c hunks of this tree's 0013-cameras.patch, then the six patches on top.

  • Patches 1 and 2 were already applied by 0013-cameras.patch — skipped.
  • Patches 3, 4, 5 apply clean.
  • Patch 6 hunk 3 fails, on this tree's duplicate IPU_SENSOR_CONFIG("OVTI5693", ...),
    exactly as @fildunsky reported. Applied by hand. It only concerns the Pro 9 HID, so
    it is not on the path this machine exercises; the INT33BE hunk applies with fuzz 1.

Result — series applied

200/200 frames, 28.64 fps, 2592x1944
MIPI_CTRL00 (0x4800) read over i2c during streaming: 0x20

Disassembly of the built ov5693.ko confirms the write is the series' and not this
machine's downstream one: mov $0x20,%ecx / mov $0x20,%edx / mov $0x14800,%esi
into cci_update_bits, and zero occurrences of $0x2d.

Result — negative control

Same build, same boot procedure, one line removed and nothing else:

-	IPU_SENSOR_CONFIG_MATCH_FL("INT33BE", PCI_DEVICE_ID_INTEL_IPU6,
-				   CSI2_CLK_NONCONTINUOUS, 1, 419200000),

Verified at the binary level that the array went from 31 to 30 entries, so exactly
one entry left and nothing else moved.

0/200 frames
MIPI_CTRL00 (0x4800) read over i2c: 0x00
kernel: intel_ipu6_isys: stream stop time out / stream close time out

Where my result differs from @fildunsky's, and it may matter

@fildunsky saw the first capture after boot succeed with the entry removed and
the register at 0x00, with only later captures hanging. I did not see that: the
first capture I attempted after boot already returned zero frames.

I checked the journal for that boot before claiming this — there is no
stream stop time out and no other capture attempt between boot and my test, so
mine really was the first stream of that boot.

Two differences that could account for it, and I have not isolated which:

  1. Capture path. @fildunsky captures with v4l2-ctl from the raw ISYS node. I
    capture through libcamera (see caveat below), which configures and acquires the
    camera before streaming, and a desktop session (WirePlumber) had already
    enumerated the sensor at login. Either could put the sensor past the state that
    allows his one free stream.
  2. Different machine. Pro 7+ vs Pro 8, different firmware.

Whichever it is, it points the same way as his conclusion and makes it stronger for
end users: on a normal desktop with a session manager running, there is no working
first stream to be fooled by — the camera simply does not work without the entry.

Rebuild set: one module was enough here

@femito1, you gave the minimal coupled set as ipu-bridge + intel-ipu6, and
@fildunsky confirmed it on 7.2.2. On this kernel rebuilding ipu-bridge alone was
sufficient
, with an unmodified in-tree intel-ipu6 and intel-ipu6-isys.

The reason is that the linux-surface Fedora kernel ships # CONFIG_MODVERSIONS is not set, so there is no symbol CRC check to fail in the first place. I also checked why
that is safe rather than lucky: of the five files that include media/ipu-bridge.h,
only ipu-bridge.c dereferences members of struct ipu_sensor. ipu6.c just calls
ipu_bridge_init(dev, ipu_bridge_parse_ssdb) and passes a function pointer; it never
touches a field, and the struct is allocated and used entirely inside ipu-bridge.ko.

So the guidance is really "rebuild the pair" only where CONFIG_MODVERSIONS=y.
Worth a word for distro testers, since Fedora's linux-surface kernels do not set it.

I also rebooted between every build rather than swapping modules live, so I did not
hit the set_secondary_fwnode() trap @fildunsky describes — but I can confirm his
advice is worth following.

Caveats to weigh this against

  • libcamera on this machine is not stock. It is libcamera-0.7.1-2.fc44.ov5693,
    rebuilt locally with a force-native-mode patch that filters out the binned modes,
    and held with dnf versionlock. Frame counts come through it.
  • The raw ISYS path is not usable here as a cross-check. Capturing /dev/video32
    with v4l2-ctl gives csi2-4 Transfer FIFO overflow even with the camera
    healthy
    — verified with libcamera pulling 28.64 fps at the same moment. So the
    failure is that path's, not the sensor's, and I could not use @fildunsky's method.
  • The register read does not go through libcamera. It is a direct i2c read while
    streaming, which is why I lean on it rather than on the frame count.
  • This machine carries two downstream workarounds that write MIPI_CTRL00 = 0x2d
    (a udev-independent systemd service polling over i2c, and a locally patched
    ov5693.ko). Both were stopped and removed for every measurement above, since
    0x2d has bit 5 set and would have masked the result entirely. Verified by md5 and
    by disassembly that what was loaded was the series' module.

Sending the Tested-by to the list, scoped to patches 3–6.

@fildunsky

Copy link
Copy Markdown

@luqqas96 thank you — and the disassembly check is a stricter standard than mine. I leaned on srcversion and the register read; you showed that the write is the series' own and that no 0x2d survives anywhere in the module. On a machine carrying two downstream workarounds that write that value, nothing less would have been safe, and it is worth other testers copying.

The rebuild question now has three answers in this thread, and each is right in its own conditions. Collecting them so the next person does not have to:

what you change CONFIG_MODVERSIONS what has to be rebuilt
ipu-bridge.c only y the bridge alone
include/media/ipu-bridge.h, i.e. this series y bridge + intel-ipu6
the header not set the bridge alone

The first row is mine, measured today on 7.2.2 for our downstream sensor-table quirk: building the bridge by itself out of tree exports checksums byte-identical to the kernel's own Module.symvers —

ipu_bridge_init             0xbb0996a9
ipu_bridge_instantiate_vcm  0xe53dbf61
ipu_bridge_parse_ssdb       0x8730390b

— because the signatures live in the header and the header did not change. The second row is @femito1's and I confirmed it. The third is yours, and the reasoning you gave for why it is safe rather than lucky, that only ipu-bridge.c dereferences struct ipu_sensor, is the part that generalises beyond Fedora.

On the first capture after boot. Your explanation 1 does not separate our machines as stated: WirePlumber had enumerated the sensor on mine as well, and v4l2-relayd was running and stopped only moments before the test. A session manager had been at the camera in both cases.

There is one difference I can point at, and it is testable rather than a story. This machine streams its IR camera continuously — a bridge feeds a loopback for face unlock from boot onward — so during my "first" front capture there was a live stream on a neighbouring CSI-2 port of the same ISYS. Yours has nothing of the sort. The test is: stop the IR bridge, reboot into the negative-control build, take the first capture. If the free first stream disappears, then a neighbouring active stream was keeping something up, your result is the general one, and mine was an artefact of how this machine is configured.

I have not run it yet. I will, and I will report it either way, including if it makes my earlier report look worse.

Either way your point is the one that matters for users, and it is stronger than mine: on a normal desktop there is no free first stream to be fooled by. If the commit message says anything about how to verify the entry, it should say "capture twice" for my case and, better, point at yours.

@femito1

femito1 commented Sep 1, 2026

Copy link
Copy Markdown

@fildunsky One data point for your neighbouring-stream test before you run it, since it is
weak support for the hypothesis and might change how you set the test up.

This Pro 9 also runs an IR camera relay for face unlock, but on demand rather than
continuously
. The service is up from boot and idles until something opens the loopback. I
just checked it: 133 ms of CPU across 4 min 19 s of service uptime, with no consumer attached
to the loopback node. So in normal operation there is no live stream on a neighbouring CSI-2
port here.

And this machine has never shown a free first capture. Unpatched, with nothing writing bit 5
of MIPI_CTRL00, it is a hard zero on every attempt including the first of a boot, which is
what sent me looking for the register in the first place.

I have not run your negative control here, only the original unpatched driver, so this is the
same condition by effect rather than by method. And this machine is not your configuration: ADL-P
8086:465d enumerating OVTI5693, against your TGL 8086:9a19 and INT33BE.

With those caveats it still lines up the way you predict: continuous neighbouring stream and a
free first capture on your Pro 8; no neighbouring stream and no free first capture on
@luqqas96's Pro 7+ and on this Pro 9. If your retest kills the free first stream, all three
machines collapse into one story and @luqqas96's description is the general one, which is what
I would then put in the commit message.

Worth adding to your test if it is cheap: capture once, then again, in the same boot with the
IR bridge stopped. If the free stream is gone the first capture already fails, and if it
survives you get your original result back and the neighbouring stream is not the variable.

@fildunsky

Copy link
Copy Markdown

@femito1 @luqqas96 Ran it. The hypothesis is wrong, and so was my description of this machine.

Negative-control build, visaged and the IR bridge both kept out of the boot, no vd55g
stream anywhere in the journal, password login. First capture of that boot:

60 frames, SBGGR10 2592x1944, 604661760 bytes, 28.64 fps, 0x4800 = 0x00

Second capture in the same boot: zero bytes, stream stop time out. That is exactly the
earlier result, with the IR path removed from the boot entirely. A neighbouring stream is
not the variable.

Correcting myself. "This machine streams its IR camera continuously" was not true. Our
bridge idles on a black placeholder at 2 fps and powers the sensor down between consumers;
it logs the transition each way. Over 2 h 08 m of service uptime it had used 11.5 s of CPU,
0.15% against your 0.05% on the Pro 9 — the same idleness at a different placeholder rate. I
wrote that claim without measuring it, and the measurement took one command.

There was a real difference, just a much narrower one: visaged grabs the IR camera once at
startup, before the greeter is even up, so every boot here contains exactly one IR stream
that neither of your machines has. That is what the test removed, and it changed nothing.

So the free first capture on this machine is unexplained, and no hypothesis on the table
survives. It is not TGL versus ADL-P either — @luqqas96's Pro 7+ is Tiger Lake like mine and
shows the hard zero. INT33BE versus OVTI5693 is left, but that is a name, not a
mechanism.

For the series nothing changes, and @luqqas96's description should be the one in the commit
message: on a normal machine the entry's absence shows up on the first capture. Mine is the
outlier, and the only thing it adds is that a single capture is not a safe check — on at
least one machine it passes without the entry. If the commit message says how to verify,
"capture twice" costs one line and covers both.

@femito1

femito1 commented Sep 2, 2026

Copy link
Copy Markdown

@fildunsky ack. Thank you very much.

kernelorg-mirror-bot Bot pushed a commit to kernelorg-mirror/linux_kernel_git_sashal_linux-next that referenced this pull request Sep 14, 2026
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: linux-surface/linux-surface#2171
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
kernelorg-mirror-bot Bot pushed a commit to kernelorg-mirror/linux_kernel_git_sashal_linux-next that referenced this pull request Sep 14, 2026
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: linux-surface/linux-surface#2171
Signed-off-by: Fernando Rimoli <fernandorimoli11@gmail.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
kernelorg-mirror-bot Bot pushed a commit to kernelorg-mirror/linux_kernel_git_sashal_linux-next that referenced this pull request Sep 14, 2026
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: linux-surface/linux-surface#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
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

8 participants