Skip to content
Digital Rhyme

IMX708 V4L2 Camera Sensor Driver

A map of the Sony IMX708 out-of-tree kernel module: the ordinary Linux driver pieces, the V4L2/media-controller pieces, the Raspberry Pi device-tree overlay, and the build/install path for the .ko and .dtbo.

Camera sensor module and CSI ribbon cable with abstract media-pipeline overlays

Big Picture

imx708.c is a Linux kernel driver for the Sony IMX708 camera sensor, used by Raspberry Pi Camera Module 3 style hardware. It is an I2C driver that registers a V4L2 sub-device, programs sensor registers, exposes camera controls, and lets a CSI-2 receiver capture the image stream.

The module itself does not create a normal user-facing /dev/video0 capture device. It creates the sensor side of a media graph. A platform CSI receiver driver, such as Raspberry Pi Unicam, binds to the other side of the graph and becomes the capture device.

The short version: ordinary Linux driver code discovers, powers, and talks to the chip. V4L2 code describes the camera stream, controls, formats, pads, and media graph.

Ordinary Linux Kernel Driver Parts

These parts would look familiar in many non-camera kernel drivers:

The ordinary kernel skeleton gives Linux a way to instantiate the device, allocate private state, claim hardware resources, and cleanly unload the module. None of that is camera-specific. A temperature sensor, EEPROM, or GPIO expander would also have a match table, probe function, remove function, I2C transfers, clocks, regulators, and power-management callbacks.

Parts Specific to V4L2 and Media Controller

The V4L2-specific layer makes the chip visible as a camera sensor entity, not merely as an I2C peripheral. The main state object, struct imx708, embeds struct v4l2_subdev, two media pads, a V4L2 control handler, and current media-bus format state.

A camera sensor is only one entity in a capture pipeline. The V4L2 media controller model describes that pipeline as connected entities: sensor, optional lens/VCM, CSI-2 receiver, ISP, scaler, and video node. This driver registers the IMX708 as a v4l2_subdev because the sensor is controlled by V4L2 but does not itself DMA frames into memory.

  • Sub-device operations are collected in imx708_subdev_ops. The video op starts and stops streaming; pad ops enumerate formats, set formats, report frame sizes, and expose crop/native-size selection.
  • Media pads are initialized in probe as two source pads: IMAGE_PAD for Bayer pixels and METADATA_PAD for embedded sensor data.
  • Controls are created in imx708_init_controls(): pixel rate, link frequency, blanking, exposure, analog/digital gain, flips, test pattern, color balance notification, and wide dynamic range.
  • Streaming is V4L2-driven. When userspace enables the pipeline, imx708_set_stream() powers the device and calls imx708_start_streaming(), which writes common registers, the selected mode table, link-frequency registers, user controls, and finally IMX708_REG_MODE_SELECT.
  • Hardware graph parsing is done by imx708_check_hwcfg(). It reads the firmware endpoint as CSI-2 D-PHY, checks that the lane count is 2 or 4, and accepts only link frequencies listed by the driver.

Why V4L2 Needs All These Functions

V4L2 separates camera control into several smaller contracts because each part of a camera pipeline has different responsibilities. The sensor driver must answer questions from the capture driver and from userspace before streaming starts, then must program the chip consistently when the final format and controls are chosen.

  • enum_mbus_code tells the pipeline which wire formats the sensor can output. For this driver the image pad exposes 10-bit Bayer orders such as MEDIA_BUS_FMT_SRGGB10_1X10; the metadata pad exposes MEDIA_BUS_FMT_SENSOR_DATA.
  • enum_frame_size reports the supported sizes for a given media bus code. Without this, the receiver and userspace would not know that 4608x2592, 2304x1296, and 1536x864 are the meaningful choices.
  • get_fmt and set_fmt implement negotiation. The caller asks for a format; the sensor driver chooses the nearest supported mode, stores it as active state, and updates blanking/exposure limits.
  • get_selection explains crop geometry. The driver can report native sensor size, active pixel-array bounds, default crop, and the crop rectangle used by the current mode.
  • s_stream is the decisive start/stop callback. It is where the V4L2 pipeline says "now the links are configured; actually start sending CSI-2 packets."
  • v4l2_ctrl_handler gives userspace a standard control API for exposure, gain, blanking, flips, HDR, test patterns, and link frequency. The callback imx708_set_ctrl() translates those generic V4L2 controls into IMX708 register writes.

