ADV7280m configuration

Hello

In our custom board we have a ADV7280m (https://www.analog.com/en/products/adv7280.html) conected to a TX2 CSI 1-lane (See attached schematic).
I want to configure the device tree and compile the driver, so I’ll can see the /dev/videoX and use it with gstreamer to capture imagens from a camera attached to this chip.
I’m using the “NVIDIA Tegra Linux Driver Package (32.2)” on section “Sensor Software Driver Programming Guide”.
I’v created the device tree on the end of the file tegra186-quill-p3310-1000-c03-00-base.dts:

/* cameras */
 plugin-manager {
	 /* To not modify file  tegra186-quill-p3310-1000-a00-00-base.dts
	    remove all camera plugin manager fragment from included file
		tegra186-quill-camera-plugin-manager.dtsi	*/
	 /delete-node/ fragment-imx390@0;
	 /delete-node/ fragment-e3326@0;
	 /delete-node/ fragment-e3323@0;
	 /delete-node/ fragment-p3310-c00-camera;
	 /delete-node/ fragment-e3333@0;
	 /delete-node/ fragment-e3322@0;
	 /delete-node/ fragment-imx185@0;
	 /delete-node/ fragment-imx274@0;
	 /delete-node/ fragment-imx274-dual@0;
	 /delete-node/ fragment-e3331@0;
 };

 /* ADV7280m */
 host1x {
	 vi@15700000 {
		 num-channels = <1>;
		 status = "okay";
		 ports {
			 #address-cells = <0x1>;
			 #size-cells = <0x0>;
			 status = "okay";
			 port@0 {
				 status = "okay";
				 reg = <0x0>;
				 adv7280m_vi_in0: endpoint {
					 status = "okay";
					 csi-port = <0>;
					 bus-width = <2>;
					 remote-endpoint = <&adv7280m_csi_out0>;
				 };
			 };
		 };
	 };
 };

 nvcsi@150c0000 {
	 num-channels = <1>;
	 #address-cells = <1>;
	 #size-cells = <0>;
	 status = "okay";
	 channel@0 {
		 reg = <0x0>;
		 status = "okay";
		 ports {
			 #address-cells = <0x1>;
		 	 #size-cells = <0x0>;
			 status = "okay";
			 port@0 {
				 status = "okay";
				 reg = <0x0>;
				 adv7280m_csi_in0: endpoint@0 {
					 status = "okay";
					 csi-port = <0>;
					 bus-width = <2>;
					 remote-endpoint = <&adv7280m_out0>;
				 };
			 };

			 port@1 {
				 status = "okay";
				 reg = <0x1>;
				 adv7280m_csi_out0: endpoint@1 {
					 status = "okay";
					 remote-endpoint = <&adv7280m_vi_in0>;
				 };
			 };
		 };
	 };
 };


 i2c@31c0000 {
	 adv7280m@21 {
		 compatible = "adi,adv7280-m";
		 reg = <0x21>;
		 devnode = "video0";
		 clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>,
		 <&tegra_car TEGRA186_CLK_PLLP_OUT0>;
		 clock-names = "extperiph1", "pllp_grtba";
		 mclk = "extperiph1";
		 clock-frequency = <24000000>;
		 reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_HIGH>;
		 pwdn-gpios = <&tegra_main_gpio CAM0_PWDN GPIO_ACTIVE_HIGH>;
		 vana-supply = <&en_vdd_cam_hv_2v8>;
		 vif-supply = <&en_vdd_cam>;
		 avdd-reg = "vana";
		 iovdd-reg = "vif";
		 status = "okay";

		 ports {
			 #address-cells = <0x1>;
			 #size-cells = <0x0>;
			 status = "okay";

			 port@0 {
				 status = "okay";
				 reg = <0>;
				 adv7280m_out0: endpoint {
					 status = "okay";
					 csi-port = <0>;
					 bus-width = <2>;
					 remote-endpoint = <&adv7280m_csi_in0>;
				 };
			 };
		 };
	 };
 };

 tegra-camera-platform {
	  status = "okay";
		compatible = "nvidia, tegra-camera-platform";
		modules {
				module0 {
						badge = "adv7280m_top_adv7280m";
						position = "bottom";
						orientation = "0";
						drivernode0 {
							  status = "okay";
								pcl_id = "v4l2_sensor";
								devname = "adv7280m 6-0021";
								proc-device-tree = "/proc/device-tree/i2c@31c0000/adv7280m@21";
						};
				};
		};
};

Also I’ve enabled the driver ADV7180 at menuconfig from L4T sources and compiled everything.

After the system boot I can’t see /dev/videoX (X is 0, 1, 2, etc)

I’m sending attached the system boot log.
The dmesg message for adv is:

nvidia@nvidia-desktop:~$ dmesg | grep -i adv
[    0.615499] Advanced Linux Sound Architecture Driver Initialized.
[    8.109943] systemd[1]: System time before build time, advancing clock.
[   10.090101] adv7180 6-0021: chip found @ 0x21 (31c0000.i2c)
[   10.122911] tegra-vi4 15700000.vi: subdev adv7180 6-0021 bound
[   10.122917] tegra-vi4 15700000.vi: Entity type for entity adv7180 6-0021 was not initialized!

And the driver is loaded:

nvidia@nvidia-desktop:~$ lsmod 
Module                  Size  Used by
bnep                   19270  2
fuse                  120203  3
zram                   30209  4
overlay                54926  0
bcmdhd                985053  0
cfg80211              727800  1 bcmdhd
adv7180                15652  1
nvgpu                1724375  18
bluedroid_pm           16187  0
ip_tables              21421  0
x_tables               38144  1 ip_tables

If I use the media-ctl on /dev/media0 we can see something loaded for adv7180 but I believe something is missing:

nvidia@nvidia-desktop:~$ sudo media-ctl -p -d /dev/media0
[sudo] password for nvidia: 
Media controller API version 0.1.0

Media device information
------------------------
driver          tegra-vi4
model           NVIDIA Tegra Video Input Device
serial          
bus info        
hw revision     0x3
driver version  0.0.0

Device topology
- entity 1: adv7180 6-0021 (1 pad, 0 link)
            type V4L2 subdev subtype Unknown flags 20004
        pad0: Source

Can, someone help-me to configure this?
I believe that the first thing I must do solve is the message: “tegra-vi4 15700000.vi: Entity type for entity adv7180 6-0021 was not initialized!”

Thanks!
csi0_adv7280m.jpg
boot_adv.txt (163 KB)

hello alfredosalvarani,

  1. we had some known issue with built sensor as kernel modules,
    could you please have modification to make ADV7280m as built-in kernel drivers.
    for example,
<i>$l4t-r32.2/public_sources/kernel/kernel-4.9/arch/arm64/configs/tegra_defconfig</i>
...
CONFIG_VIDEO_OV5693=y
  1. your media device information did not looks correct, you should have device topology as below.
    for example,
    ADV7280m–> NVCSI–> VI

  2. please refer to Sensor Software Driver Programming Guide, please review [Port Index] session to double confirm the device tree port bindings.

  3. below should be the clue of mismatch device topology, you should declare VI and NVCSI under host1x.
    for example,

host1x {
	vi@15c10000 {
	};

	nvcsi@15a00000 {
	};
};
  1. you may disassembler the dtb file into txt file for quick checking,
    for example,
$ dtc -I dtb -O dts -o output.txt tegra186.dtb

I’m trying to compile the adv7180 driver built-in but when linking the built-in.o file it doesn’t fount the function nvhost_syncpt_unit_interface_get_aperture

Do you have some config file with adv7180 enabled as built-in driver?

hello alfredosalvarani,

please access L4T Sources via DLC.
you might also found adv7180.c reference drivers as below.

for example,
$l4t-r32.2/public_sources/kernel/kernel-4.9/drivers/media/i2c/adv7180.c

Hi Jerry, what do you mean it “DLC” (maybe Downloadable content?)
I used “source_sync.sh” Nvidia script to get the source code.
But I guess you don’t understand my question: I’m trying to compile adv7180.c as part of the kernel, not as a module. The first time I did this, but the result is “kernel panic”, I had to compile “Multimedia Support” as part of the kernel too, because “menuconfig” would not allow me to compile adv7180 if Multimedia is a module (see the attached image).
After the “kernel panic”, I tried to go back to the original, but I’m experiencing this compilation issue.
menuconfig1.png
menuconfig2.png

Hi Jerry,

Today I downloaded the source code again, put my DT file, and only make the adv7180 driver as built-in in the kernel and compiled it.
But when flash it to the board it boot on “kernel panic” and start to reboot forever…
Look at the attached boot log.
I’ll try to compile and install it as a module again…
boot_adv_built-in.txt (38.3 KB)

Hi Jerry,

Compiling the kernel with the adv7180 as a module and with you sugestion in DT I can get the /dev/video0 file.
But I can’t get video :-(
If I type the command:

gst-launch-1.0 v4l2src ! xvimagesink

on a terminal, nothing appers, but on serial interface we have:

[   59.618097] Internal error: Accessing user space memory outside uaccess.h routines: 96000045 [#2] PREEMPT SMP
[   59.628008] Modules linked in: bnep fuse zram overlay bcmdhd cfg80211 adv7180(+) nvgpu bluedroid_pm ip_tables x_tables
[   59.638829] CPU: 5 PID: 7441 Comm: v4l2src0:src Tainted: G      D         4.9.140-tegra #2
[   59.647078] Hardware name: quill (DT)
[   59.650735] task: ffffffc19e436200 task.stack: ffffffc197ebc000
[   59.656658] PC is at adv7180_set_pad_format+0x94/0x120 [adv7180]
[   59.662661] LR is at __tegra_channel_try_format+0x9c/0x208
[   59.668138] pc : [<ffffff80011ba174>] lr : [<ffffff8008b3765c>] pstate: 80400145
[   59.675523] sp : ffffffc197ebfaa0
[   59.678836] x29: ffffffc197ebfaa0 x28: 0000000000000000
[   59.684170] x27: ffffffc1eb352030 x26: 0000000000000000
[   59.689505] x25: 0000000000000001 x24: ffffffc197ed8880
[   59.694873] x23: 0000000000000000 x22: ffffffc1df976c90
[   59.700215] x21: 0000000000000000 x20: ffffffc1df976c18
[   59.705562] x19: ffffffc197ebfb28 x18: 0000007f91d4ca70
[   59.710909] x17: 0000000000000000 x16: 0000000000000000
[   59.716254] x15: 0000000000000000 x14: 0000000000000000
[   59.721605] x13: 0000000000000000 x12: 0000000000000000
[   59.726992] x11: 0000000000000000 x10: 0000000000000000
[   59.732382] x9 : 0000000000000000 x8 : 0000000000000000
[   59.737770] x7 : 0000000000000000 x6 : 000000000000200f
[   59.743159] x5 : 0000000000002006 x4 : 000000000000b000
[   59.748549] x3 : 0000000400002006 x2 : 000001e0000002d0
[   59.753940] x1 : 0000000000000001 x0 : ffffffc197ebfb30
[   59.759328]
[   59.760851] Process v4l2src0:src (pid: 7441, stack limit = 0xffffffc197ebc000)
[   59.768102] Call trace:
[   59.770620] [<ffffff80011ba174>] adv7180_set_pad_format+0x94/0x120 [adv7180]
[   59.777706] [<ffffff8008b3765c>] __tegra_channel_try_format+0x9c/0x208
[   59.784261] [<ffffff8008b377f8>] tegra_channel_try_format+0x30/0x40
[   59.790579] [<ffffff8008b11cb4>] v4l_try_fmt+0x444/0x4e0
[   59.795929] [<ffffff8008b10f5c>] __video_do_ioctl+0x204/0x2c8
[   59.801708] [<ffffff8008b10908>] video_usercopy+0x2a0/0x6a0
[   59.807311] [<ffffff8008b10d44>] video_ioctl2+0x3c/0x50
[   59.812570] [<ffffff8008b0a820>] v4l2_ioctl+0x88/0x118
[   59.817755] [<ffffff8008273068>] do_vfs_ioctl+0xb0/0x8d8
[   59.823093] [<ffffff800827391c>] SyS_ioctl+0x8c/0xa8
[   59.828100] [<ffffff80080838c0>] el0_svc_naked+0x34/0x38
[   59.833459] ---[ end trace d299f4e546326990 ]---

My DT modifications:

/* ADV7280m */
 i2c@31c0000 {
 	adv7280m@21 {
 		compatible = "adi,adv7280-m";
 		reg = <0x21>;
 		devnode = "video0";
 		clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>,
 		<&tegra_car TEGRA186_CLK_PLLP_OUT0>;
 		clock-names = "extperiph1", "pllp_grtba";
 		mclk = "extperiph1";
 		clock-frequency = <24000000>;
 		reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_HIGH>;
 		pwdn-gpios = <&tegra_main_gpio CAM0_PWDN GPIO_ACTIVE_HIGH>;
 		vana-supply = <&en_vdd_cam_hv_2v8>;
 		vif-supply = <&en_vdd_cam>;
 		avdd-reg = "vana";
 		iovdd-reg = "vif";
 		status = "okay";

 		ports {
 			#address-cells = <0x1>;
 			#size-cells = <0x0>;
 			status = "okay";

 			port@0 {
 				status = "okay";
 				reg = <0>;
 				adv7280m_out0: endpoint {
 					status = "okay";
 					csi-port = <0>;
 					bus-width = <2>;
 					remote-endpoint = <&adv7280m_csi_in0>;
 				};
 			};
 		};
 	};
 };

 host1x {
	 vi@15700000 {
		 num-channels = <1>;
		 status = "okay";
		 ports {
			 #address-cells = <0x1>;
			 #size-cells = <0x0>;
			 status = "okay";
			 port@0 {
				 status = "okay";
				 reg = <0x0>;
				 adv7280m_vi_in0: endpoint {
					 status = "okay";
					 csi-port = <0>;
					 bus-width = <2>;
					 remote-endpoint = <&adv7280m_csi_out0>;
				 };
			 };
		 };
	 };

	 nvcsi@150c0000 {
		num-channels = <1>;
		#address-cells = <1>;
		#size-cells = <0>;
		status = "okay";
		channel@0 {
			reg = <0x0>;
			status = "okay";
			ports {
				#address-cells = <0x1>;
				#size-cells = <0x0>;
				status = "okay";
				port@0 {
					status = "okay";
					reg = <0x0>;
					adv7280m_csi_in0: endpoint@0 {
						status = "okay";
						csi-port = <0>;
						bus-width = <2>;
						remote-endpoint = <&adv7280m_out0>;
					};
				};

				port@1 {
					status = "okay";
					reg = <0x1>;
					adv7280m_csi_out0: endpoint@1 {
						status = "okay";
						remote-endpoint = <&adv7280m_vi_in0>;
					};
				};
			};
		};
	 };
 };

	tegra-camera-platform {
		status = "okay";
		compatible = "nvidia, tegra-camera-platform";
		modules {
			module0 {
				badge = "adv7280m_top_adv7280m";
				position = "bottom";
				orientation = "0";
				drivernode0 {
					status = "okay";
					pcl_id = "v4l2_sensor";
					devname = "adv7280m 6-0021";
					proc-device-tree = "/proc/device-tree/i2c@31c0000/adv7280m@21";
				};
			};
		};
	};
};

Look attached the boot log.

Can you help me to fix it?

Thanks!
boot_adv7180_module.txt (34.5 KB)

hello alfredosalvarani,

it’s a bit confusing that you’re repeatedly mention ADV7180 but I think you’re actually develop ADV7280m for your own custom board.

according to below failure during kernel initialization.
could you please review your sensor driver to check the regulator settings were correct.

[    5.553390] tegra-vi4 15700000.vi: Entity type for entity adv7180 6-0021 was not initialized!

you may also refer to Sensor Software Driver Programming Guide for driver development.
please also check Debugging Tips, and https://elinux.org/Jetson_TX2_Camera_BringUp to help you get further.
thanks

Yes, my board had adv7280m but the drivers is adv7180, on the file adv7180.c you can see that this driver support adv7280m. So I try to say adv7180 for the kernel driver and adv7280m for the hardware ic.

What do you mean by regulator settings? Is it responsible to Power the adv7280m?

hello alfredosalvarani,

it’s device tree property to define regulators and sensor drivers to control them.
you’ll also need to review which paragraph caused kernel panic, which usually caused by null access.
thanks

Hi Jerry,

I found that the Kernel Panic is because a function from adv7180 driver is called with a NULL pointer:

static int adv7180_get_pad_format(struct v4l2_subdev *sd,
				  struct v4l2_subdev_pad_config *cfg,
				  struct v4l2_subdev_format *format)
{

	struct adv7180_state *state = to_state(sd);

	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
		format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
	} else {
		adv7180_mbus_fmt(sd, &format->format);
		format->format.field = state->field;
	}

	return 0;
}

This function is called with parameter cfg = NULL, I’ve modified it to test if cfg is NULL and go to else (line 11) in this case. But the kernel crash in another place…
I found this post: https://devtalk.nvidia.com/default/topic/1042759/jetson-tx2/nvcsi-on-the-jetsontx2-for-custom-driver/post/5300818/#5300818
But I cant understand what I need to do, Need I change the adv7180.c driver? is it not ready to works on L4T 32.2 for TX2? I can’t find the OV5693.c file, is the imx185_1.c the reference driver for the 32.2 version? (I found this information on Sensor Software Driver Programming Guide).
But, I think, the most relevant question is: The ADV7180 driver is not ready to use with TX2? Should I develop it by myself?

Thanks

hello alfredosalvarani,

it looks that ADV7180 is an upstream sources and did not maintain by nvidia.
please access L4T Sources via download center,
BTW, you should found the ov5693, imx185, and other camera sensor drivers as below.
thanks

$l4t-r32.2/public_sources/kernel/nvidia/drivers/media/i2c/*

Hi Jerry.

If I get the sources from the site, I’ll get the adv7180 driver maintained by Nvidia?
If there’s no adv7180 maintained by Nvidia, what is easyer? Adapt this upstream sources to work with tx2 or get one source from $l4t-r32.2/public_sources/kernel/nvidia/drivers/media/i2c/ and build my own adv7180 driver?

Have you verified this post?: https://devtalk.nvidia.com/default/topic/1042759/jetson-tx2/nvcsi-on-the-jetsontx2-for-custom-driver/post/5300818/#5300818 I think I have same issue…

thanks!

hello alfredosalvarani,

sorry for confusing, you could download L4T Sources via download center.
there’re two folder in the kernel sources.

  1. you’ll found ov5693, imx185, and other camera sensor drivers as below.
    $l4t-r32.2/public_sources/kernel_src/kernel/nvidia/drivers/media/i2c/*

  2. there’s kernel-4.9 folder to include upstream kernel sources, which also ad adv7180.c
    $l4t-r32.2/public_sources/kernel_src/kernel/kernel-4.9/drivers/media/i2c/*

I don’t have experience with ADV7180 video decoder driver.
you might refer to this kernel sources and adapt it with Jetson-TX2.
thanks

Hello Jerry!

I’ve fixed the function adv7180_get_pad_format:

static int adv7180_get_pad_format(struct v4l2_subdev *sd,
                                  struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_format *format)
{

        struct adv7180_state *state = to_state(sd);

        if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
                if (cfg)
                        format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
        } else {
                adv7180_mbus_fmt(sd, &format->format);
                format->format.field = state->field;
        }

        return 0;
}

The driver crashs because nvidia code (Linux_for_Tegra/sources/kernel/nvidia/drivers/media/platform/tegra/camera/vi/channel.c) call this funcion with parameter *cfg = NULL on this code:

/* Get the format based on active code of the sub-device */
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        if (ret)
                return;

        /* Initiate the channel format to the first matched format */
        chan->fmtinfo =
                tegra_core_get_format_by_code(chan, fmt.format.code, 0);
        v4l2_fill_pix_format(&chan->format, &fmt.format);
        tegra_channel_update_format(chan, chan->format.width,
                                chan->format.height,
                                chan->fmtinfo->fourcc,
                                &chan->fmtinfo->bpp, 0);

Driver code is called by line 2, with my fix the if on line 3 fail, so the code continue.
on line 10 the chan->fmtinfo variable is NULL and kernel crashs.
channel.c is maintened by Nvidia, so do you know what is happening here? Mybe I need some value on DT to have a not null value on chan->fmtinfo?

Thanks.

hello alfredosalvarani,

there’s low-level kernel drivers to convert v4l2 pixel format (fourcc) into media bus format code for internal usage.
you may have device tree definition to indicate the sensor formats,
please refer to Sensor Software Driver Programming Guide, and check the pixel_phase property descriptions.
please also refer to below code-snippet for reference,
thanks

<i>$l4t-r32.2/public_sources/kernel_src/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-modules/tegra186-camera-e3326-a00.dtsi</i>

    mode0 { 
        pixel_phase = "bggr";


<i>$l4t-r32.2/public_sources/kernel_src/kernel/nvidia/drivers/media/platform/tegra/camera/sensor_common.c</i>

static int extract_pixel_format(const char *pixel_t, u32 *format){...}

Hello Jerry.

Maybe I’ve found a bug on Nvidia sources.
After change some properties on adv7180_probe function, the driver stooped to segfault, but it’s complain about missing DT properties.
I’ve supplied theses properties and new ones pop out, I continued on this until theses logs happen:

[    9.902901] adv7180 6-0021: sensor_common_parse_control_props:framerate_factor:property missing

But on my DT there’s framerate_factor (line 41):

/* ADV7280m */
 i2c@31c0000 {
 	adv7280m@21 {
 		compatible = "adi,adv7280-m";
 		reg = <0x21>;
		physical_w = "15.0";
    	physical_h = "12.5";
    	sensor_model ="adv7280m";
    	post_crop_frame_drop = "0";
    	use_decibel_gain = "true";
    	delayed_gain = "true";
    	use_sensor_mode_id = "true";

		mode0 {
			mclk_khz = "28636";
			num_lanes = "2";
			tegra_sinterface = "serial_a";
			phy_mode = "DPHY";
			discontinuous_clk = "no";
			dpcm_enable = "false";
			cil_settletime = "0";
			dynamic_pixel_bit_depth = "12";
			csi_pixel_bit_depth = "12";
			mode_type = "bayer";
			pixel_phase = "bggr";
			active_w = "1920";
			active_h = "1080";
			readout_orientation = "0";
			line_length = "2200";
			inherent_gain = "1";
			mclk_multiplier = "2";
			pix_clk_hz = "74250000";

			gain_factor = "10";
			min_gain_val = "0";         /* 0dB */
			max_gain_val = "480";       /* 48dB */
			step_gain_val = "3";        /* 0.3 */
			default_gain = "0";
			min_hdr_ratio = "1";
			max_hdr_ratio = "1";
			framerate_factor = "1000000";
			min_framerate = "1500000";
			max_framerate = "30000000"; /* 30 */
			min_exp_time = "30";        /* us */
			max_exp_time = "660000";    /* us */
			step_exp_time = "1";
			default_exp_time = "33334"; /* us */
			embedded_metadata_height = "1";
    	};


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

 			port@0 {
 				status = "okay";
 				reg = <0>;
 				adv7280m_out0: endpoint {
 					status = "okay";
					port-index = <0>;
 					bus-width = <2>;
 					remote-endpoint = <&adv7280m_csi_in0>;
 				};
 			};
 		};
 	};
 };

Then, after 2 day of debugin I found these on public_sources/kernel_src/nvidia/drivers/media/platform/tegra/camera/sensor_common.c:

static int sensor_common_parse_control_props(
	struct device *dev, struct device_node *node,
	struct sensor_control_properties *control)
{
	int err = 0;
	u32 value = 0;
	u64 val64 = 0;

	err = read_property_u32(node, "gain_factor", &value);
	if (err) {
		dev_dbg(dev, "%s:%s:property missing\n",
			__func__, "gain_factor");
		control->gain_factor = 1;
		return 0;
	} else
		control->gain_factor = value;

	err = read_property_u32(node, "framerate_factor", &value);
	if (err) {
		dev_err(dev, "%s:%s:property missing\n",
			__func__, "framerate_factor");
		control->framerate_factor = 1;
	} else
		control->framerate_factor = value;

	err = read_property_u32(node, "exposure_factor", &value);
	if (err) {
		dev_err(dev, "%s:%s:property missing\n",
			__func__, "framerate_factor");
		control->exposure_factor = 1;
	} else
		control->exposure_factor = value;

Look at line 29, (it’s on line 396 in the original file). I believe it’s a bug, because this piece of code is about “exposure_factor” not “framerate_factor”.

Is there some place where I can open a ticket for it?

Thanks.

hello alfredosalvarani,

nice catch, I’ve submit a changes to address that error prints.

Hi Jerry,
I’m trying to change ADV7180.c to work with v4l2 modified by Nvidia, but I’m getting segdev because of a pointer not initialized.
This happen on function tegra_channel_get_sensor_type of file channel.c (kernel/nvidia/drivers/media/platform/tegra/camera/vi/channel.c) it try to access &s_data-.sensor_props.sensor_modes[0] and this is initialized on:

static u32 tegra_channel_get_sensor_type(struct tegra_channel *chan)
{
	u32 phy_mode = 0, sensor_type = 0;
	struct v4l2_subdev *sd = chan->subdev_on_csi;
	struct camera_common_data *s_data =
		to_camera_common_data(sd->dev);
	struct sensor_mode_properties *sensor_mode;

The data structure is very very complex, but I can find that chan->subdev_on_csi is initialized on tegra_channel_init_subdevices(struct tegra_channel *chan)

I believe this data is missing because something missing on probe function, but I don’t know what is missing:

static int adv7180_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	struct adv7180_state *state;
	struct v4l2_subdev *sd;
	struct camera_common_data *common_data;
	struct adv7180 *priv;
	int err;
	int ret;
	int i;

	/* Check if the adapter supports the needed features */
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return -EIO;

	v4l_info(client, "chip found @ 0x%02x (%s)\n",
		 client->addr, client->adapter->name);

	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
	if (state == NULL)
		return -ENOMEM;

	state->client = client;
	state->field = V4L2_FIELD_INTERLACED;
	state->chip_info = (struct adv7180_chip_info *)id->driver_data;

	state->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
						   GPIOD_OUT_HIGH);
	if (IS_ERR(state->pwdn_gpio)) {
		ret = PTR_ERR(state->pwdn_gpio);
		v4l_err(client, "request for power pin failed: %d\n", ret);
		return ret;
	}

	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
		state->csi_client = i2c_new_dummy(client->adapter,
				ADV7180_DEFAULT_CSI_I2C_ADDR);
		if (!state->csi_client)
			return -ENOMEM;
	}

	if (state->chip_info->flags & ADV7180_FLAG_I2P) {
		state->vpp_client = i2c_new_dummy(client->adapter,
				ADV7180_DEFAULT_VPP_I2C_ADDR);
		if (!state->vpp_client) {
			ret = -ENOMEM;
			goto err_unregister_csi_client;
		}
	}

	common_data = devm_kzalloc(&client->dev,
			    sizeof(struct camera_common_data), GFP_KERNEL);

	priv = devm_kzalloc(&client->dev,
			    sizeof(struct adv7180) + sizeof(struct v4l2_ctrl *),
			    GFP_KERNEL);
	if (!priv) {
		dev_err(&client->dev, "unable to allocate memory!\n");
		return -ENOMEM;
	}

/*
	priv->regmap = devm_regmap_init_i2c(client, &sensor_regmap_config);
	if (IS_ERR(priv->regmap)) {
		dev_err(&client->dev,
			"regmap init failed: %ld\n", PTR_ERR(priv->regmap));
		return -ENODEV;
	}
*/
/*
	if (client->dev.of_node)
		priv->pdata = imx185_parse_dt(client, common_data);
	if (!priv->pdata) {
		dev_err(&client->dev, "unable to get platform data\n");
		return -EFAULT;
	}*/

	//common_data->ops = &adv7180_ops;
	common_data->ctrl_handler = &priv->ctrl_handler;
	common_data->dev = &client->dev;
	//common_data->frmfmt = &imx185_frmfmt[0];
	//common_data->colorfmt = camera_common_find_datafmt(
	//				  IMX185_DEFAULT_DATAFMT);
	common_data->power = &priv->power;
	common_data->ctrls = priv->ctrls;
	common_data->priv = (void *)priv;
	common_data->numctrls = 1;
	//common_data->numfmts = ARRAY_SIZE(imx185_frmfmt);
	common_data->def_mode = ADV7180_DEFAULT_MODE;
	common_data->def_width = ADV7180_DEFAULT_WIDTH;
	common_data->def_height = ADV7180_DEFAULT_HEIGHT;
	//common_data->fmt_width = common_data->def_width;
	//common_data->fmt_height = common_data->def_height;
	common_data->def_clk_freq = ADV7180_DEFAULT_CLK_FREQ;

	priv->i2c_client = client;
	priv->s_data = common_data;
	priv->subdev = &common_data->subdev;
	priv->subdev->dev = &client->dev;
	priv->s_data->dev = &client->dev;
	priv->last_wdr_et_val = 0;

	err = camera_common_initialize(common_data, "adv7180");
	if (err) {
		dev_err(&client->dev, "Failed to initialize adv7180.\n");
		return err;
	}	

	state->irq = client->irq;
	mutex_init(&state->mutex);
	state->curr_norm = V4L2_STD_NTSC;
	if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED)
		state->powered = true;
	else
		state->powered = false;
	state->input = 0;
	sd = &state->sd;
	v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;

	ret = adv7180_init_controls(state);
	if (ret)
		goto err_unregister_vpp_client;

	state->pad.flags = MEDIA_PAD_FL_SOURCE;
	sd->entity.flags |= MEDIA_ENT_F_ATV_DECODER;
	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
	ret = media_entity_pads_init(&sd->entity, 1, &state->pad);
	if (ret)
		goto err_free_ctrl;

	ret = init_device(state);
	if (ret)
		goto err_media_entity_cleanup;

	if (state->irq) {
		ret = request_threaded_irq(client->irq, NULL, adv7180_irq,
					   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
					   KBUILD_MODNAME, state);
		if (ret)
			goto err_media_entity_cleanup;
	}

	// copy properties from sd to priv->subdev:
	priv->subdev->asd = sd->asd;
	priv->subdev->ctrl_handler = sd->ctrl_handler;
	priv->subdev->dev = sd->dev;
	priv->subdev->dev_priv = sd->dev_priv;
	priv->subdev->devnode = sd->devnode;
	priv->subdev->host_priv = sd->host_priv;
	priv->subdev->internal_ops = sd->internal_ops;
	for (i = 0; i < V4L2_SUBDEV_NAME_SIZE; i++)
		priv->subdev->name[i] = sd->name[i];
	priv->subdev->notifier = sd->notifier;
	priv->subdev->of_node = sd->of_node;
	priv->subdev->ops = sd->ops;
	priv->subdev->owner = sd->owner;
	priv->subdev->pdata = sd->pdata;
	priv->subdev->v4l2_dev = sd->v4l2_dev;

	priv->subdev->entity = sd->entity;
	priv->subdev->async_list = sd->async_list;

	ret = v4l2_async_register_subdev(priv->subdev);
	if (ret)
		goto err_free_irq;

	return 0;

