The STM32MP15 processor provides a Digital Camera Memory Interface (DCMI). The ConnectCore MP15 Development Kit supports a parallel camera via a connector composed of an 8-bit data line bus, a master clock, three synchronization signals (PIXCLK, HSYNC, and VSYNC), two GPIO control signals, and the I2C2 bus.

The BSP includes support for the Omnivision ov5640 CSI camera model.

Kernel configuration

You can manage the DCMI driver support and Video4Linux (V4L2) capture driver through the following kernel configuration options:

  • STM32 Digital Camera Memory Interface (DCMI) support (CONFIG_VIDEO_STM32_DCMI)

  • OmniVision ov5640 camera support (CONFIG_VIDEO_OV5640)

These options are enabled as built-in on the default ConnectCore MP15 kernel configuration file.

Kernel driver

The drivers for Digital Camera Memory Interface (DCMI) are located at:

File Description

drivers/media/platform/stm32/stm32-dcmi.c

STM32 Digital Camera Memory Interface (DCMI) driver

drivers/media/i2c/ov5640.c

Omnivision OV5640 sensor driver

Device tree bindings and customization

Common bindings for video receiver and transmitter interfaces are described at Documentation/devicetree/bindings/media/video-interfaces.yaml.

The device tree must contain entries for:

  • The V4L2 capture interface

  • The camera sensor

  • The IOMUX

V4L2 capture interface (DCMI)

ConnectCore MP15 Development Kit device tree
&dcmi {
	status = "okay";
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&ccmp15_dcmi_pins_a>;
	pinctrl-1 = <&ccmp15_dcmi_sleep_pins_a>;

	port {
		dcmi_0: endpoint {
			remote-endpoint = <&ov5640_0>;
			bus-type = <5>;
			bus-width = <8>;
			hsync-active = <0>;
			vsync-active = <0>;
			pclk-sample = <1>;
			pclk-max-frequency = <77000000>;
		};
	};
};

Camera sensor (I2C2 slave)

ConnectCore MP15 Development Kit device tree
&i2c2 {
...
	ov5640: camera@3c {
		compatible = "ovti,ov5640";
		reg = <0x3c>;
		clocks = <&clk_ext_camera>;
		clock-names = "xclk";
		DOVDD-supply = <&v2v8>;
		powerdown-gpios = <&gpioe 5 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
		reset-gpios = <&gpioe 0 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
		rotation = <180>;
		status = "okay";

		port {
			ov5640_0: endpoint {
				remote-endpoint = <&dcmi_0>;
				bus-width = <8>;
				data-shift = <2>; /* lines 9:2 are used */
				hsync-active = <0>;
				vsync-active = <0>;
				pclk-sample = <1>;
				pclk-max-frequency = <77000000>;
			};
		};
	};
...
};

PinCtrl configuration

ConnectCore MP15 Development Kit device tree
&pinctrl {
	ccmp15_dcmi_pins_a: dcmi-0 {
		pins {
			pinmux = <STM32_PINMUX('D', 9,  AF13)>,/* DCMI_HSYNC */
				 <STM32_PINMUX('B', 7,  AF13)>,/* DCMI_VSYNC */
				 <STM32_PINMUX('A', 6,  AF13)>,/* DCMI_PIXCLK */
				 <STM32_PINMUX('H', 9,  AF13)>,/* DCMI_D0 */
				 <STM32_PINMUX('H', 10, AF13)>,/* DCMI_D1 */
				 <STM32_PINMUX('H', 11, AF13)>,/* DCMI_D2 */
				 <STM32_PINMUX('E',  1, AF13)>,/* DCMI_D3 */
				 <STM32_PINMUX('H', 14, AF13)>,/* DCMI_D4 */
				 <STM32_PINMUX('D', 3,  AF13)>,/* DCMI_D5 */
				 <STM32_PINMUX('B', 8,  AF13)>,/* DCMI_D6 */
				 <STM32_PINMUX('B', 9,  AF13)>;/* DCMI_D7 */
			bias-disable;
		};
	};

	ccmp15_dcmi_sleep_pins_a: dcmi-sleep-0 {
		pins {
			pinmux = <STM32_PINMUX('H', 8,  ANALOG)>,/* DCMI_HSYNC */
				 <STM32_PINMUX('B', 7,  ANALOG)>,/* DCMI_VSYNC */
				 <STM32_PINMUX('A', 6,  ANALOG)>,/* DCMI_PIXCLK */
				 <STM32_PINMUX('H', 9,  ANALOG)>,/* DCMI_D0 */
				 <STM32_PINMUX('H', 10, ANALOG)>,/* DCMI_D1 */
				 <STM32_PINMUX('H', 11, ANALOG)>,/* DCMI_D2 */
				 <STM32_PINMUX('E',  1, ANALOG)>,/* DCMI_D3 */
				 <STM32_PINMUX('H', 14, ANALOG)>,/* DCMI_D4 */
				 <STM32_PINMUX('D', 3,  ANALOG)>,/* DCMI_D5 */
				 <STM32_PINMUX('B', 8,  ANALOG)>,/* DCMI_D6 */
				 <STM32_PINMUX('B', 9,  ANALOG)>;/* DCMI_D7 */
		};
	};
};

Using the camera

There is a mismatch between the camera connector on the ConnectCore MP15 Development Kit and the connector of the camera. You need to connect pin 30 of the camera to pin 1 of the camera connector.

Identify the camera

When the camera is connected to the ConnectCore MP15 Development Kit and it has been enabled in the device tree, the system identifies the camera sensor on the I2C bus and assigns it a video device node /dev/videoX where X is an integer number.

Preview a camera image using gstreamer

Capture the camera image and preview it using gstreamer:

# gst-launch-1.0 v4l2src ! 'video/x-raw, width=640, height=480, framerate=(fraction)30/1' ! queue ! autovideosink -e

Take a picture with the camera using gstreamer

To capture a still image with the camera and save it using gstreamer:

# v4l2-ctl --set-parm=15; v4l2-ctl --set-fmt-video=width=640,height=480,pixelformat=JPEG --stream-mmap --stream-count=1 --stream-skip=3 --stream-to=pic-5Mp.jpeg; v4l2-ctl --set-parm=30
# weston-image pic-5Mp.jpeg

Record a video with the camera using gstreamer

To record a video with the camera and save it using gstreamer:

# v4l2-ctl --set-parm=15;v4l2-ctl --set-fmt-video=width=640,height=480,pixelformat=JPEG --stream-mmap --stream-count=100 --stream-to=pics@15fps.jpeg

You can play the recorded video back with:

# gst-play-1.0 pics@15fps.jpeg --videosink='videorate ! video/x-raw, framerate=(fraction)15/1 ! autovideosink'