<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">From 7f67a45ee7c008c3d8e45fde6fa9c4287fb3bc9e Mon Sep 17 00:00:00 2001
From: Jacopo Mondi &lt;jacopo.mondi@ideasonboard.com&gt;
Date: Thu, 20 Jul 2023 13:18:34 +0200
Subject: [PATCH] overlays: Add overlay for the OV64A40 Arducam Camera Module

Arducam have integrated an Omnivision OV64A40 with a ROHM BU64754 VCM
with a Raspberry Pi compatible cable pinout.

Provide an overlay to support the module.

Also add support to the camera mux overlays.

Signed-off-by: Jacopo Mondi &lt;jacopo.mondi@ideasonboard.com&gt;
Signed-off-by: Kieran Bingham &lt;kieran.bingham@ideasonboard.com&gt;
---
 arch/arm/boot/dts/overlays/Makefile           |  1 +
 arch/arm/boot/dts/overlays/README             | 25 +++++
 .../dts/overlays/camera-mux-2port-overlay.dts | 32 +++++++
 .../dts/overlays/camera-mux-4port-overlay.dts | 64 +++++++++++++
 .../arm/boot/dts/overlays/ov64a40-overlay.dts | 91 +++++++++++++++++++
 arch/arm/boot/dts/overlays/ov64a40.dtsi       | 34 +++++++
 6 files changed, 247 insertions(+)
 create mode 100644 arch/arm/boot/dts/overlays/ov64a40-overlay.dts
 create mode 100644 arch/arm/boot/dts/overlays/ov64a40.dtsi

--- a/arch/arm/boot/dts/overlays/Makefile
+++ b/arch/arm/boot/dts/overlays/Makefile
@@ -175,6 +175,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
 	mz61581.dtbo \
 	ov2311.dtbo \
 	ov5647.dtbo \
+	ov64a40.dtbo \
 	ov7251.dtbo \
 	ov9281.dtbo \
 	papirus.dtbo \
--- a/arch/arm/boot/dts/overlays/README
+++ b/arch/arm/boot/dts/overlays/README
@@ -817,6 +817,7 @@ Params: cam0-arducam-64mp       Select A
         cam0-imx708             Select IMX708 for camera on port 0
         cam0-ov2311             Select OV2311 for camera on port 0
         cam0-ov5647             Select OV5647 for camera on port 0
+        cam0-ov64a40            Select OV64A40 for camera on port 0
         cam0-ov7251             Select OV7251 for camera on port 0
         cam0-ov9281             Select OV9281 for camera on port 0
         cam0-imx290-clk-freq    Set clock frequency for an IMX290 on port 0
@@ -829,6 +830,7 @@ Params: cam0-arducam-64mp       Select A
         cam1-imx708             Select IMX708 for camera on port 1
         cam1-ov2311             Select OV2311 for camera on port 1
         cam1-ov5647             Select OV5647 for camera on port 1
+        cam1-ov64a40            Select OV64A40 for camera on port 1
         cam1-ov7251             Select OV7251 for camera on port 1
         cam1-ov9281             Select OV9281 for camera on port 1
         cam1-imx290-clk-freq    Set clock frequency for an IMX290 on port 1
@@ -850,6 +852,7 @@ Params: cam0-arducam-64mp       Select A
         cam0-imx708             Select IMX708 for camera on port 0
         cam0-ov2311             Select OV2311 for camera on port 0
         cam0-ov5647             Select OV5647 for camera on port 0
+        cam0-ov64a40            Select OV64A40 for camera on port 0
         cam0-ov7251             Select OV7251 for camera on port 0
         cam0-ov9281             Select OV9281 for camera on port 0
         cam0-imx290-clk-freq    Set clock frequency for an IMX290 on port 0
@@ -862,6 +865,7 @@ Params: cam0-arducam-64mp       Select A
         cam1-imx708             Select IMX708 for camera on port 1
         cam1-ov2311             Select OV2311 for camera on port 1
         cam1-ov5647             Select OV5647 for camera on port 1
+        cam1-ov64a40            Select OV64A40 for camera on port 1
         cam1-ov7251             Select OV7251 for camera on port 1
         cam1-ov9281             Select OV9281 for camera on port 1
         cam1-imx290-clk-freq    Set clock frequency for an IMX290 on port 1