err_free_irq:
	printk(KERN_DEBUG "err_free_irq %s:%i\n", __FILE__, __LINE__);
	if (state->irq > 0)
		free_irq(client->irq, state);
err_media_entity_cleanup:
	printk(KERN_DEBUG "err_media_entity_cleanup %s:%i\n", __FILE__, __LINE__);
	media_entity_cleanup(&sd->entity);
err_free_ctrl:
	printk(KERN_DEBUG "err_free_ctrl %s:%i\n", __FILE__, __LINE__);
	adv7180_exit_controls(state);
err_unregister_vpp_client:
	printk(KERN_DEBUG "err_unregister_vpp_client %s:%i\n", __FILE__, __LINE__);
	if (state->chip_info->flags & ADV7180_FLAG_I2P)
		i2c_unregister_device(state->vpp_client);
err_unregister_csi_client:
	printk(KERN_DEBUG "err_unregister_csi_client %s:%i\n", __FILE__, __LINE__);
	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
		i2c_unregister_device(state->csi_client);
	mutex_destroy(&state->mutex);
	return ret;
}

I’m try to determine where I can initialize &s_data-.sensor_props.sensor_modes[0] but it’s very hard to do.
Can you help-me?
I am still trying to find it too.

Thanks!

hello alfredosalvarani,

there’re three sensor mode property categories that you should fill-in, signal_properties, image_properties, and control_properties.
you should refer to header file for each of properties structures.
for example,
$l4t-r32.2/public_sources/kernel_src/kernel/nvidia/include/media/tegra-v4l2-camera.h

these property settings were define in the sensor device tree,
suggest you should check reference driver and create your own device tree.
for example,
$l4t-r32.2/public_sources/kernel_src/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-modules/tegra186-camera-e3326-a00.dtsi

you may also refer to Sensor Software Driver Programming Guide and check [Device Properties] session for descriptions.
thanks