nvidia相机开发--传感器驱动编程指南(1)sensor driver programming guide

实现相机传感器驱动器使得能够通过传感器提供的原始格式通过CSI总线获取相机数据。
根据相机和应用程序的不同,有两种类型的相机编程路径。

• Camera Core Library Interface
• Direct V4L2 Interface

Camera Core User Mode Library Interface

相机核心用户模式库提供应用程序和内核模式V4L2驱动程序之间的所有控件和数据处理。使用相机核心库界面的典型用例包括:

•使用Tegra ISP功能的应用程序
•必须将RGB格式转换为YUV格式并为拜耳传感器执行各种后处理任务的应用程序

具有应用程序和内核模式V4L2驱动程序的Linux for Tegra架构框架是:

框架

Direct V4L2 Interface
在支持直接V4L2接口的应用程序中,使用此接口与NVIDIA V4L2驱动程序进行通信,而无需使用相机核心用户模式库。 使用此路径从传感器捕获RAW数据或验证传感器驱动程序。
应用程序使用内核模式V4L2驱动程序如下:

image.png

提供一个拜耳像素格式传感器需要客户开发:
• Device Tree in the kernel
• V4L2 sensor driver
有两种不同版本的驱动程序可用于传感器驱动程序开发。 版本是:
•版本1.0:过去版本中使用的设计。 某些版本1.0功能在以后的版本中不可用。
•2.0版:使用新的Tegra V4L2 Camera Framework来模块化代码,简化传感器驱动程序架构并将冗余代码封装在一个公共位置的新版本。 NVIDIA建议将此版本用于任何新的驱动程序开发。

提供的示例使用Sony IMX185传感器。 索尼IMX185传感器的源代码在以下文件中:
• Version 1.0 driver: imx185_v1.c
• Version 2.0 driver: imx185.c

相机模块和设备树Camera Modules and Device Tree

安装在目标平台上的相机模块可以包括一个或多个设备。 典型的后置摄像头模块包括互补金属氧化物半导体(CMOS)传感器。 典型的前置摄像头模块可以包括单个CMOS传感器。

将一个或多个摄像头模块添加到设备树

  1. 在内核源代码树中找到或创建tegra-camera-platform设备节点:
<top>/hardware/nvidia/platform/t19x/common/kernel-dts/t19x-common-modules/tegra194-camera-imx185-a00.dtsi
  1. 在Tegra-camera-platform设备节点中,使用一个或多个模块创建模块表(modules)。
    每个module必须包含其基本信息以及该模块内部设备的定义。

注意:
相机相关设备节点中的所有值字段必须使用字符串数据类型,但引用其他设备节点的文件除外。

A typical device-tree node for a camera module is:

tegra-camera-platform {
    compatible = "nvidia, tegra-camera-platform";
    modules {
        module0 {
            badge = "imx185_bottom_liimx185";
           position = "bottom";
            orientation = "0";
            drivernode0 {
                pcl_id = "v4l2_sensor";
                devname = "imx185 30-001a";
                proc-device-tree = "/proc/device-tree/i2c@3180000/tca9546@70/i2c@0/imx185_a@1a";
            };
        };
    };
};

模块属性

The information for moduleX: module (or moduleX: modules) is:

Property Value
badge 标识此模块的唯一名称。命名badge_info属性的三个部分的准则:•第一部分是模块的摄像机板ID(camera_board_id)。 •第二部分包含模块的位置,例如后部或前部。 •第三部分包含部件号的最后六个字符,您可以在供应商的模块数据表中找到该字符。 如果部件号不可用,请使用唯一标识符。 如果您的系统有多个相同的模块,请为每个模块创建一个唯一的名称。 例如,如果您有后置摄像头,则可以调用后置摄像头模块imx185_rear_liimx185。
position The camera-facing information. The positions supported depends on the number of cameras in the system: • Two-camera system: rear and front. • Three-camera system: bottom, top, and center. • Six-camera system: bottomleft, bottomright, centerleft, centerright, topleft, and topright.
orientation 基于索引的传感器方向。 当设备具有带两个摄像头的显示器时,通常使用以下索引:•后面:0 •正面:1 对于其他相机布局,每个相机都需要一个唯一的索引。