@@ -874,6 +878,7 @@ Params: cam0-arducam-64mp       Select A
         cam2-imx708             Select IMX708 for camera on port 2
         cam2-ov2311             Select OV2311 for camera on port 2
         cam2-ov5647             Select OV5647 for camera on port 2
+        cam2-ov64a40            Select OV64A40 for camera on port 2
         cam2-ov7251             Select OV7251 for camera on port 2
         cam2-ov9281             Select OV9281 for camera on port 2
         cam2-imx290-clk-freq    Set clock frequency for an IMX290 on port 2
@@ -886,6 +891,7 @@ Params: cam0-arducam-64mp       Select A
         cam3-imx708             Select IMX708 for camera on port 3
         cam3-ov2311             Select OV2311 for camera on port 3
         cam3-ov5647             Select OV5647 for camera on port 3
+        cam3-ov64a40            Select OV64A40 for camera on port 3
         cam3-ov7251             Select OV7251 for camera on port 3
         cam3-ov9281             Select OV9281 for camera on port 3
         cam3-imx290-clk-freq    Set clock frequency for an IMX290 on port 3
@@ -3222,6 +3228,25 @@ Params: rotation                Mounting
         vcm                     Configure a VCM focus drive on the sensor.
 
 
+Name:   ov64a40
+Info:   Arducam OV64A40 camera module.
+        Uses Unicam 1, which is the standard camera connector on most Pi
+        variants.
+Load:   dtoverlay=ov64a40,&lt;param&gt;=&lt;val&gt;
+Params: rotation                Mounting rotation of the camera sensor (0 or
+                                180, default 0)
+        orientation             Sensor orientation (0 = front, 1 = rear,
+                                2 = external, default external)
+        media-controller        Configure use of Media Controller API for
+                                configuring the sensor (default on)
+        cam0                    Adopt the default configuration for CAM0 on a
+                                Compute Module (CSI0, i2c_vc, and cam0_reg).
+        vcm                     Select lens driver state. Default is enabled,
+                                but vcm=off will disable.
+        link-frequency          Allowable link frequency values to use in Hz:
+                                456000000 (default), 360000000
+
+
 Name:   ov7251
 Info:   Omnivision OV7251 camera module.
         Uses Unicam 1, which is the standard camera connector on most Pi
--- a/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts
+++ b/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts
@@ -189,6 +189,16 @@
 					#undef cam_node
 					#undef cam_endpoint
 					#undef cam1_clk
+
+					#define cam_node ov64a40_0
+					#define cam_endpoint ov64a40_0_ep
+					#define vcm_node ov64a40_0_vcm
+					#define cam1_clk clk_24mhz
+					#include "ov64a40.dtsi"
+					#undef cam_node
+					#undef cam_endpoint
+					#undef vcm_node
+					#undef cam1_clk
 				};
 
 				i2c@1 {
@@ -289,6 +299,16 @@
 					#undef cam_node
 					#undef cam_endpoint
 					#undef cam1_clk
+
+					#define cam_node ov64a40_1
+					#define cam_endpoint ov64a40_1_ep
+					#define vcm_node ov64a40_1_vcm
+					#define cam1_clk clk_24mhz
+					#include "ov64a40.dtsi"
+					#undef cam_node
+					#undef cam_endpoint
+					#undef vcm_node
+					#undef cam1_clk
 				};
 			};
 		};
@@ -450,6 +470,12 @@
 		cam0-ov2311 = &lt;&amp;mux_in0&gt;, "remote-endpoint:0=",&lt;&amp;ov2311_0_ep&gt;,
 			      &lt;&amp;ov2311_0_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in0&gt;,
 			      &lt;&amp;ov2311_0&gt;, "status=okay";
+		cam0-ov64a40 = &lt;&amp;mux_in0&gt;, "remote-endpoint:0=",&lt;&amp;ov64a40_0_ep&gt;,
+			      &lt;&amp;ov64a40_0_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in0&gt;,
+			      &lt;&amp;mux_in0&gt;, "clock-noncontinuous?",
+			      &lt;&amp;ov64a40_0&gt;, "status=okay",
+			      &lt;&amp;ov64a40_0_vcm&gt;, "status=okay",
+			      &lt;&amp;ov64a40_0&gt;,"lens-focus:0=", &lt;&amp;ov64a40_0_vcm&gt;;
 
 		cam1-arducam-64mp = &lt;&amp;mux_in1&gt;, "remote-endpoint:0=",&lt;&amp;arducam_64mp_1_ep&gt;,
 				    &lt;&amp;arducam_64mp_1_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in1&gt;,
