IMX296 sensor driver for Jetson Nano 32.2

Hi,
We are porting IMX296 sensor driver to Jetson Nano L4T 32.2.
IMX296 is mono/color sensor 1440x1080, 60 FPS, 1 lane, 1.2 Gbps/lane.

The driver probes OK, but the streaming fails. Attempt to get one frame enters into probably infinite loop with the following error messages:

v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=1
[  527.376631] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 0
[  527.392955] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 1
[  527.409834] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 2
[  527.426508] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 3
[  527.442632] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 4
[  527.459222] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 5
[  527.475890] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 6
[  527.493291] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 7
[  527.509050] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 8
[  527.525937] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 9
[  527.542422] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 10
[  527.559153] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 11
. . . . . . . . . . . . .

Here is our device tree:

#include <dt-bindings/media/camera.h>
#include <dt-bindings/platform/t210/t210.h>

#define CAM0_RST_L  TEGRA_GPIO(S, 4)
#define CAM0_PWDN   TEGRA_GPIO(S, 7)

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

    host1x {
        vi_base: vi {
            num-channels = <1>;
            status = "okay";
            ports {
                #address-cells = <1>;
                #size-cells = <0>;
                vi_port0: port@0 {
                    reg = <0>;
                    imx296_vi_in0: endpoint {
                        port-index = <0>;
                        bus-width = <2>;
                        remote-endpoint = <&imx296_csi_out0>;
                    };
                };
            };
        };

        csi_base: nvcsi {
            num-channels = <1>;
            #address-cells = <1>;
            #size-cells = <0>;
            status = "okay";
            csi_chan0: channel@0 {
                reg = <0>;
                ports {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    csi_chan0_port0: port@0 {
                        reg = <0>;
                        imx296_csi_in0: endpoint@0 {
                            port-index = <0>;
                            bus-width = <2>;
                            remote-endpoint = <&imx296_out0>;
                        };
                    };
                    csi_chan0_port1: port@1 {
                        reg = <1>;
                        imx296_csi_out0: endpoint@1 {
                            remote-endpoint = <&imx296_vi_in0>;
                        };
                    };
                };
            };
        };

        i2c@546c0000 {
            status = "okay";

            imx296_c@1a {
                compatible = "nvidia,imx296";
                reg = <0x1a>;
                devnode = "video0";

                status = "okay";
                reset-gpios = <&gpio CAM0_PWDN GPIO_ACTIVE_HIGH>;

                /* Physical dimensions of sensor */
                physical_w = "3.674";
                physical_h = "2.738";
                sensor_model ="imx296";
                use_sensor_mode_id = "true";

                mode0 { // IMX296_MODE_1440X1080, 60 FPS
                    mclk_khz = "24000";
                    num_lanes = "1";
                    tegra_sinterface = "serial_a";
                    phy_mode = "DPHY";
                    discontinuous_clk = "no";
                    dpcm_enable = "false";
                    cil_settletime = "0";

                    active_w = "1440";
                    active_h = "1080";
                    pixel_t = "y10";

                    csi_pixel_bit_depth = "8";

                    readout_orientation = "90";
                    line_length = "2048";
                    inherent_gain = "1";

                    mclk_multiplier = "9.33";

// 1440 * 1080 * 60 = 93312000:
                    pix_clk_hz = "93312000";

                    gain_factor = "16";
                    framerate_factor = "1000000";
                    exposure_factor = "1000000";

                    min_gain_val = "0";
                    max_gain_val = "480";
                    step_gain_val = "1";
                    default_gain = "200";

                    min_hdr_ratio = "1";
                    max_hdr_ratio = "1";

                    min_framerate = "10000000"; /* 10.0 fps */
                    max_framerate = "60000000"; /* 60.0 fps */
                    step_framerate = "1";
                    default_framerate = "60000000"; /* 60.0 fps */

                    min_exp_time = "29";        // us
                    max_exp_time = "15110711";  // us
                    step_exp_time = "1";
                    default_exp_time = "10000"; // us

                    embedded_metadata_height = "0";
                };

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

                    port@0 {
                        reg = <0>;
                        imx296_out0: endpoint {
                            port-index = <0>;   // <2> : TX2
                            bus-width = <2>;  // +++
                            remote-endpoint = <&imx296_csi_in0>;
                        };
                    };
                };

        };

      };

    };  // host1x

    tcp: tegra-camera-platform {
        compatible = "nvidia, tegra-camera-platform";
        num_csi_lanes = <1>;  // <2>;
        max_lane_speed = <1500000>;
        min_bits_per_pixel = <8>;
        vi_peak_byte_per_pixel = <2>;
        vi_bw_margin_pct = <25>;
        max_pixel_rate = <240000>;
        isp_peak_byte_per_pixel = <5>;
        isp_bw_margin_pct = <25>;
        status = "okay";

        modules {
            cam_module0: module0 {
                status = "okay";
                badge = "porg_front_RBPCV2";
                position = "front";
                orientation = "1";
                cam_module0_drivernode0: drivernode0 {
                    pcl_id = "v4l2_sensor";     
                    devname = "imx296 6-001a";  /* Driver v4l2 device name */
                    proc-device-tree = "/proc/device-tree/host1x/i2c@546c0000/imx296_c@1a";
                };

            };
        };
    };
};