This is why the driver has both abstract V4L2 functions and concrete I2C writes. V4L2 speaks in formats, pads, controls, crops, and streams; the sensor understands register addresses and values. The driver is the translator.

Sensor Modes

Most of the C file is sensor knowledge: register tables and mode metadata. The driver supports 10-bit Bayer output with non-HDR and HDR tables.

4608 x 2592 full resolution
2304 x 1296 2x2 binned
1536 x 864 cropped/binning mode
2304 x 1296 HDR mode

Each struct imx708_mode records dimensions, crop rectangle, line length, vertical blanking, pixel rate, exposure rules, and whether the mode is HDR or full-resolution Quad Bayer re-mosaic. The mode arrays start at supported_modes_10bit_no_hdr and supported_modes_10bit_hdr.

I2C Registers, Addresses, and Meaning

The IMX708 is configured by writing 16-bit register addresses over I2C. The helper imx708_write_reg() sends the high byte and low byte of the address, followed by one or two data bytes. The mode tables are long lists of these address/value pairs.

Address Driver symbol Meaning in this driver
0x0016 IMX708_REG_CHIP_ID Read during probe. The expected 16-bit value is 0x0708.
0x0000 module ID read Read after chip ID. The value is used to label wide/noir variants in the subdevice name.
0x0100 IMX708_REG_MODE_SELECT 0x00 puts the sensor in standby; 0x01 starts streaming.
0x0101 IMX708_REG_ORIENTATION Horizontal and vertical flip bits. The driver also changes Bayer order to match flips.
0x0340 IMX708_REG_FRAME_LENGTH Frame length in lines. V4L2 vertical blanking updates this value.
0x0342 IMX708_REG_LINE_LENGTH Line length in pixels/clocks. V4L2 horizontal blanking writes this timing value.
0x0202 IMX708_REG_EXPOSURE Main exposure/coarse integration time. In HDR mode it represents the longest exposure.
0x0204 IMX708_REG_ANALOG_GAIN Main analog gain. In HDR mode it is the gain for the longest exposure.
0x020e IMX708_REG_DIGITAL_GAIN Digital gain, written from V4L2_CID_DIGITAL_GAIN.
0x0224, 0x3116 IMX708_REG_SHT_EXPOSURE, IMX708_REG_MID_EXPOSURE Short and middle exposure registers used by the HDR mode tables.
0x0216, 0x3118 IMX708_REG_SHT_ANALOG_GAIN, IMX708_REG_MID_ANALOG_GAIN Short and middle analog gain registers used with HDR exposure ratios.
0x0600 IMX708_REG_TEST_PATTERN Enables disabled, color bars, solid color, grey bars, or PN9 test patterns.
0x0602-0x0608 test pattern colors Red, green-red, blue, and green-blue test-pattern color components.
0x0b90, 0x0b92 red/blue color balance Written by the custom V4L2_CID_NOTIFY_GAINS control.
0x3100 IMX708_LONG_EXP_SHIFT_REG Long-exposure shift value used when frame length must exceed a 16-bit register.
0x7b10, 0x7c00 PDAF gain bases Base addresses for left/right phase-detect autofocus correction gains.
0xc428, 0xc429 QBC correction Enable and strength for Quad Bayer broken-line correction in full-resolution mode.

The huge mode tables include many additional Sony-specific PLL, crop, binning, CSI output, and image-processing registers. The driver treats those as known-good recipes: choose a mode, write the table, then apply the current V4L2 controls on top.

How the Driver Gets the Sensor ID

