VC-MIPI-modules / vc_mipi_nvidia

Vision Components MIPI CSI-2 driver for NVIDIA Jetson Nano, Xavier NX, AGX Xavier, TX2 and Orin Nano, Orin NX
83 stars 34 forks source link

fix devicetree for Orin NX/Nano #23

Closed flixr closed 8 months ago

flixr commented 1 year ago

Fix device tree for cam0 on Orin NX/Nano on Auvidea JNX42.

Tested on Orin NX with two IMX296.

xaprier commented 9 months ago

We managed to get frames from OrinNano with 2 * IMX568 cameras. After a bunch of tries we could get frames from 2 csi ports at the same time(csi port 0 and 1) in Orin Nano with that device tree:

/*
 * Copyright (c) 2023, Vision Components GmbH.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

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

// ------------------------------------------------------------------------------------------------
//  Driver Configuration for NVIDIA Jetson Orin Nano on NVIDIA Jetson Orin Nano Developer Kit
// ------------------------------------------------------------------------------------------------
#define VC_MIPI_CAM_1       1   // 1: Enabled, 0: Disabled  (serial_a => CSI Port 0 => VI Stream 0)
#define VC_MIPI_CAM_0       1   // 1: Enabled, 0: Disabled  (serial_c => CSI Port 2 => VI Stream 2)
// ------------------------------------------------------------------------------------------------
//  Supported number of lanes
// -----+------------------------------------------------------------------------------------------
//  1   | OV7251, IMX296, IMX297
//  2   | OV9281, IMX264, IMX265
//  2,4 | IMX178, IMX183, IMX226, IMX250, IMX252, IMX273, IMX290, IMX327, IMX335, IMX392, 
//      | IMX412, IMX415, IMX568
// -----+------------------------------------------------------------------------------------------
#define VC_MIPI_LANES       2   // 1, 2, 4 Lanes
// ------------------------------------------------------------------------------------------------
//  Embedded Metadata Height
// -----+------------------------------------------------------------------------------------------
//  0   | IMX178, IMX183, IMX226, IMX250, IMX252, IMX264, IMX265, IMX273, IMX392, OV7251, OV9281
//  1   | IMX290, IMX327, IMX335, IMX415, IMX462
//  2   | IMX296, IMX297, IMX412
//  4   | IMX565, IMX566, IMX567, IMX568
// -----+------------------------------------------------------------------------------------------
#define VC_MIPI_METADATA_H  "4" // "0", "1", "2", "4" Lines of meta data
// ------------------------------------------------------------------------------------------------
//   Sensor Manufacturer
// -----+------------------------------------------------------------------------------------------
//   1  | Sony Sensor (IMX)
//   2  | Omni Vision Sensor (OV)
// -----+------------------------------------------------------------------------------------------
#define VC_MIPI_MANUFACTURER 1
// ------------------------------------------------------------------------------------------------
//  GStreamer Support
// ------------------------------------------------------------------------------------------------
//  If you want to use GStreamer with nvarguscamerasrc you have to adjust this settings in the 
//  device tree below. The sections which have to be modified are marked by a comment. 
//  To find the correct parameter values please follow the instruction in the main README.md of 
//  this repository https://github.com/VC-MIPI-modules/vc_mipi_nvidia#gstreamer-support
// ------------------------------------------------------------------------------------------------

#if VC_MIPI_LANES == 1
    #define BUS_WIDTH 1
    #define NUM_LANES "1" 
    #define NUM_CSI_LANES 2
    #define PIX_CLK_HZ "150000000"
#endif
#if VC_MIPI_LANES == 2
    #define BUS_WIDTH 2
    #define NUM_LANES "2" 
    #define NUM_CSI_LANES 4
    #define PIX_CLK_HZ "300000000"
#endif
#if VC_MIPI_LANES == 4
    #define BUS_WIDTH 4
    #define NUM_LANES "4" 
    #define NUM_CSI_LANES 8
    #define PIX_CLK_HZ "600000000"
#endif

#if VC_MIPI_CAM_1 == 1 && VC_MIPI_CAM_0 == 1
    #define VC_MIPI_CAMERAS 2
#else
    #define VC_MIPI_CAMERAS 1
#endif

/ {
    tegra-capture-vi  {
        num-channels = <VC_MIPI_CAMERAS>;
        ports {
            #address-cells = <1>;
            #size-cells = <0>;
#if VC_MIPI_CAM_1 == 1
            vc_vi_port0: port@0 {
                reg = <0>;
                vc_vi_in0: endpoint {
                    port-index = <1>;
                    bus-width = <2>;
                    remote-endpoint = <&vc_csi_out0>;
                };
            };
#endif
#if VC_MIPI_CAM_0 == 1
            vc_vi_port1: port@1 {
                reg = <1>;
                vc_vi_in1: endpoint {
                    port-index = <2>;
                    bus-width = <BUS_WIDTH>;
                    remote-endpoint = <&vc_csi_out1>;
                };
            };
#endif
        }; // ports
    };

    host1x@13e00000 {
        nvcsi@15a00000 {
            num-channels = <VC_MIPI_CAMERAS>;
            #address-cells = <1>;
            #size-cells = <0>;
#if VC_MIPI_CAM_1 == 1
            vc_csi_chan0: channel@0 {
                reg = <0>;
                ports {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    vc_csi_chan0_port0: port@0 {
                        reg = <0>;
                        vc_csi_in0: endpoint@0 {
                            port-index = <1>;
                            bus-width = <2>;
                            remote-endpoint = <&vc_mipi_out0>;
                        };
                    };
                    vc_csi_chan0_port1: port@1 {
                        reg = <1>;
                        vc_csi_out0: endpoint@1 {
                            remote-endpoint = <&vc_vi_in0>;
                        };
                    };
                };
            };
#endif
#if VC_MIPI_CAM_0 == 1
            vc_csi_chan1: channel@1 {
                reg = <1>;
                ports {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    vc_csi_chan1_port0: port@0 {
                        reg = <0>;
                        vc_csi_in1: endpoint@2 {
                            port-index = <2>;
                            bus-width = <BUS_WIDTH>;
                            remote-endpoint = <&vc_mipi_out1>;
                        };
                    };
                    vc_csi_chan1_port1: port@1 {
                        reg = <1>;
                        vc_csi_out1: endpoint@3 {
                            remote-endpoint = <&vc_vi_in1>;
                        };
                    };
                };
            };
#endif
        };
    };

    cam_i2cmux {
#if VC_MIPI_CAM_1 == 1
        i2c@0 {
#if VC_MIPI_MANUFACTURER == 1
            vc_mipi_cam0: vc_mipi@1a {
                reg                     = <0x1a>;
#else
            vc_mipi_cam0: vc_mipi@60 {
                reg                     = <0x60>;
#endif
                compatible              = "nvidia,vc_mipi";
                devnode                 = "video0";
                use_sensor_mode_id      = "false";
                sensor_model            = "vc_mipi";

                num_lanes               = "2";
                trigger_mode            = "1";
                io_mode                 = "0";

                // ----------------------------------------------------
                // If you want to use GStreamer with nvarguscamerasrc
                // you have to adjust this settings
                physical_w              = "6.752";
                physical_h              = "5.612";
                // ----------------------------------------------------

                // This node is needed by the Tegra framework.
                // You don't have to change any settings if just want 
                // to use the V4L API.
                mode0 {
                    num_lanes                = "2";
                    tegra_sinterface         = "serial_b";
                    embedded_metadata_height = VC_MIPI_METADATA_H;
                    readout_orientation      = "0";
                    lane_polarity            = "4";

                    // ----------------------------------------------------
                    // If you want to use GStreamer with nvarguscamerasrc
                    // you have to adjust this settings. 
                    active_l                 = "0";
                    active_t                 = "0";
                    active_w                 = "2464";
                    active_h                 = "2048";
                    mode_type                = "bayer";
                    pixel_phase              = "rggb";
                    csi_pixel_bit_depth      = "10";

                    min_gain_val             = "0";         // mdB
                    max_gain_val             = "48000";     // mdB
                    step_gain_val            = "100";       // mdB
                    default_gain             = "0";         // mdB

                    min_exp_time             = "1";         // us
                    max_exp_time             = "1000000";   // us
                    step_exp_time            = "1";         // us
                    default_exp_time         = "10000";     // us

                    // For applications like argus_camera, there should 
                    // be a minimal frame rate greater than zero!
                    min_framerate            = "100";       // mHz
                    max_framerate            = "41300";     // mHz
                    step_framerate           = "100";       // mHz
                    default_framerate        = "41300";     // mHz
                    // ----------------------------------------------------

                    gain_factor              = "1000";
                    exposure_factor          = "1000000";
                    framerate_factor         = "1000";
                    inherent_gain            = "1";
                    min_hdr_ratio            = "1";
                    max_hdr_ratio            = "1";

                    line_length              = "0";
                    phy_mode                 = "DPHY";
                    discontinuous_clk        = "no";
                    mclk_khz                 = "24000";
                    pix_clk_hz               = "300000000";
                    mclk_multiplier          = "0.0";       // deprecated
                    cil_settletime           = "0";
                    dpcm_enable              = "false";
                };

                ports {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    port@0 {
                        reg = <0>;
                        vc_mipi_out0: endpoint {
                            port-index = <1>;
                            bus-width = <2>;
                            remote-endpoint = <&vc_csi_in0>;
                        };
                    };
                };
            };
        };
#endif // VC_MIPI_CAM_1

#if VC_MIPI_CAM_0 == 1
        i2c@1 {
#if VC_MIPI_MANUFACTURER == 1
            vc_mipi_cam1: vc_mipi@1a {
                reg                     = <0x1a>;
#else
            vc_mipi_cam1: vc_mipi@60 {
                reg                     = <0x60>;
#endif
                compatible              = "nvidia,vc_mipi";
                devnode                 = "video1";
                use_sensor_mode_id      = "false";
                sensor_model            = "vc_mipi";

                num_lanes               = NUM_LANES;
                trigger_mode            = "1";
                io_mode                 = "0";

                // ----------------------------------------------------
                // If you want to use GStreamer with nvarguscamerasrc
                // you have to adjust this settings
                physical_w              = "6.752";
                physical_h              = "5.612";
                // ----------------------------------------------------

                // This node is needed by the Tegra framework.
                // You don't have to change any settings if just want 
                // to use the V4L API.
                mode0 {
                    num_lanes                = NUM_LANES;
                    tegra_sinterface         = "serial_c";
                    embedded_metadata_height = VC_MIPI_METADATA_H;
                    readout_orientation      = "0";
                    lane_polarity            = "0";

                    // ----------------------------------------------------
                    // If you want to use GStreamer with nvarguscamerasrc
                    // you have to adjust this settings. 
                    active_l                 = "0";
                    active_t                 = "0";
                    active_w                 = "2464";
                    active_h                 = "2048";
                    mode_type                = "bayer";
                    pixel_phase              = "rggb";
                    csi_pixel_bit_depth      = "10";

                    min_gain_val             = "0";         // mdB
                    max_gain_val             = "48000";     // mdB
                    step_gain_val            = "100";       // mdB
                    default_gain             = "0";         // mdB

                    min_exp_time             = "1";         // us
                    max_exp_time             = "1000000";   // us
                    step_exp_time            = "1";         // us
                    default_exp_time         = "10000";     // us

                    // For applications like argus_camera, there should 
                    // be a minimal frame rate greater than zero!
                    min_framerate            = "100";       // mHz
                    max_framerate            = "41300";     // mHz
                    step_framerate           = "100";       // mHz
                    default_framerate        = "41300";     // mHz
                    // ----------------------------------------------------

                    gain_factor              = "1000";
                    exposure_factor          = "1000000";
                    framerate_factor         = "1000";
                    inherent_gain            = "1";
                    min_hdr_ratio            = "1";
                    max_hdr_ratio            = "1";

                    line_length              = "0";
                    phy_mode                 = "DPHY";
                    discontinuous_clk        = "no";
                    mclk_khz                 = "24000";
                    pix_clk_hz               = PIX_CLK_HZ;
                    mclk_multiplier          = "0.0";       // deprecated
                    cil_settletime           = "0";
                    dpcm_enable              = "false";
                };

                ports {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    port@0 {
                        reg = <0>;
                        vc_mipi_out1: endpoint {
                            port-index = <2>;
                            bus-width = <BUS_WIDTH>;
                            remote-endpoint = <&vc_csi_in1>;
                        };
                    };
                };
            };
        };
#endif // VC_MIPI_CAM_0
    };

    lens@vc_mipi {
        min_focus_distance  = "0.0";
        hyper_focal         = "0.0";
        focal_length        = "6.0";
        f_number            = "2.0";
        aperture            = "0.0";
    };
};

/ {
    tcp: tegra-camera-platform {
        compatible = "nvidia, tegra-camera-platform";

        num_csi_lanes = <NUM_CSI_LANES>;
        max_lane_speed = <1500000>;
        min_bits_per_pixel = <10>;
        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>;

        modules {
#if VC_MIPI_CAM_1 == 1
            cam_module0: module0 {
                badge = "jakku_front_vc_mipi";
                position = "front";
                orientation = "1";
                cam_module0_drivernode0: drivernode0 {
                    pcl_id = "v4l2_sensor";
#if VC_MIPI_MANUFACTURER == 1
                    devname = "vc_mipi 9-001a";
                    proc-device-tree = "/proc/device-tree/cam_i2cmux/i2c@0/vc_mipi@1a";
#else
                    devname = "vc_mipi 9-0060";
                    proc-device-tree = "/proc/device-tree/cam_i2cmux/i2c@0/vc_mipi@60";
#endif
                };
                cam_module0_drivernode1: drivernode1 {
                    pcl_id = "v4l2_lens";
                    proc-device-tree = "/proc/device-tree/lens@vc_mipi/";
                };
            };
#endif // VC_MIPI_CAM_1

#if VC_MIPI_CAM_0 == 1
            cam_module1: module1 {
                badge = "jakku_rear_vc_mipi";
                position = "rear";
                orientation = "1";
                cam_module1_drivernode0: drivernode0 {
                    pcl_id = "v4l2_sensor";
#if VC_MIPI_MANUFACTURER == 1
                    devname = "vc_mipi 10-001a";
                    proc-device-tree = "/proc/device-tree/cam_i2cmux/i2c@1/vc_mipi@1a";
#else
                    devname = "vc_mipi 10-0060";
                    proc-device-tree = "/proc/device-tree/cam_i2cmux/i2c@1/vc_mipi@60";
#endif  
                };
                cam_module1_drivernode1: drivernode1 {
                    pcl_id = "v4l2_lens";
                    proc-device-tree = "/proc/device-tree/lens@vc_mipi/";
                };
            };
#endif // VC_MIPI_CAM_0
        };
    };
};

#define CAM0_PWDN   TEGRA234_MAIN_GPIO(H, 6)
#define CAM1_PWDN   TEGRA234_MAIN_GPIO(AC, 0)
#define CAM_I2C_MUX     TEGRA234_AON_GPIO(CC, 3)

/ {
    cam_i2cmux {
        status = "okay";
        compatible = "i2c-mux-gpio";
        #address-cells = <1>;
        #size-cells = <0>;
        mux-gpios = <&tegra_aon_gpio CAM_I2C_MUX GPIO_ACTIVE_HIGH>;
        i2c-parent = <&cam_i2c>;
#if VC_MIPI_CAM_1 == 1
        i2c@0 {
            status = "okay";
            reg = <0>;
            #address-cells = <1>;
            #size-cells = <0>;
#if VC_MIPI_MANUFACTURER == 1
            vc_mipi@1a {
#else
            vc_mipi@60 {
#endif
                reset-gpios = <&tegra_main_gpio CAM0_PWDN GPIO_ACTIVE_HIGH>;
            };
        };
#endif
#if VC_MIPI_CAM_0 == 1
        i2c@1 {
            status = "okay";
            reg = <1>;
            #address-cells = <1>;
            #size-cells = <0>;
#if VC_MIPI_MANUFACTURER == 1
            vc_mipi@1a {
#else
                    vc_mipi@60 {
#endif
                reset-gpios = <&tegra_main_gpio CAM1_PWDN GPIO_ACTIVE_HIGH>;
            };
        };
#endif
    };

    gpio@2200000 {
        camera-control-output-low {
            gpio-hog;
            output-low;
            gpios = <CAM0_PWDN 0 CAM1_PWDN 0>;
            label = "cam0-pwdn","cam1-pwdn";
        };
    };
};

There are similar changes compare to updated branch. Setting VC_MIPI_LANES to 2 for all ports, port-index to <1> and tegra_sinterface to serial_b for CAM0. CAM1 can be 4 lanes but the cameras cannot be same fps in that situation. So setting the lanes same for 2 ports will set cameras as equal. I don't know if there is any settings to set 2 csi ports as 4 lanes but I don't think so. Because Orin Nano supports CAM0 port as 2 lane and CAM1 as 2-4 lane as datasheet's says in 3.2 Camera Connector.

Also there is another issue with driver and device tree. When we checked the table for GStreamer Properties active_w and active_h is 2464x2048 for device tree. But it has adjusted to 2464x2064 in the driver.