# CSI cameras customization

## Brief introduction

To support custom CSI camera on Jetson platform, there is a need for specific v4l2 driver and device tree matching hardware configuration of carrier board. Those files are usually provided by camera module manufacturers. For this tutorial it is assumed that customer has obtained patched kernel sources in the working directory ([obtaining kernel sources](/autopilots/common-features/nvidia-jetson-kernel-customization/compilation-of-kernel-from-sources.md#obtaining-kernel-sources)), v4l2 camera driver sources ".c" and camera related device tree sources ".dts".

Camera manufacturers\\\`s guides how to implement support for custom camera module, intended to be used on some of the Jetson developer kits, not works in most cases on custom carrier boards (.Pilot board including). Those are usually based on principle of copying whole kernel image and device tree, built specifically for developer kit and do not match other hardware configurations. {% endhint %}

### Steps to do:

**Device tree:**

* [device tree source files customization](#device-tree-source-files-customization)
* [building device tree and deploying to running target](#building-device-tree)

**Camera driver:**

* [copying driver files to right destination](#copying-driver-files-to-right-destination)
* [compiling kernel and deploying into running target](#compiling-kernel)

## Device tree

#### Device tree source files customization

To start with device tree customization, we recommend to grab one of out working device tree source files, rename it and gradually modify it according to camera manufacturer device tree sources. For example sources for ov9281 camera module can be used: *"<mark style="color:purple;">tegra194-camera-ov9281-hexa.dtsi</mark>" and "*<mark style="color:purple;">tegra194-camera-jakku-ov9281-hexa.dtsi</mark>*",* which are located in : *`$target_working_directory/kernel_sources_xaviernx/hardware/nvidia/platform/t19x/jakku/kernel-dts/common` .*

{% hint style="info" %} *If you need more information or explanation of specific device tree camera nodes, please read* [*Sensor Software Driver Programming guide*](https://docs.nvidia.com/jetson/archives/r34.1/DeveloperGuide/text/SD/CameraDevelopment/SensorSoftwareDriverProgramming.html) *written by Nvidia.* {% endhint %}

Next copy new dtsi files into same repository and include main file in the upper device tree file *"<mark style="color:purple;">tegra194-p3509-0000-a00.dtsi</mark>" ,* which is also located in the same repository :

```clike
...
#include <dt-bindings/gpio/tegra194-gpio.h>
#include "dt-bindings/input/input.h"
#include "tegra194-fixed-regulator-p3509-0000-a00.dtsi"
#include "tegra194-p3509-disp.dtsi"
#include "tegra194-audio-p3668.dtsi"
#include "tegra194-super-module-e2614-p3509.dtsi"
//#include "tegra194-camera-jakku-rbpcv2-hexa-imx219.dtsi"
//#include "tegra194-camera-jakku-hexa-imx219-imx477.dtsi"
//#include "tegra194-camera-jakku-dcpilot-arducam.dtsi"
//#include "tegra194-camera-jakku-ov9281-hexa.dtsi"
//#include "tegra194-camera-jakku-hexa-imx219-imx412.dtsi"
//#include "tegra194-camera-jakku-hexa-ov9281-imx477.dtsi"
#include "tegra194-camera-jakku-custom_camera.dtsi"   //only one camera dts must be included !!

/ {
	gpio-keys {
...
```

**Common device tree modification mistakes:**

* **Wrong definition of control GPIOs:**

```clike
//DEFAULT PINS STATE DEFINITION EXAMPLE
tca6408_20: tca6408@20 {
			status = "okay";
			compatible = "ti,tca6408";
			gpio-controller;
			#gpio-cells = <2>;
			reg = <0x20>;			
			vcc-supply = <&p3509_vdd_3v3_cvb>;
			/*
			* GPIO-0 : CSI A
			* GPIO-1 : CSI F
			* GPIO-2 : CSI C
			* GPIO-3 : CSI B
			* GPIO-4 : CSI D
			* GPIO-5 : CSI E
			* GPIO-6 : EXT_GPIO_0 //GPIO out of board-do not change
			* GPIO-7 : EXT_GPIO_1 //GPIO out of board-do not change
			*/
			tca6408_20_outlow {  //Default state of this pins are output low
				gpio-hog;
				gpios = <0 0 2 0 5 0 6 0 7 0>; // GPIOS 0,2,5,6,7 set low
				output-low;
				label = "cam_rst_0",					
					"cam_rst_2",
					"cam_rst_5",
					"ext_gpio_0",
					"ext_gpio_1";
			};
			tca6408_20_outhigh { //Default state of this pins are output high
				gpio-hog;					
				gpios = <1 0 3 0 4 0>; // GPIOS 1,3,4 set high
				output-high;
				label = "cam_rst_1",
					"cam_rst_3",
					"cam_rst_4";							
			};
			tca6408_20_input { //Set gpios as input
				status = "disabled";
};

//RESET POLARITY DEFINITION EXAMPLE
i2c@0 {
	status = "okay";
	...
	camera_a@xx {
		status = "okay";
		reset-gpios = <&tca6408_20 0 GPIO_ACTIVE_LOW>; //Reset polarity = LOW
		//reset-gpios = <&tca6408_20 0 GPIO_ACTIVE_HIGH>; //Reset poalrity = HIGH
	};
};						
```

* **Wrong camera indexes:**

```cpp
//CODE SNIPPETS IN CAMERA NODE TO BE AWARE OF 	

vi@15c10000  { // Customize only labels in most cases (camxx)
	num-channels = <6>; //(preserve)
	ports {
		status="okay";
		#address-cells = <1>;
		#size-cells = <0>;
		vi_port0: port@0 {
			status="okay";
			reg = <0>;
			camxx_vi_in0: endpoint {
				status="okay";
				port-index = <0>; //(preserve)
				bus-width = <2>; //(preserve)
				remote-endpoint = <&camxx_csi_out0>; // change to custom name (labels must match within document) 
			};
		};
.
.
.

nvcsi@15a00000 { // Customize only labels in most cases (camxx)
	num-channels = <6>; //(preserve)
	...
	csi_chan0: channel@0 {
		reg = <0>;
		status="okay";
		ports {
			...
			csi_chan0_port0: port@0 {
				reg = <0>;
				status="okay";
				camxx_csi_in0: endpoint@0 {
					status="okay";
					port-index = <0>; //(preserve)
					bus-width = <2>; //(preserve)
					remote-endpoint = <&camxx_out0>; // change to custom name (labels must match within document) 
				};
			};
			csi_chan0_port1: port@1 {
				reg = <1>;
				status="okay";
				camxx_csi_out0: endpoint@1 {
					status="okay";
					remote-endpoint = <&camxx_vi_in0>; // change to custom name (labels must match within document) 
				};
			};
		};
	};				
.
.
.
		
tca9548@70 {			
	i2c_0: i2c@0 {	/*CSI A*/				
		camxx_cam0: camxx_a@60 { /* camxx - camera module name (change)
					 _a= camera index(preserve), 
					@60 = specific i2c address of module (change)*/
			...
			compatible = "nvidia,camxx"; //camxx = kernel driver name (change to .name param in driver file)
			reg = <0x60>; // i2c address of specific camera module (change)
			devnode = "video0"; //(preserve)
			sensor_model = "cammxx"; //(change)
			...
			mode0 { 						
				tegra_sinterface = "serial_a"; //(preserve)
				...
			};
			.
			.
			.
			ports {					
				port@0 {							
					xx_out0: endpoint {
						...
						port-index = <0>; //(preserve)
                               			bus-width = <2>;  //(preserve)
						...
					};
				};
			};
		};
	};
	
.
.
.
	
/ {
tcp: tegra-camera-platform {
	compatible = "nvidia, tegra-camera-platform";	
.
.
.

modules { 
	status="okay";
	cam_module0: module0 {
		badge = "jakku_bottomright_AVOV9281"; // AVOV9281 -> (change to custom)
		position = "bottomright"; //(preserve)
		orientation = "1";
		status="okay";
		cam_module0_drivernode0: drivernode0 {
			status="okay";
			pcl_id = "v4l2_sensor";
			devname = "camxx 30-0060"; // camxx -> change to driver_name,  30-00xx (xx = I2C address) 
			proc-device-tree = "/proc/device-tree/i2c@3180000/tca9548@70/i2c@0/camxx_a@60"; //camxx_a@60 -> change to driver_name_a@xx (xx=i2c address)
		};
	};	
	.
	.
	.	
```

* **I2C multiplexor driver match**

```clike
//DIFFERENCE BETWEEN BOARD REVISIONS

tca9548_70: tca9548@70 {
    status = "okay";
    compatible = "nxp,pca9548";     //"nxp,pca9548" = DroneCore.Pilot v1.0
                                    //"nxp,pca9547" = DroneCore.Pilot v1.2 and higher
    .
    .
    .
```

#### *Building device tree and deploying to running target*

*Please read* [*this section*](/autopilots/common-features/nvidia-jetson-kernel-customization/compilation-of-kernel-from-sources.md#compilation) *to build whole Jetson\`s device tree on host PC and apply compiled output into running target.*

## *Camera driver*

Assumed that "*driver.c*" and optionally "*driver\_mode\_tbls.h*" "*driver.h*" files are obtained from camera provider.

#### Copying driver files to right destination

*Driver files must be copied into compilation folder.*

*Destination path for "driver.c" and optionally "driver\_mode\_tbls.h" files: `$target_working_directory`*`/Linux_for_Tegra/kernel_sources_xaviernx/kernel/nvidia/drivers/media/i2c`

Destination path for optional "*driver.h*" file:

*`$target_working_directory`*`/Linux_for_Tegra/kernel_sources_xaviernx/kernel/nvidia/include/media`

#### Compiling kernel

Add driver to end of make file (*`$target_working_directory`*`/Linux_for_Tegra/kernel_sources_xaviernx/kernel/nvidia/drivers/media/i2c/Makefile)`

```
obj-y += camxx.o  //camxx replace with driver name
```

Next follow [this section](/autopilots/common-features/nvidia-jetson-kernel-customization/compilation-of-kernel-from-sources.md#compilation) to compile kernel sources, create kernel image on host PC and deploy it to target Jetson device.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.airvolute.com/autopilots/common-features/nvidia-jetson-kernel-customization/csi-cameras-customization.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
