Support for OV9281 camera

I would like to use an OV9281 camera on Zero 3w. However, the official OS image only supports RaspberryPi Cameras which work on OV5647/IMX219. I wonder if recompiling the kernel will get the driver for OV9281 and the overlay. If so, could anyone gives some steps to build the kernel and get the driver?
I tried bsp and found that I can modify the kernel build config with make config, and I found the support for OV9281, but after the build, I did not find anything related to OV9281, and the config seemed to roll back to the original one without OV9281. May I ask how to config kernel with bsp?


first, you need compile the kernel with bsp in order to pull the kernel source,
then, enter the kernel source .src/linux, open the ov9281’s config with menuconfig , then copy the ov9281’s config and dependence to rk356x kconfig.conf, then compile the kernel again, finally you’ll get a kernel with ov9281 driver.

for Overlay dts, you can refer to https://github.com/radxa-pkg/radxa-overlays/blob/main/arch/arm64/boot/dts/rockchip/overlays/radxa-zero3-rpi-camera-v1.3.dts

for the usage of bsp tool, you can refer to https://docs.radxa.com/en/zero/zero3/low-level-dev/kernel

Thank you very much, but after some attempts I still can not get the camera to work.
I compiled the kernel, and tried to write the overlay file.
At first I got message like

[   15.813587] ov9281 2-0060: driver version: 00.01.05
[   15.813685] ov9281 2-0060: no pinctrl
[   15.813794] ov9281 2-0060: Looking up avdd-supply from device tree
[   15.813952] ov9281 2-0060: Looking up dovdd-supply from device tree
[   15.813999] ov9281 2-0060: Looking up dvdd-supply from device tree
[   15.816488] ov9281 2-0060: Unexpected sensor id(000000), ret(-5)

And I checked the i2c information with sudo i2cdetect -y 2 and I do get something on address 0x60 0x70.

After some modification of the overlay, I still got

[   15.203320] ov9281 2-0060: driver version: 00.01.05
[   15.203362] ov9281 2-0060: Failed to get reset-gpios
[   15.203407] ov9281 2-0060: no pinctrl
[   15.203516] ov9281 2-0060: Looking up avdd-supply from device tree
[   15.203672] ov9281 2-0060: Looking up dovdd-supply from device tree
[   15.203718] ov9281 2-0060: Looking up dvdd-supply from device tree
[   15.206100] ov9281 2-0060: Unexpected sensor id(000000), ret(-5)

And I found that the sudo i2cdetect -y 2 can no longer find the chip. Maybe I have broken my camera and I just bought a new one, together with a raspberry pi to test and make sure if any camera is working.

Could you please give some suggestions on how to debug this problem?

My final overlay file:

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rockchip.h>


/ {
	metadata {
		title = "ov9281 from 5647";
		compatible = "radxa,zero3";
		category = "camera";
		exclusive = "csi2_dphy0";
		description = "Enable ov9281 from 5647";
	};
};

&{/} {
	clk_cam_24m: external-camera-clock-24m {
		status = "okay";
		compatible = "fixed-clock";
		clock-frequency = <24000000>;
		clock-output-names = "clk_cam_24m";
		#clock-cells = <0>;
	};

		ov9281_avdd: fixedregulator_ov9281@0 {
		compatible = "regulator-fixed";
		regulator-name = "ov9281_avdd";
		regulator-min-microvolt = <2800000>;
		regulator-max-microvolt = <2800000>;
		regulator-always-on;
		regulator-boot-on;
	};

	ov9281_dovdd: fixedregulator_ov9281@1 {
		compatible = "regulator-fixed";
		regulator-name = "ov9281_dovdd";
		regulator-min-microvolt = <1800000>;
		regulator-max-microvolt = <1800000>;
		regulator-always-on;
		regulator-boot-on;
	};

	ov9281_dvdd: fixedregulator_ov9281@2 {
		compatible = "regulator-fixed";
		regulator-name = "ov9281_dvdd";
		regulator-min-microvolt = <1200000>;
		regulator-max-microvolt = <1200000>;
		regulator-always-on;
		regulator-boot-on;
	};
};

&i2c2 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&i2c2m1_xfer>;
	#address-cells = <1>;
	#size-cells = <0>;

	camera_ov9281: camera-ov9281@60 {
		status = "okay";
		compatible = "ovti,ov9281";
		reg = <0x60>;
		clocks = <&clk_cam_24m>;
		clock-names = "xvclk";
		pwdn-gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_LOW>;
		rockchip,camera-module-index = <0>;
		rockchip,camera-module-facing = "back";
		rockchip,camera-module-name = "ov9281-camera";
		rockchip,camera-module-lens-name = "default";

		avdd-supply = <&ov9281_avdd>;
		dovdd-supply = <&ov9281_dovdd>;
		dvdd-supply = <&ov9281_dvdd>;

		port {
			ucam_out0: endpoint {
				remote-endpoint = <&mipi_in_ucam0>;
				data-lanes = <1 2>;
			};
		};
	};
};

&csi2_dphy_hw {
	status = "okay";
};