The sensor ID path is imx708_identify_module(). Probe powers the sensor first because the ID register cannot be read while the chip is off. Then the driver reads register 0x0016 as a 16-bit value and compares it with 0x0708.

ret = imx708_read_reg(imx708, IMX708_REG_CHIP_ID,
                      IMX708_REG_VALUE_16BIT, &val);
if (val != IMX708_CHIP_ID)
        return -EIO;

The low-level read uses a two-message I2C transaction. First it writes the 16-bit register address, then it performs an I2C read for the requested number of bytes. For the chip ID, the address bytes are 0x00 and 0x16, and the driver expects the returned data to decode as 0x0708.

After that, the driver also reads 0x0000. This is not the main chip ID check. It is used as a camera module ID; the code logs it and uses bits in that value to append _wide and _noir to the V4L2 sub-device name.

From a running Linux system, the normal way to see this is through kernel logs, because the driver reads the ID during probe:

dmesg | grep -i imx708

To read it manually with I2C tools, the overlay must already have powered the camera rail and selected the correct camera I2C bus. The sensor address is 0x1a. On the correct bus, a 16-bit-address register read would conceptually target register 0x0016; the exact command depends on whether your I2C utility supports 16-bit register addresses. If the kernel driver is bound, unbind it or avoid manual probing while the camera stack is active.

Device Tree Parts

The overlay is split into imx708-overlay.dts and the included imx708.dtsi. The overlay connects Raspberry Pi board symbols to the sensor node and CSI receiver. The included DTSI describes the actual sensor and focus motor.

  • imx708@1a creates an I2C device at address 0x1a with compatible = "sony,imx708".
  • clock-names = "inclk" matches the driver's devm_clk_get(dev, "inclk") call.
  • The supply names vana1, vana2, vdig, and vddl match the driver's regulator list.
  • The sensor endpoint declares CSI-2 wiring: data-lanes = <1 2 3 4> and link-frequencies = 450000000.
  • fragment@101 enables the CSI receiver endpoint and connects it back to cam_endpoint with remote-endpoint.
  • __overrides__ provides Raspberry Pi overlay parameters such as cam0, rotation, orientation, vcm, and link-frequency.
The C driver validates lane count and link frequency, so the device tree is part of driver configuration, not just hardware description.

Build and Install

The repository Makefile builds the kernel object against the running kernel headers and has a rule for compiling the overlay.

sudo apt install raspberrypi-kernel-headers build-essential device-tree-compiler dkms
cd imx708-v4l2-driver-4lane_dkms
make
make imx708-overlay.dtbo

After a successful build, the important outputs are normally:

  • imx708.ko: the loadable kernel module.
  • imx708-overlay.dtbo: the compiled Raspberry Pi overlay blob.

Install the module into the current kernel's extra modules directory, install the overlay into Raspberry Pi's overlay directory, then refresh module dependency metadata.

sudo install -D -m 644 imx708.ko /lib/modules/$(uname -r)/extra/imx708.ko
sudo depmod -a
sudo install -m 644 imx708-overlay.dtbo /boot/overlays/imx708.dtbo

On some newer Raspberry Pi OS images the firmware partition is mounted at /boot/firmware. In that case, install the overlay here instead:

sudo install -m 644 imx708-overlay.dtbo /boot/firmware/overlays/imx708.dtbo

Enable the overlay in the boot config. The usual Raspberry Pi pattern is:

camera_auto_detect=0
dtoverlay=imx708

If the module should be managed by DKMS, the existing dkms.conf builds imx708.ko and runs dkms.postinst, which compiles and installs imx708.dtbo.

Runtime Checks

After rebooting with the overlay enabled, confirm that the module and media graph are present:

lsmod | grep imx708
dmesg | grep -i imx708
media-ctl -p
v4l2-ctl --list-devices

If probe fails, the first places to check are the I2C address, the 24 MHz inclk, regulator names, lane count, and link frequency. Those are exactly the properties that imx708_probe() and imx708_check_hwcfg() require before the V4L2 sub-device is registered.