个人成像设备Individual Imaging Device

一个成像设备可以是一个相机模块内的组件,他可以是:
•传感器 sensor
•聚焦器 focuser
•闪光灯 flash
必须将所需信息添加到设备树节点以支持设备操作。
每个设备树节点对应一个设备,分配一个设备树节点包含以下内容:
• The name of the device 设备名称
• The slave address for the device 设备从机地址(设备从机地址可从设备数据手册中获取)
• A compatible string that identifies the node 标识该节点的匹配字符串

注意:
除引用其他设备节点的设备外,相机相关设备节点中的所有值字段都必须使用字符串数据类型。
An example device-tree node for the IMX185 V4L2 sensor driver is:

imx185_a@1a {
compatible = "nvidia,imx185";
reg = <0x1a>;
physical_w = "15.0";
physical_h = "12.5";
sensor_model ="imx185";
post_crop_frame_drop = "0";
use_decibel_gain = "true";
delayed_gain = "true";
use_sensor_mode_id = "true";

mode0 {
    mclk_khz = "37125";
    num_lanes = "4";
    tegra_sinterface = "serial_a";
    phy_mode = "DPHY";
    discontinuous_clk = "no";
    dpcm_enable = "false";
    cil_settletime = "0";
    dynamic_pixel_bit_depth = "12";
    csi_pixel_bit_depth = "12";
    mode_type = "bayer";
    pixel_phase = "rggb";
    active_w = "1920";
    active_h = "1080";
    readout_orientation = "0";
    line_length = "2200";
    inherent_gain = "1";
    mclk_multiplier = "2";
    pix_clk_hz = "74250000";

    gain_factor = "10";
    min_gain_val = "0";         /* 0dB */
    max_gain_val = "480";       /* 48dB */
    step_gain_val = "3";        /* 0.3 */
    default_gain = "0";
    min_hdr_ratio = "1";
    max_hdr_ratio = "1";
    framerate_factor = "1000000";
    min_framerate = "1500000";
    max_framerate = "30000000"; /* 30 */
    min_exp_time = "30";        /* us */
    max_exp_time = "660000";    /* us */
    step_exp_time = "1";
    default_exp_time = "33334"; /* us */
    embedded_metadata_height = "1";
};
. . .
ports {
    #address-cells = <1>;
    #size-cells = <0>;
    port@0 {
        reg = <0>;
        liimx185_imx185_out0: endpoint {
        port-index = <0>;
        bus-width = <4>;
        remote-endpoint = <&liimx185_csi_in0>;
    };
};

};
设备属性
对于V4L2传感器设备的设备树节点,请为设备定义所需的硬件资源,如下所示:

property value
compatible 指定设备标识符。 Linux内核使用此关键字将设备驱动程序绑定到特定设备。
reg 指定i2c从机地址
mclk 指定设备的输入时钟名称。默认值为extperiph1。extperiph1的最大频率为24 MHz。 如果MCLK> 24 MHz,则使用外部时钟源。
xxx-gpio 指定设备的通用输入/输出(GPIO)引脚,其中XXX是摄像机的GPIO引脚。相机的默认GPIO引脚包括: •H3 - Camera0重置 •H6 - Camera0掉电 •T6 - Camera1重置 •T5 - Camera1断电
xxx-supply 指定设备的调节器,其中XXX是在设备树中的其他位置定义的实际调节器名称。 -supply后缀是必需的。 以下是定义的监管机构: •vana-supply = <&en_vdd_cam_hv_2v8>; //模拟2.8v •vdig-supply = <&en-vdd-cam_1v2>; //数字1.2v •vif-supply = <&en-vdd-cam>; //界面1.8v •vvcm-supply = <&en_vdd_vcm_2v8>; //模拟2.8v for vcm
xxx-reg 指定调节器的名称,其中XXX是传感器驱动器的调节器名称。 该字段的值是带有后缀-reg的调节器名称。 以下是定义的监管机构: •avdd-reg =“vana”; •dvdd-reg =“vdig” •iovdd-reg =“vif” •vcmvdd-reg =“vvcm”
physical_w 指定传感器的物理宽度(以毫米为单位)
physical_h 指定传感器的物理高度(以毫米为单位)
sensor_model* 指定该模块中的传感器
set_mode_delay_ms* 指定捕获开始后第一帧的最长等待时间(以毫秒为单位)
post_crop_frame_drop* 指定应用传感器裁剪设置后要删除的帧数。有关更多信息,请参阅IMX185传感器驱动程序文档。
use_decibel_gain* 对于使用分贝表示模拟增益的传感器,请使用此选项。 设置为true时,驱动程序接收的模拟增益值以分贝(dB)表示,基于用户模式库中的以下转换:dB = 20 * log(模拟增益)有关更多信息,请参阅IMX185传感器驱动程序文档。
delayed_gain* 用于延迟增益设置。 设置为true时,用户模式驱动程序会将更新后的增益值延迟一帧发送给驱动程序。 默认为“false”。有关更多信息,请参阅IMX185传感器驱动程序文档。
user_sensor_mode_id* 设置为true时,用户模式驱动程序使用TEGRA_CAMERA_CID_SENSOR_MODE_ID控件选择特定传感器模式并绕过默认模式选择逻辑。 默认为“false”。有关更多信息,请参阅IMX185传感器驱动程序文档。
* 可选的 可以在不同的DTSI文件中指定此表中的属性。 例如,可以在平台DTSI文件中指定时钟,GPIO和调节器属性,并且可以在传感器DTSI文件中指定其余属性。

property-value pairs
适用于V4L2实现的传感器模式的属性 - 值对是:

注意:
下表中的所有属性均按模式设置,必须精确设置

property value
modeX 指定传感器模式信息,即基于X:0的索引。
ports 提供媒体控制器图形绑定信息。有关更多信息,请参阅端口绑定
mclk_khz 指定标准mipi驱动时钟,以khz为单位
num_lanes 指定传感器编程输出的通道数。
tegra_sinterface 指定通道所连接的基本Tegra串行接口。
dsicontinuous_clk 指定传感器编程为在MIPI通道上使用不连续时钟的指示。
cil_settletime 指定MIPI通道的THS-Settle时间的值。 0值尝试根据mclk_multiplier参数自动校准。如果您不使用自动校准,则可以使用以下公式计算值: 85ns + 6 * UI <(cli_settletime + 5)<145ns + 10 * UI。 其中UI是单位间隔,并且等于时钟通道上HS状态的持续时间。有关详细信息,请参阅MIPI联盟D-PHY规范。
dpcm_enable 指定是否为此模式启用dpcm压缩。设置为true或false。
active_h 指定像素有效区域的高度。
active_w 指定像素有效区域的宽度
pixel_t(弃用) 不推荐使用此属性并将其替换为以下属性:•mode_type •csi_pixel_bit_depth •pixel_phase
mode_type 指定传感器模式类型。 可能的值包括: •yuv •bayer •bayer_wdr_pwl - 宽动态范围模式,使用分段线性函数压缩多重曝光融合像素数据。 还在传感器上执行多重曝光融合。 有关更多信息,请参阅IMX185传感器驱动程序文档。
csi_pixel_bit_depth 指定CSI总线上最终传感器输出的位深度。“mode_type = bayer_wdr_pwl”表示在应用基于分段线性函数的压缩之后的位深度输出。有关更多信息,请参阅IMX185传感器驱动程序文档。
pixel_phase* Specifies the sensor pixel phase. Possible values include: • uyvy • vyuy • yuyv • yvyu • rggb • bggr • grbg • gbrg For more information, consult to the IMX185 Sensor Driver documentation.
line_length 指定用于校准相机堆栈中的要素的传感器模式的像素线宽水平时序大小。 该值必须等于或大于active_w。
mclk_multiplier (deprecated) 指定MCLK的乘数,以计时硬件的捕获序列。 使用以下等式计算此值: mclk_multiplier =所需的ISP时钟频率/ mclk。 此值必须大于pixel_clk_hz / mclk以防止ISP欠载。
pix_clk_hz 指定用于计算曝光,帧速率等的传感器像素时钟。该值基于输入时钟(mclk)和传感器模式表中的PLL设置计算。 有关如何计算此值,请参阅传感器数据表。\有关更多信息,请参阅传感器像素时钟。
inherent_gain 指定从模式固有获得的增益,即像素合并。如果您不知道此值,请设置为1。

分段线性压缩函数示例
分段线性压缩功能的示例如下:

image.png

• Input signal has 16-bit depth
• Output signal has 12-bit depth
• csi_pixel_bit_depth = “12”
• dynamic_pixel_bit_depth = “16”
The control point properties are:

Property Value
num_control_point 4
control_point_x_0 0
control_point_x_1 2048
control_point_x_2 16384
control_point_x_3 65536
control_point_y_0 0
control_point_y_1 2048
control_point_y_2 2944
control_point_y_3 3712

示例数字重叠WDR曝光帧(3840x2160)
该图示出了双曝光DOL(数字重叠)多帧的示例。

image.png

适用于4K数字重叠WDR帧的此图的值为:


image.png

•LI(行信息)标题像素有助于区分垂直空白周期(VBP)行和不同的曝光行。因此,上图中有三种LI:VBP,长曝光和短曝光。 VP(行)由VI(视频输入)模块基于LI滤除。
•num_of_exposure表示每次数字重叠捕获中的曝光次数。对于4K数字重叠WDR的上述示例,这是2(两次曝光)。
•num_of_ignored_lines表示位于每个曝光帧顶部且未包含在输出帧中的行数。这包括OB行和Ignored Area Effective Pixel行,两者都使用与它们所在的曝光帧相同的LI头。因此,这些行由VI模块读取并被裁剪掉。对于上面的示例,此值为14行= 8 OB行+ 6个忽略区域有效像素行。
•num_of_lines_offset_0表示在双曝光DOL多帧中单次曝光和帧中出现的VBP行数。相同数量的VBP行出现在长曝光帧的末尾和短曝光帧的开始处。对于上面的示例,该值为50(长曝光帧结束时为50行,短曝光帧开始时为50行)。
•num_of_ignored_pixels表示每行开头的LI像素,用于区分不同的曝光行和VBP行。对于上面的示例,此值为4(四个像素)。
•num_of_left_margin_pixels表示每行上图像日期之前左侧的边距像素。这些是裁剪对齐所必需的。对于上面的示例,此值为12(12像素)。
•num_of_right_margin_pixels表示每行图像日期后右侧的边距像素。这些是裁剪对齐所必需的。对于上面的示例,此值为0(零像素)。
•active_w表示像素活动区域的总宽度。在这种情况下,它是3840 + 4(LI)+12(左边距)+ 0(右边距)= 3856。
•active_h表示像素活动区域的总高度。在这种情况下,它是(2160 + 8(OB)+ 6(忽略区域有效像素+50(VBP))* 2 = 4448。
Port Binding端口绑定

vi {
num-channels = <1>;
ports {
    #address-cells = <1>;
    #size-cells = <0>;
    port@0 {
        reg = <0>;
        liimx185_vi_in0: endpoint {
            port-index = <2>;
            bus-width = <4>;
            remote-endpoint = <&liimx185_csi_out0>;
          };
      };
  };
};

nvcsi {
num-channels = <1>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
    reg = <0>;
    ports {
        #address-cells = <1>;
        #size-cells = <0>;
        port@0 {
            reg = <0>;
            liimx185_csi_in0: endpoint@0 {
                port-index = <0>;
                bus-width = <4>;
                remote-endpoint = <&liimx185_imx185_out0>;
            };
        };
        port@1 {
            reg = <1>;
            liimx185_csi_out0: endpoint@1 {
                remote-endpoint = <&liimx185_vi_in0>;
            };
        };
    };
};
};

端口绑定属性是:

function description
port 指定媒体填充端口连接。 所有成像器设备都有一个介质垫,用于绑定与VI的连接。
port-index 定义传感器端口连接。 对于成像器设备,例如聚焦器或闪光灯,不需要该字段。有关更多信息,请参阅端口索引。
bus-width 通过识别连接到传感器的CSI通道的数量来定义总线宽度。
remote-endpoint 定义绑定两个端口的标签。 绑定期望一个端口用于接收器,另一个端口用于源。

验证相机接口绑定

  • 执行以下命令
//if have sudo apt-get install media-player-info
sudo media-ctl -p -d /dev/media0


对于本身不带该命令的系统可以通过apt-get install进行安装:
sudo apt-get install v4l-utils

返回的输出类似于以下内容:

Media controller API version 0.1.0
Media device information
------------------------
driver          tegra-vi4
model           NVIDIA Tegra Video Input Device
serial          
bus info        
hw revision     0x3
driver version  0.0.0

Device topology
- entity 1: 150c0000.nvcsi-0 (2 pads, 2 links)
        type V4L2 subdev subtype Unknown flags 0
        device node name /dev/v4l-subdev0
pad0: Sink
    <- "imx185 30-001a":0 [ENABLED]
pad1: Source
    -> "vi-output, imx185 30-001a":0 [ENABLED]

- entity 2: imx185 30-001a (1 pad, 1 link)
        type V4L2 subdev subtype Sensor flags 0
        device node name /dev/v4l-subdev1
pad0: Source
    [fmt:SRGGB12/1920x1080 field:none]
    -> "150c0000.nvcsi-0":0 [ENABLED]

- entity 3: vi-output, imx185 30-001a (1 pad, 1 link)
        type Node subtype V4L flags 0
        device node name /dev/video0
pad0: Sink
    <- "150c0000.nvcsi-0":1 [ENABLED]

Sensor Pixel Clock传感器像素时钟

相机软件使用传感器像素时钟来计算传感器的曝光和帧速率。 必须正确设置才能避免潜在问题。
根据传感器供应商提供的信息,有几种方法可以获得正确的传感器像素时钟频率:

  • Using PLL multiplier and PLL pre/post dividers:
    MCLK Multiplier = PLL Multiplier / PLL Pre-divider / PLL Post-divider
    pixel_clk_hz = MCLK * MCLK Multiplier
    For example:
    MCLK = 24MHz
    PLL Multiplier = 30
    PLL Pre-divider = 3
    PLL Post-divider = 3
    MCLK Multiplier = 30 / 3 / 3 = 6.67
    Pixel_clk_hz = 24000000 * 6.67 = 160000000
    • Using sensor CSI lane output rate:
    pixel_clk_hz = sensor data rate per lane (Mbps) * number of lanes / bits per pixel
    For example:
    Sensor data rate = 891 Mbps (per lane)
    Number of lanes = 4
    Bits per pixel = 10
    pixel_clk_hz = 891 Mbps * 4 / 10 = 356400000
    • Using frame size and frame rate
    pixel_clk_hz = sensor output size * frame rate

注意:
传感器输出大小不是最终输出大小。 它是传感器用于生成最终输出大小的总像素数。
例如:
传感器输出尺寸= 2200 * 1125(实际输出尺寸1920 * 1080)
帧速率= 30 FPS
pixel_clk_hz = 2200 * 1125 * 30 = 742500000

SerDes Pixel Clock
对于使用串行器/解串器芯片(GMSL或FPD Link)的传感器模块,SoC接收的帧是从SerDes输出的,而不是从传感器输出的。 因此,必须正确指定SerDes像素时钟才能正确配置SoC相机接口并避免缓冲区溢出问题。
必须根据用例(连接到SerDes的摄像机数量)设置SerDes像素时钟。 如果您不确定采用什么用例,请设置为SerDes最大输出速率。
Port Index
端口索引用于指定两个不同模块之间的连接。 对于VI模块,端口索引表示输入流。 对于CSI模块,它表示摄像机所连接的实际CSI端口。
下图显示了不同Jetson平台的端口索引映射。

For NVIDIA® Jetson™ TX2 and NVIDIA® Jetson Nano™:


image.png

For NVIDIA® Jetson AGX Xavier™:

image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容