实现相机传感器驱动器使得能够通过传感器提供的原始格式通过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驱动程序如下:
提供一个拜耳像素格式传感器需要客户开发:
• 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传感器。
将一个或多个摄像头模块添加到设备树
- 在内核源代码树中找到或创建tegra-camera-platform设备节点:
<top>/hardware/nvidia/platform/t19x/common/kernel-dts/t19x-common-modules/tegra194-camera-imx185-a00.dtsi
- 在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。 |
分段线性压缩函数示例
分段线性压缩功能的示例如下:
• 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(数字重叠)多帧的示例。
适用于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
网友评论