Failed tegra camera driver registration on JetPack4.2

We are porting IMX378 sensor from JetPack3.3 to JetPack4.2.

However, the following error occurs:

nvidia@nvidia-desktop:~$ dmesg | grep imx378
[    0.184620] DTS File Name: arch/arm64/boot/dts/../../../../../../hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-imx378.dts
[    0.441643] DTS File Name: arch/arm64/boot/dts/../../../../../../hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-imx378.dts
[    3.694327] imx378 30-001a: Failed to find port index
[    3.694331] imx378 30-001a: Failed to find port info.
[    3.694334] imx378 30-001a: Failed to initialize imx378
[    3.694337] imx378 30-001a: tegra camera driver registration failed
[    3.694518] imx378: probe of 30-001a failed with error -22

The same phenomenon occurs even if imx378.c source code is ported to imx219.c or imx185.c.

Is there a problem with the following device tree?

File1: /usr/src/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-imx378.dts

#include "tegra186-quill-p3310-1000-c03-00-base.dts"
#include "quill-platforms/tegra186-quill-camera-imx378-c03.dtsi"

/ {
	nvidia,dtsfilename = __FILE__;

	/* GPIO */
	gpio@2200000 {
		camera-control-input {
			status = "disabled";
		};
		camera-control-output-low {
			status = "disabled";
		};
		camera-control-output-high {
			gpio-hog;
			gpios = <CAM0_RST_L 0 CAM0_PWDN 0>;
			label = "cam0-rst cam0-pwdn";
			output-high;
			status = "okay";
		};
	};

	host1x {
		vi_base: vi@15700000 {
			ports {
				imx378_vi_port0: port@0 {
					status = "okay";
					imx378_vi_in0: endpoint {
						status = "okay";
					};
				};
			};
		};
		csi_base: nvcsi@150c0000 {
			csi_chan0: channel@0 {
				status = "okay";
				ports {
					csi_chan0_port0: port@0 {
						status = "okay";
						imx378_csi_in0: endpoint@0 {
							status = "okay";
						};
					};
					csi_chan0_port1: port@1 {
						status = "okay";
						imx378_csi_out0: endpoint@1 {
							status = "okay";
						};
					};
				};
			};
		};
	};
};

File2: /usr/src/hardware/nvidia/platform/t18x/quill/kernel-dts/quill-platforms/tegra186-quill-camera-imx378-c03.dtsi

#include <quill-modules/tegra186-camera-imx378-c03.dtsi>
#include "dt-bindings/clock/tegra186-clock.h"

#define CAM0_RST_L	TEGRA_MAIN_GPIO(R, 5)
#define CAM0_PWDN	TEGRA_MAIN_GPIO(R, 0)
#define CAM1_RST_L	TEGRA_MAIN_GPIO(R, 1)
#define CAM1_PWDN	TEGRA_MAIN_GPIO(L, 6)

/* camera control gpio definitions */

/ {
	i2c@3180000 {
		tca9548@70 {
			compatible = "nxp,pca9548";
			reg = <0x70>;
			#address-cells = <1>;
			#size-cells = <0>;
			skip_mux_detect = "yes";
			#vif-supply = <&en_vdd_cam>;
			vcc-supply = <&en_vdd_cam>;
			#vcc_lp = "vif";
			status = "okay";
			force_bus_start = <CAMERA_I2C_MUX_BUS(0)>;
			i2c@0 {
				reg = <0>;
				i2c-mux,deselect-on-exit;
				#address-cells = <1>;
				#size-cells = <0>;
				imx378_a@1a {
					/* Define any required hw resources needed by driver */
					/* ie. clocks, io pins, power sources */
					clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>,
							 <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
					clock-names = "extperiph1", "pllp_grtba";
					mclk = "extperiph1";
					reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_HIGH>;
					vana-supply = <&en_vdd_cam_hv_2v8>;
					vif-supply = <&en_vdd_cam>;
					vdig-supply = <&en_vdd_cam_1v2>;
					status = "okay";
				};
			};
		};
	};
};

File3: /usr/src/hardware/nvidia/platform/t18x/quill/kernel-dts/quill-modules/tegra186-camera-imx378-c03.dtsi