@@ -496,6 +522,12 @@
 		cam1-ov2311 = &lt;&amp;mux_in1&gt;, "remote-endpoint:0=",&lt;&amp;ov2311_1_ep&gt;,
 			      &lt;&amp;ov2311_1_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in1&gt;,
 			      &lt;&amp;ov2311_1&gt;, "status=okay";
+		cam1-ov64a40 = &lt;&amp;mux_in1&gt;, "remote-endpoint:0=",&lt;&amp;ov64a40_1_ep&gt;,
+			      &lt;&amp;ov64a40_1_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in1&gt;,
+			      &lt;&amp;mux_in1&gt;, "clock-noncontinuous?",
+			      &lt;&amp;ov64a40_1&gt;, "status=okay",
+			      &lt;&amp;ov64a40_1_vcm&gt;, "status=okay",
+			      &lt;&amp;ov64a40_1&gt;,"lens-focus:0=", &lt;&amp;ov64a40_1_vcm&gt;;
 
 		cam0-imx290-clk-freq = &lt;&amp;clk_imx290&gt;,"clock-frequency:0",
 				       &lt;&amp;imx290_0&gt;,"clock-frequency:0";
--- a/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts
+++ b/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts
@@ -247,6 +247,16 @@
 					#undef cam_node
 					#undef cam_endpoint
 					#undef cam1_clk
+
+					#define cam_node ov64a40_0
+					#define cam_endpoint ov64a40_0_ep
+					#define vcm_node ov64a40_0_vcm
+					#define cam1_clk clk_24mhz
+					#include "ov64a40.dtsi"
+					#undef cam_node
+					#undef cam_endpoint
+					#undef vcm_node
+					#undef cam1_clk
 				};
 
 				i2c@1 {
@@ -347,6 +357,16 @@
 					#undef cam_node
 					#undef cam_endpoint
 					#undef cam1_clk
+
+					#define cam_node ov64a40_1
+					#define cam_endpoint ov64a40_1_ep
+					#define vcm_node ov64a40_1_vcm
+					#define cam1_clk clk_24mhz
+					#include "ov64a40.dtsi"
+					#undef cam_node
+					#undef cam_endpoint
+					#undef vcm_node
+					#undef cam1_clk
 				};
 
 				i2c@2 {
@@ -447,6 +467,16 @@
 					#undef cam_node
 					#undef cam_endpoint
 					#undef cam1_clk
+
+					#define cam_node ov64a40_2
+					#define cam_endpoint ov64a40_2_ep
+					#define vcm_node ov64a40_2_vcm
+					#define cam1_clk clk_24mhz
+					#include "ov64a40.dtsi"
+					#undef cam_node
+					#undef cam_endpoint
+					#undef vcm_node
+					#undef cam1_clk
 				};
 
 				i2c@3 {
@@ -547,6 +577,16 @@
 					#undef cam_node
 					#undef cam_endpoint
 					#undef cam1_clk
+
+					#define cam_node ov64a40_3
+					#define cam_endpoint ov64a40_3_ep
+					#define vcm_node ov64a40_3_vcm
+					#define cam1_clk clk_24mhz
+					#include "ov64a40.dtsi"
+					#undef cam_node
+					#undef cam_endpoint
+					#undef vcm_node
+					#undef cam1_clk
 				};
 			};
 		};
@@ -725,6 +765,12 @@
 		cam0-ov2311 = &lt;&amp;mux_in0&gt;, "remote-endpoint:0=",&lt;&amp;ov2311_0_ep&gt;,
 			      &lt;&amp;ov2311_0_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in0&gt;,
 			      &lt;&amp;ov2311_0&gt;, "status=okay";
+		cam0-ov64a40 = &lt;&amp;mux_in0&gt;, "remote-endpoint:0=",&lt;&amp;ov64a40_0_ep&gt;,
+			      &lt;&amp;ov64a40_0_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in0&gt;,
+			      &lt;&amp;mux_in0&gt;, "clock-noncontinuous?",
+			      &lt;&amp;ov64a40_0&gt;, "status=okay",
+			      &lt;&amp;ov64a40_0_vcm&gt;, "status=okay",
+			      &lt;&amp;ov64a40_0&gt;,"lens-focus:0=", &lt;&amp;ov64a40_0_vcm&gt;;
 
 		cam1-arducam-64mp = &lt;&amp;mux_in1&gt;, "remote-endpoint:0=",&lt;&amp;arducam_64mp_1_ep&gt;,
 				    &lt;&amp;arducam_64mp_1_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in1&gt;,
