Failed to configure sensor_mode by using v4l2 API

I followed Camera Development Guide to set sensor_mode, but failed to set by using V4L2 VIDIOC_S_CTRL

In my device tree, have two sensor modes (mode0 & mode1) configuration.

 kernel/nvidia/include/media/tegra-v4l2-camera.h

#define TEGRA_CAMERA_CID_BASE                   (V4L2_CTRL_CLASS_CAMERA | 0x2000)
#define TEGRA_CAMERA_CID_VI_BYPASS_MODE         (TEGRA_CAMERA_CID_BASE+100)
#define TEGRA_CAMERA_CID_SENSOR_MODE_ID         (TEGRA_CAMERA_CID_BASE+8)

static void start_capturing(uint8_t cam_id)
{
	unsigned int i;
	enum v4l2_buf_type type;
	struct v4l2_control camera_control;

	//IO_METHOD_MMAP:
	for (i = 0; i < n_buffers[cam_id]; ++i) {
		struct v4l2_buffer buf;

		CLEAR(buf);
		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		buf.memory = V4L2_MEMORY_MMAP;
		buf.index = i;

		if (-1 == xioctl(fd[cam_id], VIDIOC_QBUF, &buf))
				errno_exit("VIDIOC_QBUF");
	}

	type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if (-1 == xioctl(fd[cam_id], VIDIOC_STREAMON, &type))
			errno_exit("VIDIOC_STREAMON");

	memset(&camera_control,0,sizeof(camera_control));
	camera_control.id=TEGRA_CAMERA_CID_VI_BYPASS_MODE;
	camera_control.value=0;
	if (-1 == xioctl(fd[cam_id],VIDIOC_S_CTRL,&camera_control)) {
			printf("Failed to configure %d sensor bypass mode\n", cam_id);
			errno_exit("VIDIOC_S_CTRL");
	}

	memset(&camera_control,0,sizeof(camera_control));
	camera_control.id=TEGRA_CAMERA_CID_SENSOR_MODE_ID;
	camera_control.value=1;
	if (-1 == xioctl(fd[cam_id],VIDIOC_S_CTRL,&camera_control)) {
			printf("Failed to configure %d sensor mode\n", cam_id);
			errno_exit("VIDIOC_S_CTRL");
	}
}

This results
Failed to configure 1 sensor mode
VIDIOC_S_CTRL error 22, Invalid argument

But, Able to configure with v4l2-ctl command line tool.

linux:~$ v4l2-ctl -d0 --set-ctrl sensor_mode=0
linux:~$ v4l2-ctl -d0 --get-ctrl sensor_mode
sensor_mode: 0

linux:~$ v4l2-ctl -d0 --set-ctrl sensor_mode=1
linux:~$ v4l2-ctl -d0 --get-ctrl sensor_mode
sensor_mode: 1

I’m unsure, what is missing in my configuration, can anyone spread light ?

Thanks

hello thiru.shetty,

please refer to Verifying the V4L2 Sensor Driver session for the commands to specify --set-ctrl options to set different sensor modes for verification.
you may using argus_camera to launch camera and choose different modes through user-interface.

please check reference driver for sensor define mode table and also sensor device tree settings,
for example,
there’re three sensor modes available for ov5693.
$L4T_Sources/r32.4.3/Linux_for_Tegra/source/public/kernel/nvidia/drivers/media/i2c/ov5693_mode_tbls.h

