Problem porting CSI camera driver from 4.4 kernel to 4.9 kernel

We are trying to port an existing, operating camera driver from the 4.4 / L4T 28.1 BSP
to the new 4.9 kernel / L4T 32.1 BSP. This is proving to be a frustrating task.

I have followed the recommendations in the “Sensor Driver Programming Guide” regarding
this update, but I still cannot get the video inputs to register.

The problem results in a kernel access violation during the _probe funciton
when the module is loaded, with the following backtrace.

71.574691] Call trace:
[   71.577242] [<ffffff8008b1a224>] camera_common_g_fmt+0x8c/0x100
[   71.583242] [<ffffff8008b1e5f8>] v4l2sd_get_fmt+0x48/0x58
[   71.588767] [<ffffff8008cb48c0>] tegra_channel_fmts_bitmap_init+0x230/0x320
[   71.595818] [<ffffff8008b0abdc>] tegra_channel_init_subdevices+0x754/0x7a8
[   71.602750] [<ffffff8008b0b978>] tegra_vi_graph_notify_complete+0x500/0x688
[   71.609805] [<ffffff8008aefe48>] v4l2_async_test_notify+0x108/0x120
[   71.616129] [<ffffff8008af0088>] v4l2_async_register_subdev+0x88/0x108
[   71.622720] [<ffffff8008b1e3bc>] tegracam_v4l2subdev_register+0xec/0x1c8
[   71.629575] [<ffffff8000f49594>] cti_4chrolan_hd_in_probe+0x1b4/0x3f0 [cti_4chrolan_hd_in]

The new driver is modeled on the existing imx185.c driver.

As near as I can tell, the problem is that in “camera_common_g_fmt”, the colorfmt
pointer is not set.

int camera_common_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
{
	struct camera_common_data *s_data;
	const struct camera_common_colorfmt *fmt;

	printk( "%s start\n", __func__);

	s_data = to_camera_common_data(sd->dev);
	printk( "%s A camera_common_data * s_data %p mf %p\n", __func__, s_data, mf);

	fmt = s_data->colorfmt;
	printk( "%s C fmt %p \n", __func__, fmt); // fmt is null
	mf->code	= fmt->code;
	mf->colorspace	= fmt->colorspace;
	mf->width	= s_data->fmt_width;
	mf->height	= s_data->fmt_height;
	printk( "%s D\n", __func__);
	mf->field	= V4L2_FIELD_NONE;
	mf->xfer_func = fmt->xfer_func;
	mf->ycbcr_enc = fmt->ycbcr_enc;
	mf->quantization = fmt->quantization;
	
	printk( "%s finished\n", __func__);
	return 0;
}

when I run this I get.

71.406737] camera_common_g_fmt start
[   71.410459] camera_common_g_fmt A camera_common_data * s_data ffffffc1e1f89418 mf ffffffc1b3ea7790
[   71.419459] camera_common_g_fmt C fmt           (null)

All of the video formats are provided in the _probe operation in the “camera_common_sensor_ops”
structure set in the “tc_dev->sensor_ops” field.

The rest of the initialization (i.e the vi subsystem parsing the device tree) seems
to be working correctly.

Any insight into how to go forward and solve this problem.

I think the underlying problem happens in “tegra_channel_fmts_bitmap_init”, in that
when it tries to loop through the formats, i.e the call to

ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
				       NULL, &code);

Returns an error the first time.

Any ideas how to go about debugging this problem?

Thanks in advance,

Cary

I made some progress, the pixel format issue has been resolved. We still
have a couple of problems.

Problem 1

After loading the kernel module with the camera driver, there is an internal attempt
to open /dev/v4l-subdev0 and /dev/v4l2-subdev1. Since there is only a single device,
the second attempt throws an access violation in subdev_open because sd->v4l2_dev is
null.

PROBLEM 2

The v4l2src element does not seem to be present in gstreamer. This is a bit of a problem
since this is used for our video capture application.

Any insight would be appreciated.

Thank you.

Cary

Don’t understand well for the problem 1.
The v4l2src should be there by default system package.
Please confirm the gst-inspect-1.0 v4l2src to check.

I think I’ve figured out what is wrong.

gst-inspect-1.0 will attempt to open /dev/video0, (?) /dev/v4l-subdev0, /dev/v4l-subdev1

If there is an error there, the gstreamer module cache will not register the element.

My camera driver is a loadable kernel module, so if I reboot (# indicates commands I type)…

# gst-inspect-1.0 | grep v4l2src
video4linux2:  v4l2src: Video (video4linux2) Source

# insmod camera_driver.ko
 [1611.636653] Internal error: Accessing user space memory outside uaccess.h routines: 96000005 

# gst-inspect-1.0 | grep v4l2src
[ 1616.781393] subdev_open A file ffffffc18abb1400
[ 1616.785944] path: /dev/v4l-subdev0
(ok)
[ 1616.818655] subdev_open A file ffffffc18abb1100
[ 1616.823200] path: /dev/v4l-subdev1
...
[ 1617.169076] Internal error: Accessing user space memory outside uaccess.h routines
(fails)
# gst-launch-1.0 v4l2src ! fakesink
WARNING: erroneous pipeline: no element "v4l2src"

So if there is an error in your camera driver, gstreamer will fail to register the
module with the v4l2src element.

I am working on solving the second subdevice problem.

I have found solutions to the two problems described here. I haven’t been
able to fully test the ported driver yet, but I’m going to detail them and close this issue
in case this information can help someone later.

  1. access violation in camera_common_g_fmt

This was caused by the pixel format in the device tree not matching the
pixel formats in camera_common.c and sensor_common.c

Our video capture circuitry presents uyvy, not bayer video, so these
formats needed to be added.

in device tree (Based on comments in "Sensor Programming Guide) add pixel_phase,
and set pixel_t and pixel_phase (new?) to the right value (“uyvy” in our case) in
each video capture mode for the device.

in sensor_common.c

static int extract_pixel_format(
	const char *pixel_t, u32 *format)
{
	size_t size = strnlen(pixel_t, OF_MAX_STR_LEN);

	if (strncmp(pixel_t, "bayer_bggr10", size) == 0)
		*format = V4L2_PIX_FMT_SBGGR10;
        // other bayer formats ...

        // our format

        else if (strncmp(pixel_t, "uyvy", size) == 0) {
		*format = V4L2_PIX_FMT_UYVY;
        }

in camera_common.c

static const struct camera_common_colorfmt camera_common_color_fmts[] = {

// bayer formats...

// our format

  {
	MEDIA_BUS_FMT_UYVY8_1X16,
	V4L2_COLORSPACE_SRGB,
	V4L2_PIX_FMT_UYVY
    },
};

Ideally this should be caught and flagged as an error in tegracam_device_register()

2 error opening /dev/v4l-subdev1

This was caused by inadvertently copying the call to tegracam_v4l2subdev_register()
twice from imx185.c

This interacted with gstreamer because calling gst-inspect-1.0 can (surprisingly)
cause an iteration of the devices in

/sys/devices/13e10000.host1x/15700000.vi/video4linux

Due to the incorrect device, the v4l2src element wasn’t available.

As always, thanks for your help.