Accessing raw MIPI CSI-2 D-PHY data from a non standard IMX636 sensor

We are trying to read the data from a novel event-based sensor from Sony, the IMX636 which outputs the data on a two-lane MIPI CSI-2 interface. We can configure the sensor using I2C successfully. However, we struggle with implementing the kernel driver to dump the RAW MIPI frames.

Our idea is to just dump the Raw byte stream to a char device so that we can process it later. The tricky part is, the camera packages the events into the MIPI frames in a non-standard way.

The MIPI frames are variable length and don’t contain pixel data in a standard format. To keep it brief, the camera produces 16-bit messages that it packages into a MIPI packet. To reduce the latency, the packets may be sent out before being filled resulting in variable size packets being sent.

As a result, trying to use v4l2 (which already tries to parse the MIPI frames) doesn’t work for us.

All we need is to dump the data as it comes in, however, we have little experience with writing custom Kernel modules. Thus any pointers on where to start would be appreciated.

I have tried adapting the imx185 driver that uses v4l2 with the idea that we would specify the format to be RAW16 and then access the data as the pixel values in the “images” that v4l2 gives us back. However we seem to get the following errors:

[ 2430.263429] tegra-camrtc-capture-vi tegra-capture-vi: corr_err: discarding frame 0, flags: 0, err_data 131072

This is the device overlay we have used:

/dts-v1/;
/plugin/;