static const struct camera_common_frmfmt ov5693_frmfmt[] = {
        {{2592, 1944},  ov5693_30fps,   1, 0,   OV5693_MODE_2592X1944},
        {{2592, 1458},  ov5693_30fps,   1, 0,   OV5693_MODE_2592X1458},
        {{1280, 720},   ov5693_120fps,  1, 0,   OV5693_MODE_1280X720_120FPS},

you should also have same corresponding settings in device tree to indicate these mode properties .
$L4T_Sources/r32.4.3/Linux_for_Tegra/source/public/hardware/nvidia/platform/t19x/common/kernel-dts/t19x-common-modules/tegra194-camera-e3326-a00.dtsi

        i2c@3180000 {
                ov5693_c@36 {
                        compatible = "nvidia,ov5693";
...
                        mode0 { // OV5693_MODE_2592X1944
                        mode1 { //OV5693_MODE_2592X1458
                        mode2 { //OV5693_MODE_1280X720

here’s also another driver for your reference,
you should check below kernel sources for the sensor mode CID controls,
for example, TEGRA_CAMERA_CID_SENSOR_MODE_ID.
$L4T_Sources/r32.4.3/Linux_for_Tegra/source/public/kernel/nvidia/drivers/media/platform/tegra/camera/tegracam_ctrls.c

Hello JerryChang,

Thanks for response…

I configured Device tree and as well as driver, then only able to see v4l2-ctl -d /dev/video0 --set-ctrl sensor_mode=0 working.

But, failed to make it work through v4l2 API i.e VIDIOC_S_CTRL

Is there any example code, which i can refer ? because normal V4L2 doesn’t have such FLAG (SENSOR_MODE_ID)

Driver:

static const struct camera_common_frmfmt imx219_frmfmt = {
{{1472, 1080}, imx219_226fps, 1, 0, IMX219_MODE_1472x1080_226FPS},
{{1248, 2048}, imx219_144fps, 1, 0, IMX219_MODE_1248x2048_144FPS},
};

Device Tree:

/* mode0 for IMX273 */
mode0 { /* IMX219_MODE_1440x1080_226.58FPS */
	mclk_khz = "74250"; //"37125";
	num_lanes = "4";
	tegra_sinterface = "serial_c";
	phy_mode = "DPHY";
    .....
    .....
};
/* mode1 for IMX250 */
mode1 { /* IMX219_MODE_1248x2048_144.7FPS */
	mclk_khz = "74250"; //"37125";
	num_lanes = "4";
	tegra_sinterface = "serial_c";
	phy_mode = "DPHY";
    .....
    .....
};

linux:~$ v4l2-compliance -d /dev/video0
v4l2-compliance SHA   : not available

Driver Info:
        Driver name   : tegra-video
        Card type     : vi-output, imx219 9-0010
        Bus info      : platform:15c10000.vi:0
        Driver version: 4.9.140
        Capabilities  : 0x84200001
                Video Capture
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps   : 0x04200001
                Video Capture
                Streaming
                Extended Pix Format

Compliance test for device /dev/video0 (not using libv4l2):

Required ioctls:
        test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
        test second video open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK
        test for unlimited opens: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 1 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

Test input 0:

        Control ioctls:
                test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
                test VIDIOC_QUERYCTRL: OK
                test VIDIOC_G/S_CTRL: OK
                test VIDIOC_G/S/TRY_EXT_CTRLS: OK
                test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
                test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
                Standard Controls: 1 Private Controls: 20

        Format ioctls:
                test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
                fail: v4l2-test-formats.cpp(1184): ret && node->has_frmintervals
                test VIDIOC_G/S_PARM: FAIL
                test VIDIOC_G_FBUF: OK (Not Supported)
                test VIDIOC_G_FMT: OK
                test VIDIOC_TRY_FMT: OK
                test VIDIOC_S_FMT: OK
                test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
                test Cropping: OK (Not Supported)
                test Composing: OK (Not Supported)
                test Scaling: OK (Not Supported)

        Codec ioctls:
                test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
                test VIDIOC_G_ENC_INDEX: OK (Not Supported)
                test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

        Buffer ioctls:
                test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
                test VIDIOC_EXPBUF: OK

Test input 0:


Total: 43, Succeeded: 42, Failed: 1, Warnings: 0

linux:~$ v4l2-ctl --list-formats-ext

 ioctl: VIDIOC_ENUM_FMT
         Index       : 0
         Type        : Video Capture
         Pixel Format: 'BG10'
         Name        : 10-bit Bayer BGBG/GRGR
                 Size: Discrete 1472x1080
                         Interval: Discrete 0.004s (226.000 fps)
                 Size: Discrete 1248x2048
                         Interval: Discrete 0.007s (144.000 fps)

But only fails with V4L2 API call

It’s could be VIDIOC_S_EXT_CTRLS instead of VIDIOC_S_CTRL

Hello ShaneCCC,

If VIDIOC_S_EXT_CTRLS use, the following error throws.

         struct v4l2_control control;

         memset(&control,0,sizeof(control));
        control.id=TEGRA_CAMERA_CID_SENSOR_MODE_ID;
        control.value=1;
        if (xioctl(fd,VIDIOC_S_EXT_CTRLS,&control)<0) {
           printf("Error in setting sensor mode 0x%X\n", TEGRA_CAMERA_CID_SENSOR_MODE_ID);
           errno_exit("VIDIOC_S_EXT_CTRLS");
        }

Output:
Error in setting sensor mode 0x9A2008
VIDIOC_S_EXT_CTRLS error 14, Bad address\n

Have a reference to below code.

    memset(&ctrls, 0, sizeof(ctrls));
    memset(&ctrl, 0, sizeof(ctrl));

    ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(id);
    ctrls.count = 1;
    ctrls.controls = &ctrl;

    ctrl.id = id;
    if (is_64 == NV_TRUE)
        ctrl.value64 = val;
    else
        ctrl.value = val;

    errno = 0;
    ret = ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
    if (ret && (errno == EINVAL || errno == ENOTTY) && (is_64 == NV_FALSE)) {
        struct v4l2_control old;

        old.id = id;
        old.value = val;
        ret = ioctl(fd, VIDIOC_S_CTRL, &old);
        if (ret) {
            NV_LOGE("%s: Failed to set control %d: %s",
                __func__, id, strerror(errno));
            return NvError_BadValue;
        }
    }

Thanks for quick reply,

ctrls is struct v4l2_ext_controls ?
ctrl is struct v4l2_ext_control ?

Yes, both of them are

    struct v4l2_ext_controls ctrls;
    struct v4l2_ext_control ctrl;
1 Like