Porting camera interface from JP4.6.1 to JP5.0.2 open() function differences

Currently migrating from 4.6.1 to 5.0.2. We use C++ scripts to interface with the cameras we have developed drivers for. We are having an issue where calling the open() function open("/dev/video0", O_RDWR); previously this would toggle the camera enable GPIO High (call the power_on function). However this no longer happens in 5.0.2. Has there been a change in the kernel which could cause this behaviour?

hello benm12y6,

here’s developer guide, Camera Driver Porting.

BTW,
are you using kernel APIs to toggle the pin? which pin it is?
please note that GPIO number has changed since k-5.10, please refer to developer guide, [Identifying the GPIO Number].
you may follow the GPIO debugfs for looking up the port and offset.
besides, I saw an issue for using marco to export the pin and toggling GPIO pin, you may try modify the code for using GPIO number directly for testing.

Hi JerryChang

Thanks for getting back to me so quickly. We are using an I2C GPIO chip for this application. The Pin comes up fine and toggles on command. In order to turn on power to the sensor we were not ever manually controlling the pin. This happened by default when calling the open() function on the camera device.

I still had a Jetson running 4.6.1 so I did a stack trace to see what the function call order was when the open() function was called in our c++ application.

[14936.318380]  gpiod_set_raw_value
[14936.318397]  imxtest_power_on
[14936.318408]  camera_common_s_power
[14936.318416]  tegra_channel_set_power
[14936.318423]  vi5_power_on
[14936.318430]  tegra_channel_open
[14936.318438]  v4l2_open

There appears to have been changes in the function tegra_channel_open() between jetpack 4.6.1 and 5.0.2.
(file: sources/kernel/nvidia/drivers/media/platform/tegra/camera/vi/channel.c )

The particular change to this function is shown here:

@@ -2149,14 +2297,14 @@
 	vi = chan->vi;
 	csi = vi->csi;
 
-	/* The first open then turn on power */
-	if (vi->fops) {
-		ret = vi->fops->vi_power_on(chan);
+	chan->fh = (struct v4l2_fh *)fp->private_data;
+
+	if (tegra_channel_verify_focuser(chan)) {
+		ret = tegra_channel_set_power(chan, true);
 		if (ret < 0)
-			goto fail;
-	}
-
-	chan->fh = (struct v4l2_fh *)fp->private_data;
+			return ret;
+	}
+

It seems like previously this function would be called following a call to open() on a video device (specifically v4l2_open) This would then turn power on to any camera. This seems to have changed, and now the function checks if the device is a ‘focuser’ by calling the function tegra_channel_verify_focuser(). As far as I can tell, this function simply checks if a video devices name contains a string for a model number of a focuser.

static bool tegra_channel_verify_focuser(struct tegra_channel *chan)
{
	char *focuser;

	/*
	 * WAR - to avoid power on/off during open/close for sensor
	 * nodes but not focuser nodes.
	 * add an array when more focusers are available, this logic is
	 * not needed once the focuser is bound to sensor channel
	 */
	focuser = strnstr(chan->video->name, "lc898212", sizeof(chan->video->name));

	return (focuser != NULL);
}

This all indicates that the open() function is intended to no longer control the power to sensors. I would like to power on the sensor before the streaming begins in order to apply settings and access eeprom. Is there a way I can do this which isn’t manually toggling the GPIO pin?

hello benm12y6,

it’s common API, camera_common_s_power() for doing this.
you may see reference camera drivers for reading fuse-id,
thanks

Hi Jerry,

Thanks again for getting back to me. I am a bit confused by your response. I need to turn on power to the sensor from user space. This used to happen by default just by calling open() but no longer does. How can I do this from user space? I don’t need help reading from the sensor memory in the driver. Inside the eeprom we have sensor settings needed for post processing the images, this information is required in user space.

It looks like this commit is what has changed SHA: da57b3133ee51a79cb110855c3eb61bfa147f4aa

hello benm12y6,

this change is resolving the issue that desired channel opened and closed multiple times before it gets finally opened for streaming.
it may cause capture timeout issue, and it also effect camera launch KPI.

the latest update is…
it only powering on/off sensor when streaming, don’t power on/off sensor when querying static properties.
besides, I see this change has check-in to rel-32 code-line also. JP-4.6.x should also include this update.

So I guess my question is, is there a way to turn power on to the camera from user space before beginning streaming? This change at the kernel is essentially breaking of functionality in user space, there could be other use applications which are impacted by changes in how cameras behave.

hello benm12y6,

as you can see… it actually power-on sensor module before streaming.
however, this being called by start_streaming API.

static int tegra_channel_start_streaming(struct vb2_queue *vq, u32 count)
...
  		/* power on hw at the start of streaming */
  		ret = vi->fops->vi_power_on(chan);
 		...
 		return vi->fops->vi_start_streaming(vq, count);

HI Jerry,

Thanks, I can see that this is whats happening. Sorry perhaps I haven’t been clear. The sensor does come on and stream fine. However our use case looks like this:

  • Power on the sensor.

  • Get data in userspace from eeprom device on the camera (this contains information about the colour correction, intrinsics of the camera, etc) We need this in userspace as it needs to be passed down stream to post processing steps which consume the camera data.

  • Apply some settings to the camera which must be applied before we start streaming. These are configuration settings stored in user space.

  • Start streaming.

The issue we have now is that from our perspective in user space, the only time the camera in powered on is after we call the start_streaming command through ioctl(). This is a problem because the functionality that existed before is now broken. We cant access the eeprom in user space until we start streaming. We cant set these settings when the camera isn’t streaming.

hello benm12y6,

could you please try this…

struct v4l2_subdev_core_ops {
...
	int (*s_power)(struct v4l2_subdev *sd, int on);

you should calling this API to power-on the device without start streaming.
please have a try, thanks