Please enable the trace log to get more information.

https://elinux.org/Jetson_TX2_Camera_BringUp

At the moment we can’t get kernel trace info on Jetson Nano. The procedure, described in https://elinux.org/Jetson_TX2_Camera_BringUp
does not work on Nano, some files are missing.

OOPS not notice it’s Nano/TX1.
Could you enable the debug log in the csi2_fops.c by below command

sudo su
echo file csi2_fops.c +p > /sys/kernel/debug/dynamic_debug/control
[   62.866269] imx296 6-001a: imx296_set_mode(): fmt_width,fmt_height=1440,1080 pix_fmt=0x20303159 'Y10 ', cam_mode=0
[   62.877038] imx296 6-001a: imx296_set_gain: Set gain = 200
[   62.884906] imx296 6-001a: imx296_set_exposure: min_exp_time,max_exp_time=29,15110711 default_exp_time=10000
[   62.906575] imx296 6-001a: imx296_start_streaming(): err=0

[   62.912100] vi 54080000.vi: Calibrate csi port 0
[   62.963984] imx296 6-001a: imx296_stop_streaming(): err=0

[   63.020041] vi 54080000.vi: cil_settingtime was autocalculated
[   63.020047] vi 54080000.vi: csi clock settle time: 13, cil settle time: 10
[   63.020064] imx296 6-001a: imx296_set_mode(): fmt_width,fmt_height=1440,1080 pix_fmt=0x20303159 'Y10 ', cam_mode=0
[   63.032707] imx296 6-001a: imx296_set_gain: Set gain = 200
[   63.039826] imx296 6-001a: imx296_set_exposure: min_exp_time,max_exp_time=29,15110711 default_exp_time=10000
[   63.062831] imx296 6-001a: imx296_start_streaming(): err=0
[   63.080016] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 0
[   63.096281] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 1
. . . . . .

Should print the status like below code.

void tegra_csi_status(struct tegra_csi_channel *chan, int port_idx)
{
        int i;
        u32 val;
        struct tegra_csi_port *port;

        for (i = 0; i < chan->numports; i++) {
                port = &chan->ports[i];
                val = pp_read(port, TEGRA_CSI_PIXEL_PARSER_STATUS);

                dev_dbg(chan->csi->dev,
                        "TEGRA_CSI_PIXEL_PARSER_STATUS 0x%08x\n",
                        val);

                val = cil_read(port, TEGRA_CSI_CIL_STATUS);
                dev_dbg(chan->csi->dev,
                        "TEGRA_CSI_CIL_STATUS 0x%08x\n", val);

                val = cil_read(port, TEGRA_CSI_CILX_STATUS);
                dev_dbg(chan->csi->dev,
                        "TEGRA_CSI_CILX_STATUS 0x%08x\n", val);
        }
}
EXPORT_SYMBOL(tegra_csi_status);

