Porting the OmniVision OV13B10 to the Fairphone 6 Mainline Linux Kernel
Developers have achieved experimental Linux support for the Fairphone 6’s ultra-wide camera by porting the capture subsystem to the mainline qcom-camss driver. The implementation details hardware enablement on the Qualcomm SM7635 SoC, resolving ISP write-bus configuration mismatches, and adapting the sensor driver for ARM device trees.
The Fairphone 6 (FP6), powered by the Qualcomm Milos (SM7635) SoC, represents a viable platform for mainline Linux and postmarketOS due to active vendor contributions and its open bootloader. However, complete usability remains blocked by onboard audio and camera subsystem integration. On downstream Android kernels, imaging is handled by Qualcomm’s proprietary CAMX stack. To replicate this on a mainline kernel, developers must adapt the qcom-camss driver and the libcamera userspace framework.
Among the FP6's three cameras—a Sony IMX896 main sensor, a Samsung S5KKD1 front sensor, and an OmniVision OV13B10 ultra-wide sensor—only the OV13B10 features an existing mainline Linux driver. Though originally designed for x86/ACPI platforms, this 13 MP sensor serves as the primary target for bringing up initial capture support on the device.
Porting the SM7635 Capture Subsystem to qcom-camss
The camera hardware pipeline on the SM7635 SoC comprises a TFE665 thin-front-end ISP, a CSID665, and a CSIPHY v2.2.1. While the upstream qcom-camss driver did not support the Milos platform, analysis of downstream registers showed that the TFE665 shares identical internal logic with the supported TFE530 IP. The primary architectural difference lies in the register base offsets, where the write bus is located at 0x1800 rather than 0xa00.
To bridge this, a new camss-vfe-665.c driver was implemented, mirroring the logic of the TFE530 driver while encapsulating the offset shift. The CSID665 block successfully reused existing generation-2 CSID operations because its RDI register offsets were identical. For CSIPHY v2.2.1, a new lane-configuration table and D-PHY tuning values for the 1.1 Gbps per lane data rate were transcribed from downstream headers, mapping the register window to offset 0x1000.
Overcoming Clock Gating and Power Domain Pitfalls
Initial binding of the newly registered qcom,milos-camss platform driver resulted in a silent failure; reading the TFE hardware-version register returned 0x0, and hardware resets timed out. This issue was traced to a missing clock gate outside the immediate ISP clock tree: CAM_CC_SOC_AHB_CLK.
Without this clock, the AHB register bus servicing the entire camera complex and the Camera Control Interface (CCI) remains unpowered, causing register reads to silently fail. Incorporating CAM_CC_SOC_AHB_CLK alongside the CAMNOC AXI data-path clocks successfully initialized the ISP, returning the expected hardware version of 0x30000000.
Sensor Enablement and Devicetree Calibration
Adapting the x86-targeted OV13B10 driver for ARM required adding an OpenFirmware match table (ovti,ov13b10) to allow device tree probing. The sensor was defined on the CCI I2C bus at address 0x36, configured with a 19.2 MHz master clock (MCLK1), and tied to a reset GPIO with regulators forced active.
Two critical device tree parameters required correction. First, downstream device trees declared data lanes as 1-indexed (<1 2 3 4>), whereas mainline qcom-camss expects 0-indexed values (<0 1 2 3>). The incorrect configuration prevented the CSIPHY from establishing a proper lane mask, causing the physical layer lock to fail. Second, physical routing lines mapped the ultra-wide sensor specifically to CSIPHY1.
Resolving the 128-bit ISP Bus Packer Mismatch
While the sensor probed successfully and the CSIPHY locked onto incoming data, initial frames delivered to memory were entirely black, populated only by zeroes. The kernel log outputted a repeating "VFE0: Bad config violation" error once per frame.
The bug originated from a bus-width discrepancy between the hardware blocks. The mainline driver was designed for the TFE530, which operates on a 64-bit RDI write bus and hardcodes a packer configuration value of PLAIN64 (0xa). The TFE665 on the SM7635 platform utilizes a 128-bit RDI bus. Consequently, the write engine rejected the incoming pixel stream due to the packer mismatch. Modifying the register configuration to use packer value 0x0 resolved the violation, enabling the direct pipeline of raw Bayer frames from the sensor to system memory.
Libcamera Integration and Software ISP Pipe
To transition from raw Bayer frames to usable RGB streams, the pipeline relies on the libcamera userspace framework. The libcamera simple pipeline handler automatically detected the qcom-camss media graph. It utilized its software ISP block to debayer the stream, offloading processing to the Adreno GPU via EGL to output frames at approximately 30 frames per second.
To implement functional auto-exposure, a custom sensor helper class was compiled into libcamera's sensor database. Because the OV13B10 uses a linear analogue gain equation where 0x80 represents 1× gain, the helper defines AnalogueGainLinear { 1, 0, 0, 128 }. This mapping allows the software loop to dynamically compute and write back the appropriate gain registers, enabling functional exposure control under variable lighting conditions.