@@ -771,6 +817,12 @@
 		cam1-ov2311 = &lt;&amp;mux_in1&gt;, "remote-endpoint:0=",&lt;&amp;ov2311_1_ep&gt;,
 			      &lt;&amp;ov2311_1_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in1&gt;,
 			      &lt;&amp;ov2311_1&gt;, "status=okay";
+		cam1-ov64a40 = &lt;&amp;mux_in1&gt;, "remote-endpoint:0=",&lt;&amp;ov64a40_1_ep&gt;,
+			      &lt;&amp;ov64a40_1_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in1&gt;,
+			      &lt;&amp;mux_in1&gt;, "clock-noncontinuous?",
+			      &lt;&amp;ov64a40_1&gt;, "status=okay",
+			      &lt;&amp;ov64a40_1_vcm&gt;, "status=okay",
+			      &lt;&amp;ov64a40_1&gt;,"lens-focus:0=", &lt;&amp;ov64a40_1_vcm&gt;;
 
 		cam2-arducam-64mp = &lt;&amp;mux_in2&gt;, "remote-endpoint:0=",&lt;&amp;arducam_64mp_2_ep&gt;,
 				    &lt;&amp;arducam_64mp_2_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in2&gt;,
@@ -817,6 +869,12 @@
 		cam2-ov2311 = &lt;&amp;mux_in2&gt;, "remote-endpoint:0=",&lt;&amp;ov2311_2_ep&gt;,
 			      &lt;&amp;ov2311_2_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in2&gt;,
 			      &lt;&amp;ov2311_2&gt;, "status=okay";
+		cam2-ov64a40 = &lt;&amp;mux_in2&gt;, "remote-endpoint:0=",&lt;&amp;ov64a40_2_ep&gt;,
+			      &lt;&amp;ov64a40_2_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in2&gt;,
+			      &lt;&amp;mux_in2&gt;, "clock-noncontinuous?",
+			      &lt;&amp;ov64a40_2&gt;, "status=okay",
+			      &lt;&amp;ov64a40_2_vcm&gt;, "status=okay",
+			      &lt;&amp;ov64a40_2&gt;,"lens-focus:0=", &lt;&amp;ov64a40_2_vcm&gt;;
 
 		cam3-arducam-64mp = &lt;&amp;mux_in3&gt;, "remote-endpoint:0=",&lt;&amp;arducam_64mp_3_ep&gt;,
 				    &lt;&amp;arducam_64mp_3_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in3&gt;,
@@ -863,6 +921,12 @@
 		cam3-ov2311 = &lt;&amp;mux_in3&gt;, "remote-endpoint:0=",&lt;&amp;ov2311_3_ep&gt;,
 			      &lt;&amp;ov2311_3_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in3&gt;,
 			      &lt;&amp;ov2311_3&gt;, "status=okay";
+		cam3-ov64a40 = &lt;&amp;mux_in3&gt;, "remote-endpoint:0=",&lt;&amp;ov64a40_3_ep&gt;,
+			      &lt;&amp;ov64a40_3_ep&gt;, "remote-endpoint:0=",&lt;&amp;mux_in3&gt;,
+			      &lt;&amp;mux_in3&gt;, "clock-noncontinuous?",
+			      &lt;&amp;ov64a40_3&gt;, "status=okay",
+			      &lt;&amp;ov64a40_3_vcm&gt;, "status=okay",
+			      &lt;&amp;ov64a40_3&gt;,"lens-focus:0=", &lt;&amp;ov64a40_3_vcm&gt;;
 
 		cam0-imx290-clk-freq = &lt;&amp;clk_imx290&gt;,"clock-frequency:0",
 				       &lt;&amp;imx290_0&gt;,"clock-frequency:0";