&csi2_dphy0 {
	status = "okay";

	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		port@0 {
			reg = <0>;
			#address-cells = <1>;
			#size-cells = <0>;

			mipi_in_ucam0: endpoint@1 {
				reg = <1>;
				remote-endpoint = <&ucam_out0>;
				data-lanes = <1 2>;
			};
		};

		port@1 {
			reg = <1>;
			#address-cells = <1>;
			#size-cells = <0>;

			dphy0_out: endpoint@1 {
				reg = <1>;
				remote-endpoint = <&isp0_in>;
			};
		};
	};
};

&rkisp_vir0 {
	status = "okay";

	port {
		#address-cells = <1>;
		#size-cells = <0>;

		isp0_in: endpoint@0 {
			reg = <0>;
			remote-endpoint = <&dphy0_out>;
		};
	};
};

&rkisp {
	status = "okay";
};

&rkisp_mmu {
	status = "okay";
};

&rkcif_mmu {
	status = "okay";
};

&rkcif {
	status = "okay";
};

By the way, I tested with OV5647 cameras and they work fine. So the problem should be the driver/overlay/OV9281camera

The i2c address may need to be shifted one position to the right, please try this:


reg = <0x30>;


I checked the datasheet of OV9281 and <0x60> is the right shift of <0xC0>

The OV9281 responds to two SCCB ID set by register SC_SCCB_ID1 (default 0xC0) and SC_SCCB_ID2 (default 0xE0).
One of them can be used as a broadcasting ID and the other one can be programmed to a unique ID.

Did you try the other register 0xE0 ? Then right shit one is 0x70.

I tried <0x60> and <0x70>, it seems to be no difference.
I also tried to hack the driver source code, as I found the error message is coming from


	ret = ov9281_read_reg(client, OV9281_REG_CHIP_ID,
			      OV9281_REG_VALUE_16BIT, &id);
	if (id != CHIP_ID) {
		dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);
		return -ENODEV;
	}

the ret is always -5, even if I do not connect any camera physically. I assume that these code might not work well so I deleted them.

Now I can get the following information

radxa@radxa-zero3 ~> sudo dmesg | grep ov9
[   12.361208] ov9281_dvdd: 1200 mV, enabled
[   12.361521] reg-fixed-voltage fixedregulator_ov9281@2: ov9281_dvdd supplying 1200000uV
[   12.361731] ov9281_dovdd: 1800 mV, enabled
[   12.362035] reg-fixed-voltage fixedregulator_ov9281@1: ov9281_dovdd supplying 1800000uV
[   12.362249] ov9281_avdd: 2800 mV, enabled
[   12.362504] reg-fixed-voltage fixedregulator_ov9281@0: ov9281_avdd supplying 2800000uV
[   14.572165] ov9281 2-0060: driver version: 00.01.05
[   14.572230] ov9281 2-0060: Failed to get reset-gpios
[   14.572282] ov9281 2-0060: no pinctrl
[   14.572388] ov9281 2-0060: Looking up avdd-supply from device tree
[   14.572588] ov9281 2-0060: Looking up dovdd-supply from device tree
[   14.572707] ov9281 2-0060: Looking up dvdd-supply from device tree
[   14.575372] ov9281 2-0060: Detected OV009281 sensor
[   14.575433] rockchip-csi2-dphy csi2-dphy0: dphy0 matches m00_b_ov9281 2-0060:bus type 5

How ever when I tried to capture someting I got error

radxa@radxa-zero3 ~/pyopencv [1]> gst-launch-1.0 v4l2src device=/dev/video0 io-mode=4 ! videoconvert ! video/x-raw,format=NV12,width=1280,height=800 ! jpegenc ! multifilesink location=/home/radxa/test.jpg
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
ERROR: from element /GstPipeline:pipeline0/GstV4l2Src:v4l2src0: Failed to allocate required memory.
Additional debug info:
../sys/v4l2/gstv4l2src.c(700): gst_v4l2src_decide_allocation (): /GstPipeline:pipeline0/GstV4l2Src:v4l2src0:
Buffer pool activation failed
Execution ended after 0:00:00.017532707
ERROR: from element /GstPipeline:pipeline0/GstV4l2Src:v4l2src0: Internal data stream error.
Setting pipeline to NULL ...
Additional debug info:
../libs/gst/base/gstbasesrc.c(3127): gst_base_src_loop (): /GstPipeline:pipeline0/GstV4l2Src:v4l2src0:
streaming stopped, reason not-negotiated (-4)
Freeing pipeline ...

I guess there must be something wrong with the i2c
I added some printing debug and found that

[   55.275992] ov9281 debug: enter __ov9281_start_stream
[   55.276191] ov9281 debug: ret of ov9281_write_array: -5
[   55.276198] m00_b_ov9281 2-0060: start stream failed while write regs
[  140.761336] ov9281 debug: enter __ov9281_start_stream
[  140.761561] ov9281 debug: ret of ov9281_write_array: -5
[  140.761568] m00_b_ov9281 2-0060: start stream failed while write regs

where -5 should come from the error code #define EIO 5 /* I/O error */

any idea?

Add the reset-gpios attribute under the ov9281 node and let’s see the error later.