Hi ShaneCCC,
Thank you for your support.

We fixed the infinite error message dump:

[  527.376631] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 0
[  527.392955] vi 54080000.vi: tegra_channel_error_status:error 4000 frame 1
. . . . . . . . . . . . .

The problem was in the device tree:
num_lanes = “1”;
num_csi_lanes = <1>;
require:
bus-width = <1>; // was <2>

Now we are able to stream, but we receive error MW_ACK_DONE syncpoint time out! i=0.
A single frame image seems OK. Multiple image captures give the following results:
1 valid frame, 3 zero frames, 1 valid frame, 3 zero frames, …

We had similar error with another driver, which was caused by mismatch between the dimensions of the sensor output and what Nano expected (frame stride != k*64). But now the frame size seems correct.

Here is the system dump (+ dump from our driver):

[ 1199.669238] imx296 6-001a: imx296_set_mode(): fmt_width,fmt_height=1440,1080 pix_fmt=0x20303159 'Y10 ', cam_mode=0
[ 1199.680491] imx296 6-001a: imx296_set_gain: Set gain = 20
[ 1199.687699] imx296 6-001a: imx296_set_exposure: min_exp_time,max_exp_time=29,15110711 default_exp_time=10000
[ 1199.697668] imx296 6-001a: imx296_exposure(): exposure_time=10000, SHS=0x1bc (444)
[ 1199.711883] imx296 6-001a: imx296_start_streaming(): err=0
[ 1199.717430] vi 54080000.vi: Calibrate csi port 0
[ 1199.769531] imx296 6-001a: imx296_stop_streaming(): err=0

[ 1199.827872] vi 54080000.vi: cil_settingtime was autocalculated
[ 1199.827878] vi 54080000.vi: csi clock settle time: 13, cil settle time: 10
[ 1199.827893] imx296 6-001a: imx296_set_mode(): fmt_width,fmt_height=1440,1080 pix_fmt=0x20303159 'Y10 ', cam_mode=0
[ 1199.838902] imx296 6-001a: imx296_set_gain: Set gain = 20
[ 1199.847752] imx296 6-001a: imx296_set_exposure: min_exp_time,max_exp_time=29,15110711 default_exp_time=10000
[ 1199.857604] imx296 6-001a: imx296_exposure(): exposure_time=10000, SHS=0x1bc (444)
[ 1199.869034] imx296 6-001a: imx296_start_streaming(): err=0
[ 1199.952809] video4linux video0: Syncpoint already enabled at capture done!0
[ 1200.155108] video4linux video0: tegra_channel_capture_done: MW_ACK_DONE syncpoint time out! i=0
[ 1200.172186] video4linux video0: tegra_channel_capture_error(): index=0: TEGRA_VI_CSI_ERROR_STATUS 0x00000008
[ 1200.188273] vi 54080000.vi: TEGRA_CSI_PIXEL_PARSER_STATUS 0x00000000
[ 1200.194675] vi 54080000.vi: TEGRA_CSI_CIL_STATUS 0x00000000
[ 1200.200287] vi 54080000.vi: TEGRA_CSI_CILX_STATUS 0x00000000
[ 1200.206572] vi 54080000.vi: cil_settingtime was autocalculated
[ 1200.206632] vi 54080000.vi: csi clock settle time: 13, cil settle time: 10
[ 1200.261852] imx296 6-001a: imx296_stop_streaming(): err=0

Modify the discontinuous_clk to opposite to try.

mode0 {
                                mclk_khz = "24000";
                                num_lanes = [32 00];
                                tegra_sinterface = "serial_c";
                                phy_mode = "DPHY";
                                discontinuous_clk = "yes";
                                dpcm_enable = "false";
                                cil_settletime = [30 00];
                                active_w = "2592";
                                active_h = "1944";

Hi ShaneCCC,

Change of discontinuous_clk from “no” to “yes” - no effect.
While testing, in very rare cases the message “MW_ACK_DONE syncpoint time out!” did not appear.

Maybe we have some time issue?
Any recommendations how to change timings or insert delays ?

Thanks