/ {
    overlay-name = "IMX636 CSI2";
    jetson-header-name = "Jetson AGX CSI Connector";
    compatible = "nvidia,p3737-0000+p3701-0000","nvidia,p3737-0000+p3701-0004";

    /* imx636 camera driver */
    fragment@0 {
        target = <&gen2_i2c>;
        __overlay__ {
            #address-cells = <1>;
            #size-cells = <0>;

            imx636: imx636@3c { // The address of the camera on the I2C bus
                compatible = "sony,imx636";
                reg = <0x3c>; // I2C address of the camera
                
                sensor_model="imx636";
                physical_w = "6.22";
                physical_h = "3.50";

                status = "okay";
                
                reset-gpios = <&tegra_main_gpio 0x3b 0 >; // GPIO_ACTIVE_LOW
                power-gpios = <&tegra_main_gpio 0x3e 0>; // GPIO_ACTIVE_HIGH


                // pinctrl-names = "default";
                // pinctrl-0 = <&pinctrl_camera>;
                // clock-frequency = <400000>; // I2C clock frequency
                // csi-channel = <0>; // CSI channel the camera is connected to
                
                ports {
                    status = "okay";
                    #address-cells = <1>;
                    #size-cells = <0>;
                    port@0 {
                        reg = <0x00>;
                        status = "okay";
                        imx636_out0: endpoint {
                            port-index = <0>;
                            bus-width = <2>;
                            status = "okay";
                            remote-endpoint = <&imx636_csi_in0>; // Connect to the CSI input endpoint
                        };
                    };
                };
                mode0 {
						mclk_khz = "37125";
						num_lanes = "2";
						tegra_sinterface = "serial_a";
						discontinuous_clk = "yes";
						dpcm_enable = "false";
						cil_settletime = "0";
						dynamic_pixel_bit_depth = "8";
						csi_pixel_bit_depth = "16";
						mode_type = "yuv";
						pixel_phase = "yuyv";
                        phy_mode = "DPHY";

						active_w = "1920";
						active_h = "1080";
						readout_orientation = "0";
						line_length = "2200";
						inherent_gain = "1";
						mclk_multiplier = "4";
						pix_clk_hz = "74250000";

						min_gain_val = "0"; /* dB */
						max_gain_val = "48"; /* dB */
						min_hdr_ratio = "1";
						max_hdr_ratio = "1";
						min_framerate = "1.5";
						max_framerate = "30";
						min_exp_time = "30";
						max_exp_time = "660000";
						embedded_metadata_height = "0";
					};
            };
        };
    };
    /* Enable VI ports */
     fragment@1 {
        target-path = "/tegra-capture-vi";
        __overlay__ {
      		num-channels = <0x01>;
            status = "okay";
            ports {
                #address-cells = <1>;
                #size-cells = <0>;
                status = "okay";
                port@0 {
                    reg = <0x00>;
                    status = "okay";
                    imx636_vi_in0: endpoint {
                        vc-id = <0>;
                        status = "okay";
                        port-index = <0>;
                        bus-width = <2>;
                        remote-endpoint = <&imx636_csi_out0>;
                    };
                };
            };
        };  
    };


    /* Enable CSI ports */

    fragment@5 {
        //// target = <&csi_base>;
        target-path = "/host1x@13e00000/nvcsi@15a00000";
        __overlay__ {
            num-channels=<1>;
            #address-cells = <1>;
            #size-cells = <0>;
            channel@0 {
   				reg = <0x00>;
                status = "okay";
                ports {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    port@0{
                        reg = <0x00>;
                        status = "okay";
                        imx636_csi_in0: endpoint@0 {
                            port-index = <0>;
                            bus-width = <2>;
                            status = "okay";
                            remote-endpoint = <&imx636_out0>;
                        };
                    };
                    port@1 {
                        reg = <0x01>;
                        status = "okay";
                        imx636_csi_out0: endpoint@1 {
                            status = "okay";
                            remote-endpoint = <&imx636_vi_in0>;
                        };
                    };
                };
            };
        };
	};

    /* Tegra camera platform */
    fragment@6 {
        target-path = "/tegra-camera-platform";
        __overlay__ {
            num_csi_lanes = <2>;
            
            modules{
                module0 {
                    badge = "imx636_front_0";
                    position = "front";
                    orientation = "0";
                    status = "okay";
                    drivernode0 {
                        pcl_id = "v4l2_sensor";
                        devname = "imx636 30-003c";
                        proc-device-tree = "/proc/device-tree/i2c@c240000/imx636@3c";
                        status = "okay";
                    };
                };
            };
        };
    };


    /*
    fragment@7 {
    //// target = <&csi_base>;
    target-path = "/host1x@13e00000/nvcsi@15a00000";
    __overlay__ {
        num-channels=<1>;
        

    };
	};
	fragment@8 {
		//// target = <&csi_chan0>;
		target-path = "/host1x@13e00000/nvcsi@15a00000/channel@0";
		__overlay__ {
			status = "okay";
		};
	};
	fragment@9 {
		target-path = "/host1x@13e00000/nvcsi@15a00000/channel@0/ports/port@0";
		__overlay__ {
			status = "okay";
		};
	};
	/*
    fragment@10 {
		target-path = "/host1x@13e00000/nvcsi@15a00000/channel@0/ports/port@0/endpoint@0";
		__overlay__ {
			status = "okay";
			port-index = <0x00>;
			bus-width = <0x02>;
			remote-endpoint = <&imx636>;
		};
	};
	fragment@11 {
		//// target = <&csi_chan0_port1>;
		target-path = "/host1x@13e00000/nvcsi@15a00000/channel@0/ports/port@1";
		__overlay__ {
			status = "okay";
		};
	};
	fragment@12 {
		//// target = <&liimx185_csi_out0>;
		target-path = "/host1x@13e00000/nvcsi@15a00000/channel@0/ports/port@1/endpoint@1";
		__overlay__ {
			status = "okay";
			remote-endpoint = "/tegra-capture-vi/ports/port@0/endpoint";
		};
	};*/
};

Hi @jmandula, which Jetson Hardware are you using here? Then I can maybe refer you to the correct sub-categories for better exposure of this post.

Thanks!

Hey, we are using the Jetson Orin developer kit and connecting the camera using the bottom CSI connector.

Thanks!

I think this might be AGX Orin, so I move your post into their capable hands.