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

cameras: ov5693: make the IPU6 Surface front cameras stream (Pro 8/9, Go 4)#2171
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 cameras: ov5693: make the IPU6 Surface front cameras stream (Pro 8/9, Go 4) 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.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Surface Go 4 IPU6 camera status: rear OV8865 detected/partially streams, front OV5693 LED only

6 participants