OV5647 Camera Module Adaptation Guide
This guide uses the OV5647 camera module as an example to detail the development and adaptation process on the NG4520 platform, covering hardware preparation, device tree configuration, driver compilation, system loading, and debugging steps.
Terms and Explanations
Terms | Explanations |
---|---|
ISP | Converts raw sensor data into usable images, handling demosaicing, noise reduction, exposure, focus, and white balance. |
Bayer | Bayer sensors uses alternating red, green, and blue filters over photosites, with green taking half, to capture color images. |
CSI | High-speed serial interface for transferring image data between sensors and processors. |
V4L2 | Linux kernel driver interface for video capture and output devices. |
libargus | NVIDIA API for acquiring camera images and metadata. |
Camera Core Library | Provides controls and processing between user applications and V4L2 drivers. |
GStreamer | Multimedia framework supporting playback and advanced audio/video processing. |
Host1x | Tegra DMA engine managing graphics/multimedia register access and sync via client FIFOs. |
Aperture | Controls the size of the lens opening. |
UVC | USB video devices with standard streaming functions that connect directly to hosts. |
VI | Transfers video data from an input device. |
Software Driver Architecture
The NVIDIA platform supports two types of camera driver architectures:
- Camera Core Library Interface: Enables access to the ISP and advanced image processing. Applications interact through the libargus API (e.g., the nvgstcapture-1.0 tool).
- Direct V4L2 Interface:Directly uses the V4L2 driver without the NVIDIA ISP.
It is recommended to use the Camera Core Library Interface to fully leverage the capabilities of the NVIDIA ISP.
OV5647 Driver Configuration Process
Prerequisites
-
To find the I2C address and pinout of a camera module,verify the Power-Down (PWDN) and RESET pins.
-
Obtain the device’s power-up sequence, external clock parameters, supported resolutions and frame rates, and the color filter array type(BGGR/GBRG/GRBG/RGGB).
-
Confirm the connection interface and the corresponding
tegra_sinterface
mapping (for example, on the NG452X platform, cam0 = serial_c).
This example is based on Jetson Orin NX, with cam0 as the hardware connection interface.
To add camera modules to a device tree
-
Locate or create a tegra-camera-platform device tree node in the kernel source tree at:
Linux_for_Tegra/source/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3767-camera-p3768-ov5647.dts`
-
Configure the
tegra-camera-platform
node, including video stream ports and connection relationships. For example:tegra-capture-vi {
num-channels = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
vi_port1: port@1 {
reg = <0>;
rbpcv2_ov5647_vi_in1: endpoint {
port-index = <2>;
bus-width = <2>;
remote-endpoint = <&rbpcv2_ov5647_csi_out1>;
};
};
};
}; -
I2C Device Node Configuration
Configure camera parameters (I2C address, modes, clock, resolution, etc.):
rbpcv2_ov5647_c@36 {
reset-gpios = <&gpio CAM0_RST GPIO_ACTIVE_HIGH>;
pwdn-gpios = <&gpio CAM1_PWDN GPIO_ACTIVE_HIGH>;
compatible = "ovti,ov5647";
/* I2C device address */
reg = <0x36>;
/* V4L2 device node loation */
devnode = "video0";
/* Physical dimensions of sensor */
physical_w = "3.670";
physical_h = "2.740";
sensor_model = "ov5647";
use_sensor_mode_id = "true";
clocks = <&bpmp TEGRA234_CLK_EXTPERIPH2>,
<&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "extperiph2", "pllp_grtba";
mclk = "extperiph2";
clock-frequency = <24000000>;
mode0 { /* ov5647_MODE0_1920x1080_30FPS */
mclk_khz = "25000";
num_lanes = "2";
// lane_polarity = "4";
tegra_sinterface = "serial_c";
phy_mode = "DPHY";
discontinuous_clk = "yes";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "1920";
active_h = "1080";
mode_type = "bayer";
pixel_phase = "bggr";
csi_pixel_bit_depth = "10";
readout_orientation = "90";
line_length = "2416";
inherent_gain = "1";
mclk_multiplier = "3.6669";
pix_clk_hz = "81666663";
gain_factor = "16";
framerate_factor = "1000000";
exposure_factor = "1000000";
min_gain_val = "16";
max_gain_val = "128";
step_gain_val = "1";
default_gain = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "1";
min_framerate = "30000000"; /* 30.0 fps */
max_framerate = "30000000"; /* 30.0 fps */
step_framerate = "1";
default_framerate = "45000000"; /* 30.0 fps */
min_exp_time = "60"; /* us */
max_exp_time = "30000"; /* 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>;
rbpcv2_ov5647_out1: endpoint {
status = "okay";
port-index = <1>;
bus-width = <2>;
remote-endpoint = <&rbpcv2_ov5647_csi_in1>;
};
};
};
}; -
Port Binding Configuration
-
Use
remote-endpoint
to connect the camera, CSI, and VI modules, ensuring a complete video stream pipeline.tegra-capture-vi {
num-channels = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
vi_port1: port@1 {
reg = <0>;
rbpcv2_ov5647_vi_in1: endpoint {
port-index = <2>;
bus-width = <2>;
remote-endpoint = <&rbpcv2_ov5647_csi_out1>;
};
};
};
};
host1x@13e00000 {
nvcsi@15a00000 {
num-channels = <1>;
#address-cells = <1>;
#size-cells = <0>;
csi_chan1: channel@1 {
reg = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
csi_chan1_port0: port@0 {
reg = <0>;
rbpcv2_ov5647_csi_in1: endpoint@2 {
port-index = <2>;
bus-width = <2>;
remote-endpoint = <&rbpcv2_ov5647_out1>;
};
};
csi_chan1_port1: port@1 {
reg = <1>;
rbpcv2_ov5647_csi_out1: endpoint@3 {
remote-endpoint = <&rbpcv2_ov5647_vi_in1>;
};
};
};
};
};
};
-
-
Overlay Makefile Configuration,add the following in
overlay/Makefile
:dtbo-y += tegra234-p3767-camera-p3768-ov5647.dtbo
-
Build the dtbo:
make dtbs
Building Driver
-
Add Driver Source Code
- Example pat:
drivers/media/i2c/ov5647.c
- It is recommended to modify it based on
nv_ov5693.c
- Main functions include:
- Use
tegracam_device_register
to register the driver - Set up these key function structures:
tc_dev->sensor_ops
(power on/off, register read/write, mode setting, stream control, etc.)tc_dev->v4l2sd_internal_ops
(e.g., open/s_stream)tc_dev->tcctrl_ops
(gain, exposure, frame rate control, etc.)
- Use
static struct tegracam_sensor_ops ov5647_sensor_ops = {
.power_on = ov5647_power_on,
.power_off = ov5647_power_off,
.write_reg = ov5647_write_reg,
.read_reg = ov5647_read_reg,
.set_mode = ov5647_set_mode,
.start_streaming = ov5647_start_streaming,
.stop_streaming = ov5647_stop_streaming,
.sensor_init = ov5647_sensor_init,
}; - Example pat:
The implementation of these functions should follow the OV5647 datasheet and related documentation
-
Add Register Table Header File
- Example path:
drivers/media/i2c/ov5647_modes_tbls.h
- This should include register configuration tables for various resolutions and exposure settings, and keep the same order as defined in the device tree modes.
static struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = {
.open = ov5647_open,
}; - Example path:
-
Driver Makefile Configuration,add the following line to to
drivers/media/i2c/Makefile
to include the OV5647 driver:obj-m += ov5647.o
-
Compile the kernel module:
make modules
Driver Installation and Loading
Copy Files
- Copy the generated
.dtbo
andov5647.ko
to the target device (for example, NG4520):
cd Linux_for_Tegra/source
scp ./kernel-devicetree/generic-dts/dtbs/tegra234-p3767-camera-p3768-ov5647.dtbo milesight@192.168.60.3:/home/milesight
scp ./kernel-devicetree/generic-dts/dtbs/tegra234-p3767-camera-p3768-ov5647.dtbo milesight@192.168.60.3:/home/milesight
Driver Installation
- Copyov5647.ko to the modules directory and run
depmod
to load the driver:
sudo cp ./ov5647.ko /usr/lib/modules/5.15.148-tegra/updates/drivers/media/i2c/
depmod
-
Copy
.dtbo
to/boot
,and load it using theconfig-by-hardware.py
-
After completing these steps, reboot the development board.
Verification Process
-
Check the Device Tree Load
-
Check if
extlinux.conf
has loaded the.dtbo
:cat /boot/extlinux/extlinux.conf
-
Verify whether the device tree node is effective:
cat /proc/device-tree/tegra-camera-platform/modules/module1/drivernode0/sysfs-device-tree
-
-
Check the Driver Load
-
Check the driver module using the following command:
lsmod | grep ov5647 sudo dmesg | grep ov5647
-
Check I2C device matching using the following command:
sudo i2cdetect -y -r 9
-
-
Camera Function Test
-
Run
nvgstcapture-1.0
,to verify resolution and mode matching, and ensure there are no errors. -
Check the video stream pipeline using the following command:
sudo media-ctl -p -d /dev/media0
-
References
Sensor Software Driver Programming
ov5647_driver/ov5647.c at main · mkm684/ov5647_driver
For adapting to other camera models, Please refer to the original vendor datasheet and the NVIDIA official documentation, as the steps are generally similar.