--- /dev/null
+++ b/arch/arm/boot/dts/overlays/ov64a40-overlay.dts
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Definitions for OV64A40 camera module on VC I2C bus
+/dts-v1/;
+/plugin/;
+
+/{
+	compatible = "brcm,bcm2835";
+
+	i2c_frag: fragment@0 {
+		target = &lt;&amp;i2c_csi_dsi&gt;;
+		__overlay__ {
+			#address-cells = &lt;1&gt;;
+			#size-cells = &lt;0&gt;;
+			status = "okay";
+
+			#include "ov64a40.dtsi"
+		};
+	};
+
+	csi_frag: fragment@1 {
+		target = &lt;&amp;csi1&gt;;
+		csi: __overlay__ {
+			status = "okay";
+			brcm,media-controller;
+
+			port{
+				csi_ep: endpoint{
+					remote-endpoint = &lt;&amp;cam_endpoint&gt;;
+					clock-lanes = &lt;0&gt;;
+					data-lanes = &lt;1 2&gt;;
+				};
+			};
+		};
+	};
+
+	fragment@2 {
+		target = &lt;&amp;i2c0if&gt;;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	clk_frag: fragment@3 {
+		target = &lt;&amp;cam1_clk&gt;;
+		__overlay__ {
+			clock-frequency = &lt;24000000&gt;;
+			status = "okay";
+		};
+	};
+
+	fragment@4 {
+		target = &lt;&amp;i2c0mux&gt;;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@5 {
+		target = &lt;&amp;cam_node&gt;;
+		__overlay__ {
+			lens-focus = &lt;&amp;vcm_node&gt;;
+		};
+	};
+
+	__overrides__ {
+		rotation = &lt;&amp;cam_node&gt;,"rotation:0";
+		orientation = &lt;&amp;cam_node&gt;,"orientation:0";
+		media-controller = &lt;&amp;csi&gt;,"brcm,media-controller?";
+		cam0 = &lt;&amp;i2c_frag&gt;, "target:0=",&lt;&amp;i2c_csi_dsi0&gt;,
+		       &lt;&amp;csi_frag&gt;, "target:0=",&lt;&amp;csi0&gt;,
+		       &lt;&amp;clk_frag&gt;, "target:0=",&lt;&amp;cam0_clk&gt;,
+		       &lt;&amp;cam_node&gt;, "clocks:0=",&lt;&amp;cam0_clk&gt;,
+		       &lt;&amp;cam_node&gt;, "avdd-supply:0=",&lt;&amp;cam0_reg&gt;,
+		       &lt;&amp;vcm_node&gt;, "vdd-supply:0=",&lt;&amp;cam0_reg&gt;;
+		vcm = &lt;&amp;vcm_node&gt;, "status",
+		      &lt;0&gt;, "=5";
+		link-frequency = &lt;&amp;cam_endpoint&gt;,"link-frequencies#0";
+	};
+};
+
+&amp;cam_node {
+	status = "okay";
+};
+
+&amp;cam_endpoint {
+	remote-endpoint = &lt;&amp;csi_ep&gt;;
+};
+
+&amp;vcm_node {
+	status = "okay";
+};
--- /dev/null
+++ b/arch/arm/boot/dts/overlays/ov64a40.dtsi
@@ -0,0 +1,34 @@
+// Fragment that configures an OV64A40
+
+cam_node: ov64a40@36 {
+	compatible = "ovti,ov64a40";
+	reg = &lt;0x36&gt;;
+	status = "disabled";
+
+	clocks = &lt;&amp;cam1_clk&gt;;
+	clock-names = "xclk";
+
+	avdd-supply = &lt;&amp;cam1_reg&gt;;	/* 2.8v */
+	dovdd-supply = &lt;&amp;cam_dummy_reg&gt;;/* 1.8v */
+	dvdd-supply = &lt;&amp;cam_dummy_reg&gt;;	/* 1.1v */
+
+	rotation = &lt;180&gt;;
+	orientation = &lt;2&gt;;
+
+	port {
+		cam_endpoint: endpoint {
+			bus-type = &lt;4&gt;;
+			clock-lanes = &lt;0&gt;;
+			data-lanes = &lt;1 2&gt;;
+			link-frequencies =
+				/bits/ 64 &lt;456000000&gt;;
+		};
+	};
+};
+
+vcm_node: bu64754@76 {
+	compatible = "rohm,bu64754";
+	reg = &lt;0x76&gt;;
+	status = "disabled";
+	vdd-supply = &lt;&amp;cam1_reg&gt;;
+};
</pre></body></html>