/ {
	host1x {
		vi@15700000 {
			num-channels = <1>;
			ports {
				#address-cells = <1>;
				#size-cells = <0>;
				port@0 {
					reg = <0>;
					vi_in0: endpoint {
						csi-port = <0>;
						bus-width = <2>;
						remote-endpoint = <&csi_out0>;
					};
				};
			};
		};

		nvcsi@150c0000 {
			num-channels = <1>;
			channel@0 {
				reg = <0>;
				ports {
					#address-cells = <1>;
					#size-cells = <0>;
					port@0 {
						reg = <0>;
						csi_in0: endpoint@0 {
							csi-port = <0>;
							bus-width = <2>;
							remote-endpoint = <&imx378_out0>;
						};
					};
					port@1 {
						reg = <1>;
						csi_out0: endpoint@1 {
							remote-endpoint = <&vi_in0>;
						};
					};
				};
			};
		};
	};

	i2c@3180000 {
		tca9548@70 {
			i2c@0 {
				imx378_a@1a {
					devnode = "video0";
					compatible = "nvidia,imx378";
					reg = <0x1a>;

					physical_w = "7.564";
					physical_h = "5.476";

					sensor_model ="imx378";
					dovdd-supply = <&en_vdd_cam>;
					avdd-reg = "vana";
					dvdd-reg = "vdig";
					iovdd-reg = "dovdd";

					mode0 { // IMX378_MODE_4056X3040
						mclk_khz = "6000";
						num_lanes = "2";
						tegra_sinterface = "serial_a";
						phy_mode = "DPHY";
						discontinuous_clk = "yes";
						cil_settletime = "0";

						active_w = "4056";
						active_h = "3040";
						mode_type = "bayer";
						pixel_phase = "rggb";
						readout_orientation = "90";
						line_length = "4350";
						inherent_gain = "1";
						mclk_multiplier = "348";
						pix_clk_hz = "417600000";

						gain_factor = "1000000";
						min_gain_val = "1000000";
						max_gain_val = "22000000";
						min_hdr_ratio = "1";
						max_hdr_ratio = "64";
						framerate_factor = "1000000";
						min_framerate = "1000000";
						max_framerate = "30000000";
						min_exp_time = "1";
						max_exp_time = "65515";
						default_exp_time = "3180";/* us */
						embedded_metadata_height = "0";
					};
					mode1 { // IMX378_MODE_3840X2160
						mclk_khz = "6000";
						num_lanes = "2";
						tegra_sinterface = "serial_a";
						phy_mode = "DPHY";
						discontinuous_clk = "yes";
						cil_settletime = "0";

						active_w = "3840";
						active_h = "2160";
						mode_type = "bayer";
						pixel_phase = "rggb";
						readout_orientation = "90";
						line_length = "4250";
						inherent_gain = "1";
						mclk_multiplier = "238";
						pix_clk_hz = "285600000";

						gain_factor = "1000000";
						min_gain_val = "1000000";
						max_gain_val = "22000000";
						min_hdr_ratio = "1";
						max_hdr_ratio = "64";
						framerate_factor = "1000000";
						min_framerate = "1000000";
						max_framerate = "30000000";
						min_exp_time = "1";
						max_exp_time = "65515";
						default_exp_time = "2220";/* us */
						embedded_metadata_height = "0";
					};
					mode2 { // IMX378_MODE_1920X1080
						mclk_khz = "6000";
						num_lanes = "2";
						tegra_sinterface = "serial_a";
						phy_mode = "DPHY";
						discontinuous_clk = "yes";
						cil_settletime = "0";

						active_w = "1920";
						active_h = "1080";
						mode_type = "bayer";
						pixel_phase = "rggb";
						readout_orientation = "90";
						line_length = "2240";
						inherent_gain = "1";
						mclk_multiplier = "126";
						pix_clk_hz = "151200000";

						gain_factor = "1000000";
						min_gain_val = "1000000";
						max_gain_val = "22000000";
						min_hdr_ratio = "1";
						max_hdr_ratio = "64";
						framerate_factor = "1000000";
						min_framerate = "1000000";
						max_framerate = "60000000";
						min_exp_time = "1";
						max_exp_time = "65515";
						default_exp_time = "1105";/* us */
						embedded_metadata_height = "0";
					};
					mode3 { // IMX378_MODE_640X480
						mclk_khz = "6000";
						num_lanes = "2";
						tegra_sinterface = "serial_a";
						phy_mode = "DPHY";
						discontinuous_clk = "yes";
						cil_settletime = "0";

						active_w = "640";
						active_h = "480";
						mode_type = "bayer";
						pixel_phase = "rggb";
						readout_orientation = "90";
						line_length = "1600";
						inherent_gain = "1";
						mclk_multiplier = "84";
						pix_clk_hz = "100800000";

						gain_factor = "1000000";
						min_gain_val = "1000000";
						max_gain_val = "22000000";
						min_hdr_ratio = "1";
						max_hdr_ratio = "64";
						framerate_factor = "1000000";
						min_framerate = "1000000";
						max_framerate = "120000000";
						min_exp_time = "1";
						max_exp_time = "65515";
						default_exp_time = "505";/* us */
						embedded_metadata_height = "0";
					};
					ports {
						#address-cells = <1>;
						#size-cells = <0>;
						port@0 {
							reg = <0>;
							imx378_out0: endpoint {
								csi-port = <0>;
								bus-width = <2>;
								remote-endpoint = <&csi_in0>;
							};
						};
					};
				};
			};
		};
	};

	lens_imx378_a@3e {
		min_focus_distance = "0.0";
		hyper_focal = "0.0";
		focal_length = "4.52";
		f_number = "2.0";
		aperture = "2.0";
	};

	tegra-camera-platform {
		compatible = "nvidia, tegra-camera-platform";
		/**
		* Physical settings to calculate max ISO BW
		*
		* num_csi_lanes = <>;
		* Total number of CSI lanes when all cameras are active
		*
		* max_lane_speed = <>;
		* Max lane speed in Kbit/s
		*
		* min_bits_per_pixel = <>;
		* Min bits per pixel
		*
		* vi_peak_byte_per_pixel = <>;
		* Max byte per pixel for the VI ISO case
		*
		* vi_bw_margin_pct = <>;
		* Vi bandwidth margin in percentage
		*
		* max_pixel_rate = <>;
		* Max pixel rate in Kpixel/s for the ISP ISO case
		*
		* isp_peak_byte_per_pixel = <>;
		* Max byte per pixel for the ISP ISO case
		*
		* isp_bw_margin_pct = <>;
		* Isp bandwidth margin in percentage
		*/
		num_csi_lanes = <2>;
		max_lane_speed = <1500000>;
		min_bits_per_pixel = <10>;
		vi_peak_byte_per_pixel = <2>;
		vi_bw_margin_pct = <25>;
		max_pixel_rate = <750000>;
		isp_peak_byte_per_pixel = <5>;
		isp_bw_margin_pct = <25>;

		/**
		 * The general guideline for naming badge_info contains 3 parts, and is as follows,
		 * The first part is the camera_board_id for the module; if the module is in a FFD
		 * platform, then use the platform name for this part.
		 * The second part contains the position of the module, ex. "rear" or "front".
		 * The third part contains the last 6 characters of a part number which is found
		 * in the module's specsheet from the vender.
		 */
		modules {
			module0 {
				status = "okay";
				badge = "imx378_CH1_396CP";
				position = "0";
				orientation = "1";
				drivernode0 {
					status = "okay";
					/* Declare PCL support driver (classically known as guid)  */
					pcl_id = "v4l2_sensor";
					/* Driver v4l2 device name */
					devname = "imx378 30-001a";
					/* Declare the device-tree hierarchy to driver instance */
					proc-device-tree = "/proc/device-tree/i2c@3180000/tca9548@70/i2c@0/imx378_a@1a";
				};
				drivernode1 {
					/* Declare PCL support driver (classically known as guid)  */
					pcl_id = "v4l2_lens";
					proc-device-tree = "/proc/device-tree/lens_imx378_a@3e/";
				};
			};
		};
	};
};

hello yasuo-tanaka,

suggest you check the documentation, [Sensor Software Driver Programming Guide],
and you should refer to Port Index session for the port index mapping diagram.

you may also disassembler the dtb file into txt file for quick checking,
for example,

$ dtc -I dtb -O dts -o results.txt $OUT/kernel/dtb/tegra186-quill-p3310-1000-c03-00-base.dtb

hello JerryChang,

Thank you for your reply.
I understand that I need to change some parameters like “port-index” in the device tree.
I will check the guidance and try it.

hello JerryChang,

Thank you very much.
This problem was solved with the parameter names in the device tree.

Hello CenturyArks-Support

Which’s params of device tree you changed?

Hello hoanganhv1svm,

It is published on our GitHub.
https://github.com/centuryarks/CA378-AOIS/blob/master/JetsonTX2/src/hardware/nvidia/platform/t18x/quill/kernel-dts/quill-modules/tegra186-camera-imx378-c03.dtsi

Hello bro,

Thanks for your sharing. Did you porting adv72xx to nano.
i’m stuck with adv7280 from few a week before :(